对于我的OS程序之一,我有几个使用SSE4.1指令的优化案例。在SSE3专用机器上,运行非优化分支:
// SupportsSSE4_1 returns true on CPUs that support SSE4.1, false otherwise
if (SupportsSSE4_1()) {
// Code that uses _mm_dp_ps, an SSE4 instruction
...
__m128 hDelta = _mm_sub_ps(here128, right128);
__m128 vDelta = _mm_sub_ps(here128, down128);
hDelta = _mm_sqrt_ss(_mm_dp_ps(hDelta, hDelta, 0x71));
vDelta = _mm_sqrt_ss(_mm_dp_ps(vDelta, vDelta, 0x71));
...
} else {
// Equivalent code that uses SSE3 instructions
...
}为了使上面的内容能够编译,我必须将CLANG_X86_VECTOR_INSTRUCTIONS设置为sse4.1。
然而,这似乎指示clang可以在我的程序中的任何地方使用ROUNDSD指令。因此,该程序是崩溃的SSE3专用计算机与SIGILL: ILL_ILLOPC。
对于SupportsSSE4_1() if块真正分支中的代码行,启用SSE4.1的最佳实践是什么?
发布于 2014-06-08 02:07:54
目前还没有办法针对clang中块/函数粒度的不同ISA扩展。您只能在文件粒度(将SSE4.1代码放入一个单独的文件并指定该文件使用-msse4.1)时才能这样做。如果这是您的一个重要功能,请提交一个错误报告请求它!
但是,我应该注意到,在大多数实际场景中,DPPS的实际好处非常小(而且使用DPPS甚至会减慢一些代码序列!)除非这个特定的代码序列是关键的,并且您已经仔细地测量了使用DPPS的效果,否则即使编译器特性可用,也不值得为SSE4.1的特殊情况而麻烦。
发布于 2014-06-10 08:43:13
你可以做一个CPU调度器。您可以在一个文件中这样做,但您必须编译两次。首先使用SSE4.1,然后不使用SSE4.1,然后在SSE4.1的对象文件中链接。第一次调用函数myfunc时,它调用函数myfunc_dispatch,该函数确定指令集并设置指向myfunc_SSE41或myfunc_SSE3的指针。下次调用func myfunc时,它直接跳到指令集的函数。
//clang -c -O3 -msse4.1 foo.cpp -o foo_sse41.o
//clang -O3 -msse3 foo.cpp foo_sse41.o
typedef float MyFuncType(float*);
MyFuncType myfunc, myfunc_SSE41, myfunc_SSE3, myfunc_dispatch;
MyFuncType * myfunc_pointer = &myfunc_dispatch;
#ifdef __SSE4_1__
float myfunc_SSE41(float* a) {
//SSE41 code
}
#else
float myfunc_SSE3(float *a) {
//SSE3 code
}
float myfunc_dispatch(float *a) {
if(SupportsSSE4_1()) {
myfunc_pointer = myfunc_SSE41;
}
else {
myfunc_pointer = myfunc_SSE3;
}
myfunc_pointer(a);
}
float myfunc(float *a) {
(*myfunc_pointer)(a);
}
int main() {
//myfunc(a);
}
#endif发布于 2014-06-08 20:07:19
根据操作系统的不同,将来您可能可以使用类似于函数多版本控制的东西。我现在正在研究这个特性,但还需要一段时间才能在生产编译器中使用。
有关更多详细信息,请参阅http://gcc.gnu.org/wiki/FunctionMultiVersioning。
https://stackoverflow.com/questions/24101875
复制相似问题