我会举一个例子来问我的问题。现在我有一个名为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()
时会导致“非法指令”。
也许我有一些不好的做法。你能提一些建议吗?感谢。
答案 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没有提供内在函数。