【问题标题】:Deterministic floating point and .NET确定性浮点和 .NET
【发布时间】:2011-01-23 12:24:31
【问题描述】:

如何保证 .NET 应用程序(例如 C#)中的浮点计算总是产生相同的位精确结果?尤其是在使用不同版本的 .NET 并在不同平台上运行时(x86 与 x86_64)。浮点运算的不准确性无关紧要。

在 Java 中,我会使用 strictfp。在 C/C++ 和其他低级语言中,这个问题基本上是通过访问 FPU / SSE 控制寄存器来解决的,但在 .NET 中这可能是不可能的。

即使控制了 FPU 控制寄存器,.NET 的 JIT 也会在不同的平台上生成不同的代码。在这种情况下,像 HotSpot 这样的东西会更糟......

我为什么需要它?我正在考虑编写一个实时策略 (RTS) 游戏,该游戏严重依赖于快速浮点数学以及锁步模拟。本质上,我只会通过网络传输用户输入。这也适用于通过存储用户输入来实现回放的其他游戏。

不是一个选项:

  • 小数(太慢)
  • 定点值(使用 sqrt、sin、cos、tan、atan... 时太慢太麻烦)
  • 像 FPS 一样通过网络更新状态:发送数百或数千个单位的位置信息不是一种选择

有什么想法吗?

【问题讨论】:

    标签: .net floating-point deterministic real-time-strategy


    【解决方案1】:

    我不确定您的问题的确切答案,但您可以使用 C++ 并在 c++ dll 中完成所有浮动工作,然后通过 interopt 将结果返回给 .Net。

    【讨论】:

    • 如果我用 C/C++ 编写游戏的关键部分(模拟),那么我可以在没有 .Net 的情况下编写整个游戏。也许这就是这里的“正确”方式。
    • 查看 MSVC 编译器的 C/C++ IJW (It-Just-Works) 功能。它可以让您将需要编写的内容编写为非托管代码,并将其余部分作为托管代码执行,以便与游戏的其他托管部分顺利交互。
    【解决方案2】:

    针对不同平台的 Bitexact 结果令人头疼。 如果您只使用 x86,那没关系,因为 FPU 不会从 32 到 64 位。但问题是超越函数可能更多 在新处理器上准确。

    四个基本操作不应给出不同的结果,但您的虚拟机可能 优化表达式,这可能会产生不同的结果。所以正如蚂蚁提出的, 为了安全起见,将您的 add/mul/div/sub 例程编写为非托管代码。

    对于超越函数,恐怕你必须使用查找表来 保证位的准确性。计算例如的结果4096 个值,存储它们 作为常量,如果您需要它们之间的值,请进行插值。 这不会给你很大的准确性,但它会很精确。

    【讨论】:

    • 当 SSE 单元和 FPU 未正确配置时,即使在单个处理器上,四个基本操作也会产生不同的结果(禁用两者的次正规数,在 fpu 上使用 32 位或 64 位值而不是最大值精确)。超越函数可以在 C/C++ 中使用这种受控环境在软件中实现。
    【解决方案3】:

    如果您想要浮点确定性,您需要消除所有变量。如果您稍微限制您的范围,这是可能的。

    1. 仅将您的应用程序设为 64 位。这样您就不必处理 x87 与 SSE(x86 JIT 仍会发出 x87 fp 代码,其他 JIT 会发出 SSE)。
    2. 使用 .NET Core 和 bundle the runtime with your application。这样,您就可以保证应用程序的任何给定版本都具有相同的代码生成。这一点至关重要,最细微的代码生成差异都会导致 fp 计算得出不同的结果。
    3. 坚持使用一个操作系统。说真的,有多少跨平台RTS?是的,有星际争霸2;就是这样。暴雪已经掌握了这项艺术很长一段时间,很少有人能复制这一壮举。如果您真的想支持 Mac-PC 多人游戏,您将不得不煞费苦心地验证您的 .NET 运行时是否在两个平台上生成相同的 fp 代码。如果不是这样,那你就不走运了。

    我仍然不确定的一点是,鉴于上述限制,您是否可以信任 Math 类给出一致的结果;但我想应该。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-11
      • 1970-01-01
      相关资源
      最近更新 更多