- 指令級並行(ILP):指指令之間存在的一種並行性,利用它,計算機可以並行執行兩條或兩條以上的指令。
- 開發
ILP
的途徑有兩種- 資源重復,重復設置多個處理部件,讓它們同時執行相鄰或相近的多條指令;
- 采用流水線技術,使指令重疊並行執行。
- 本部分研究:如何利用各種技術來開發更多的指令級並行(硬件的方法)
指令級並行的概念
開發ILP
的方法可以分為兩大類
- 主要基於硬件的動態開發方法
- 基於軟件的靜態開發方法
流水線處理機的實際CPI
-
理想流水線的
CPI
加上各類停頓的時鍾周期數:\(CPI_{流水線} = CPI_{理想} + {停頓}_{結構沖突}+{停頓}_{數據沖突} + {停頓}_{控制沖突}\)
-
理想
CPI
是衡量流水線最高性能的一個指標 -
IPC
:每個時鍾周期完成的指令條數
基本程序塊
- 定義:一串連續的代碼除了入口和出口以外,沒有其他的分支指令和轉入點。
- 程序平均每\(4 \sim 7\)條指令就會有一個分支。
循環級並行:使一個循環中的不同循環體並行執行。
-
開發循環的不同迭代之間存在的並行性(最常見、最基本)
-
是指令級並行研究的重點之一
-
例如,考慮下述語句:
for(i = 1 ; i <= 500 ; i = i + 1) a[i] = a[i] + s;
- 每一次循環都可以與其它的循環重疊並行執行
- 在每一次循環的內部,卻沒有任何的並行性。
最基本的開發循環級並行的技術
- 循環展開技術
- 采用向量指令和向量數據表示
相關與指令級並行
相關與流水線沖突
- 相關有三種類型:數據相關、名相關、控制相關
- 流水線沖突是指對於具體的流水線來說,由於相關的存在,使得指令流中的下一條指令不能在指定的時鍾周期執行。流水線沖突有三種類型:結構沖突、數據沖突、控制沖突。
- 相關是程序固有的一種屬性,它反映了程序中指令之間的相互依賴關系。
- 具體的一次相關是否會導致實際沖突的發生以及該沖突會帶來多長的停頓,則是流水線的屬性。
可以從兩個方面來解決相關問題
- 保持相關,但避免發生沖突。即指令調度。
- 通過代碼變換,消除相關。
程序順序:由原來程序確定的在完全串行方式下指令的執行順序。只有在可能會導致錯誤的情況下,才保持程序順序。
控制相關並不是一個必須嚴格保持的關鍵屬性。
對於正確地執行程序來說,必須保持的最關鍵的兩個屬性:數據流和異常行為。
-
保持異常行為是指:無論怎么改變指令的執行順序,都不能改變程序中異常的發生狀況。
- 即原來程序中是怎么發生的,改變執行順序后還是怎么發生。
- 弱化為:指令執行順序的改變不能導致程序中發生新的異常。
-
數據流:指數據值從其產生者指令到其消費者指令的實際流動。
- 分支指令使得數據流具有動態性,因為一條指令有可能數據相關於多條先前的指令。
- 分支指令的執行結果決定了那條指令真正是所需數據的產生者。
-
有時,不遵守控制相關既不影響異常行為,也不改變數據流
-
可以大膽地進行指令調度,把失敗分支中的指令調度到分支指令之前。
-
舉例:
DADDU R1 , R2 , R3 BEQZ R12 , Skipnext DSUBU R4, R5, R6 #將這條指令放在分支指令前執行 不會對程序操作影響 DADDU R5 , R4 , R9 Skipnext: OR R7 , R8 , R9
-
指令的動態調度
-
靜態調度
- 依靠編譯器對代碼進行靜態調度,以減少相關和沖突。
- 它不是在程序執行的過程中,而是在編譯期間進行代碼調度和優化。
- 通過把相關的指令拉開距離來減少可能產生的停頓。
-
動態調度
- 在程序的執行過程中,依靠專門硬件對代碼進行調度,減少數據相關導致的停頓。
- 優點:能夠處理一些在編譯時情況不明的相關(比如涉及到存儲器訪問的相關),並簡化了編譯器;能夠使本來是面向某流水線優化編譯的代碼在其它的流水線(動態調度)上也能高效的執行。
- 缺點:以硬件復雜性的顯著增加為代價
動態調度的基本思想
到目前為止我們所使用流水線的最大的局限性:
-
指令是按序流出和按序執行的
-
考慮下面一段代碼:
DIV.D F4, F0, F2 ADD.D F10, F4, F6 SUB.D F12, F6, F14
ADD.D
指令與DIV.D
指令關於F4
相關,導致流水線停頓;SUB.D
指令與流水線中的任何指令都沒有關系,但也因此受阻。在前面的基本流水線中,一旦一條指令受阻,其后的指令都將停頓。
-
為了能使上述指令序列中的
SUB.D
指令能繼續執行下去,必須把指令流出的工作拆分為兩步:- 檢測結構沖突
- 等待數據沖突消失
只要檢測到沒有結構沖突,就可以讓指令流出。並且流出后的指令一旦其操作數就緒就可以立即執行。
亂序執行
- 指令的執行順序與程序順序不相同
- 指令的完成也是亂序完成的,即指令的完成順序與程序順序不相同。
為了支持亂序執行,我們將5
段流水線的譯碼階段再分為兩個階段:
- 流出(IS):指令譯碼,檢查是否存在結構沖突。
- 讀操作數(RO):等待數據沖突消失,然后讀操作數。
在前述5
段流水線中,是不會發生WRA
沖突和WAW
沖突的,但亂序執行就使得它們可能發生了。
考慮下面的代碼:
DIV.D F10, F0 , F2
ADD.D F10, F4 , F6
SUB.D F6, F8 , F14
可以通過使用寄存器重命名來消除。
動態調度的流水線支持多條指令同時處於執行當中。
- 要求:具有多個功能部件或者功能部件流水化或者二者兼有。
- 我們假設具有多個功能部件。
指令亂序完成帶來的最大問題:異常處理比較復雜
-
動態調度的處理機要保持正確的異常行為
對於一條會產生異常的指令來說,只有當處理機確切地知道該指令將被執行時,才允許它產生異常。
-
即使保持了正確的異常行為,動態調度處理機仍可能發生不精確異常。
-
不精確異常:當執行指令
i
導致發生異常時,處理機的現場(狀態)與嚴格按程序順序執行時指令i
的現場不同。- 發送不精確異常的原因:因為當發送異常(設為指令
i
)時,流水線可能已經執行完按程序順序是位於指令i
之后的指令;流水線可能還沒完成按程序順序是指令i
之前的指令。 - 不精確異常使得在異常處理后難以接着繼續執行程序。
- 發送不精確異常的原因:因為當發送異常(設為指令
-
精確異常:如果發生異常時,處理機的現場跟嚴格按程序順序執行時指令
i
的現場相同。
記分牌算法和Tomasulo算法是兩種比較典型的動態調度算法。
記分牌動態調度算法
基本思想
CDC 6600
計算機最早采用此功能- 該機器用一個稱為記分牌的硬件實現了對指令的動態調度。
- 該硬件中維護着
3
張表,分別用於記錄指令的執行狀態、功能部件狀態、寄存器狀態以及數據相關關系等。 - 它把前述
5
段流水線中的譯碼段ID
分解成兩個段,流出和讀操作數,以避免當某條指令在ID
段被停頓時擋住后面無關指令的流動。
- 記分牌的目標:在沒有結構沖突時,盡可能早地執行沒有數據沖突的指令,實現每個時鍾周期執行一條指令。
- 要發揮指令亂序執行的好處,必須有多條指令同時處於執行階段。
CDC 6600
具有16
個獨立的功能部件:4
個浮點部件;5
個訪問部件;7
個整數操作部件。
- 假設:所考慮的處理器有
2
個乘法器、1
個加法器、1
個除法部件和1
個整數部件。整數部件用來處理所有的存儲器訪問、分支處理和整數操作。 - 采用了記分牌的
MIPS
處理器的基本結構:每條指令都要經過記分牌,記分牌負責相關檢測並控制指令的流出和執行。 - 每條指令的執行過程分為
4
段(主要考慮浮點操作)- 流出:如果當前流出指令所需的功能部件空閑並且所有其他正在執行的指令的目的寄存器與該指令的不同,記分牌就向功能部件流出該指令,並修改記分牌內部的記錄表。解決了
WAW
沖突。 - 讀操作數:記分牌檢測源操作數的可用性,如果數據可用,它就通知功能部件從寄存器中讀出源操作數並開始執行。動態地解決了
RAW
沖突,並導致指令可能亂序開始執行。 - 執行:取到操作數后,功能部件開始執行。當產生出結果后,就通知記分牌它已經完成執行。在浮點流水線中,這一段可能要占用多個時鍾周期。
- 寫結果:記分牌一旦知道執行部件完成了執行,就檢測是否存在
WAR
沖突。如果不存在或者原有的WAR
沖突已消失,記分牌就通知功能部件把結果寫入目的寄存器,並釋放該指令所使用的所有資源。
- 流出:如果當前流出指令所需的功能部件空閑並且所有其他正在執行的指令的目的寄存器與該指令的不同,記分牌就向功能部件流出該指令,並修改記分牌內部的記錄表。解決了
- 如果檢測到
WAR
沖突,就不允許該指令將結果寫到目的寄存器。這發生在以下情況:- 前面的某條指令(按順序流出)還沒有讀取操作數;而且其中某個源操作數寄存器與本指令的目的寄存器相同。在這種情況下,記分牌必須等待,直到該沖突消失。
- 記分牌中記錄的信息由
3
部分構成- 指令狀態表:記錄正在執行的各條指令已經進入到了那一階段。
- 功能部件狀態表:記錄各個功能部件的狀態。每個功能部件有一項,每一項由以下
9
個字段組成。Busy
:忙標志,指出功能部件是否忙。初始值為no
。Op
:該功能部件正在執行或將要執行的操作。Fi
:目的寄存器編號。Fj , Fk
:源寄存器編號。Qj , Qk
:指出向源寄存器Fj , Fk
寫數據的功能部件。Rj , Rk
:標志位,為yes
表示Fj , Fk
中的操作數繼續且還未被取走。否則就被設置為no
。
- 結果寄存器狀態表
Result
:每個寄存器在該表中有一項,用於指出那個功能部件(編號)將把結果寫入該寄存器。- 如果當前正在運行的指令都不以它為目的寄存器,則其相應值置為
no
。 Result
各項的初值為no
。
- 如果當前正在運行的指令都不以它為目的寄存器,則其相應值置為
具體算法
-
約定:
FU
:表示當前指令所要用的功能部件D
:目的寄存器的名稱S1,S2
:源操作數寄存器的名稱Op
:要進行的操作Fj[FU]
:功能部件FU
的Fj
字段(其他字段依此類推)Result[D]
:結果寄存器狀態表中與寄存器D
相對應的內容。其中存放的是將把結果寫入寄存器D
的功能部件的名稱。
-
指令流出
#進入條件 not Busy[Fu] & not Busy Result[D] #功能部件空閑且沒有寫后寫沖突 #記分牌內容修改 Busy[Fu] ← yes # 把當前指令的相關信息填入功能部件狀態表。功能部件狀態表中各字段的含義見前面。 Op[FU] ← Op # 記錄操作碼 Fi[FU] ← D #記錄目的寄存器編號 Fj[FU] ← S1 # 記錄第一個源寄存器編號 Fk[FU] ← S2 # 記錄第二個源寄存器編號。 Qj[FU] ← Result[S1] # 記錄將產生第一個源操作數的部件。 Qk[FU]←Result[S2] #記錄將產生第二個源操作數的部件。 Rj[FU]←not Qj[FU] #置第一個源操作數是否可用的標志。如果Qj[FU]為“no”,就表示沒有操作部件要寫S1,數據可用。置Rj[FU]為“yes”。否則置Rj[FU]為“no”。 Rk[FU]←not Qk[FU]#置第二個源操作數是否可用的標志。 Result[D]←FU #D是當前指令的目的寄存器。功能部件FU將把結果寫入D。
-
讀操作數
#進入條件: Rj[FU] & Rk[FU]# 兩個源操作數都已就緒。 #計分牌內容修改: Rj[FU]←no # 已經讀走了就緒的第一個源操作數。 Rk[FU]←no # 已經讀走了就緒的第二個源操作數。 Qj[FU]←0 # 不再等待其他FU的計算結果。 Qk[FU]←0
-
執行
結束條件:功能部件操作結束。
-
寫結果
#進入條件: \forall f((Fj[f] \neq Fi[FU] or Rj[f]=no) & (Fk[f] \neq Fi[FU] or Rk[f]=no));# 不存在WAR沖突。 #計分牌內容修改: \forall f(if Qj[f]=FU then Rj[f]←yes); # 如果有指令在等待該結果(作為第一源操作數),則將其Rj置為“yes”,表示數據可用。 \forall f(if Qk[f] = FU then Rk[f]←yes); # 如果有指令在,等待該結果(作為第二源操作數),則將其Rk置為“yes”,表示數據可用。 Result(Fi[FU])←0; # 釋放目的寄存器Fi[FU]。 Busy[FU]=no; # 釋放功能部件FU。
記分牌的性能受限於以下幾個方面:
- 程序代碼中可開發的並行性,即是否存在可以並行執行的不相關的指令。
- 記分牌的容量:記分牌的容量決定了流水線能在多大范圍內尋找不相關指令。流水線中可以同時容納的指令數量稱為指令窗口。
- 功能部件的數目和種類:功能部件的總數決定了結構沖突的嚴重程度。
- 反相關和輸出相關:它們引起記分牌中
WAR
和WAW
沖突。
Tomasulo算法
基本思想
-
記錄和檢測指令相關,操作數一旦就緒就立即執行,把發生
RAW
沖突的可能性減少到最小; -
通過寄存器換名來消除
WAR
沖突和WAW
沖突。 -
基於
Tomasulo
算法的MIPS
處理器浮點部件的基本結構 -
保留站:每個保留站中存一條已經流出並等待到本功能部件執行的指令(相關信息)。包括:操作碼、操作數以及用於檢測和解決沖突的信息。
- 在一條指令流出到保留站的時候,如果該指令的源操作數已經在寄存器中就緒,則將之取到該保留站中。
- 如果操作數還沒有計算出來,則在該保留站中記錄將產生這個操作數的保留站的標識。
- 浮點加法器有
3
個保留站:ADD1
、ADD2
、ADD3
- 浮點乘法器有
2
個保留站:MULT1
、MULT2
- 每個保留站都有一個標識符字段,唯一地標識了該保留站。
-
公共數據總線
CDB
一條重要的數據通路- 所有功能部件的計算結果都是送到
CDB
上,由它把這些結果直接送到各個需要該結果的地方。 - 在具有多個執行部件且采用多流出(即每個時鍾周期流出多條指令)的流水線中,需要采用多條
CDB
。
- 所有功能部件的計算結果都是送到
-
load
緩沖器和store
緩沖器- 存放讀/寫存儲器的數據或地址
load
緩沖器的作用有3
個:存放用於計算有效地址的分量;記錄正在進行的load
訪存,等待存儲器的響應;保存已經完成了的load
的結果(即從存儲器取出來的數據),等待CDB
傳輸。store
緩沖器的作用有3
個:存放用於計算有效地址的分量;保存正在進行的store
訪存的目標地址,該store
正在等待存儲數據的到達;保存該store
的地址和數據,直到存儲部件接收。
-
浮點寄存器
FP
:共有16
和浮點寄存器F0 , F2 , F4 , ... , F30
;它們通過一對總線連接到功能部件,並通過CDB
連接到store
緩沖器。 -
指令隊列:指令部件送來的指令放入指令隊列;指令隊列中的指令按先進先出的順序流出。
-
運算部件:浮點加法器完成加法和減法操作;浮點乘法器完成乘法和除法操作。
在Tomasulo
算法中,寄存器換名是通過保留站和流出邏輯來共同完成的。
- 當指令流出時,如果其操作數還沒有計算出來,則該指令中相對應的寄存器號換名為將產生這個操作數的保留站的標識。
- 指令流出到保留站后,其操作數寄存器號或者換成了數據本身(如果該數據已經就緒)或者換成了保留站的標識,不再與寄存器有關系。
Tomasulo
算法有以下兩個特點:
- 沖突檢測和指令執行控制是分布的:每個功能部件的保留站中的信息決定了什么時候指令可以在該功能部件開始執行。
- 計算結果通過
CDB
直接從產生它的保留站傳送到所有需要它的功能部件,而不用經過寄存器。
指令執行的步驟:
使用Tomasulo
算法的流水線需3
段:
- 流出:從指令隊列的頭部取一條指令。如果該指令的操作所要求的保留站有空閑的,就把該指令送到該保留站(設為
r
);如果其操作數在寄存器中已經就緒,就將這些操作數送入保留站r
;如果其操作數還沒有就緒,就把將產生該操作數的保留站的標識送入保留站r
;一旦被記錄的保留站完成計算,它將直接把數據送給保留站r
。寄存器換名對操作數進行緩沖,消除WAR
沖突。完成對目標寄存器的預約工作(消除了WAW
沖突);如果沒有空閑的保留站,指令就不能流出(發生了結構沖突)。 - 執行:當兩個操作數都就緒后,本保留站就用相應的功能部件開始執行指令規定的操作;
load
和store
指令的執行需要兩個步驟:計算有效地址和把有效地址放入load
或store
緩沖器。 - 寫結果:功能部件計算完畢后,就將計算結果放到
CDB
上,所有等待該計算結果的寄存器和保留站(包括store
緩沖器)都同時從CDB
上獲得所需要的數據。
每個保留站有以下7
個字段:
Op
:要對源操作數進行的操作Qj , Qk
:將產生源操作數的保留站;等於0
表示操作數已經就緒且在Vj
或Vk
中,或者不需要操作數。Vj , Vk
:操作數的值,對於每一個操作數來說,V
或Q
字段只有一個有效;對於load
來說Vk
字段用於保存偏移量。Busy
:為yes
表示本保留站或緩沖單元忙。A
:僅load
和store
緩沖器有該字段。開始是存放指令中國的立即數字段,地址計算后存放有效地址。Qi
:寄存器狀態表;每個寄存器在該表中有對應的一項,用於存放將把結果寫入該寄存器的保留站的站號;為0
表示當前沒有正在執行的指令要寫入該寄存器,也即該寄存器中的內容就緒。
動態分支預測技術
所開發的ILP
越多,控制相關的制約就越大,分支預測就要有更高的准確度。
本部分中介紹的方法對於每個時鍾周期流出多條指令(若為n
條,就稱為n
流出)的處理機來說非常重要。因為:在n
-流出的處理機中,遇到分支指令的可能性增加了n
倍。要給處理器連續提供指令,就需要准確地預測分支。
動態分支預測:在程序運行時,根據分支指令過去的表現來預測其將來的行為。如果分支行為發生了變化,預測結果也跟着改變。有更好的預測准確度和適應性。
分支預測的有效性取決於:
-
預測的准確性
-
預測正確和不正確兩種情況下的分支開銷
決定分支開銷的因素:流水線的結構;預測的方法;預測錯誤時的恢復策略等。
-
采用動態分支預測技術的目的:預測分支是否成功;盡快找到分支目標地址(或指令)避免控制相關造成流水線停頓。
-
需要解決的關鍵問題
- 如何記錄分支的歷史信息,要記錄那些信息?
- 如何根據這些信息來預測分支的去向,甚至提前取出分支目標處的指令?
-
在預測錯誤時,要作廢已經預期和分析的指令,恢復現場,並從另一條分支路徑重新取指令。
采用分支歷史表BHT
分支歷史表BHT
:最簡單的動態分支預測方法;用BHT
來記錄分支指令最近一次或幾次的執行情況(成功還是失敗)並據此進行預測。
只有1
個預測位的分支預測:記錄分支指令最近一次的歷史,BHT
中只需要1
位二進制。
采用兩位二進制來記錄歷史
-
提高預測的准確度
-
研究結果表明:兩位分支預測的性能與
n
位分支預測的性能差不多 -
兩位分支預測的狀態轉換如下所示:
-
兩位分支預測中的操作有兩個步驟
- 分支預測:當分支指令到達譯碼階段
ID
時,根據從BHT
讀出的信息進行分支預測;若預測正確,就繼續處理后續的指令,劉淑嫻沒有斷流;否則就要作廢已經預取和分析的指令,恢復現場,並從另一條分支路徑重新取指令。 - 狀態修改
- 分支預測:當分支指令到達譯碼階段
BHT
方法只在以下情況下才有用:
- 判定分支是否成功所需的時間大於確定分支目標地址所需的時間。
- 前述
5
段經典流水線:由於判定分支是否成功和計算分支目標地址都是在ID
段完成,所以BHT
方法不會給該流水線帶來好處。
研究結果表明:對於SPEC89
測試程序來說,具有大小為4KB
的BHT
的預測准確率為82%-99%
。一般來說,采用4KB
的BHT
就可以了。
BHT
可以跟分支指令一起存放在指令Cache
中,也可以用一塊專門的硬件來實現。
采用分支目標緩沖器BTB
目標:將分支的開銷降為0
方法:分支目標緩沖
- 將分支成功的分支指令的地址和它的分支目標地址都放到一個緩沖區中保存起來,緩沖區以分支指令的地址作為標識。
- 這個緩沖區就是分支目標緩沖器,簡記為
BTB
,或者分支目標cache
。
BTB
的結構:
- 看成是用專門的硬件實現的一張表格
- 表格中的每一項至少有兩個字段:執行過的成功分支指令的地址作為該表的匹配標識;預測的分支目標地址。
采用BTB
后,在流水線各個階段所進行的相關操作:
采用BTB
后,各種可能情況下的延遲
指令在BTB 中? |
預測 | 實際情況 | 延遲周期 |
---|---|---|---|
是 | 成功 | 成功 | 0 |
是 | 成功 | 不成功 | 2 |
不是 | 成功 | 2 | |
不是 | 不成功 | 0 |
BTB
的另一種形式
-
在分支目標緩沖器中增設一個至少是兩位的
分支歷史表
字段 -
更進一步,在表中對於每條分支指令都存放若干條分支目標處的指令,就形成了分支目標指令緩沖器。
基於硬件的前瞻執行
前瞻執行的基本思想:對分支指令的結果進行猜測,並假設這個猜測總是對的,然后按這個猜測結果繼續取、流出和執行后續的指令。只是執行指令的結果不是寫回到寄存器或存儲器,而是寫入一個稱為再定序緩沖器ROB(ReOrder Buffer)
中 。等到相應的指令得到“確認”(commit)(即確實是應該執行的)之后,
才將結果寫入寄存器或存儲器。
基於硬件的前瞻執行結合了3
種思想:
- 動態分支預測。用來選擇后續執行的指令。
- 在控制相關的結果尚未出來之前,前瞻執行后續指令。
- 用動態調度對基本塊的各種組合進行跨基本塊的調度。
對Tomasulo
算法加以擴充,就可以支持前瞻執行
把Tomasulo
算法的寫結果和指令完成加以區分,分成兩個不同的段:寫結果、指令確認。
- 寫結果段:把前瞻執行的結果寫到
ROB
中;通過CDB
在指令之間傳送結果,供需要用到這些結果的指令使用。 - 指令確認段:在分支指令的結果出來后,對相應指令的前瞻執行給予確認。如果前面所做的猜想是對的,把在
ROB
中的結果寫到寄存器或存儲器;如果發現前面對分支結果的猜測是錯誤的,那就不予以確認,並從那條分支指令的另一條路徑開始重新執行。
實現前瞻的關鍵思想:允許指令亂序執行,但必須順序確認;在指令被確認之前,不允許它進行不可恢復的操作。
支持前瞻執行的浮點部件的結構:
ROB
中的每一項由以下4
個字段組成:- 指令類型:指出該指令是分支指令、
store
指令或寄存器操作指令。 - 目標地址:給出指令執行結果應寫入的目標寄存器號或存儲單元的地址。
- 數據值字段:用來保存指令前瞻執行的結果,直到指令得到確認。
- 就緒字段:指出指令是否已經完成執行並且數據已就緒。
- 指令類型:指出該指令是分支指令、
Tomasulo
算法中保留站的換名功能是由ROB
來完成的。
采用前瞻執行機制后,指令的執行步驟:
- 流出:從浮點指令隊列的頭部取一條指令;如果有空閑的保留站(假設為
r
)且有空閑的ROB
項(設為b
),就流出該指令,並把相應的信息放入保留站r
和ROB
項b
;如果保留站或ROB
全滿,便停止流出指令,直到它們都有空閑的項。 - 執行:如果有操作數尚未就緒,就等待,並不斷地檢測
CDB
;當兩個操作數都已在保留站中就緒后,就可以執行指令的操作。 - 寫結果:當結果產生后,將該結果連同本指令在流出段所分配到的
ROB
項的編號放在CDB
上,經CDB
寫到ROB
以及所有等待該結果的保留站;釋放產生該結果的保留站;store
指令在本階段完成,其操作為:如果要寫入存儲器的數據已經就緒,就把該數據寫入分配給該store
指令的ROB
項。否則,就監測CDB
,直到那個數據在CDB
上播送出來,才將之寫入分配給該store
指令的ROB
項 - 確認:對分支指令、
store
指令以及其它指令的處理不同- 其它指令(除分支指令和
store
指令):當該指令到達ROB
隊列的頭部而且其結果已經就緒時,就把該結果寫入該指令的目的寄存器,並從ROB
中刪除該指令。 store
指令:處理與上面類似,只是它把結果寫入存儲器。- 分支指令: 當預測錯誤的分支指令到達
ROB
隊列的頭部時,清空ROB
,並從分支指令的另一個分支重新開始執行。(錯誤的前瞻執行)當預測正確的分支指令到達ROB
隊列的頭部時,該指令執行完畢。
- 其它指令(除分支指令和
前瞻執行
- 通過
ROB
實現了指令的順序完成 - 能夠實現精確異常
- 很容易地推廣到整數寄存器和整數功能單元上。
- 主要缺點:所需的硬件太復雜
多指令流出技術
-
在每個時鍾周期內流出多條指令
CPI < 1
。 -
單流出和多流出處理機執行指令的時空圖對比:
多流出處理機有兩種基本風格:
- 超標量:
- 在每個時鍾周期流出的指令條數不固定,依代碼的具體情況而定。(存在一個上限)
- 設這個上限為
n
,就稱該處理機為n
-流出。 - 可以通過編譯器進行靜態調度,也可以基於
Tomasulo
算法進行動態調度。
- 超長指令字
VLIW
:- 在每個時鍾周期流出的指令條數是固定的,這些指令構成一條長指令或者一個指令包。
- 指令包中,指令之間的並行性是通過指令顯式地表示出來的。
- 指令調度是由編譯器靜態完成的。
超標量處理機與VLIW
處理機相比有兩個優點:
- 超標量結構對程序員是透明的,處理機能自己檢測下一條指令能否流出,不需要由編譯器或專門的變換程序對程序中的指令進行重新排列。
- 即使是沒有經過編譯器針對超標量結構進行調度優化的代碼或是舊的編譯器生成的代碼也可以運行,並且運行的效果不會很好。要想達到很好的效果,方法之一為使用動態超標量調度技術。
基於靜態調度的多流出技術
- 在典型的超標量處理器中,每個時鍾周期可流出
1
到8
條指令。 - 指令按序流出,在流出時進行沖突檢測。
舉例:一個4
-流出的靜態調度標量處理機
- 在取指令階段,流水線將從取指令部件收到\(1 \sim 4\)條指令(稱為流出包)。在一個時鍾周期內,這些指令有可能是全部都能流出,也可能是只有一部分能流出。
- 流出部件檢測結構出圖或者數據沖突。一般分兩階段實現:
- 第一階段:進行流出包內的沖突檢測,選出初步判定可以流出的指令。
- 第二階段:檢測所選出的指令與正在執行的指令是否有沖突。
MIPS
處理機是怎么實現超標量的?
假設每個時鍾周期流出兩條指令:1
條整數型指令+1
條浮點操作指令;其中,把load
指令、store
指令、分支指令歸類為整數型指令。
要求同時取兩條指令(64
位),譯碼兩條指令(64
位)。
對指令的處理包括以下步驟:
- 從
cache
中取兩條指令; - 確定那幾條指令可以流出
- 把他們發送到相應的功能部件。
雙流出超標量流水線中指令執行的時空圖
- 假設:所有的浮點指令都是加法指令,其執行時間為兩個時鍾周期
- 為簡單起見,圖中總是把整數指令放在浮點指令的前面。
采用1
條整數型指令+1
條浮點指令並行流出的方式,需要增加的硬件很少。
浮點load
或浮點store
指令將使用整數部件,會增加對浮點寄存器的訪問沖突。可以增設一個浮點寄存器的讀寫端口。
由於流水線中的指令多了一倍,定向路徑也要增加。
限制超標量流水線的性能發揮的障礙:
load
指令:load
后續3
條指令都不能使用其結構,否則就會引起停頓。- 分支延遲:如果分支指令是流出包中的第一條指令,則其延遲是
3
個時鍾周期;否則就是流出包中的第二條指令,其延遲就是兩個時鍾周期。
基於動態調度的多流出技術
- 擴展
Tomasulo
算法:支持雙流出超標量流水線,每個時鍾周期流出兩條指令;一條是整數指令,另一條是浮點指令。
采用一種比較簡單的方法:
- 指令按順序流向保留站,否則會破壞程序語義。
- 將整數所用的表結構與浮點用的表結構分離開,分別進行處理,這樣就可以同時地流出一條浮點指令和一條整數指令到各自的保留站。
有兩種不同的方法實現多流出,關鍵在於對保留站的分配和對流水線控制表格的修改:
-
在半個時鍾周期里完成流出步驟,這樣一個時鍾周期就能處理兩條指令。
-
設計一次能同時處理兩條指令的邏輯電路。
現代的流出
4
條或4
條以上指令的超標量處理機經常是兩種方法都采用。
超長指令字技術
能把並行執行的多條指令組裝成一條很長的指令;
設計多個功能部件
指令字被分割成一些字段,每個字段稱為一個操作槽,直接獨立地控制一個功能部件。
在VLIW
處理機中,在指令流出時不需要進行復雜的沖突檢測,而是依靠編譯器全部安排好了。
VLIW
存在的一些問題:
-
程序代碼長度增加了:提高並行性而進行的大量的循環展開,指令字中的操作槽並非總能填滿。
解決:采用指令共享立即數字段的方法,或者采用指令壓縮存儲調入
cache
或譯碼時展開的方法。 -
采用了鎖步機制:任何一個操作部件出現停頓時,整個處理機都要停頓。
-
機器代碼的不兼容性。
多流出處理器受到的限制
- 程序所固有的指令級並行性;
- 硬件實現上的困難;
- 超標量和超長指令字處理器固有的技術限制。
超流水線處理機
- 將每個流水段進一步細分,這樣在一個時鍾周期內能夠分時流出多條指令。這種處理機稱為超流水線處理機。
- 對於一台每個時鍾周期能流出
n
條指令的超流水計算機來說,這n
條指令不是同時流出的,而是每隔\(\frac{1}{n}\)個時鍾周期流出一條指令,實際上該超流水線計算機的流水線周期為\(\frac{1}{n}\)個時鍾周期。 - 一台每個時鍾周期分時流出兩條指令的超流水線計算機的時空圖。
- 在有的資料上,把指令流水線級數為
8
或8
以上的流水線處理機稱為超流水線處理機。