[解決済み] If文とif-else文、どちらが速いか?
質問
先日、友人とこの2つのスニペットについて議論しました。どちらが速いのか、そしてそれはなぜなのか?
value = 5;
if (condition) {
value = 6;
}
とする。
if (condition) {
value = 6;
} else {
value = 5;
}
もし
value
が行列の場合は?
注:私は
value = condition ? 6 : 5;
が存在することは知っていますし、その方が高速であることも期待していますが、選択肢には入っていませんでした。
Edit (質問が現在保留されているため、スタッフから依頼されました)。
- 以下のいずれかを考慮して回答してください。 x86 アセンブリ 主流のコンパイラによって生成される ( g++、clang++、vc、mingw と言ってください。 ) の最適化バージョンと非最適化バージョンの両方、あるいは MIPS アセンブリ .
- アセンブリが異なる場合、なぜそのバージョンが速いのか、また、どのような場合にそうなるのかを説明します ( 例: "分岐がなく、分岐には次の問題があるため、より優れている blahblah" )
どのように解決するのですか?
TL;DRです。
最適化されていないコードでは
if
がなく
else
は無関係に効率的に見えますが、最も基本的なレベルの最適化でさえ有効にすると、コードは基本的に次のように書き直されます。
value = condition + 5
.
I 試してみた を試してみたところ、以下のコードのアセンブリが生成されました。
int ifonly(bool condition, int value)
{
value = 5;
if (condition) {
value = 6;
}
return value;
}
int ifelse(bool condition, int value)
{
if (condition) {
value = 6;
} else {
value = 5;
}
return value;
}
gcc 6.3 で最適化を無効にしている場合 (
-O0
) の場合、関連する差分は
mov DWORD PTR [rbp-8], 5
cmp BYTE PTR [rbp-4], 0
je .L2
mov DWORD PTR [rbp-8], 6
.L2:
mov eax, DWORD PTR [rbp-8]
に対して
ifonly
が、一方
ifelse
は
cmp BYTE PTR [rbp-4], 0
je .L5
mov DWORD PTR [rbp-8], 6
jmp .L6
.L5:
mov DWORD PTR [rbp-8], 5
.L6:
mov eax, DWORD PTR [rbp-8]
後者は余分なジャンプがあるため若干効率が悪く見えますが、どちらも少なくとも2つ、多くても3つの割り当てがあるので、本当に最後の一滴まで性能を絞り出す必要がない限り(ヒント:スペースシャトルに取り組んでいない限り、そうではありませんし、そうであったとしても おそらく ヒント: スペース シャトルで作業していない限り、そのようなことはありませんし、その場合でも、おそらくありません)。
しかし、最も低い最適化レベルでも (
-O1
) でも、両関数は同じになります。
test dil, dil
setne al
movzx eax, al
add eax, 5
とは基本的に同じです。
return 5 + condition;
仮定
condition
が 0 か 1 であると仮定します。
より高い最適化レベルでは、出力はあまり変わりません。
movzx
を効率的にゼロにすることで
EAX
レジスタを効率的にゼロにすることによって
免責事項です。
あなたはおそらく
5 + condition
を自分で書くべきではありません(標準では
true
を整数型に変換すると
1
というのは、あなたのコードを読む人(将来の自分も含む)にとって、あなたの意図はすぐにはわからないかもしれないからです。) このコードのポイントは、コンパイラが両方のケースで生成するものが(実質的に)同じであることを示すことです。
Ciprian Tomoiaga
はコメントで非常にうまくそれを述べています。
a 人間 の仕事は、コードを書くことです。 人間のために であり コンパイラに のためのコードを書く。 マシン .
関連
-
[解決済み] クラスにデフォルトコンストラクタが存在しない。
-
[解決済み】ファイルから整数を読み込んで配列に格納する C++ 【クローズド
-
[解決済み】1つ以上の多重定義されたシンボルが見つかる
-
[解決済み】std::cin.getline( ) vs. std::cin
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] <は<=より速いのか?
-
[解決済み] Collatz予想の検証を行うC++のコードは、なぜ手書きのアセンブリよりも高速に動作するのでしょうか?
-
[解決済み] どちらが速いですか?スタックアロケーションとヒープアロケーション
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
-
[解決済み] EBPフレームポインタレジスタの目的は何ですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】コンストラクターでのエラー:識別子を期待されますか?
-
[解決済み】C++でint型に無限大を設定する
-
[解決済み】 != と =! の違いと例(C++の場合)
-
[解決済み】C++ 式はポインタからオブジェクトへの型を持っている必要があります。
-
[解決済み] 非常に基本的なC++プログラムの問題 - バイナリ式への無効なオペランド
-
[解決済み】「std::operator」で「operator<<」にマッチするものがない。
-
[解決済み】エラー。switchステートメントでcaseラベルにジャンプする
-
[解決済み] to_string は std のメンバーではない、と g++ が言っている (mingw)
-
[解決済み】警告 - 符号付き整数式と符号なし整数式の比較
-
[解決済み】エラー。引数リストに一致するコンストラクタのインスタンスがない