CPU亂序執行基礎 —— Tomasulo演算法及執行過程

張雅宸發表於2022-03-09

朋友們可以關注下我的公眾號,獲得最及時的更新:

 

IBM 360/91浮點單元最先實現Tomasulo演算法從而允許亂序執行。360體系只有4個雙精度浮點暫存器,限制了編譯器排程的有效性。而且,IBM 360/91的訪存和浮點延遲都很長,如果順序執行指令,雖然只有RAW hazard,但是後面無關的指令只能被stall。如果亂序執行,還會額外引入WAR和WAW hazard。Tomasulo演算法通過Register renaming解決了這些問題。

Tomasulo演算法1966年提出,設計目標是讓編譯器在360系列計算機中通用,不用為每臺計算機專門做一個編譯器。

因為亂序執行,基礎的Tomasulo演算法不能保證Precise Exception和Speculation,帶有Reorder buffer的Tomasulo演算法可以解決這個問題。

作用

  • 指令順序發射(issue/dispatch),亂序執行(execute),順序提交(commit)。
  • Register renaming : 通過reservation station和ROB實現。
    • distributed RS : 如果多個指令同時等待一個暫存器的資料,那麼可以在一個時鐘週期內通過CDB傳輸到多個RS.
  • 實現Bypassing/forwarding
    • 通過CDB,資料直接從執行單元EU傳輸到等待該運算元的RS。
  • 通過Reorder buffer(ROB),可以實現Precise exception和HW Speculation,同時由於ROB保證指令順序提交,順便也消除了WAR & WAW hazard.

不帶ROB

CPU亂序執行基礎 —— Tomasulo演算法及執行過程圖來自computer architecture —— a quantitative approach 6th edition(英文版) P198

在不帶ROB的版本里,執行單元(FP adders/FP mulitipliers)產出的資料會直接寫入到對應的register file和等待這個資料的RS中,不能實現Precise exception和HW Speculation,所以這裡關注帶有ROB版本的Tomasulo 演算法。

Precise exception(精確異常) 的意思是當指令出現異常時(除0、page fault,etc),前面的指令已經完成,後面的指令不能對暫存器、記憶體等進行修改,即跟順序執行的效果一樣,比如:

fdiv.d f0,f2,f4
fadd.d f10,f10,f8
fsub.d f12,f12,f14

3條指令之間沒有hazard,後兩條指令會比除法指令先結束。如果在結束後除法指令發生了exception,作業系統在進行exception處理時,只能假設之前的指令執行完成,後面指令沒有執行,exception恢復後,加法和減法指令還得再執行一次,結果就不對了。

帶ROB

CPU亂序執行基礎 —— Tomasulo演算法及執行過程圖來自computer architecture —— a quantitative approach 6th edition(英文版) P210

ROB的存在使得指令雖然亂序執行,但是必須順序提交,防止不可撤銷的更新操作發生(寫暫存器,寫記憶體)。

Instruction queue

FIFO queue,存取到的指令。

Reservation Station

當前面的指令由於hazard、cache miss被阻塞時,後面不相關的指令可以繼續執行,被阻塞的指令臨時放在RS中,不至於整個流水線被阻塞。當被阻塞指令需要的運算元通過CDB傳輸到對應的RS時,指令被送到EU中執行。RS包含的欄位:

  • Op —— 此保留站存放的指令需要執行的運算,fadd、fld、fds,etc.
  • Qj,Qk —— 即將更新此源運算元的指令對應的ROB entry tag。 0意味著不存在RAW hazard,該源運算元當前可用。比如fadd f0,f1,f2; fsub f3,f0,f2; 這裡針對f0存在RAW hazard,假如為fadd指令分配的ROB entry tag是#1,那麼fsub的RS entry裡Qj就是#1, 意思是等待ROB tag為#1的指令更新這個運算元。其實這裡就是通過Register renaming減少RAW hazard。
  • Vj, Vk —— 源運算元的值。對於每一個運算元,Q和V只有一個是有效的。
  • A —— 在load/store指令中存放記憶體地址相關資訊。比如fld f6, 32(x2), 32+x2是effective address,放在此欄位中。
  • Dest —— 此指令對應的ROB entry tag。用來更新對應ROB中的field.
  • Busy —— 是否被佔用。

Common data bus(CDB)

資料傳輸,EU -> RS、ROB -> Register File,etc。傳輸時還會帶著更新此資料的指令對應的ROB entry tag,這樣RS裡就可以通過匹配tag來更新源運算元。

Reorder buffer(ROB)

FIFO queue,每一項ROB包含4個欄位:

  • Instruction type —— 指令型別。branch、store、load、ALU operation.
  • Destination —— 對於load和ALU operation來說是目標暫存器,對於store是記憶體地址,branch此欄位無意義。
  • Value —— 指令結果值。
  • Ready —— 指令是否已經完成執行。

Register File

