【问题标题】:Consistant behaviour of float code with GCC使用 GCC 的浮点代码的一致行为
【发布时间】:2011-01-21 09:15:30
【问题描述】:

我做一些数值计算,在使用 GCC 时,我经常遇到浮点计算问题。对于我目前的目的,我不太关心结果的真实精度,但我想要这个坚定的财产:

无论 SAME 代码在我的程序中的 WHERE 位置,当它在 SAME 输入上运行时,我希望它提供 SAME 输出。

如何强制 GCC 执行此操作?具体来说,--fast-math 的行为是什么,以及不同的 -O 优化?

我听说 GCC 可能会很聪明,有时会在寄存器中加载浮点数,有时会直接从内存中读取它们,这可能会改变浮点数的精度,从而导致不同的输出。我怎样才能避免这种情况?

再次,我想要:

  • 我的计算要快
  • 我的计算要可靠(即相同的输入 -> 相同的结果)
  • 我不太关心这个特定代码的精度,所以如果这能带来可靠性,我可以降低精度

谁能告诉我解决这个问题的方法是什么?

【问题讨论】:

    标签: optimization gcc floating-point


    【解决方案1】:

    如果您的目标包括 x86 处理器,则使用使 gcc 使用 SSE2 指令(而不是历史上基于堆栈的指令)的开关将使这些运行起来更像其他处理器。

    如果您的目标包括 PowerPC 处理器,则使用使 gcc not 使用 fmadd 指令的开关(在源代码中替换乘法和加法)将使这些运行更像其他人。

    不要使用--fast-math:这允许编译器走一些捷径,这会导致架构之间的差异。如果没有此选项,Gcc 更符合标准,因此可预测。

    在您的应用程序中包含您自己的数学函数(expsin、...)而不是依赖系统库中的数学函数只会有助于提高可预测性。

    最后,即使编译器确实严格遵守标准(我在这里指的是 C99),也可能存在一些差异,因为 C99 允许以高于表达式类型所需的精度计算中间结果。如果您真的希望程序始终给出相同的结果,请写three-address code。或者,仅使用可用于所有计算的最大精度,如果可以避免使用历史 x86 指令,则为 double。在任何情况下,不要使用较低精度的浮点数来提高可预测性:根据标准中的上述条款,效果会适得其反。

    【讨论】:

    • 另外,困扰您的事情正是困扰那些试图为 C 编写正确分析器的人的事情,因此您应该对这份报告感兴趣:hal.archives-ouvertes.fr/hal-00128124/en。除了分析器作者无法控制编译选项,但他们在一个框架中工作,足以考虑所有可能性而不会忘记任何可能性。
    【解决方案2】:

    我认为 GCC 有很好的文档记录,因此我不会通过尝试回答您关于其选项及其影响的部分问题来揭示我自己的无知。不过,我会做出一般性声明,即当涉及数字精度和性能时,阅读手册会带来很大的好处。从事 GCC 工作的聪明人在他们的文档中付出了很多努力,阅读它是有益的(好吧,它可能有点乏味,但见鬼,这是一本编译器手册,而不是紧身胸衣)。

    如果获得与最后一位相同的数字结果对您很重要,那么您将不得不关注的不仅仅是 GCC 以及如何控制其行为。您需要锁定它调用的库、运行它的硬件以及可能我还没有想到的许多其他因素。在最坏的(?)情况下,您甚至可能想要,并且我已经看到这样做了,编写您自己的 f-p 数学实现以保证跨平台的位同一性。这很困难,因此也很昂贵,而且与 GCC 使用的代码相比,您可能更不确定自己代码的正确性。

    但是,你写

    我不太关心这个特定代码的精度,所以如果这能带来可靠性,我可以降低精度

    这向您提出了一个问题——您为什么不简单地使用 5 位小数精度作为您的(降低的)精度标准?这就是我们很多从事数值计算的人一直在做的事情。我们忽略了数值分析的更精细方面,因为它们很难规避,而且计算时间昂贵。我正在考虑区间算术和高精度数学之类的事情。 (当然,如果 5 不适合您,请选择另一个个位数。)

    但好消息是,这是完全合理的:我们正在处理的科学数据,就其本质而言,会附带错误(当然,我们通常不知道错误是什么,但那是另一回事)所以可以忽略十进制表示中的最后几位数字,例如 64 位 fp 数字。继续并忽略其中的几个。更好的是,无论您的 f-p 数字有多少位,在计算机上进行数值计算时总会丢失一些精度;添加更多位只会将错误推回,无论是朝向最低有效位还是朝向长时间运行的计算结束。

    您必须注意的情况是您的算法很差,或者算法的实现很差,以至于它很快就会失去很多精度。这通常会出现在任何合理大小的 f-p 数上。如果这对您来说是一个真正的问题,您的测试套件应该已经暴露了这一点。

    总结:您必须以某种方式处理精度损失,将更精细的细节刷到地毯下不一定是错误的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-01
      • 1970-01-01
      • 2013-05-26
      • 2020-05-14
      相关资源
      最近更新 更多