我一直在重写一个混合使用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中运行导致不同的结果导致额外的计算(值超出其预期范围等),这可能吗?如果是这样,是否可以将行为更改回原始的调试设置?
如果您需要更多信息可以提供帮助,请与我们联系。
克里斯。
编辑:系统信息:
答案 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
之间a
或c
完成(两者似乎都有效)。注意,这行不必运行。你可以将它放入永远不会为真的if
语句中(例如if (a == INT_MAX)
),但不能将编译器知道的某个地方永远不会运行(例如if (false)
)。
至少这是我和我的主管,关于此事的当前想法。仍然不完全确定优化的哪个部分导致了这一点,或者在最新版本中修复了什么,但我希望这对其他人有帮助,并为他们节省一周的困惑。
无论如何,谢谢你的帮助。 - 克里斯。