gcc 中的 fast-math 是做什么的?

我理解gcc的--ffast-math标志可以大大提高浮点运算的速度,并且超出了IEEE标准,但我似乎找不到关于它打开时真正发生了什么的信息。谁能解释一些细节,或者给出一个清晰的例子,如果国旗是开着或关着,事情会发生什么变化?

我确实试着在sos中寻找类似的问题,但没有找到任何解释快速数学工作原理的东西。

77658 次浏览

正如您所提到的,它允许不严格遵守IEEE的优化。

一个例子是:

x = x*x*x*x*x*x*x*x;

x *= x;
x *= x;
x *= x;

因为浮点算术不是关联运算,运算的排序和分解会因为舍入而影响结果。因此,这种优化不是在严格的FP行为下完成的。

我实际上并没有检查GCC是否确实进行了这种特定的优化。但理念是一样的。

-ffast-math做的不仅仅是打破严格的IEEE遵从。

首先,当然,它严格遵守IEEE,允许例如,指令的重新排序是数学上相同的(理想情况下),但不是完全相同的浮点数。

其次,它禁用在单指令数学函数后设置errno,这意味着避免写入线程局部变量(这可以使某些体系结构上的这些函数100%不同)。

第三,它假设所有的数学都是有限的,这意味着在NaN(或零)会产生有害影响的地方不会进行检查。人们只是简单地假设这不会发生。

第四,它为除法和平方根倒数启用互惠的近似

此外,它还禁用了有符号零(代码假定有符号零不存在,即使目标支持它)和舍入数学,从而在编译时支持常量折叠。

最后,它生成的代码假定由于信令/捕获数学运算不会发生硬件中断(也就是说,如果这些不能在目标体系结构上禁用并因此会发生,它们将不会被处理)。