3

我已经开始在新的英特尔 Sandy Bridge 处理器上使用 AVX 指令。我正在使用 GCC 4.5.2,TDM-GCC 64 位版本的 MinGW64。

我想重载 operator<< 以便 ostream 能够将向量类型等打印__m256__m128控制台。但是我遇到了超载冲突。以下代码中的第二个函数产生错误“与先前声明冲突void f(__vector(8) float)”:

void f(__m128 v) {
cout << 4;
}

void f(__m256 v) {
    cout << 8;
}

似乎编译器无法区分这两种类型并同时考虑它们f(float __vector)

有没有解决的办法?我一直无法在网上找到任何东西。任何帮助是极大的赞赏。

4

2 回答 2

4

当函数模板遇到类似问题时,我不小心偶然发现了答案。在这种情况下,GCC 错误消息实际上提出了一个解决方案:

添加-fabi-version=4编译器选项。

这解决了我的问题,希望在链接标准库时不会引起任何问题。

可以在ABI Policy and GuidelinesABI specification阅读更多关于 ABI(应用程序二进制接口)和 GCC 的信息。ABI 指定当代码被编译成目标文件时函数名称是如何被修改的。显然,GCC 默认使用的 ABI 版本 3 无法区分各种向量类型。

于 2011-05-10T07:01:27.247 回答
1

我对更改编译器 ABI 标志来解决这个问题的解决方案不满意,所以我去寻找不同的解决方案。似乎他们在编写 Eigen 库时遇到了这个问题 - 有关详细信息,请参阅此源文件http://eigen.tuxfamily.org/dox-devel/SSE_2PacketMath_8h_source.html

我对此的解决方案是他们的稍微调整的版本:

template <typename T, unsigned RegisterSize>
struct Register
{
    using ValueType = T;
    enum { Size = RegisterSize };

    inline operator T&() { return myValue; }
    inline operator const T&() const { return myValue; }
    inline Register() {}
    inline Register(const T & v) : myValue(v) {} // Not explicit
    inline Register & operator=(const T & v)
    {
        myValue = v;
        return *this;
    }

    T myValue;
};

using Register4 = Register<__m128, 4u>;
using Register8 = Register<__m256, 8u>;
// Could provide more declarations for __m128d, __m128i, etc. if needed

使用上述方法,您可以重载Register4,Register8等或生成模板函数,Register而不会遇到链接问题,也不会更改 ABI 设置。

于 2014-12-04T14:53:32.987 回答