【问题标题】:What's the proper way to use different versions of SSE intrinsics in GCC?在 GCC 中使用不同版本的 SSE 内在函数的正确方法是什么?
【发布时间】:2013-03-13 04:10:21
【问题描述】:

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

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

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

但是,如果我设置-msse4,那么gcc就可以使用SSE4指令,do_something_sse3()中的一些内在函数也会被翻译成一些SSE4指令。因此,如果我的程序在仅支持 SSE3(但不支持 SSE4)的 CPU 上运行,则在调用 do_something_sse3() 时会导致“非法指令”。

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

【问题讨论】:

  • 我认为标准的做法是在不同的编译单元中编译不同的版本。
  • @Mysticial,首先感谢您编辑我的问题。据我了解,“在单独的编译单元中编译不同的版本”是指:将所有do_things_sse4放在一个文件functios_sse4.c中,并使用选项-msse4进行编译;并用-msse3 编译functions_sse3.c。我会试试这个。 (我可能需要重构我的代码,这些代码最初是为 MSVC 编写的)
  • 是的,这正是我的意思。 :)
  • @BoPersson,某些功能可以通过使用一些新的 SSE4 指令来进一步加速。由于我们正在处理可能非常耗时的视频编码/解码,我认为 SSE4 优化是有意义的。
  • @BoPersson:仍然有很多计算机没有 SSE4/SSE3 支持,甚至没有任何 SSE 支持。非 SSE 版本适合他们。

标签: c gcc sse intrinsics


【解决方案1】:

如果您在 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 不提供内在函数。

【讨论】:

    【解决方案2】:

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

    我会检查 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
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        【解决方案4】:

        我认为Mystical的提示很好,但如果你真的想在one文件中这样做,你可以使用正确的pragmas,例如:

        #pragma GCC target("sse4.1")
        

        需要 GCC 4.4,AFAIR。

        【讨论】:

        • 感谢您的建议。稍后我也会尝试#pragma 指令。
        • 即使使用 #pragma GCC target("sse4") 也不能包含 smmintrin.h
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2010-11-10
        • 1970-01-01
        • 1970-01-01
        • 2012-08-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多