【问题标题】:Are FPU control functions relevant for x64_64 processors?FPU 控制功能是否与 x64_64 处理器相关?
【发布时间】:2018-03-31 10:24:39
【问题描述】:

我问这个问题是因为我试图在 Visual Studio 2017 (cl.exe) 和 gcc 5.4.0 之间实现按位(哈希)相等。有问题的函数使用了 sin() 和 cos()。所有变量都是双倍的,FMAD 也是相关的。

我一直在 SO 和网络上广泛阅读有关浮点确定性、再现性和锁存 MP 游戏设计的内容。我知道单编译器、单构建确定性并不难,但我正在尝试 2-编译器、单构建确定性。

这里的效率不是问题。我只希望结果匹配。

我问是因为我希望缩小我对测试/尝试什么的担忧。

这些东西是否与 x86_64 处理器和构建相关?

  1. 控制 x87 fpu 的函数
  2. XPFPA_{DECLARE,RESTORE,etc}
  3. "、_FPU_SINGLE、_FPU_DOUBLE等
  4. _controlfp_s()、_PC24、_PC53、_PC_64

我问是因为我读过带有 SSE (x86_64) 的平台默认使用 SSE 进行浮点运算,所以 fpu 控制功能应该无关紧要吗?

我发现thisthis 提供的信息最多。 MSDN article 表示 x64 架构不支持设置浮点精度掩码。 this SO post 表示 SSE 具有固定精度。

我的测试表明 /fp:{strict,precise,fast} 没有改变哈希值。优化级别也不是。所以我希望把注意力集中在罪上,因为。

【问题讨论】:

  • gcc 和 MSVC 使用不同的标准库,因此可能会使用不同的触发函数实现。除此之外,SIMD 的不同硬件实现可以给出不同的答案。在两个平台上使用相同的第 3 方数学库(例如 MKL)可能会更幸运。以我的经验,如果你能在两个平台上始终获得精确的按位结果,你会很幸运。也许读过这个 - software.intel.com/en-us/articles/…
  • 证明问题的 mcve 会很有用。
  • 我认为如果您希望 sin/cos 相同,那么您需要使用相同的实现(即查找/创建这些函数的实现,并将它们包含到您的项目中)。这是因为 SSE 没有 sin/cos,所以这些是通过某种算法实现的。不同的库会为您提供不同的保证(唯一的例外是,如果它们保证使用相同的舍入得到最精确的结果)。
  • 您可能会发现this Random ASCII blog entry 很有用。
  • 例如,crlibm 为 sin/cos 提供了正确四舍五入的结果(我没用过这个库)

标签: c++ c


【解决方案1】:

大多数浮点函数必须以一种或另一种方式执行舍入。 C/C++ 标准在这个主题上相当模糊,并且 IEEE 一致性对三角函数不够严格。这意味着在实践中,尝试以可移植的方式从编译器默认数学实现中挤出正确的舍入是没有用的。

例如,sin/cos 的 libm 实现(由 gcc 使用)是用汇编语言编写的,算法因架构不同而不同,很可能取决于库的版本。

因此,您有两种可能性:

  • 仅使用精确舍入的浮点运算来实现您自己的 sin/cos(融合乘法累加 + 泰勒级数)
  • 使用具有强舍入考虑的 3rd 方库

我个人使用MPFR 库作为处理舍入错误的黄金标准。会有运行时成本,尽管我从未尝试将其与 libm 性能进行基准测试。


自定义实现

请注意,如果您决定自己实现,则需要选择舍入模式并告知编译器这对您很重要。

在 C++ 中是这样完成的:

#include <cfenv>
#pragma STDC FENV_ACCESS ON
#pragma STDC FP_CONTRACT OFF

int main(int, char**) {
    ...
    if(!std::fesetround(FE_TONEAREST))
        throw std::runtime_error("fesetround failed!");
    ...
}

【讨论】:

  • 这个答案最能解决我的问题;这(很可能)是跨平台和构建的 sin/cos 实现。如果没有人发布有关 x64 上 FPU 的答案,我会选择这个。
  • 请注意,我不会在游戏引擎中使用 MPFR。它被设计为尽可能精确(精确舍入),这对于您的目的来说可能太昂贵了。在您的情况下,我会选择自定义实现,但不要忘记使用 std::fesetround 和 STDC pragma 设置舍入模式。
猜你喜欢
  • 2013-11-05
  • 2013-02-28
  • 1970-01-01
  • 2011-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多