【问题标题】:Prevent optimizations for one operation in c防止优化 c 中的一项操作
【发布时间】:2014-10-04 10:25:24
【问题描述】:

我正在使用补偿求和来实现一种算法,以减少累加的舍入误差。我想知道是否可以以某种方式告诉编译器不要优化代码的某个特定部分中的浮点运算。更准确地说,我想保留操作顺序。这是一个示例代码sn-p(所有变量都是double):

while(1){
    a = y;
    e = e + d;
    y = a + e;
    e = e + (a - y);
}

我担心最后一行可能会被优化以读取e=e-ee = (e+a)-y。在什么情况下会发生这种情况,我该如何预防?

【问题讨论】:

  • 它真的得到优化了吗?通常,编译器不会使用正常的数学属性来优化浮点运算因为您提到的舍入错误。
  • 这正是我想知道的。括号是否足以防止编译器重新排列浮点运算?
  • AFAIK 即使没有括号,它也不会优化/重新排列。

标签: c floating-point c99


【解决方案1】:

没有严格的标准方法来防止优化(通常)。但是,如果使用最近的GCC 编译器,您可以使用#pragma GCC optimizeoptimize function attribute

顺便说一句,我不确定这是否值得。您可以查看较低级别的 Gimple(可能使用 MELT 或一些 -fdump-tree-*),或者查看生成的汇编代码(使用 -fverbose-asm 以获得更易读的汇编代码)。

【讨论】:

  • 标准本身阻止了这种优化,除非您通过编译器标志或编译指示对其进行许可。
【解决方案2】:

如果编译器声称符合 IEEE 754,那么它必须完全按照您编写的操作执行操作 - 除非它可以证明结果是相同的(在这种情况下,不同的计算不会伤害您)。

有时,如果允许编译器给出稍微不同的结果,这会使代码运行得更慢。一些编译器可以选择允许编译器进行这种优化。如果你的编译器有这样的选项,你需要关闭它们。

编译器必须尊重括号。例如,在“e = e + (a - y);”中它必须从 a 中减去 y,将结果添加到 e,并将总和存储到 e。

【讨论】:

  • 谢谢。对于 gcc,我是否正确地假设只有在打开 -fassociative-math 时才会优化(即不使用 -O3)?
  • C 标准不允许这种优化(无需诉诸 IEEE-754),即使没有括号。
  • @hanno 是的,GCC 包含一些违反 C 规范的优化选项,因此在所有 -O 优化级别上默认禁用。其中大部分都可以使用-ffast-math 选项打开。
猜你喜欢
  • 2018-07-23
  • 1970-01-01
  • 1970-01-01
  • 2010-09-21
  • 2023-03-27
  • 2011-01-14
  • 1970-01-01
  • 2012-05-04
  • 1970-01-01
相关资源
最近更新 更多