Boi*_*nst 11 c++ g++ compiler-optimization visual-studio-2008 ubuntu-10.04
背景:
许多年前,我继承了一个使用Visual Studio(VC++)标志'/ fp:fast'的代码库,以在特定的计算重量库中生成更快的代码.不幸的是,'/ fp:fast'产生的结果与不同编译器(Borland C++)下的同一个库略有不同.当我们需要产生完全相同的结果时,我切换到'/ fp:precise',这很好,从那以后一切都很好.但是,现在我在uBuntu Linux 10.04上用g ++编译同一个库,我看到了类似的行为,我想知道它是否有类似的根本原因.我的g ++构建的数值结果与我的VC++构建的数值结果略有不同.这让我想到了我的问题:
题:
g ++与VC++中的'fp:fast'和'fp:precise'选项有相同或相似的参数吗?(它们是什么?我想激活'fp:precise'等价物.)
更详细的信息:
我使用'make'编译,它调用g ++.据我所知(make文件有点神秘,而且不是我写的)g +调用中添加的唯一参数是"普通"(包括文件夹和要编译的文件)和-fPIC(我不确定这个开关是做什么的,我没有在'man'页面上看到它.
'man g ++'中唯一相关的参数似乎是用于打开优化选项.(例如-funsafe-math-optimizations).但是,我认为我没有打开任何东西,我只是想关闭相关的优化.
我已经尝试过发布和调试版本,VC++为发布和调试提供了相同的结果,g ++给出了与发布和调试相同的结果,但是我不能让g ++版本给出与VC++版本相同的结果.
Dre*_*all 18
从GCC手册:
-ffloat-store 不将浮点变量存储在寄存器中,并禁止可能改变浮点值是从寄存器或内存中获取的其他选项.
这个选项可以防止诸如68000之类的机器上出现不希望的过度精度,其中浮动寄存器(68881)比双重应该具有更高的精度.同样适用于x86架构.对于大多数程序来说,多余的精度只会很好,但有些程序依赖于IEEE浮点的精确定义.在修改它们以将所有相关的中间计算存储到变量中之后,对这些程序使用-ffloat-store.
为了扩展一点,大多数这些差异来自于使用x86 80位浮点寄存器进行计算(相对于用于存储double值的64位).如果中间结果保存在寄存器中而不写回存储器,则有效地在计算中获得16位额外的精度,使它们更精确,但可能与通过向存储器写入/读取中间值(或从只有64位FP寄存器的架构).
这些标志(在GCC和MSVC中)通常强制将每个中间结果截断为64位,从而使计算对代码生成和优化以及平台差异的变幻莫测不敏感.除了精度/精度方面的成本之外,这种一致性通常还带有轻微的运行时成本.
Ofe*_*lon 10
过多的寄存器精度仅在FPU寄存器上存在问题,编译器(具有正确的使能开关)往往会避免.当在SSE寄存器中执行浮点计算时,寄存器精度等于存储器1.
根据我的经验,大多数/ fp:快速影响(和潜在的差异)来自编译器冒昧执行代数转换.这可以像更改summands顺序一样简单:
( a + b ) + c --> a + ( b + c)
Run Code Online (Sandbox Code Playgroud)
可以 - 随意分配像*(b + c)这样的乘法,并且可以得到一些相当复杂的变换 - 所有这些都旨在重用以前的计算.在无限精度中,这种变换当然是良性的 - 但是在有限的精度下,它们实际上改变了结果.作为一个玩具示例,尝试使用a = b = 2 ^( - 23),c = 1的summand-order-example.MS的Eric Fleegal 更详细地描述了它.
在这方面,最靠近/ fp:precise的gcc开关是-fno-unsafe-math-optimizations.我认为它默认是开启的 - 也许你可以尝试明确地设置它,看看它是否有所作为.类似地,您可以尝试显式关闭所有-ffast-math优化:-fno-finite-math-only,-fmath-errno,-ftrapping-math,-frounding-math和-fsignaling-nans(最后两个选项是非默认!)