天天看點

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

現代CPU由于存在多級流水線,對于分支處理又存在分支預測功能,是以在實際cpu的運作過程中,beq指令的周期不是固定的。

另外,即使對于其他指令,比如lw指令,其指令周期也不是固定的。取決于該指令跟後面的指令有沒有依賴關系。

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

使用2周期的那些lw指令的bne指令都是需要用到前一條lw指令的結果,是以必須等前一條完成之後才能執行。比如 lw a0,1540(t1)與bne a0,x0,-1,bne指令必須等 a0 的 load 結果出來之後才能開始執行。lw 本身都是4周期的,如果前後沒有依賴關系就可以pipeline起來,看起來就是一個周期完成一樣。比如圖中前面那些1個周期的lw指令都是沒有依賴關系的。另外,lw 周期數跟具體實作有關系,最少2周期,如果存儲接口插入了等待周期會更長,具體到某個指令多少得分析微架構。是以說,并不能直接從代碼段知道一個函數的實際運作時間,需要實際運作看看。

執行一個小程式進行測試(測試cpu為8級流水線),從log中獲知一共使用了31個不同的指令。指令和指令次數為:

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

1, 跳轉和傳回指令

jal指令:

即使沒有依賴關系,也是最少5周期:本測試一共有2983個jal指令,其指令周期和次數有:

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

可以看出,jalr指令的大部分的指令周期是5。

jalr指令:

jalr指令一共有2279個jalr指令,其指令周期和次數有:

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

可以看出,jalr指令的大部分的指令周期是5。

mret指令

mret指令,一共79個:

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

大部分為9個周期。

2, add和addi指令

add指令,一共4129個,1個周期和4個周期大約各占一半。

addi指令,一共22708個,大部分是1個周期。

僞代碼中的li指令,會轉換為addi指令來執行。比如li a5,4指令,會轉換為addr a5,x0,4。

3, load和store指令

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

lw指令

lw指令,一共24338個,1個周期和2個周期的大約各占一半。

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

lbu指令

lbu指令,一共1572個:

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

可以看出,lbu指令的時間周期并沒有比lw指令少。

sw指令

sw指令,一共13636個,大部分需要1個時鐘周期。

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

sb和sh指令

sb和sh指令與sw指令類似,大部分需要1個時鐘周期。

4,分支預測指令

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

bne指令

bne指令,一共5389個:

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

66%是7個周期。

有1次15 cycle是因為後面來了一個中斷,需要跳轉到中斷服務函數。

有11次用了13個cycle, 主要就是分支開銷, 沒有指令預測, 結果遇到分支跳轉,開銷就大;一般跳轉後面的時間長, 很大可能都是分支跳轉的開銷。開銷最大的情況是跳轉後 又遇到 cache miss; 計算這個開銷是 從取指令到送出的流水線級數+cache miss的取指時間。

總結:是以我們在寫代碼的時候,最好把運作機率大的那個分支寫到if中。

bge,begu,blt指令

這三個指令大部分都是6個周期。可以看到,分支跳轉指令是比較耗時的。

5, 與狀态寄存器有關的指令

csrrs,csrrw,csrrwi,這些指令在實際測試中一般耗費4個時鐘周期。

6,nop指令

nop指令,一共1060個:

RISC-V 不定長的指令周期1, 跳轉和傳回指令2, add和addi指令3, load和store指令4,分支預測指令5, 與狀态寄存器有關的指令6,nop指令7,其他指令

7,其他指令

大部分都是1個時鐘周期。

繼續閱讀