我一直在研究x86指令集扩展,它们只在某些特定情况下才有用(例如SSE3中的HADDPD-水平添加打包双精度)。这些扩展需要特定的寄存器布局,需要通过特定的指令序列来设置。像gcc这样的通用编译器实际上多少会使用这些指令(或其子集),还是主要用于手写汇编语言?编译器如何检测何时适合使用SIMD指令?
我一直在研究x86指令集扩展,它们只在某些特定情况下才有用(例如SSE3中的HADDPD-水平添加打包双精度)。这些扩展需要特定的寄存器布局,需要通过特定的指令序列来设置。像gcc这样的通用编译器实际上多少会使用这些指令(或其子集),还是主要用于手写汇编语言?编译器如何检测何时适合使用SIMD指令?
通常情况下,很少有编译器使用它们。GCC和Visual Studio通常不能使用SIMD指令。如果您将SSE作为编译器标志启用,它将使用标量SSE指令进行常规浮点运算,但通常不要期望自动使用向量化指令。最近的版本可能在某些情况下能够使用它们,但上次我尝试时并未生效。Intel的C ++编译器是我所知道的唯一一个能够自动矢量化某些循环的大型编译器。
总的来说,您将不得不亲自使用它们。可以使用原始汇编语言或使用编译器内置函数。一般而言,我会说内置函数是更好的方法,因为它们更容易让编译器理解代码,并进行调度和优化,但实际上,我知道至少MSVC并不总是从内置函数生成非常高效的代码,因此纯汇编可能是最好的解决方案。尝试实验,看看哪种方式有效。但是,除非您1)使用正确的编译器,2)编写相当简单的循环以便进行矢量化,否则不要期望编译器为您使用这些指令。
更新2012
好的,自我写这个答案以来已经过去三年了。几年前,GCC已经能够自动矢量化(简单的)代码,在VS2012中,MSVC 终于获得了相同的功能。当然,我的答案的主要部分仍然适用:编译器仍然只能将相当简单的代码向量化。对于任何更复杂的内容,您都必须使用内置函数或内联汇编语言。
-O3
或特定标志。他们在这里有一个信息页面:http://gcc.gnu.org/projects/tree-ssa/vectorization.html。A[i] = B[i] * x + C[i]
或其他类型(整数或FP)。不适用于像A[idx[i]]
这样的gather或scatter操作。对于具有不同类型宽度、任何重组或结构的数组,或任何更复杂的类似于串行依赖关系(例如前缀和)的东西,你仍然经常需要手动向量化才能获得最佳效果。 - Peter Cordes