5

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

编辑:添加了 c++ 标签。
还要澄清:我需要可重现的结果运行时。我不希望从不同的编译中得到相同的结果。

4

2 回答 2

9

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

根据 Glenn Fiedler 的关于浮点决定论的文章,​​答案是“可能是一个响亮的跛行”;如果您在相同的架构上运行相同的二进制文件限制使用不如基本浮点指定的功能,那么您可以获得相同的结果。否则,如果您使用不同的编译器,或者允许您的代码使用 SSE 或 80 位浮点,那么不同的可执行文件和不同的机器之间的结果会有所不同。

Yosef Kreinin建议

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

当然,在多台不同的机器上测试你的代码;获取中间输出的哈希值,这样您就可以知道您的模拟在何时何地发散。

于 2012-08-14T13:30:39.477 回答
4

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

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

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

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

如果您同时为 32 位目标 (i386) 和 64 位目标 (x86_64) 构建,那么您正在制作两个可执行映像(在一个“胖”文件中),并且需要考虑不同的编译器产品。

于 2012-08-14T16:17:24.180 回答