-ffast-math 有什么作用?

计算科学 优化 浮点 计算机算术
2021-12-03 23:12:42

该选项-ffast-math做了哪些优化?

我看到使用该选项的简单算法所花费的时间减少到算法所花费的时间。O(n2)O(n)

2个回答

在 GCC 的 wiki 中有一个关于这个问题的规范答案,大概是维护的,它是迄今为止这类问题最权威的信息来源。另一方面,这个问题最终可能会过时。这一切都在 wiki 中通过示例进行了更详细的解释。以下基本上是它的引述,以说明它如何回答这个确切的问题,并附有少量评论:

  • -fno-signaling-nans
  • -fno-trapping-math

    IEEE 标准建议实现允许陷阱处理程序处理被零除和溢出等异常。此标志假定不会发生使用可见陷阱。

  • -funsafe-math-optimizations- 这些优化打破了浮点运算法则,并可能用普通的无限精度运算法则代替它们:

    由于舍入误差,代数的结合律不一定适用于浮点数,因此像 (x + y) + z 这样的表达式不一定等于 x + (y + z)。

  • -ffinite-math-only- 特殊数量,例如infnan假定永远不会出现,这样可以节省寻找和适当处理它们的时间。例如,是否应该始终等于xx0.0

  • -fno-errno-math

    在调用数学库例程时禁用 C89/C99 要求的 errno 变量设置。对于 Fortran,这是默认设置。

  • -fcx-limited-range

    导致在执行复杂除法时省略范围缩小步骤。这使用并且可能无法正常工作输入的任意范围。a/b=((arbr+aibi)/t)+i((aibrarbi)/t)t=brbr+bibi

  • -fno-rounding-math

  • -fno-signed-zeros

    由于舍入误差,代数的结合律不一定适用于浮点数,因此像 (x + y) + z 这样的表达式不一定等于 x + (y + z)。

严格地说,后两者的含义并不总是像人们想象的那样直观。例如(参见 wiki),怎么样,是还是我相信有大量关于确切含义的文献,尤其是比尔·卡汉( Bill Kahan)。(aa)=aa+0.00.0

  • 没有直接提到(我没看到?),但是用-ffast-math,某些常见的特殊函数,如倒数和平方根被替换为速度更快但仍然有的不太精确的版本一些“可容忍”的错误级别(相对于标准要求的 0ulp 错误) -例如,这里是 glibc 的 libm 通常提供的精度确实,这是加速的最常见原因,在使用除法和平方根进行大量算术运算的代码中,几乎到了我(个人)认为其他子选项(尤其是类似信号)的地步1/xx-ffast-math-ffinite-math-onlyNaNs 对于调试非常有用)在成本/收益方面造成了一些麻烦。

我看到使用该选项的简单算法所花费的时间减少到算法所花费的时间。O(n2)O(n)

我认为这是不可能的,您可能在分析中犯了错误。由于有更多的优化选择,不安全的浮点优化可能会使单个表达式的评估成本更低。但是加速应该始终是一个恒定的因素。你有没有可能比较一个O(n2)算法与O(n)对于不够大n?

一个n2算法可以简化为行为O(n)如果,例如,如果n是编译器已知的,并且是处理器支持的向量指令(如果有)的向量大小的倍数。如果编译器可以看到所有这些,它可以展开一个内部循环并使用向量指令来完成这项工作。这可以将完成的整体操作减少到少数,并大大提高性能。

我的阅读是fast-math不启用这样的优化,但如果unsafe-math-optimizations由于其中禁用的关联性限制而隐式启用它们,则可以。