在GCC中使用不同版本的SSE内在函数的正确方法是什么?

时间:2013-03-23 08:54:05

标签: c gcc sse intrinsics

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

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

问题是:当我使用GCC构建程序时,我必须为-msse4设置do_something_sse4()进行编译(例如,对于头文件<smmintrin.h>被包括)。

但是,如果我设置-msse4,则允许gcc使用SSE4指令,do_something_sse3()中的某些内在函数也会转换为某些SSE4指令。因此,如果我的程序在仅支持SSE3(但没有SSE4)的CPU上运行,则在调用do_something_sse3()时会导致“非法指令”。

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

4 个答案:

答案 0 :(得分:9)

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

#pragma GCC target("sse4.1")

需要GCC 4.4,AFAIR。

答案 1 :(得分:2)

我认为您想构建所谓的“CPU调度程序”。我为GCC工作了一次(据我所知),但还没有使用Visual Studio cpu dispatcher for visual studio for AVX and SSE

我会查看Agner Fog的vectorclass和文件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

答案 2 :(得分:0)

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

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

答案 3 :(得分:0)

如果您在i686或x86_64计算机上使用GCC 4.9或更高版本,那么无论您使用-march=XXX-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()和朋友。另请参阅Intrinsics for CPUID like informations?

另见GCC Issue 57202 - Please make the intrinsics headers like immintrin.h be usable without compiler flags。但我不相信这个功能有用。我经常遇到编译失败,因为GCC没有提供内在函数。