2012-04-17 8 views
2

変更することなく常にゼロに等しい変数A、関数F、関数G、関数Hをお持ちで、最新のIntelデスクトッププロセッサで次のコードを呼び出しますGCCの最新バージョンでの-O3最適化:C++のパフォーマンスを説明できません

for(i = 0; i < a_big_number; i++) 
{ 
if(A != 0) F(); 
else G(); 
} 

実行に2秒かかります。 Aは常に0なのでFは決して呼び出されないことに注意してください。あるいは、

for(i = 0; i < a_big_number; i++) 
{ 
if(A != 0) H(); 
else G(); 
} 

は実行に1秒かかります。再び、Aは常に0であり、Hは決して呼び出されない。最後に、

for(i = 0; i < a_big_number; i++) 
{ 
G(); 
} 

の実行には0.5秒しかかかりません。

最初の2つの例の条件文を考えると、FとHの内容はどうなるのですか?彼らは決して呼び出されないので、なぜ彼らは何をするのですか?また、インテルプロセッサーは洗練された分岐予測を持っているので、G()が常に呼び出され、条件文で時間を無駄にすることはありません。私は、条件付き命令は時間を無駄にしなければならないと理解していますが、なぜそれがあまりにも多くの時間を無駄にするのか分かりません。

+14

相対的なパフォーマンスを示す完全でシンプルでコンパイル可能なスタンドアロンの例を提供してください。 (また、数秒以内に実行されるベンチマークは、非常にノイズの多い結果をもたらす可能性が非常に高く、性能差の原因を突き止める最も良い方法は、しばしば生成されたアセンブリを見ることです。 ) –

+0

なぜ比較文はゼロ時間かかりますか?もしGCCがそれを最適化するのに十分な情報を持っていなければ、あなたのCPUサイクルが進みます。 – dasblinkenlight

+2

F、G、またはHのいずれかが 'inline'宣言されていますか? Aは 'const'と宣言されていますか?これらの3つのコードフラグメントは単一の 'main'に出現しますか?後者に関しては、キャッシュはパフォーマンスの違いのいくつかを説明するかもしれません。 3つのコードブロックを並べ替えてみてください。 –

答えて

1

そのコンパイラはAが一定で、それはこのコードをオンにする必要があることを理解仮定すると:この中

for(i = 0; i < a_big_number; i++) 
{ 
    if(A != 0) F(); 
    else G(); 
} 

if(A != 0) 
    for(i = 0; i < a_big_number; ++i) 
     F(); 
else 
    for(i = 0; i < a_big_number; ++i) 
     G(); 

または完全に定数がに表示された場合F()関数呼び出しを最適化しますコンパイル時定数です。

コンパイルでどのように最適化されているかが保証されていない副作用などがある場合、ループは分岐の誤予測から生じるパフォーマンスの低下に遭遇します。 CPUがループをロックし、Aが変更されておらず、呼び出された関数が十分小さいので、同じミスを何度も何度も繰り返さない場合は、分岐を覚えておく必要があります。一方、ループは展開される可能性があり、並列化できず、CPUが追跡しなければならないコードサイズや数多くのものだけを吹き飛ばしてしまうため、多くの場合傷つく可能性があります。

実行時間をどのように測定するかは、私の謎であり、ループで呼び出す関数が何をしているのかということです。たとえば、プロセスの実行スワップアウトを測定することができます。したがって、測定方法の詳細な説明を含む完全な実例を提供しない限り、何が起こっているのかを伝えることは不可能です。

いずれにせよ、私はあなたの時間の測定値が間違っているか、あなたが表示していないコードで何か悪いこと、または上記のすべてを行うと確信しています。

+2

実際に時間を測定する際のポイントは+1です。残念なことに、あなたが望むものを実際に測定しない方法で時間を測定するのは簡単です。そしてさらに残念なことに、これほど多くをやっていない人は、時間を測定する方法が問題にならないと徹底的に確信する傾向があります。 :( – Hurkyl

0

私が知る限り、コンパイラはブランチが実行されないかどうか判断できません。コンパイラが行うことができる最良のことは、どのブランチの可能性が高いかを予測することです。

+0

コンパイラはできませんが、CPUは非常にうまく動作する分岐予測メカニズムを持っています。実際には、コンパイラはプロファイルベースの最適化と、生成されたコードを再配置するための分岐予測のヒントを持っています。 –

関連する問題