2013-11-21 3 views

答えて

13

コンパイル時に余計な作業や解析を行うので、実行時にいくつかの貴重なCPUサイクルの報酬を得ることができます。例を挙げて説明するのが最善でしょう。

このようなループを考えてみましょう:

const int n = 5; 
for (int i = 0; i < n; ++i) 
    cout << "bleh" << endl; 

あなたは最適化せずにこれをコンパイルする場合、コンパイラはあなたのための余分な作業を行うことはありません - アセンブリこのコードスニペット用に生成比較にそう直訳になりますジャンプ命令。あなたが最適化してコンパイルすると、それは知っているのでnconstあるので(これは最速ではありません、ただ最も簡単)

しかし、コンパイラが簡単にinlineこのループ上限はこれまでに変更することはできません。 (すなわち、ループ終了条件を比較/チェックする代わりに、繰り返しコードを5回直接コピーすることができる)。

ここでは、最適化された関数呼び出しを使用した別の例を示します。以下は私の全体のプログラムです:

#include <stdio.h> 
static int foo(int a, int b) { 
    return a * b; 
} 


int main(int argc, char** argv) { 
    fprintf(stderr, "%d\n", foo(10, 15)); 
    return 0; 
} 

私は私のx86マシン上でgcc foo.cを使用して最適化をせずにこのコードをコンパイルする場合は、私のアセンブリは次のようになります。ここでは

movq %rsi, %rax 
movl %edi, -4(%rbp) 
movq %rax, -16(%rbp) 
movl $10, %eax  ; these are my parameters to 
movl $15, %ecx  ; the foo function 
movl %eax, %edi 
movl %ecx, %esi 
callq _foo 
; .. about 20 other instructions .. 
callq _fprintf 

、それが何かを最適化していません。私の定数値をレジスタにロードし、私のfoo関数を呼び出しています。私は-O2フラグ付きで再コンパイルした場合でも、見て:

movq (%rax), %rdi 
leaq L_.str(%rip), %rsi 
movl $150, %edx 
xorb %al, %al 
callq _fprintf 

コンパイラが、それももうfooを呼び出さないようにスマートです。戻り値だけをインラインで入力します。

+0

非常に涼しい!関数を呼び出すようなことをしているときに違いがありますか? – kayla

+0

@TidusSmithは深い例でより多くの答えを更新しました。あなたはそれが有用であることを願っています。 – yamafontes

0

最適化のほとんどは、アセンブリが生成される前にコンパイラの中間表現で行われます。あなたは間違いなくAgner FogのSoftware optimization resourcesをチェックしてください。第1章の第8章では、コンパイラによるサンプルの最適化について説明します。

関連する問題