我一直在阅读 x86 指令集扩展,它们似乎只在某些非常特定的情况下有用(例如,HADDPD - SSE3 中的(Horizontal-Add-Packed-Double))。这些需要一定的寄存器布局,需要刻意设置,或者从之前的一系列指令中发生。像 gcc 这样的通用编译器多久实际使用一次这些指令(或其子集),或者它们主要用于手工编码的汇编程序?编译器如何检测适合使用 SIMD 指令的位置?
5 回答
通常,很少有编译器使用它们。GCC 和 Visual Studio 通常不能使用 SIMD 指令。如果启用 SSE 作为编译器标志,它将使用标量 SSE 指令进行常规浮点运算,但通常不要期望自动使用矢量化指令。在某些情况下,最新版本的 GCC 可能能够使用它们,但我上次尝试时并没有工作。英特尔的 C++ 编译器是我所知道的唯一能够自动矢量化某些循环的大型编译器。
不过,一般来说,您必须自己使用它们。在原始汇编程序中,或通过使用编译器内在函数。一般来说,我会说内在函数是更好的方法,因为它们更好地允许编译器理解代码,从而安排和优化,但在实践中,我知道 MSVC 至少并不总是从内在函数生成非常有效的代码,所以简单的 asm 可能是那里最好的解决方案。实验一下,看看有什么效果。但是不要指望编译器会为您使用这些指令,除非您 1) 使用正确的编译器,以及 2) 编写可以简单矢量化的相当简单的循环。
更新 2012
好的,自从我写这个答案以来已经过去了三年。GCC 已经能够自动矢量化(简单)代码几年了,在 VS2012 中,MSVC终于获得了同样的能力。当然,我的回答的主要部分仍然适用:编译器仍然只能向量化相当琐碎的代码。对于任何更复杂的事情,您都被困在内部函数或内联汇编中。
只要您将 Mono 的类用于向量,Mono 就可以使用 SIMD 扩展。你可以在这里阅读:http: //tirania.org/blog/archive/2008/Nov-03.html
只要您使用-O3
或使用特定标志,GCC 就应该进行一些自动矢量化。他们在这里有一个信息页面:http: //gcc.gnu.org/projects/tree-ssa/vectorization.html
一段时间以来,如何自动利用 SSE 和其他小型向量单元(无需程序员以特殊语言结构或特别祝福的编译器“内在”形式提供指导)的问题一直是编译器研究的主题。大多数结果似乎专门针对特定问题域,例如数字信号处理。我没有跟上关于这个主题的文献,但我读到的内容表明,利用向量 (SSE) 单元仍然是一个研究主题,人们应该对该领域常用的通用编译器抱有较低的期望.
建议搜索词:向量化编译器
我已经看到 gcc 使用 sse 将默认的 std::string 对象清零。sse 的使用不是特别强大,但它确实存在。在大多数情况下,尽管您必须自己编写。
我知道这一点是因为我让堆栈变得未对齐并且它崩溃了,否则我可能不会注意到!
如果您使用向量 pascal 编译器,您将获得 SIMD 具有优势的类型的高效 SIMD 代码。基本上这是长度小于 64 位的任何内容。(对于 64 位实数,执行 SIMD 实际上更慢)。最新版本的编译器还将自动跨内核并行化