由於Commit階段存在,Register File只能由ROB通過CDB去更新,RS不能直接更新Register File. Register File存放著將要向此暫存器更新值的ROB entry tag。如果沒有值或者為0,代表此暫存器的值可用,否則,意味著該暫存器的值會被前面的指令更新,用該暫存器作為源運算元的需要等待CDB將更新後的值傳輸過來。

CPU亂序執行基礎 —— Tomasulo演算法及執行過程

Load Buffer/Store Buffer

Load Buffer存放effective address。Store Buffer的功能一般整合到了ROB中,因為Store Buffer需要的value和effective address在ROB中已經有了。

load/store指令對於相同的effective address也是存在hazard的,而且必須是effective address在execute階段計算好後才知道是否有hazard存在。比如:

    • fsd f5, 1000(f0), fld f0, 1000(f0)
    • fsd f5, 1000(f0), fld f0, 1000(f1) —— 雖然base register不同,但是有可能f0和f1的值相同,計算後的effective address也相同,這就存在RAW hazard.

CPU亂序執行基礎 —— Tomasulo演算法及執行過程

指令執行過程

發射(Issue)

從instruction queue取一條指令(單發射)。如果RS和ROB均有空位,則發射指令到RS,如果有一個沒有空位,會stall指令發射。如果運算元對應的暫存器/ROB中的資料可用,。更新Busy欄位表明此RS項被佔用。為分配的ROB

執行(Execute)

如果運算元均準備好了,直接執行,可能佔用多個時鐘週期,如果在同一個時鐘週期內有多個指令可以執行,一般策略是隨機挑選。如果任一一個運算元沒有準備好,監控CDB獲取計算好的運算元,此步驟檢查RAW hazard.

對於store指令,此步驟僅僅計算effective address.

對於load指令,除了計算effective address,還需要確保當前ROB中的Store指令沒有相同的Destination時,才會去記憶體/cache中讀資料,這裡避免了針對同一effective address的RAW hazard.

寫回(Write result)

計算結果和指令對應的ROB entry tag沿著CDB傳輸到ROB和等待此操作結果的RS項。對於store指令比較特殊,如果要儲存的值已經準備好了,將其寫到對應ROB entry的Value欄位,否則,還需要等CDB將需要儲存的值傳輸過來,更新Value.

注意和不帶ROB的演算法不同,為了之後可回退計算結果,此步驟不會直接將結果寫入到Register File中。

提交(Commit)

當指令到達ROB頭部且ready欄位為1,根據指令型別不同,操作不同:

  • normal commit —— 用Value更新Destination暫存器,並將對應的專案從ROB移除。
  • store —— 和上面類似,只是根據Destination和Value更新對應的記憶體地址。
  • branch with incorrect prediction —— 意味著branch預測錯誤(CPU分支預測器是另外一個很大的話題),需要flush ROB,也就是不要提交branch預測錯誤後執行指令,從應該執行的指令處重新開始執行。

如果一個指令丟擲了異常/預測錯誤,會在ROB中記錄。只有在Commit階段且指令到達ROB頭部時才會識別並flush ROB。

這個是整體流程的虛擬碼,來自computer architecture —— a quantitative approach 6th edition(英文版) P216

CPU亂序執行基礎 —— Tomasulo演算法及執行過程

  • rd —— 目標暫存器,rs/rt —— 源暫存器。
  • RS —— Reservation Station,r和b —— 為指令分配的Reservation Station entry和ROB entry。
  • h —— ROB頭部entry。
  • result —— RS通過CDB傳輸的EU計算結果。
  • RegisterStat —— 暫存器結構,Regs —— 實際暫存器。

RS和ROB的項數

可以看出RS和ROB的總項數反映出一個處理器的亂序執行能力。項數越大表明in-flight(正在執行)的指令數目越多。Intel公司的Nehamel有128項ROB,IBM公司的Power 4/5有200項ROB.

Reservation Station組織形態一般有三種:

  • 獨立 —— 一個EU一個RS,設計簡單,只要一個寫入埠和讀出埠。但是利用率低,容易忙的忙死,閒的閒死。
  • 分組 —— 把EU分為幾組,同組的共享一個RS,需要多個寫入和讀出埠。分組時通常考慮定點、浮點和訪問3類。MIPS R1000是定點、浮點和訪問3個RS,每個各16項。Alpha 21264是定點和訪存共用一個20項的RS,浮點共用一個15項的RS。
  • 全域性 —— 所有EU共用一個RS,讀出和寫入埠很多,控制比較複雜。當然使用效率最高,而且CDB只要送到全域性RS。Intel P6架構的Pentium Pro、Pentuim II、Pentuim III都是類似的結構,只有一個RS,共20項。

 

Onur Mutlu的這個Lecture講的更加詳細

 
 
(完)
 

朋友們可以關注下我的公眾號,獲得最及時的更新:

相關文章