gcc -O1优化比-O0慢

时间:2014-11-18 11:38:14

标签: c gcc optimization fortran

我一直在重写一个混合使用Fortran和C的程序,它是大约10k行的随机粒子模拟。但是,我最近意识到Release模式运行 lot 比Debug慢。

调试(-O0):23秒。释放(-O1或-O2):43秒。对于小型试运行。

仅在Project-> Properties-> C / C ++ Build-> GCC C Compiler-> Optimization Level中更改C优化设置时更改,并且不受GNU Fortran编译器设置的影响。

调查一下,似乎-O1和-O2运行缓慢,而-O0运行速度要快得多。即使手动设置了所有优化标志(来自GCC Docs),它仍然比-O1运行得快。

可能是在Release中运行导致不同的结果导致额外的计算(值超出其预期范围等),这可能吗?如果是这样,是否可以将行为更改回原始的调试设置?

如果您需要更多信息可以提供帮助,请与我们联系。

克里斯。

编辑:系统信息:

  • Windows 8.1 Pro
  • GCC版本4.8.1
  • Eclipse for Parallel Application Developers,Juno SR2

1 个答案:

答案 0 :(得分:0)

好的,事实证明这发生在gcc的4.8.1版本中,而不是更高版本(用4.8.3修复)。对于等效的C和Fortran代码,使用-O1或更高版本会导致编译器错误地优化代码。

为简化代码,行中出现错误结果:

a = b - c;
c = c + a;

如果通常计算的是c = b + (c - c);,则减少到c = b;。 但似乎计算为c = c + (b - c);,这是正常计算的。

这会产生非常轻微的不准确性(-0.0999999978与-0.1000000015相比)。 在这种情况下,这导致一个循环运行2次,运行1500次,并且在整个运行过程中发生超过500次。

(意外)修复的方式是强制编译器在运行a = b - c之前计算c = c + a。这可以在计算printf("%f\n",a);c = c + 0之间ac完成(两者似乎都有效)。注意,这行不必运行。你可以将它放入永远不会为真的if语句中(例如if (a == INT_MAX)),但不能将编译器知道的某个地方永远不会运行(例如if (false))。

至少这是我和我的主管,关于此事的当前想法。仍然不完全确定优化的哪个部分导致了这一点,或者在最新版本中修复了什么,但我希望这对其他人有帮助,并为他们节省一周的困惑。

无论如何,谢谢你的帮助。 - 克里斯。