[解決済み] <は<=より速いのか?
質問
は
if (a < 901)
よりも速い
if (a <= 900)
?
この単純な例と全く同じではありませんが、ループ複雑なコードで若干のパフォーマンスの変化があります。これは、生成されたマシンコードと関係があるのでしょうけど、もしそうだとしたら、それは本当なのでしょうか?
解決方法は?
いいえ、ほとんどのアーキテクチャで高速化できません。特に指定はありませんが、x86では、積分比較は通常2つの機械語命令で実装されます。
-
A
test
またはcmp
を設定する命令です。EFLAGS
-
そして
Jcc
(ジャンプ)命令 は、比較タイプ(とコードレイアウト)によります。 -
jne
- 等しくない場合はジャンプ -->ZF = 0
-
jz
- ゼロ(イコール)ならジャンプ -->ZF = 1
-
jg
- 大きければジャンプ -->ZF = 0 and SF = OF
- (その他...)
例
(簡潔にするために編集) コンパイルは
$ gcc -m32 -S -masm=intel test.c
if (a < b) {
// Do something 1
}
にコンパイルします。
mov eax, DWORD PTR [esp+24] ; a
cmp eax, DWORD PTR [esp+28] ; b
jge .L2 ; jump if a is >= b
; Do something 1
.L2:
そして
if (a <= b) {
// Do something 2
}
にコンパイルします。
mov eax, DWORD PTR [esp+24] ; a
cmp eax, DWORD PTR [esp+28] ; b
jg .L5 ; jump if a is > b
; Do something 2
.L5:
つまり、両者の違いは
jg
に対して
jge
という命令があります。この2つは同じ時間がかかります。
異なるジャンプ命令で同じ時間がかかることを示すものは何もない、というコメントについて述べたいと思います。 これは少し難しいのですが、私が答えられることは以下の通りです。の中で
インテル® インストラクション・セット・リファレンス
というように、1つの共通命令でまとめられています。
Jcc
(条件を満たした場合にジャンプ)。の下でも同じようにグループ化されています。
最適化リファレンスマニュアル
は、付録Cに記載されています。レイテンシーとスループット
レイテンシー - に必要なクロックサイクルの数。 実行コアがμopsを構成する全ての実行を完了するまでに 1つの命令。
<ブロッククオートスループット - に必要なクロックサイクルの数。 イシューポートが同じ命令を受け入れることができるまで待機します。 また 多くの命令では、命令のスループットが レイテンシーよりかなり小さい
の値は
Jcc
があります。
Latency Throughput
Jcc N/A 0.5
に以下の脚注を付けています。
Jcc
:
- 条件付きジャンプ命令の選択は、3.4.1節「分岐予測の最適化」の推奨事項に基づいて、分岐の予測性を向上させる必要があります。分岐の予測に成功した場合のレイテンシは
jcc
は事実上ゼロです。
そのため、Intelのドキュメントでは、1つを扱うことはありません。
Jcc
命令と他の命令とで、何ら異なる点はありません。
命令を実装するための実際の回路を考えてみると、単純なAND/ORゲートで
EFLAGS
というように、条件を満たしているかどうかを判断します。2ビットをテストする命令が、1ビットをテストする命令よりも時間がかかる理由はありません(クロック周期よりもはるかに小さいゲートの伝搬遅延は無視します)。
Edit: 浮動小数点
これはx87浮動小数点にも当てはまります:(上記とほぼ同じコードですが
double
の代わりに
int
.)
fld QWORD PTR [esp+32]
fld QWORD PTR [esp+40]
fucomip st, st(1) ; Compare ST(0) and ST(1), and set CF, PF, ZF in EFLAGS
fstp st(0)
seta al ; Set al if above (CF=0 and ZF=0).
test al, al
je .L2
; Do something 1
.L2:
fld QWORD PTR [esp+32]
fld QWORD PTR [esp+40]
fucomip st, st(1) ; (same thing as above)
fstp st(0)
setae al ; Set al if above or equal (CF=0).
test al, al
je .L5
; Do something 2
.L5:
leave
ret
関連
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】クラステンプレートの引数リストがない
-
[解決済み】C++でランダムな2倍数を生成する
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] B "の印刷が "#"の印刷より劇的に遅いのはなぜですか?
-
[解決済み] 要素ごとの加算は、結合ループよりも分離ループの方がはるかに高速なのはなぜですか?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] Swift Betaのパフォーマンス:配列のソート
-
[解決済み】高放射能環境下で使用するアプリケーションのコンパイルについて
-
[解決済み] Intel CPU の _mm_popcnt_u64 で、32 ビットのループカウンターを 64 ビットに置き換えると、パフォーマンスが著しく低下します。
最新
-
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 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】文字列関数で'char const*'のインスタンスを投げた後に呼び出されるterminate [閉店].
-
[解決済み】IntelliSense:オブジェクトに、メンバー関数と互換性のない型修飾子がある
-
[解決済み】C++の変数はイニシャライザーを持っているが、不完全な型?
-
[解決済み】「Expected '(' for function-style cast or type construction」エラーの意味とは?
-
[解決済み】#include<iostream>は存在するのですが、「識別子 "cout "は未定義です」というエラーが出ます。なぜですか?
-
[解決済み] 非静的データメンバの無効な使用
-
[解決済み】システムが指定されたファイルを見つけられませんでした。
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み】演算子のオーバーロード C++; <<操作のパラメータが多すぎる
-
[解決済み] 変数サイズのオブジェクトが初期化されないことがある c++