在某种意义上,手动矢量化代码,使用显式编译指示还是依赖或使用自动矢量化更好?为了使用自动矢量化获得最佳性能,必须监视编译器输出以确保循环被矢量化或修改它们直到它们可矢量化。
使用手动编码,可以确定正在发出所需的指令,但现在代码可能不可移植(对于其他架构或其他编译器)。
在某种意义上,手动矢量化代码,使用显式编译指示还是依赖或使用自动矢量化更好?为了使用自动矢量化获得最佳性能,必须监视编译器输出以确保循环被矢量化或修改它们直到它们可矢量化。
使用手动编码,可以确定正在发出所需的指令,但现在代码可能不可移植(对于其他架构或其他编译器)。
自动矢量化对我来说从来都不是很好。对我来说,目前自动矢量化似乎只适用于非常微不足道的循环。
我使用 pragma/intrinsic 方法并查看程序集。如果编译器生成错误代码(例如将 SSE 寄存器溢出到堆栈上或添加冗余移动),我将内联汇编程序用于整个循环体。
顺便说一句,便携性不是问题。通常,您从 C/C++ 循环开始并使用内在函数对其进行优化。只需保留旧循环并将其用作 SIMD 实现的单元测试/备用。此外,能够通过编译时定义从项目中删除所有 SIMD 代码总是明智的。这样调试应用程序要容易得多。相同的定义可用于交叉编译。
我永远不会依赖任何编译器的自动矢量化。gcc
我会加倍小心,因为 's 优化的效果总是gcc
因版本而异。我认识的几乎每个依赖特殊优化或 gcc 扩展的人都必须在新gcc
版本发布时处理损坏问题。
您通常可以信任 pragma 和内在函数,但您应该密切关注新 gcc 版本的发行说明,并且应该告诉您自己的用户编译您的代码需要什么 gcc 版本。
有一次或两次,当向量化真的很重要时,我们在测试套件中添加了一些东西来调用objdump
和验证向量指令是否真正被使用。能够自动检测“坏矢量代码”(如 Nils 所描述的那样)会很好,但我们从未走到那一步。