浮点运算结果的再现性

时间:2012-08-14 12:42:48

标签: c++ floating-point fixed-point

浮点算术运算是否有可能在不同的CPU上产生不同的结果? CPU是指x86和x64的全部内容。并且通过不同的结果,我的意思是即使只有一个最不重要的位是不同的。我需要知道我是否可以在项目上使用浮点运算,这对于在不同机器上具有与相同输入相对应的完全相同的结果是至关重要的。

编辑:添加了c ++标签 还要澄清一下:我需要可重现的结果运行时间。我不希望不同编辑的结果相同。

2 个答案:

答案 0 :(得分:9)

在游戏行业中,这被称为 deterministic lockstep ,对于客户端和服务器需要就物理对象的状态达成一致的实时网络游戏非常重要(玩家,抛射物,可变形地形等)。

根据Glenn Fiedler关于Floating Point Determinism的文章,答案是“ a laoundingly limp maybe ”;如果在相同的体系结构上运行相同的二进制文件并且限制使用不如基本浮点指定的功能,那么您可以获得相同的结果。否则,如果您使用不同的编译器,或允许您的代码使用SSE或80位浮点,那么不同的可执行文件和不同的机器之间的结果会有所不同。

Yosef Kreinin recommends

  • 扫描汇编程序输出以进行代数优化并将其应用于源代码;
  • 抑制融合乘法加法和其他高级指令(例如sin三角函数);
  • 并使用SSE或SSE2,或以其他方式将FPU CSR设置为64位。 (是的,这与Glenn Fiedler的建议相冲突。)

当然,在多台不同的机器上测试您的代码;获取中间输出的哈希值,这样您就可以确定模拟发生的时间和地点。

答案 1 :(得分:4)

如果您调用动态链接库,则可能会在不同的处理器上获得不同的代码。 (例如,Mac OS X上的Accelerate库在不同的处理器上使用其例程的不同实现。)

但是,如果使用相同的可执行映像(包括所有库),这些映像不基于处理器模型进行调度并具有相同的输入(包括对浮点模式或可影响浮点的其他全局状态所做的任何更改),然后处理器为所有基本浮点运算产生相同的结果(加,减,乘,除,比较,转换)。

某些操作可能未完全指定在不同的处理器上返回相同的结果,例如反平方根估计指令。

ecatmur关于编译器,融合乘法 - 加法和SSE / SSE2 / FPU使用的优化的答案中提到的问题不适用于相同的二进制文件。这些问题仅适用于不同的编译(不同的开关,不同的目标平台,不同的编译器版本)可能产生不同的代码。由于您排除了不同的编辑,因此这些问题无关紧要。

如果为32位目标(i386)和64位目标(x86_64)构建,则会生成两个可执行映像(在一个“胖”文件中),并且会关注不同的编译器产品。< / p>