【问题标题】:Floating point operations 32 bit mode vs 64 bit mode浮点运算 32 位模式与 64 位模式
【发布时间】:2013-06-07 06:00:25
【问题描述】:

我在 Delphi 中有相同的数字运算源代码,它既可以编译为 32 位应用程序,也可以编译为 64 位应用程序。从日志文件中我可以看到数字略有不同(1e-14 相对误差)。所以我想知道在运行 32 位和 64 位代码时,同一个 CPU 是否有可能执行不同的浮点运算。还是编译器负责的事情。

【问题讨论】:

标签: delphi 32bit-64bit floating-accuracy


【解决方案1】:

我将假设代码没有明确使用Extended。由于该数据类型在 32 位和 64 位之间有所不同(在 32 位中是 10 个字节,在 64 位中是 8 个字节),任何显式使用 Extended 都会带来直接的差异。我将假设您对所有变量都使用Double。尽管下面的论点同样传递给Single。

除此之外,最常见的原因是两个浮点单元之间的行为差​​异。

32 位代码使用的 x87 单元将中间值存储到 80 位扩展精度。 64 位代码使用的 SSE 单元将中间值存储为 64 位双精度。

现在,可以使用控制字配置 x87 单元以将中间值存储为 64 位精度。它在性能方面没有区别,但会使您的 32 位和 64 位结果更接近。

即便如此,您也不会在不同的单位上得到完全相同的结果。事实上,您不会在所有 x87 单元上得到完全相同的结果。尽管这些单位都符合 IEEE754,但该标准允许一定程度的计算余地。

此外,三角函数、对数、指数等高阶计算在 32 位和 64 位之间的执行方式完全不同。 32 位单元比 64 位单元具有更多的内置功能。您将在 Delphi 源代码中注意到,例如,三角函数都是在 64 位的 RTL 中实现的。在 32 位代码上,它们是通过调用 x87 操作来实现的。

最重要的是,当涉及浮点计算时,您永远不会让您的 32 位和 64 位程序完全一致。您将不得不接受细微的差异。

【讨论】:

  • 你的假设是正确的:没有明确的Extended,只是Doubles。我想知道为什么 64 位模式下的 CPU 不能使用 x87 单元。好像比较准确。
  • 64 位代码中的 CPU 可以使用 x87 单元。虽然它不再准确。而且 SSE FP 比 x87 FP 快很多。最近的趋势是牺牲 x87 将晶体管预算用于 SSE 单元。
  • 有一个使用 64 位 x87 FPU 向后移植一些数学功能的库。 TExtendedX87: FPU-backed 80-bit Extended type for Win64.
  • @LURD 这是一个非常整洁的库。它只是扩展的,所以它不会帮助您在 x87 上运行双精度数学,在我看来这不是一个好主意。如果我记得,该库将记录声明为已打包,我认为这是一个错误。
  • 大卫,TExtendedX87 是一个变体记录,我认为打包关键字在 Win64 中是可以的。 TExtendedX87 = packed record case byte of 0: (AsBytes: packed array [0..9] of byte); 1: (AsExtRec80: System.TExtended80Rec); end;.
【解决方案2】:

Extended 等于 X64 中的 Double。 X32 模式使用 FPU 浮点单元,而 X64 使用 SSE 寄存器进行浮点执行。

还有编译器指令Floating point precision control (Delphi for x64),默认情况下是打开的,并将中间单浮点数保持为双精度数。

【讨论】:

    猜你喜欢
    • 2012-07-02
    • 1970-01-01
    • 2021-03-24
    • 2014-07-29
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 2014-07-23
    • 1970-01-01
    相关资源
    最近更新 更多