2017-05-11 5 views
2

次のswitch文の間にパフォーマンスの違いはありますか?スイッチブロックから戻ったときのパフォーマンスの違いはありますか?

プロファイリング時に意味のある違いはありませんでしたが、どちらかを使用するとコンパイラ/フラグが改善されるかどうかはまだ不思議です。

// f, g, h can be functions such as int f(int) 

int choose1(int x) { 
    switch (x) { 
    case 0: return f(x); 
    case 2: return g(x); 
    case 5: return h(x); 
    } 
    return x; 
} 

int choose2(int x) { 
    switch (x) { 
    case 0: return f(x); 
    case 2: return g(x); 
    case 5: return h(x); 
    default: return x; 
    } 
} 

何case文は次のように、それほど単純ではない場合について:私だけでは非常に共通の単一の出口点(に関連する記事を見つけたしばらく検索しても

int choose3(int x) { 
    switch (x) { 
    case 0: /* some actions1 */; return f(x); 
    case 2: /* some actions2 */; return g(x); 
    case 5: /* some actions3 */; return h(x); 
    } 
    /* more actions */ 
    return x; 
} 

int choose4(int x) { 
    switch (x) { 
    case 0: /* some actions1 */; return f(x); 
    case 2: /* some actions2 */; return g(x); 
    case 5: /* some actions3 */; return h(x); 
    default: /* more actions */; return x; 
    } 
} 

C)またはプログラミングの実践(メンテナンス、読みやすさなど)について話すだけです。同様の質問はif文に関連するthis oneですが、すべての回答は基本的に実際のパフォーマンスの違いではなく、早期復帰の便宜(プログラミングの練習)について話し終えます。

私はこのようなプログラミングの実践には興味がありませんが、私はあなたのコメントにあなたの貢献を知ってうれしいです。

+0

どうして違うのですか?コンパイラは今日はまったくばかだから。 :)疑わしい場合は、生成されたアセンブリコード...オンラインを見てください。 – knivil

+0

@knivil素敵なアイデア、私はちょうどそれをした、私の答えを見て、あなたの考えについて私に知らせてください! – gsamaras

+0

1つの問題は、多くのコーディングガイドライン(MISRAなど)の「1エントリ1出口」ルールに違反することです。 –

答えて

3

これは早すぎる最適化の心配です。

どちらも効率的です。

機械命令を生成し、それを調べることができますが、switch文は通常は一連のif文です。

結果として、分岐予測はここでボトルネックになる可能性があるため、単純な最適化アプローチは、成功する可能性が最も高い条件を最初のケースに配置することですそれらの残りの部分を評価する)。

Efficient switch statementDefault in Switch caseを読むことができます。


PS - あなたのケースでは、あなたがintを戻ってきているので、大したことないが、戻り値の型は大きなものとなりますクラスか何かだった場合、値によって返すことはコストがかかります。しかし、RVOはそれを世話するべきです。


アップデート:このCompiler Explorer

あなたがアセンブリを見ることができます:

choose1(int): 
     push rbp 
     mov  rbp, rsp 
     sub  rsp, 8 
     mov  DWORD PTR [rbp-4], edi 
     mov  eax, DWORD PTR [rbp-4] 
     cmp  eax, 2 
     je  .L9 
     cmp  eax, 5 
     je  .L10 
     test eax, eax 
     jne  .L13 
     mov  eax, DWORD PTR [rbp-4] 
     mov  edi, eax 
     call f(int) 
     jmp  .L12 
.L9: 
     mov  eax, DWORD PTR [rbp-4] 
     mov  edi, eax 
     call g(int) 
     jmp  .L12 
.L10: 
     mov  eax, DWORD PTR [rbp-4] 
     mov  edi, eax 
     call h(int) 
     jmp  .L12 
.L13: 
     mov  eax, DWORD PTR [rbp-4] 
.L12: 
     leave 
     ret 
choose2(int): 
     push rbp 
     mov  rbp, rsp 
     sub  rsp, 8 
     mov  DWORD PTR [rbp-4], edi 
     mov  eax, DWORD PTR [rbp-4] 
     cmp  eax, 2 
     je  .L16 
     cmp  eax, 5 
     je  .L17 
     test eax, eax 
     jne  .L20 
     mov  eax, DWORD PTR [rbp-4] 
     mov  edi, eax 
     call f(int) 
     jmp  .L19 
.L16: 
     mov  eax, DWORD PTR [rbp-4] 
     mov  edi, eax 
     call g(int) 
     jmp  .L19 
.L17: 
     mov  eax, DWORD PTR [rbp-4] 
     mov  edi, eax 
     call h(int) 
     jmp  .L19 
.L20: 
     mov  eax, DWORD PTR [rbp-4] 
.L19: 
     leave 
     ret 

と期待通りのコードが同じであることがわかります。

+0

私は、議論を避けるためにintを正確に使用して、構築/コピーと単一-exit点。 – cbuchart

+0

また、最適化の問題ではなく、実際の相違についての好奇心です。(私が言ったように、プロファイリングには有意差は見られません) – cbuchart

+0

だから私はPS @cbuchartとして言いました。あなたは今より良く奉仕します! =)いい質問BTW、+1! – gsamaras

関連する問題