< は <= より速いですか? 質問する

< は <= より速いですか? 質問する

if (a < 901)より速いですかif (a <= 900)?

この単純な例とまったく同じではありませんが、ループの複雑なコードではパフォーマンスがわずかに変化します。これが本当であるならば、生成されたマシン コードと何か関係があると思います。

ベストアンサー1

いいえ、ほとんどのアーキテクチャでは高速化されません。指定されていませんが、x86 では、すべての整数比較は通常、2 つのマシン命令で実装されます。

  • または命令はtestcmpEFLAGS
  • そして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:

したがって、これら 2 つの違いは、命令jgjge実行命令の 2 つだけです。どちらも同じ時間がかかります。


異なるジャンプ命令が同じ時間を要することを示すものは何もないというコメントについてお答えしたいと思います。これは少し答えるのが難しいのですが、私が言えることは次の通りです。Intel 命令セットリファレンス、それらはすべて1つの共通の命令Jcc(条件が満たされたらジャンプ)の下にグループ化されます。同じグループ化が、最適化リファレンスマニュアル、付録 C. レイテンシとスループット。

レイテンシ— 実行コアが命令を構成するすべての μop の実行を完了するために必要なクロック サイクル数。

スループット— 発行ポートが同じ命令を再び受け入れることができるようになるまでに待機する必要があるクロックサイクル数。多くの命令では、命令のスループットはレイテンシよりも大幅に低くなることがあります。

の値は次のJccとおりです。

      Latency   Throughput
Jcc     N/A        0.5

には次の脚注がありますJcc:

  1. 分岐の予測可能性を向上させるには、条件付きジャンプ命令の選択は、セクション 3.4.1「分岐予測の最適化」の推奨事項に基づいて行う必要があります。分岐が正しく予測されると、のレイテンシはjcc実質的にゼロになります。

したがって、Intel のドキュメントでは、1 つのJcc命令を他の命令と異なる方法で扱うことはまったくありません。

命令を実装するために使用される実際の回路について考えると、EFLAGS条件が満たされているかどうかを判断するために、 のさまざまなビットに単純な AND/OR ゲートがあると想定できます。したがって、2 つのビットをテストする命令が、1 つのビットのみをテストする命令よりも長い時間または短い時間を要する理由はありません (ゲートの伝播遅延は無視します。これはクロック周期よりもはるかに短いです)。


編集: 浮動小数点

これは 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

おすすめ記事