矩阵/向量运算的GCC优化标志

时间:2013-04-17 15:35:19

标签: optimization gcc matrix linear-algebra compiler-flags

我正在使用C执行矩阵运算。我想知道什么是各种编译器优化标志,以提高双和int64数据的这些矩阵运算的执行速度 - 如乘法,反向等。我不是在寻找手动优化代码,我只想使用编译器标志更快地生成本机代码,并了解有关这些标志的更多信息。

到目前为止我找到的改进矩阵代码的标志。

-O3/O4
-funroll-loops
-ffast-math

1 个答案:

答案 0 :(得分:16)

首先,由于以下原因,我不建议使用-ffast-math

  1. 已经证明,当性能实际上降低时 在大多数(如果不是全部)情况下使用此选项。所以“快速数学”是 实际上并不那么快。

  2. 此选项在浮点上违反了严格的IEEE合规性 最终导致计算累积的操作 不可预测的错误。

  3. 您可能会在不同的环境中获得不同的结果,但差异可能会有所不同 可观。术语环境(在这种情况下)意味着组合:硬件, OS,编译器。这意味着当你出现意想不到的情况时的多样性 结果呈指数增长。

  4. 另一个令人遗憾的后果是与之相关的节目 使用此选项构建的库可能 期望正确(符合IEEE标准)浮点数学,这是 他们的期望在哪里破裂,但这很难实现 为什么。

  5. 最后,请查看this article

  6. 出于同样的原因,你应该避免-Ofast(因为它包括邪恶的-ffast-math)。提取物:

      

    -Ofast

         

    无视严格的标准合规性。 -Ofast启用所有-O3优化。它还支持对所有符合标准的程序无效的优化。它会启用-ffast-math和特定于Fortran的-fno-protect-parens-fstack-arrays

    没有-O4这样的旗帜。至少我不知道那个,并且官方GCC文档中没有它的痕迹。因此,这方面的最大值是-O3,您应该肯定使用它,不仅要优化数学,还要在发布版本中进行优化。

    -funroll-loops是数学例程的一个很好的选择,特别是涉及向量/矩阵运算,其中循环的大小可以在编译时推断(并且因此由编译器展开)。

    我可以推荐另外两个标志:-march=native-mfpmath=sse。与-O3类似,-march=native通常适用于任何软件的发布版本,而不仅仅是数学密集型。 -mfpmath=sse允许在浮点指令中使用XMM寄存器(而不是x87 mode中的堆栈)。

    此外,我想说很遗憾你不想修改代码以获得更好的性能,因为这是矢量/矩阵例程加速的主要来源。感谢SIMDSSE IntrinsicsVectorization,重线性代数代码比没有它们快几个数量级。但是,正确应用这些技术需要深入了解其内部结构,并需要花费大量时间/精力来修改(实际上重写)代码。

    尽管如此,有一种选择可能适用于您的情况。 GCC提供的auto-vectorization可由-ftree-vectorize启用,但由于您使用的是-O3(因为它已包含-ftree-vectorize),因此无需提供。关键是你应该仍然帮助GCC了解哪些代码可以自动矢量化。修改通常很小(如果需要的话),但你必须熟悉它们。请参阅上面链接中的 Vectorizable Loops 部分。

    最后,我建议您研究Eigen,这是一个基于C ++模板的库,它可以高效地实现最常见的线性代数例程。到目前为止,它以非常聪明的方式利用了这里提到的所有技术。界面纯粹是面向对象的,整洁且易于使用。面向对象的方法看起来与线性代数非常相关,因为它通常操纵纯对象,如矩阵,向量,四元数,旋转,滤波器等。因此,当使用Eigen进行编程时,您不必自己处理这种低级概念(如SSE,Vectorization等),而只是喜欢解决您的特定问题。