【问题标题】:Reproducibility of floating point operation result浮点运算结果的再现性
【发布时间】:2012-08-10 18:07:36
【问题描述】:

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

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

【问题讨论】:

  • 它们应该产生完全相同的结果。除非您使用的是非常旧的奔腾...
  • 对于真正具有数学意义的可重现结果,请使用小数,而不是浮点数。有关两者之间区别的更多信息,请参阅this 帖子。
  • @aguazales 我不使用 Ruby,只要它们在所有 FPU 上的工作方式完全相同,我也可以使用浮点数,所以如果它们真的可以使用,那么最大的问题仍然存在? :]
  • @Wug haha​​ 是的,我听说过那个错误,我不需要介绍那个案例:]
  • 哎呀,对不起!我以为我正在浏览 Ruby on Rails 标签:S 我的错。

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


【解决方案1】:

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

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

约瑟夫·克里宁recommends:

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

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

【讨论】:

  • 谢谢,我仍然不确定是否尝试 FP 一致性,或者只是使用固定精度:(
【解决方案2】:

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

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

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

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

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

【讨论】:

    猜你喜欢
    • 2014-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-17
    • 1970-01-01
    • 2021-12-30
    • 2013-01-31
    相关资源
    最近更新 更多