2016-04-24 11 views
1

現在、さまざまなx86-64コマンド(&の構文)のパフォーマンスを測定する課題を行っています。x86-64相対jmpパフォーマンス

私がやや混乱しているコマンドは、「無条件jmp」コマンドです。これは私がそれを実現してきた方法です:

.global uncond 
uncond: 

.rept 10000 
jmp . + 2 
.endr 


mov $10000, %rax 
ret 

それはかなり簡単です。このコードでは、 "uncond"という関数を作成します。この関数は.reptディレクティブを使用してjmpコマンドを10000回呼び出し、jmpコマンドを呼び出した回数に戻り値を設定します。

"。" &のt構文は現在のアドレスを意味し、jmp命令自体を考慮するために2バイト増加します(jmp。+ 2は単に次の命令に移動する必要があります)。

私が示していないコードは、10000コマンドを処理するのに要するサイクル数を計算します。

私の結果は(単一jmp命令を処理するために10サイクルかかります)JMPはかなり遅いと言う - しかし、私はパイプライン化について理解するものから、無条件ジャンプは(無分岐予測誤差)は非常に高速である必要があります。

何か不足していますか?私のコードは間違っていますか?それだけで次のinsnにジャンプJMP命令をデコードし、パイプラインを継続する特殊なケースを処理しないように

+0

[低速jmp命令](http://stackoverflow.com/questions/38811901/slow-jmp-instruction)の可能な複製。より詳細な質問には、はるかに優れた詳細な答えがあります。 –

答えて

1

CPUは、無操作のためにjmp指示に最適化されていません。

CPUはループ用に最適化されています。 jmp .は、多くのCPUでは1クロックで実行され、一部のCPUでは2クロックで実行されます。


ジャンプは、命令フェッチでバブルを作成します。よく予測される単一のジャンプは正常ですが、ジャンプ以外は何も実行するのは問題があります。私は、あなたのコア2のE6600の結果(メロム/コンローmicroarch)再現:

# jmp-test.S 
.globl _start 
_start: 

    mov $100000, %ecx 
jmp_test: 
    .rept 10000 
    jmp . + 2 
    .endr 

    dec %ecx 
    jg jmp_test 


    mov $231, %eax 
    xor %ebx,%ebx 
    syscall   # exit_group(0) 

ビルドをしてして実行します(%で

7,886,461,952  L1-icache-loads   # 2377.687 M/sec     (74.95%) 
    7,715,854  L1-icache-load-misses  # 2.326 M/sec     (50.08%) 
1,012,038,376  iTLB-loads    # 305.119 M/sec     (75.06%) 
      240  iTLB-load-misses   # 0.00% of all iTLB cache hits (75.02%) 

(番号:別の実行から

gcc -static -nostartfiles jmp-test.S 
perf stat -e task-clock,cycles,instructions,branches,branch-misses ./a.out 

Performance counter stats for './a.out': 

     3318.616490  task-clock (msec)   # 0.997 CPUs utilized   
    7,940,389,811  cycles     # 2.393 GHz      (49.94%) 
    1,012,387,163  instructions    # 0.13 insns per cycle   (74.95%) 
    1,001,156,075  branches     # 301.679 M/sec     (75.06%) 
      151,609  branch-misses    # 0.02% of all branches   (75.08%) 

     3.329916991 seconds time elapsed 

)は、カウンターがアクティブであった合計実行時間のうちどれくらいですか:perfは、HWが一度に数えることができるものより多くのものをカウントするよう要求したときに、マルチプレクスする必要があります。

実際にはIキャッシュミスではなく、定数ジャンプによるフロントエンドのボトルネックをフェッチ/デコードするだけです。

私のSnBマシンは壊れているので、その上で数字をテストすることはできませんが、jmpあたり8サイクルの処理速度は結果に非常に近くなります(これはおそらく別のマイクロアーキテクチャのものでした)。

詳細については、http://agner.org/optimize/タグwikiの他のリンクを参照してください。