流水線三大冒險(xiǎn):結(jié)構(gòu)、數(shù)據(jù)、控制

流水線讓CPU同時(shí)執(zhí)行多條指令,但指令之間會(huì)打架。結(jié)構(gòu)冒險(xiǎn)搶硬件,數(shù)據(jù)冒險(xiǎn)搶數(shù)據(jù),控制冒險(xiǎn)搶方向。這篇聊聊這三種冒險(xiǎn)的本質(zhì)和應(yīng)對(duì)方法。


1. 結(jié)構(gòu)冒險(xiǎn):硬件不夠用了

1.1 什么是結(jié)構(gòu)冒險(xiǎn)

多條指令同時(shí)需要同一個(gè)硬件資源[1]。比如:

  • 兩條指令都要寫寄存器,但寄存器堆只有一個(gè)寫端口
  • 兩條指令都要用除法器,但除法器只有一個(gè)
  • 取指和訪存同時(shí)訪問內(nèi)存,但只有一個(gè)內(nèi)存端口

1.2 MIPS浮點(diǎn)流水線的例子

MIPS的浮點(diǎn)單元有多個(gè)功能部件[2]

  • FP Adder:3-4周期
  • FP Multiplier:6-7周期
  • FP Divider:24周期(非流水化)

寄存器寫端口沖突

Cycle 11:
  ADD.D F2, F4, F6   ; 完成,要寫F2
  MUL.D F8, F10, F12 ; 完成,要寫F8
  L.D   F14, 0(R2)   ; 完成,要寫F14

三個(gè)指令同時(shí)到達(dá)WB階段,但FP寄存器堆只有一個(gè)寫端口[2]。這就是結(jié)構(gòu)冒險(xiǎn)。

解決方案

  1. 增加寫端口:成本高,利用率低(大部分時(shí)間只有一個(gè)寫)
  2. 檢測(cè)并停頓:在ID階段檢測(cè)沖突,延遲發(fā)射
  3. 移位寄存器跟蹤:記錄未來哪些周期會(huì)寫寄存器,提前沖突檢測(cè)

1.3 除法單元的獨(dú)占

MIPS的FDIV需要24周期,且非流水化[2]

Cycle 1:  FDIV.D F1, F2, F3   ; 開始除法
Cycle 2-24: 其他指令執(zhí)行,但第二個(gè)FDIV必須等
Cycle 25: FDIV.D F4, F5, F6   ; 下一個(gè)除法才能開始

這是結(jié)構(gòu)冒險(xiǎn)的極端情況——功能部件被長(zhǎng)期占用。

解決方案

  1. 流水化除法器:把24周期拆成多級(jí),每級(jí)可重疊
  2. 增加除法單元:成本高,除法不頻繁
  3. 編譯器調(diào)度:在除法后面插入無關(guān)指令

2. 數(shù)據(jù)冒險(xiǎn):數(shù)據(jù)還沒準(zhǔn)備好

2.1 RAW(Read After Write)

最普遍的冒險(xiǎn)。后一條指令讀前一條指令要寫的結(jié)果,但還沒寫好。

MIPS例子[2][3]

L.D   F4, 0(R2)      ; 加載數(shù)據(jù)到F4
MUL.D F0, F4, F6     ; 用F4做乘法

L.D在MEM階段才拿到數(shù)據(jù),MUL.D在EX階段就需要F4。即使轉(zhuǎn)發(fā),也需要停頓1周期[3]。

轉(zhuǎn)發(fā)(Forwarding/Bypassing)[3][4][5]

  • 把ALU結(jié)果直接傳給下一條指令的EX輸入
  • 把MEM結(jié)果傳給EX輸入
  • 減少但無法完全消除停頓

Load-Use Hazard的特殊性[3]

LW  x1, 0(x2)      ; 加載
ADD x3, x1, x1     ; 立即使用x1

Load數(shù)據(jù)在MEM階段末尾才可用,ADD在EX階段就需要。轉(zhuǎn)發(fā)無法解決(不能向過去轉(zhuǎn)發(fā)),必須停頓1周期插入NOP[3]

2.2 WAW(Write After Write)

兩條指令寫同一個(gè)寄存器,可能亂序完成導(dǎo)致錯(cuò)誤結(jié)果。

MIPS浮點(diǎn)例子[2]

ADD.D F2, F4, F6   ; 延遲3周期
L.D   F2, 0(R2)    ; 延遲1周期

L.D比ADD.D快,可能先寫F2,然后ADD.D覆蓋它。程序期望的是ADD.D的結(jié)果。

解決方案

  1. ROB順序提交:指令按程序順序從ROB退休,強(qiáng)制ADD.D先寫
  2. 寄存器重命名:給每條指令分配不同的物理寄存器,消除WAW[6][7]

2.3 WAR(Write After Read)

后一條指令寫前一條指令要讀的寄存器。但在流水線中,讀總是在ID階段,寫在WB階段,所以WAR不會(huì)自然發(fā)生[3]。

只有在亂序執(zhí)行讀延后的情況下才可能發(fā)生,現(xiàn)代CPU通過寄存器重命名消除[7][8]。


3. 控制冒險(xiǎn):分支走哪條路

3.1 分支延遲

