我知道 gcc 的--ffast-math
标志可以大大提高浮动操作的速度,并且超出了 IEEE 标准,但我似乎无法找到有关它开启时实际发生的情况的信息。任何人都可以解释一些细节,并给出一个明确的例子来说明如果标志打开或关闭,事情会如何变化?
我确实尝试通过 SO 挖掘类似的问题,但找不到任何解释 ffast-math 工作原理的东西。
我知道 gcc 的--ffast-math
标志可以大大提高浮动操作的速度,并且超出了 IEEE 标准,但我似乎无法找到有关它开启时实际发生的情况的信息。任何人都可以解释一些细节,并给出一个明确的例子来说明如果标志打开或关闭,事情会如何变化?
我确实尝试通过 SO 挖掘类似的问题,但找不到任何解释 ffast-math 工作原理的东西。
-ffast-math
不仅仅是打破严格的 IEEE 合规性。
首先,当然,它确实违反了严格的 IEEE 合规性,例如允许将指令重新排序为数学上相同(理想情况下)但在浮点上不完全相同的东西。
其次,它在单指令数学函数之后禁用设置,这意味着避免写入线程局部变量(这对于某些架构上的这些函数可能产生 100% 的差异)。errno
第三,它假设所有数学都是有限的,这意味着没有对 NaN(或零)进行检查,因为它们会产生不利影响。只是假设这不会发生。
第四,它使除法和倒数平方根的倒数近似成为可能。
此外,它禁用有符号零(代码假定不存在有符号零,即使目标支持它)和舍入数学,这在编译时启用了常量折叠等。
最后,它生成的代码假定不会由于信号/陷阱数学而发生硬件中断(也就是说,如果在目标架构上无法禁用这些中断并且因此确实发生了,它们将不会被处理)。
正如您所提到的,它允许不保持严格的 IEEE 合规性的优化。
一个例子是这样的:
x = x*x*x*x*x*x*x*x;
到
x *= x;
x *= x;
x *= x;
由于浮点运算不是关联的,因此运算的排序和因式分解会因舍入而影响结果。因此,这种优化不是在严格的 FP 行为下进行的。
我实际上并没有检查 GCC 是否真的做了这个特定的优化。但想法是一样的。