【问题标题】:How to detect differences in floating point behaviour across platforms如何检测跨平台的浮点行为差异
【发布时间】:2019-08-13 11:38:56
【问题描述】:

我可以执行哪些检查来确定两个硬件平台的浮点行为有何不同?

验证 IEE-754 合规性或检查已知错误可能就足够了(解释我观察到的输出差异)。

我通过 /proc/cpu 查看了 CPU 标志,都声称支持 SSE2 我看了看:

但它们看起来很难使用。 我已经构建了 TestFloat,但我不确定如何处理它。主页说:

“很遗憾,TestFloat 的输出并不容易解释。详细 使用 TestFloat 需要了解 IEEE 标准 负责任的。”

理想情况下,我只需要一个或两个程序或一些简单的配置样式检查,我可以运行并比较两个平台之间的输出。

理想情况下,我会将其转换为配置检查,以确保 尝试在行为异常的平台上编译不可移植代码,在配置时而不是运行时检测到。

背景

我发现 C++ 应用程序在两个不同平台上的行为有所不同:

  • Intel(R) Xeon(R) CPU E5504
  • Intel(R) Core(TM) i5-3470 CPU

在任何一台机器上本地编译的代码在另一台机器上运行,但 对于一项测试,行为取决于代码在哪台机器上运行。

澄清 在机器 A 上编译的可执行文件在复制到机器 B 上运行时,其行为类似于在机器 B 上编译的可执行文件,反之亦然。

它可能是一个未初始化的变量(尽管在 valgrind 中没有出现任何东西)或许多其他的东西,但是 我怀疑原因可能是浮点的非便携式使用。 也许一台机器对浮点程序集的解释与另一台机器不同? 实施者已确认他们知道这一点。 它不是我的代码,我不想完全重写它来测试它。不过重新编译就好了。 我想检验我的假设。

related question 我正在研究如何启用软件浮点。这个问题是从另一面解决问题。

更新

我已经按照@chux 的提示进行了配置检查,尝试了以下操作。

#include <iostream>
#include <cfloat>

int main(int /*argc*/, const char* /*argv*/[])
{
   std::cout << "FLT_EVAL_METHOD=" << FLT_EVAL_METHOD << "\n";
   std::cout << "FLT_ROUNDS=" << FLT_ROUNDS << "\n";
#ifdef __STDC_IEC_559__
   std::cout << "__STDC_IEC_559__ is defined\n";
#endif
#ifdef __GCC_IEC_559__
   std::cout << "__GCC_IEC_559__ is defined\n";
#endif
   std::cout << "FLT_MIN=" << FLT_MIN << "\n";
   std::cout << "FLT_MAX=" << FLT_MAX << "\n";
   std::cout << "FLT_EPSILON=" << FLT_EPSILON << "\n";
   std::cout << "FLT_RADIX=" << FLT_RADIX << "\n";
   return 0;
}

在两个平台上提供相同的输出:

./floattest 
FLT_EVAL_METHOD=0
FLT_ROUNDS=1
__STDC_IEC_559__ is defined
FLT_MIN=1.17549e-38
FLT_MAX=3.40282e+38
FLT_EPSILON=1.19209e-07
FLT_RADIX=2

我仍在寻找可能有所不同的东西。

【问题讨论】:

  • 验证 IEEE754 合规性不够,因为两个合规的实现可能仍会给出不同的结果。这就是为什么在 TestFloat 上有这样一个警告的原因之一;掌握 IEEE754 非常复杂。
  • 我说可能。我的意思是,如果在我的机器上报告了不合规或众所周知的硬件错误,它可能会解释我所看到的行为差异。为了以防万一,我添加了一个说明。
  • 这就是我添加评论的原因。您的“验证 IEEE754 合规性可能就足够了”(发现差异)表明您不确定。事实上,您观察到的差异可能是两个兼容的 IEEE754 实现之间的差异。举一个简单的例子,sin(1.0) 的舍入不是由 IEEE754 指定的。
  • 我有另一个与此相关的古怪想法,请参阅emulator-to-run-an-application-as-if-its-on-a-different-cpu
  • long double 在平台之间的差异比double/floatfloat 的差异更常见于double,因此检查long double 特征更有可能发现float 的问题。有时可以在检查 xxx_TRUE_MIN 时发现意外的亚法线。对各种舍入模式的支持有时会有所不同。请参阅 C 规范“B.6 浮动类型 的特征”中的 xxx_HAS_SUBNORM 和其他内容。不妨都检查一下。

标签: c++ floating-point hardware


【解决方案1】:

OP 有 2 个目标有点冲突。

  1. 如何检测跨平台的浮点行为差异 (?)

  2. 我只想要一个或两个程序或一些简单的配置样式检查,我可以运行并比较两个平台之间的输出。

是的,有些差异很容易发现,但有些差异可能非常微妙。
示例Can the floating-point status flag FE_UNDERFLOW set when the result is not sub-normal?

一般问题没有简单的测试。

推荐:

  1. 修改编码目标以允许名义上的差异。

  2. 查看_STDC_IEC_559__ 是否已定义,希望足以满足您的应用需求。考虑到FLT_EVAL_METHODFLT_ROUNDS 等各种其他因素以及优化级别,代码仍然可以合规但提供不同的结果,但程度将更易于管理。

  3. 如果需要超高的一致性,不要使用浮点数。

【讨论】:

  • 我已经根据您迄今为止提出的建议进行了非常基本的检查,并用结果更新了问题。重写代码目前不是我的选择。这不是“我的”开始代码。我会使用整数,因为我需要高一致性。
  • 请参阅我的说明:在机器 A 上编译的可执行文件在复制到机器 B 上运行时,其行为类似于在机器 B 上编译的可执行文件,反之亦然。一些帖子建议“相同的本机汇编代码很可能是确定性的,前提是您注意浮点标志和编译器设置。”有没有明显的情况不是这种情况?
【解决方案2】:

我发现了一个名为esparanoia 的程序,它对浮点行为进行了一些检查。这是基于William Kahan's原始偏执程序发现的臭名昭著的奔腾划分错误。

虽然它没有检测到我的测试系统有任何问题(因此不足以回答这个问题),但它可能会引起其他人的兴趣。

【讨论】:

    猜你喜欢
    • 2014-01-24
    • 1970-01-01
    • 1970-01-01
    • 2015-06-28
    • 2020-03-17
    • 2011-10-26
    • 1970-01-01
    • 2013-07-19
    • 2010-09-21
    相关资源
    最近更新 更多