5級(jí)流水線中,分支在EX階段才確定目標(biāo)地址:

Cycle 1: BEQ taken? (EX階段計(jì)算)
Cycle 2: 如果預(yù)測(cè)錯(cuò)誤,已取兩條錯(cuò)誤指令

分支預(yù)測(cè)失敗的代價(jià)

  • 簡(jiǎn)單流水線:2-3周期
  • 深度流水線(20+級(jí)):15-20周期[9][10]

3.2 預(yù)測(cè)與恢復(fù)

靜態(tài)預(yù)測(cè):總是預(yù)測(cè)不跳轉(zhuǎn),或編譯器標(biāo)記[10]

動(dòng)態(tài)預(yù)測(cè):基于歷史記錄預(yù)測(cè)[10]

  • Bimodal:簡(jiǎn)單的2位飽和計(jì)數(shù)器
  • Global:考慮全局分支歷史
  • Local:考慮每個(gè)分支的歷史

恢復(fù)機(jī)制

  • 預(yù)測(cè)錯(cuò)誤時(shí),清空流水線(flush)
  • 從正確地址重新取指
  • ROB丟棄推測(cè)執(zhí)行的指令[6][7]

3.3 精確異常

異常發(fā)生時(shí),處理器狀態(tài)必須與程序順序一致[6][7][8]。ROB保證:

  • 異常指令前的所有指令已提交
  • 異常指令后的指令未修改狀態(tài)
  • 可以正確恢復(fù)并跳轉(zhuǎn)到異常處理程序

4. 三類冒險(xiǎn)的對(duì)比

冒險(xiǎn)類型 原因 檢測(cè)階段 解決方案 代價(jià)
結(jié)構(gòu)冒險(xiǎn) 資源爭(zhēng)用 ID 增加資源/停頓調(diào)度 面積/性能
RAW 數(shù)據(jù)未就緒 ID/EX 轉(zhuǎn)發(fā)/停頓/亂序執(zhí)行 邏輯復(fù)雜度
WAW 亂序?qū)懟?/td> ID ROB順序提交/重命名 硬件復(fù)雜度
控制冒險(xiǎn) 分支方向 EX 預(yù)測(cè)/延遲槽/ROB 預(yù)測(cè)失敗懲罰

5. 現(xiàn)代處理器的應(yīng)對(duì)

5.1 亂序執(zhí)行(Out-of-Order)

通過ROB和保留站[7][8]

  • 指令順序發(fā)射(Issue)
  • 亂序執(zhí)行(Execute)
  • 順序提交(Commit)

消除WAW/WAR,隱藏RAW延遲。

5.2 推測(cè)執(zhí)行(Speculative Execution)

分支預(yù)測(cè)后,提前執(zhí)行后續(xù)指令[7]

  • 預(yù)測(cè)正確:加速執(zhí)行
  • 預(yù)測(cè)錯(cuò)誤:ROB丟棄結(jié)果,恢復(fù)狀態(tài)

5.3 轉(zhuǎn)發(fā)網(wǎng)絡(luò)

多級(jí)轉(zhuǎn)發(fā)覆蓋各種依賴[3][11]

  • EX→EX:ALU結(jié)果直接轉(zhuǎn)發(fā)
  • MEM→EX:Load數(shù)據(jù)轉(zhuǎn)發(fā)
  • WB→EX:寫回階段轉(zhuǎn)發(fā)

6. 總結(jié)

流水線冒險(xiǎn)的本質(zhì)是并行執(zhí)行與程序順序的沖突。

結(jié)構(gòu)冒險(xiǎn):硬件資源有限,需要復(fù)制或調(diào)度
數(shù)據(jù)冒險(xiǎn):數(shù)據(jù)依賴存在,需要轉(zhuǎn)發(fā)或等待
控制冒險(xiǎn):程序流程不確定,需要預(yù)測(cè)和恢復(fù)

現(xiàn)代CPU通過亂序執(zhí)行+ROB+寄存器重命名+分支預(yù)測(cè)的組合拳,把冒險(xiǎn)的影響降到最低。但這些機(jī)制增加了硬件復(fù)雜度和功耗,是性能與成本的永恒權(quán)衡。


參考


  1. GeeksforGeeks. Pipeline Hazards. ?

  2. Jyoti Prakash Blog. Delving Deeper into the MIPS Pipeline. FP pipeline hazards. ? ? ? ? ?

  3. Chipmunk Logic. Designing RISC-V CPU from scratch – Part 3. Pipeline hazards. ? ? ? ? ? ? ?

  4. Lori Academic Direct. Data hazards examples. ?

  5. Imperial College London. EIE2 Instruction Architectures & Compilers Lecture 8. ?

  6. CS Shivi. Precise Exceptions & Register Renaming. ? ? ?

  7. 知乎. ARM體系架構(gòu). ROB and precise exceptions. ? ? ? ? ? ?

  8. CSDN博客. CPU亂序執(zhí)行基礎(chǔ) —— Tomasulo算法及執(zhí)行過程. ? ? ?

  9. IEEE. Characterizing the branch misprediction penalty. ?

  10. University of Utah. Lecture 7: Branch prediction. ? ? ?

  11. UPC Commons. Bypassing in pipelines. ?

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容