【发布时间】:2013-10-28 16:12:46
【问题描述】:
对不起,这个问题可能太抽象了,但对我来说这很实用+可能有一些专家有类似的经验,可以解释一下。
我有一个大代码,大约 10000 行大小。
我注意到如果我放在某个地方
if ( expression ) continue;
其中表达式总是假(用代码和cout的逻辑双重检查),但取决于未知参数(因此编译器在编译期间不能简单地去掉这一行)程序的速度增加25%(计算结果相同)。如果我测量循环本身的速度,则加速因子大于 3。
为什么会发生这种情况以及在没有这些技巧的情况下使用这种加速可能性的可能方法是什么?
附:我使用 gcc 4.7.3,-O3 优化。
更多信息:
我尝试了两种不同的表达方式,都有效。
-
如果我将行更改为:
if ( expression ) { cout << " HELLO " << endl; continue; };加速消失了。
-
如果我将行更改为:
expression;加速消失了。
-
围绕该行的代码如下所示:
for ( int i = a; ; ) { do { i += d; if ( d*i > d*ilast ) break; // small amount of calculations, and conditional calls of continue; } while ( expression0 ); if ( d*i > dir*ilast ) break; if ( expression ) continue; // very big amount calculations, and conditional calls of continue; }for 循环看起来很奇怪。这是因为我已经修改了循环以抓住这个瓶颈。最初表达式等于表达式0,而不是do-loop,我只有这个继续。
-
我尝试使用 __builtin_expect 来理解分支预测。与
// the expression (= false) is supposed to be true by branch prediction. if ( __builtin_expect( !!(expression), 1) ) continue;速度提升 25%。
// the expression (= false) is supposed to be false by branch prediction. if ( __builtin_expect( !!(expression), 0) ) continue;加速消失了。
如果我使用 -O2 而不是 -O3,效果就会消失。该代码比带有 false 条件的快速 O3 版本稍慢 (~3%)。
与“-O2 -finline-functions -funswitch-loops -fpredictive-commoning -fgcse-after-reload -ftree-vectorize”相同。再加一个选项:“-O2 -finline-functions -funswitch-loops -fpredictive-commoning -fgcse-after-reload -ftree-vectorize -fipa-cp-clone”效果会被放大。使用“line”的速度是一样的,没有“line”的代码会慢 75%。
-
原因就在下面的条件运算符。所以代码看起来像这样:
for ( int i = a; ; ) { // small amount of calculations, and conditional calls of continue; if ( expression ) continue; // calculations1 if ( expression2 ) { // calculations2 } // very big amount calculations, and conditional calls of continue; }表达式2 的值几乎总是假的。所以我改成这样:
for ( int i = a; ; ) { // small amount of calculations, and conditional calls of continue; // if ( expression ) continue; // don't need this anymore // calculations1 if ( __builtin_expect( !!(expression2), 0 ) ) { // suppose expression2 == false // calculations2 } // very big amount calculations, and conditional calls of continue; }并且已经获得了预期的 25% 加速。甚至更多一点。而且行为不再取决于临界线。
如果有人知道材料,可以不用猜测就能解释这种行为,我会很高兴阅读并接受他们的回答。
【问题讨论】:
-
我怀疑没有SSCCE我们可以告诉你一些事情。
-
这可能是平台和编译器特定的行为;如果不查看周围的代码,这将是非常难以判断的。 (除非您弄错了,并且实际上有时表达是正确的。)最好将其简化为 SSCCE。 sscce.org
-
如果没有看到更多代码和您已完成的基准测试的细分(例如,运行时在多次运行中更改前后是否一致?),将很难缩小范围。
-
听起来像是分支预测的结果。
-
如果您可以公开您的代码,您可以参与改进 gcc 并提交错误报告。
标签: c++ optimization cpu-speed