1

私はx86プロセッサを実行していますが、私の質問はかなり一般的だと思います。CMP + JEシーケンスと単一の操作で消費されるクロックサイクルの理論的な違いに興味がありMULます。

C 疑似コードでは:

unsigned foo = 1;    /* must be 0 or 1 */
unsigned num = 0;

/* Method 1: CMP + JE*/
if(foo == 1){
    num = 5;
}

/* Method 2: MUL */
num = foo*5;    /* num = 0 if foo = 0 */

疑似コードはあまり深く調べないでください。純粋に、2 つのメソッドの背後にある数学的論理を明らかにするためのものです。

私が実際に比較しているのは、次の 2 つの一連の命令です。

方法 1: CMP + JE

    MOV EAX, 1    ; FOO = 1 here, but can be set to 0
    MOV EBX, 0    ; NUM = 0

    CMP EAX, 1    ; if(foo == 1)
    JE  SUCCESS   ; enter branch
    JMP FINISH    ; end program

SUCCESS:
    MOV EBX, 5    ; num = 5

FINISH:

方法 2: MUL

    MOV EAX, 1    ; FOO = 1 here, but can be set to 0

    MOV ECX, EAX  ; save copy of FOO to ECX
    MUL ECX, 5    ; result = foo*5
    MOV EBX, ECX  ; num = result = foo*5

単一MUL(合計 4 命令) は (合計 6 命令) よりも効率的であるように見えますが、クロック サイクルは命令に対して同じようCMP + JEに消費されます。つまり、命令を完了するのにかかるクロック サイクル数は、他の命令と同じです。 ?

消費される実際のクロック サイクルがマシンに依存する場合、MULほとんどのプロセッサでは、必要な合計命令数が少ないため、通常、単一の分岐アプローチは分岐アプローチよりも高速ですか?

4

2 に答える 2

10

最新の CPU パフォーマンスは、各命令のサイクル数をカウントするだけではなく、はるかに複雑です。次のすべてを考慮する必要があります (少なくとも)。

  • 分岐予測
  • 命令の並べ替え
  • 改名登録
  • 命令キャッシュのヒット/ミス
  • データキャッシュのヒット/ミス
  • TLB ミス/ページ フォールト

これらはすべて、周囲のコードの影響を大きく受けます。

したがって、基本的に、このようなマイクロベンチマークを実行して有用な結果を得ることはほとんど不可能です!

ただし、推測する必要がある場合は、JE を使用しないコードの方が、分岐を排除し、分岐予測の動作が簡素化されるため、一般的により効率的であると言えます。

于 2013-05-29T18:56:04.863 に答える
1

通常、最新の x86 プロセッサでは、CMPMUL命令の両方が 1 サイクルの整数実行ユニットを占有します (CMP基本的にSUBは結果を破棄し、フラグ レジスタを変更するだけです)。ただし、最新の x86 プロセッサは、パイプライン化され、スーパースカラーであり、アウトオブオーダーでもあります。つまり、パフォーマンスは、この基本的なサイクル コストだけに依存するだけではありません。

分岐を適切に予測できない場合、分岐予測ミスのペナルティが他の要因を圧倒し、MULバージョンのパフォーマンスが大幅に向上します。

一方、分岐適切に予測さnum、その後の計算ですぐに使用できる場合は、平均的なケースで分岐バージョンのパフォーマンスが向上する可能性があります。これは、分岐を正しく予測するとnum、比較の結果が得られる前に、 の予測値を使用して次の命令の投機的な実行を開始できるためです (このMUL場合、その後の の使用はnumMUL- その結果がリタイアするまで実行できません)。

于 2013-05-30T00:20:07.963 に答える