15

我会举一个例子来问我的问题。现在我有一个名为do_something().

它具有三个版本:do_something()do_something_sse3()do_something_sse4()。当我的程序运行时,它会检测 CPU 功能(查看它是否支持 SSE3 或 SSE4)并相应地调用三个版本之一。

问题是:当我用 GCC 构建我的程序时,我必须设置-msse4do_something_sse4()编译(例如,<smmintrin.h>要包含头文件)。

但是,如果我设置-msse4了 ,则允许 gcc 使用 SSE4 指令,并且其中的一些内在函数do_something_sse3()也被翻译为一些 SSE4 指令。因此,如果我的程序在仅支持 SSE3(但不支持 SSE4)的 CPU 上运行,则会在调用do_something_sse3().

也许我有一些不好的做法。你能给一些建议吗?谢谢。

4

4 回答 4

11

我认为 Mystical 的提示很好,但是如果您真的想在一个文件中执行此操作,则可以使用适当的pragmas,例如:

#pragma GCC target("sse4.1")

需要 GCC 4.4,AFAIR。

于 2013-03-23T09:16:20.453 回答
2

我认为您想要构建所谓的“CPU 调度程序”。我有一个(据我所知)为 GCC 工作,但没有让它与 Visual Studio 一起工作。
用于 AVX 和 SSE 的 Visual Studio 的 CPU 调度程序

我会检查 Agner Fog 的矢量类和文件 dispatch_example.cpp http://www.agner.org/optimize/#vectorclass

g++ -O3 -msse2   -c dispatch_example.cpp -od2.o
g++ -O3 -msse4.1 -c dispatch_example.cpp -od5.o
g++ -O3 -mavx    -c dispatch_example.cpp -od8.o
g++ -O3 -msse2      instrset_detect.cpp d2.o d5.o d8.o
于 2013-03-25T08:38:40.637 回答
0

以下是为每个优化设置编译单独的目标文件的示例:http: //notabs.org/lfsr/software/index.htm

但是,当使用 gcc 链接时间优化 (-flto) 时,即使这种方法也会失败。那么如何构建一个针对不同处理器进行全面优化的可执行文件呢?我能找到的唯一解决方案是使用包含指令使 C 文件表现为单个编译单元,因此不需要 -flto。这是使用该方法的示例:http: //notabs.org/blcutil/index.htm

于 2013-03-25T05:04:37.813 回答
0

-march=XXX如果您在 i686 或 x86_64 机器上使用 GCC 4.9 或更高版本,那么无论您的和-mXXX选项如何,您都应该能够使用内在函数。你可以相应地写你的do_something()

void do_something()
{
    byte temp[18];

    if (HasSSE2())
    {
        const __m128i i = _mm_loadu_si128((const __m128i*)(ptr));
        ...
    }
    else if (HasSSSE3())
    {
        const __m128i MASK = _mm_set_epi8(12,13,14,15, 8,9,10,11, 4,5,6,7, 0,1,2,3);
        _mm_storeu_si128(reinterpret_cast<__m128i*>(temp),
           _mm_shuffle_epi8(_mm_loadu_si128((const __m128i*)(ptr)), MASK));
    }
    else
    {
        // Do the byte swap/endian reversal manually
        ...
    }
}

你必须供应HasSSE2()HasSSSE3()和朋友。另请参阅CPUID 之类的内部信息?.

另请参阅GCC 问题 57202 - 请使 immintrin.h 等内在函数头文件在没有编译器标志的情况下可用。但我不相信该功能有效。我经常遇到编译失败,因为 GCC 不提供内在函数。

于 2017-04-17T13:20:31.540 回答