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

Optimization 矩阵/向量运算的GCC优化标志,optimization,gcc,matrix,linear-algebra,compiler-flags,Optimization,Gcc,Matrix,Linear Algebra,Compiler Flags,我正在使用C执行矩阵运算。我想知道各种编译器优化标志是什么,可以提高double和int64数据(如乘法、求逆等)矩阵运算的执行速度。我不是在寻找手动优化的代码,我只是想使用编译器标志使本机代码更快,并了解更多关于这些标志的信息 到目前为止,我发现的改进矩阵代码的标志 -O3/O4 -funroll-loops -ffast-math 首先,我不建议使用-ffast math,原因如下: 事实证明,当 在大多数(如果不是全部)情况下使用此选项。所以“快速数学”是 其实没那么快 此选项打破了对

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

到目前为止,我发现的改进矩阵代码的标志

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

首先,我不建议使用
-ffast math
,原因如下:

  • 事实证明,当 在大多数(如果不是全部)情况下使用此选项。所以“快速数学”是 其实没那么快

  • 此选项打破了对浮点运算的严格IEEE遵从性 最终导致计算量累积的操作 性质难以预料的错误

  • 在不同的环境中,您可能会得到不同的结果,而这种差异可能是不同的 实质性的。术语环境(在本例中)意味着:硬件, 操作系统,编译器。这意味着当你遇到意想不到的情况时,情况的多样性 结果呈指数增长

  • 另一个可悲的后果是,与 使用此选项生成的库可能会 期望正确的(符合IEEE的)浮点数学,这是 他们的期望有何突破,但这将很难预测 找出原因

  • 最后,看一看

  • 出于同样的原因,您应该避免使用
    -Ofast
    (因为它包括邪恶的
    -ffast math
    )。摘录:

    -Ofast

    无视严格的标准遵从性
    -Ofast
    启用所有
    -O3
    优化。它还支持对所有标准兼容程序无效的优化。它打开
    -ffast math
    和Fortran特有的
    -fno protect parens
    -fstack数组

    没有像
    -O4
    这样的标志。至少我不知道这一点,在GCC的官方文档中也没有它的踪迹。因此,这方面的最大值是
    -O3
    ,您应该明确地使用它,不仅是为了优化数学,而且通常是在发布版本中使用它

    -funroll循环
    对于数学例程来说是一个非常好的选择,特别是涉及向量/矩阵运算,其中循环的大小可以在编译时推导出来(结果由编译器展开)

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

    此外,我想说,很遗憾,您不想修改代码以获得更好的性能,因为这是向量/矩阵例程加速的主要来源。多亏了,而且,重线性代数代码可以比没有重线性代数代码快几个数量级。然而,这些技术的正确应用需要对其内部结构有深入的了解,并且需要花费相当多的时间/精力来修改(实际重写)代码

    然而,有一种选择可能适合您的情况。GCC提供了可通过
    -ftree vectorize
    启用的功能,但由于您正在使用
    -O3
    (因为它已经包括
    -ftree vectorize
    )。关键是,您仍然应该帮助GCC了解哪些代码可以自动矢量化。修改通常很小(如果需要的话),但是你必须让自己熟悉它们。因此,请参见上面链接中的可矢量化循环部分


    <>最后,我建议您研究一下基于C++模板的库,它高效地实现了大多数常见的线性代数例程。它以一种非常巧妙的方式利用了这里提到的所有技术。该界面纯粹是面向对象的,简洁,易于使用。面向对象的方法看起来与线性代数非常相关,因为它通常处理纯对象,如矩阵、向量、四元数、旋转、过滤器等。因此,在使用Eigen编程时,您不必亲自处理此类低级概念(如SSE、矢量化等),只需享受解决特定问题的乐趣。

    我绝对建议您使用Eigen。这很容易学。虽然这篇文章提到了许多在优化过程中需要考虑的常见问题,但是EGEN又做了很多事情,做了很多非常先进的事情。谢谢!这帮了大忙。实际上,我正在尝试将编译器优化代码提供的最佳加速比(这是我的问题)与我手工优化的矩阵运算代码进行比较。@Haroogan:谢谢你的提示。我完全接受你的回答:)。很抱歉,我还不能升级。
    ffast math
    导致代码速度变慢可能被认为是一个编译器错误,而且是一个非常令人惊讶的错误(可能在编译时没有
    march=native
    ?)。根据我的经验,自动矢量化和并行化并不是特别有用。。即使是最新的ICC(通常是最好的)也存在代码简单的问题,小而无害的更改可能会产生令人惊讶的效果。如果依赖于性能,请使用编译器内部函数,并将其显式写入imo。不过,对于Eigen;,使用+1)我找到了关于
    -ffast math
    性能反转的信息,但这有点让我不知所措。从中,我看到“这意味着没有矢量化,除非你有非常有效的水平矢量加法”;在第5点,可能David的代码在这两种情况下都得到了矢量化,或者两者都没有,但这些值属于某种边缘情况,其中IEEE浮点的性能优于实现(通常)的快速浮点表示?(Int)