2016-10-24 13 views
5

最適化と分岐予測の観点から、これらの2つのコードには違いがありますか?ブランチ付きファンクションの開始

まず:

void think_and_do(){ 
    if(expression){ 
     //Set_A of instructions 
    } 
    else{ 
     //Set_B of instructions 
    } 
} 

int main(){ 
    think_and_do(); 
} 

第二:あなたの例であれば、私は、think_and_doをgodbolt.orgにしてmain

最初の観測でテストを行った

void do_A(){ 
    //Set_A of instructions 
} 

void do_B(){ 
    //Set_B of instructions 
} 

int main(){ 
    if(expression){ 
     do_A(); 
    } 
    else{ 
     do_B(); 
    } 
} 
+4

私はあなたが同じコードを得るだろうと思うだろうが、それはコンパイラ最適化の設定に依存します。両方をコンパイルしてアセンブリをチェックすることができます。 – NathanOliver

+1

これは経験的に最もよく答える質問のようです。いくつかの反復可能な擬似ランダムデータに対して数百万回反復し、[測定する](http://stackoverflow.com/questions/11437523/can-i-measure-branch-prediction-failures-on-a-modern-intel -core-cpu?rq = 1)。 – dlatikay

+1

1つのキーは、両方の機能に必要なパラメータの数になります。関数 'do_A()'または 'do_B()'のみがすべてのパラメータを必要とする場合(通常 'do_A()'がオブジェクトを作成し、 'do_B()'がすべてのパラメータを持つ必要があります) 'このオブジェクトを削除します)。 –

答えて

3

彼らはほとんどが最適化されています。

xor  eax, eax 
    add  rsp, 8 #may or may not be present. 
    ret 

第2の観察は、コードがメインでまったく同じであるということである:・機能のどれが呼び出されていない、すべてがインライン化されcinがなければ、両方の例がにコンパイルしている必要があります。

第観察の両方の実施例は、それらが発行を最大限に活用(及びCMPジャンプのマクロ融合の可能性を無視する4命令の1サイクル充填され、次のコード

mov  edx, DWORD PTR a[rip] 
    mov  eax, DWORD PTR b[rip] 
    cmp  edx, eax 
    je  .L8 

を作ることです)。彼らは、問題の帯域幅の

cmp  edx, eax 
    je  .L8 

半分で開始していた場合は

は、潜在的に浪費されていたであろう。

+1

私はその点があなたが関数をインライン化できない場合についてのものだと思う。 – Leeor

+0

@Leeorそして結論は、それを指定しなくてもコンパイラがインラインで行い、違いがないということだ。 – Surt

関連する問題