2012-01-27 15 views
4

機能の速度をテストしようとすると、私のコードのすべての部分がReleaseモードで動作するわけではありません。しかし、同じコードはDebugモードでは完全に機能します。コードの一部をスキップするリリースモード

私は/O2最適化でVC++コンパイラを使用しています。

ここでは切り取った部分がありますが、これは機能しません。

int main() 
{ 
    boost::timer::auto_cpu_timer t; 

    for(int i = 0; i < 1000000; i++) 
     gcdb(i, 5); 
    return 0; 
} 

リリースモードで生成されたアセンブリでは、forループのコードがこのモードでのみ失われています。

int main() 
{ 
000000013F8E1280 sub   rsp,88h 
000000013F8E1287 mov   rax,qword ptr [__security_cookie (013F8E7150h)] 
000000013F8E128E xor   rax,rsp 
000000013F8E1291 mov   qword ptr [rsp+70h],rax 
    boost::timer::auto_cpu_timer t; 
000000013F8E1296 lea   rcx,[t] 
000000013F8E129B mov   edx,6 
000000013F8E12A0 call  boost::timer::auto_cpu_timer::auto_cpu_timer (013F8E2DA0h) 

    for(int i = 0; i < 1000000; i++) 
     gcdb(i, 5); 
    return 0; 
000000013F8E12A5 lea   rcx,[t] 
000000013F8E12AA call  boost::timer::auto_cpu_timer::~auto_cpu_timer (013F8E2810h) 
000000013F8E12AF xor   eax,eax 
} 

gcdb() 2つの数の最大公約数を見つけるためだけの機能です。

このコードをスキップする原因は何ですか?

+2

コンパイラはそれを最適化しますが、それはいい理由ではありませんか? –

+0

その部分を最適化しないようにすることはできますか? – SMK

+1

ループ外の変数を宣言し、 'gcdb()'の結果を代入してみてください。 – lapk

答えて

8

ここには、Dead Code Eliminationというコンパイラの最適化があります。

コンパイラは、コードの結果が不要であると判断した場合は、自由に削除できます。これは、現代のすべてのコンパイラで採用されている標準的な最適化です。

回避策それを最適化し、コンパイラを保つためには、実際にいくつかの方法で出力を使用することです:

int main() 
{ 
    boost::timer::auto_cpu_timer t; 

    int sum = 0; 

    for(int i = 0; i < 1000000; i++) 
     sum += gcdb(i, 5); 

    cout << sum << endl; 
    return 0; 
} 

関連:How does GCC optimize out an unused variable incremented inside a loop?

+0

ありがとうございました! – SMK

+2

@Ynau:コンパイラは 'gcdb'に副作用がないことを検出しているため、プログラムの機能を変更せずに削除できます。同様に、 'for'ループを削除することができます。これが最適化の目的です。機能を変更せずにパフォーマンスを向上させることです。 – MRAB

+0

デバッグモードでも実行できますが、デバッグなしでデバッグを実行できますか? –

2

コンパイラは側 - がないことを証明できた場合結果をどこにも使用しない場合、ループを完全に削除することは自由です。

結果を合計してから、メインから整数の合計を戻してください。オプティマイザがあまりにも巧妙になるのを止めるべき、観察可能な副作用があります。

関連する問題