许多年前,我继承了一个使用Visual Studio(VC)标志’/ fp:fast’的代码库,在特定的计算重型库中生成更快的代码.不幸的是,’/ fp:fast’产生的结果与不同编译器(Borland C)下的同一个库略有不同.当我们需要产生完全相同的结果时,我切换到’/ fp:精确’,这是很好的,从那以后,一切都是桃子.然而,现在我正在使用u在Ubuntu Linux 10.04上编译同一个库,我看到类似的行为,我想知道它是否可能有类似的根本原因.我的g构建的数值结果与VC构建的数值结果略有不同.这带给我我的问题:
题:
g对VC中的“fp:fast”和“fp:precise”选项有相同或相似的参数? (和他们是什么?我想激活’fp:精确’等价物.)
更详细信息:
我使用’make’编译,它调用g.据我所知(make文件有点隐含,并不是由我写的),g调用中添加的唯一参数是“正常”(包括文件夹和要编译的文件)和-fPIC(我不知道这个开关是什么,我在’man’页面上看不到它).
“man g”中唯一的相关参数似乎是打开优化选项. (例如,安全数学优化).但是,我不认为我打开任何东西,我只想关闭相关优化.
我已经尝试发布和调试版本,VC为发布和调试提供相同的结果,g给出相同的发布和调试结果,但是我无法获得g版本,以提供与VC版本相同的结果.
解决方法
在我的经验中,大多数/ fp:快速影响(和潜在的差异)来自于编译器自由地执行代数变换.这可以像更改总和顺序一样简单:
( a + b ) + c --> a + ( b + c)
可以像*(b c)一样分布乘法,并且可以获得一些相当复杂的变换 – 所有这些都旨在重用以前的计算.
在无限精度下,这种变换当然是良性的 – 但是在有限的精度下,它们实际上改变了结果.作为玩具的例子,尝试a = b = 2 ^( – 23),c = 1的summand-order-example.MS的Eric Fleegal describes it in much more detail.
在这方面,最接近/ fp:precise的gcc开关是-fno-unsafe-math-optimizations.我认为这是默认的 – 也许您可以尝试明确设置它,看看它是否有所作为.类似地,您可以尝试明确地关闭所有的-ffast-math优化:-fno-finite-math-only,-fmath-errno,-ftrapping-math,-frounding-math和-fsignaling-nans(最后2个选项是非默认!)