2016-04-24 72 views
1

我目前正在做一項測量各種x86-64命令(在& t語法)的性能的任務。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指令) - 但是從我對流水線的瞭解,無條件跳轉應該非常快(沒有分支預測錯誤)。

我錯過了什麼嗎?我的代碼錯了嗎?

+0

[Slow jmp-instruction]的可能重複(http://stackoverflow.com/questions/38811901/slow-jmp-instruction)。這個更詳細的問題有一個更好,更詳細的答案。 –

回答

1

的CPU是不是無操作優化jmp說明,所以它不處理繼續解碼和管道JMP指令只是跳轉到下一個insn的特殊情況。但是,CPU針對循環進行了優化。 jmp .將在許多CPU上以每個時鐘一個insn運行,或者在某些CPU上每2個時鐘運行一個insn。


跳轉在指令讀取中創建一個氣泡。一個預測良好的跳躍是可以的,但沒有任何運轉,但跳躍是有問題的。我複製你在酷睿2 E6600的結果(Merom處理器/ Conroe的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) 

構建和運行:

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 

從另一個運行:

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%) 

(在(%編號)是每行結束時計數器處於活動狀態的總運行時間的多少:perf當您要求它計算比硬件可以一次計數更多的事情時,必須爲您複用)。因此它實際上並不是I緩存未命中,它只是由不斷跳轉引起的取指/解碼前端瓶頸。

我的SnB機器壞了,所以我無法測試它的數字,但是每個jmp持續吞吐量的8個週期與您的結果非常接近(可能來自不同的微架構)。

有關更多詳細信息,請參閱http://agner.org/optimize/以及標記wiki的其他鏈接。