在GCC中启用严格的浮点模式

13

我还没有创建一个程序来查看GCC是否需要传递它,当我这样做时,我想知道如何启用严格的浮点模式,这将允许在运行和计算机之间产生可重复的结果,谢谢。


3
请注意,由于硬件错误,即使强制启用严格模式也可能无法获得可重复的结果。并且这些情况确实存在:http://www.cs.earlham.edu/~dusko/cs63/fpu.html,http://lwn.net/Articles/89586/,http://www.reghardware.com/2006/04/28/amd_opteron_fpu_bug/... - liori
1
@liori,您所说的“bug”是指“以非常出名和有文献记录的方式仅提供比IEEE 754双精度更高的精度”。硬件没有漏洞。它确实不允许编译器获得他们想要的干净的IEEE 754双精度语义,但这不是一个漏洞,只是一个缺陷。 - Pascal Cuoq
@liori,我必须指出,在您添加链接之前,我已经写下了我的评论。有趣的是,我撤回了我评论中“硬件没有错误”的部分。 - Pascal Cuoq
@Pascal Cuoq:是的,我添加了这些链接,因为我认为有人可能会这样想 :-) - liori
1
即使存在硬件缺陷,我也不认为这支持“浮点数不会产生可重复结果”的观点。这只意味着某些硬件已经损坏,不应该使用。你会声称x86锁定前缀由于f00f漏洞而无法产生可重复的结果吗?不,你只会称出现该漏洞的CPU是有缺陷的... - R.. GitHub STOP HELPING ICE
显示剩余2条评论
3个回答

6
使用-msse2编译支持它的英特尔/AMD处理器几乎可以实现目标。不要让任何库将FPU置于FTZ/DNZ模式下,这样你就可以基本完成任务(处理器错误除外)。
对于其他架构,答案会有所不同。那些没有提供任何方便的方法来获得精确IEEE 754语义的架构(例如,早期的SSE2 IA32 CPU)需要使用浮点仿真库才能获得所需结果,但会面临非常高的性能惩罚。
如果你的目标架构支持fmadd(无中间舍入的乘法和加法)指令,请确保在源代码中有显式乘法和加法时,你的编译器不要使用它。GCC不应该这样做,除非你使用-ffast-math选项。

1
@highsciguy 我之所以说“快完成了”,是因为使用-msse2的副作用使得编译器生成非严格的IEEE 754代码比生成严格的IEEE 754代码更加困难,但并非不可能。编译器仍有可能在努力打破浮点语义。以夸张的例子来说,GCC开发人员可能在某个版本中实现优化“将除以常数替换为乘以倒数”,然后稍后可能会有人抱怨,这个特定的优化可能会被移动到-ffast-math选项中。 - Pascal Cuoq
1
@highsciguy 总结一下,编译器制造商通常不在意把这种保证写进文档里面,但是在最好的情况下,如果你报告说他们所做的更改破坏了严格的 IEEE 754 语义,他们会倾听。结果可能取决于使用的精确编译器版本。你最好的选择是使用“-S -msse2”并阅读汇编以检查不正确的转换。对于历史指令集来说,有点无望:一些细节可以在 http://gcc.gnu.org/ml/gcc-patches/2008-11/msg00105.html 找到。 - Pascal Cuoq
1
您可能还想查看编译器设置的宏FLT_EVAL_METHOD的值。该宏由编译器设置。还请参阅程序员设置的FP_CONTRACT - Pascal Cuoq
1
@PascalCuoq:我希望编程语言能够包含不同的严格和非严格运算符,因为许多算法需要使用严格的语义执行一些关键步骤,但在其他步骤中可以容忍更宽松的语义[例如,因为一个步骤上的+/- 1lsb误差会在下一个步骤中被取消]。如果算法中有25%的步骤需要精确执行,最好是标出这25%并让其他操作运行得更快,而不是让所有操作都变慢。 - supercat
1
作为一个对浮点数不太感兴趣的人,上个月我第一次编写了一个数值稳定的算法,实际上希望编译器用FMAs替换乘法和加法,我完全同意@supercat的观点。据我所知,GCC仍然不允许在编译单元以下的规模选择其中一种模式。 - Pascal Cuoq
显示剩余2条评论

2
如果您使用-ffloat-store并始终将中间值存储到变量中或应用(显式)转换为所需的类型/精度,则应至少达到目标的90%,甚至更多。欢迎评论是否还有此方法无法覆盖的情况。请注意,我声称即使没有任何SSE选项,这也可以实现。

两个词: "双重舍入" http://www.exploringbinary.com/double-rounding-errors-in-floating-point-conversions/ - Pascal Cuoq
1
不错的观点。个人而言,当我需要精确的浮点数行为时,我只是使用 long double 来处理所有事情... - R.. GitHub STOP HELPING ICE
这是一个不错的解决方案,但是在没有80位“long double”的计算机之间就无法实现可移植性。现在我想起来了,我想知道当OP说“计算机”时,他是否真正意味着跨架构,还是仅指给定架构内的处理器(在这种情况下,他应该是安全的)。 - Pascal Cuoq
1
避免双重舍入问题的另一种方法是使用不同的舍入模式,例如 fesetround(FE_TOWARDZERO)... :-) - R.. GitHub STOP HELPING ICE
1
说句实话,我发现在GCC中使用-ffloat-store与Microsoft的/fp:precise模式相符。这是一件好事。 - Peter M

2

特别是“确定性跨平台”这篇文章非常棒。谢谢! - Peter M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接