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