lax*_*axy 4 optimization gcc matrix linear-algebra compiler-flags
我正在使用C执行矩阵运算.我想知道什么是各种编译器优化标志,以提高双和int64数据的这些矩阵运算的执行速度 - 如乘法,反向等.我不是在寻找手动优化的代码,我只想使用编译器标志更快地生成本机代码,并了解有关这些标志的更多信息.
到目前为止我发现的标志改进了矩阵码.
-O3/O4
-funroll-loops
-ffast-math
Run Code Online (Sandbox Code Playgroud)
Ale*_*aev 16
首先,我建议不要使用-ffast-math
,原因如下:
已经证明,在大多数(如果不是全部)情况下使用此选项时,性能实际上会降低.所以"快速数学"实际上并不那么快.
该选项打破了对浮点运算的严格IEEE遵从性,最终导致不可预测性质的计算错误的累积.
您可能会在不同的环境中获得不同的结果,但差异可能很大.术语环境(在这种情况下)意味着组合:硬件,OS,编译器.这意味着当你可以获得意想不到的结果时,情况的多样性呈指数级增长.
另一个令人遗憾的结果是,与使用此选项构建的库链接的程序可能期望正确的(符合IEEE标准)浮点数学,这是他们的预期中断的地方,但要弄清楚原因将非常困难.
最后,看看这篇文章.
出于同样的原因你应该避免-Ofast
(因为它包括邪恶-ffast-math
).提取:
-Ofast
无视严格的标准合规性.
-Ofast
启用所有-O3
优化.它还支持对所有符合标准的程序无效的优化.它打开-ffast-math
并且特定于Fortran-fno-protect-parens
和-fstack-arrays
.
没有这样的旗帜-O4
.至少我不知道那个,并且官方GCC文档中没有它的痕迹.所以这方面的最大值是-O3
,你应该肯定使用它,不仅要优化数学,还要在发布版本中.
-funroll-loops
对于数学例程来说是一个非常好的选择,特别是涉及向量/矩阵运算,其中循环的大小可以在编译时推导出来(并且因此由编译器展开).
我可以推荐另外2个标志:-march=native
和-mfpmath=sse
.类似地-O3
,-march=native
对于任何软件的发布版本而言通常都是好的,而不仅仅是数学密集型.-mfpmath=sse
允许在浮点指令中使用XMM寄存器(而不是在x87模式下使用堆栈).
此外,我想说遗憾的是你不想修改代码以获得更好的性能,因为这是矢量/矩阵例程加速的主要来源.由于SIMD,SSE内在函数和矢量化,重线性代数代码比没有它们快几个数量级.但是,正确应用这些技术需要深入了解其内部结构以及修改(实际重写)代码的相当长的时间/精力.
尽管如此,有一种选择可能适用于您的情况.GCC提供了可以启用的自动向量化-ftree-vectorize
,但是由于您正在使用-O3
它(因为它-ftree-vectorize
已经包含),因此它是不必要的.关键是你应该仍然帮助GCC了解哪些代码可以自动矢量化.修改通常很小(如果需要的话),但你必须熟悉它们.请参阅上面链接中的Vectorizable Loops部分.
最后,我建议您研究一下基于C++模板的Eigen,它可以高效地实现最常见的线性代数例程.到目前为止,它以非常聪明的方式利用了这里提到的所有技术.界面纯粹是面向对象的,整洁且易于使用.面向对象的方法看起来与线性代数非常相关,因为它通常操纵纯对象,如矩阵,向量,四元数,旋转,滤波器等.因此,当使用Eigen编程时,您自己永远不必处理这样的低级概念(如SSE,Vectorization等),而只是喜欢解决您的特定问题.