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

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

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

问题是:当我使用GCC构建程序时,我必须为do_something_sse4()设置-msse4以进行编译(例如,要包含头文件 )。

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

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

我认为Mystical的提示很好,但是如果你真的想在一个文件中执行它,你可以使用适当的编译指示 ,例如:

 #pragma GCC target("sse4.1") 

需要GCC 4.4,AFAIR。

我想你想建立一个所谓的“CPU调度员”。 我为GCC工作了一次(据我所知),但是还没有使用Visual Studio。
用于AVX和SSE的visual studio的cpu调度程序

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

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

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

如果您在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,如信息? 。

另请参阅GCC问题57202 – 请使immintrin.h之类的内在函数标题在没有编译器标志的情况下可用 。 但我不相信这个function有用。 我经常遇到编译失败,因为GCC没有提供内在函数。