流水线问题--计算机体系结构
參考書:《計(jì)算機(jī)體系結(jié)構(gòu)量化研究方法》 作者:John L. Hennessy
一、 基本概念
先理解幾個(gè)基本概念:
流水線:是一種將多條指令重疊執(zhí)行的實(shí)現(xiàn)技術(shù)。一條指令的執(zhí)行需要多個(gè)操作,流水線技術(shù)充分利用了這些操作之間的并行性。
流水級(jí):不同步驟并行完成不同指令的不同部分。這些步驟中的每一步都稱為流水級(jí)或流水段
吞吐量:由指令退出流水線的頻率決定。
處理器周期:一條指令在流水線中下移一步所需要的時(shí)間。一個(gè)處理器周期通常為1個(gè)時(shí)鐘周期。(又是為2個(gè),但要少見的多)
流水線的作用:縮短每條指令的平均執(zhí)行時(shí)間。降低了每條指令時(shí)鐘周期數(shù)(CPI)
1.1 RISC精簡指令集基礎(chǔ)知識(shí)
以MIPS指令集為例,其提供了32個(gè)寄存器,通常由以下三類指令:
1)ALU指令:取兩個(gè)寄存器或者一個(gè)寄存器與一個(gè)符號(hào)擴(kuò)展立即數(shù)進(jìn)行運(yùn)算并存儲(chǔ)到第三個(gè)寄存器中
2)載入和存儲(chǔ)指令:這些指令獲取一個(gè)寄存器源(基址寄存器)和一個(gè)立即數(shù)字段(16位,偏移量),作為操作數(shù)計(jì)算有效地址用作存儲(chǔ)器地址。
3)分支與跳轉(zhuǎn):條件轉(zhuǎn)移。通常由兩種方式指定分支條件:其一,采用一組條件位(條件碼);其二通過兩個(gè)寄存器之間、寄存器與0之間的對(duì)比來設(shè)定。MIPS采用后者。
1.2 RISC指令集的簡單實(shí)現(xiàn)
RISC子集中的每條指令都可以在最多5個(gè)時(shí)鐘周期內(nèi)實(shí)現(xiàn),如下
1)指令提取周期(IF)
將程序計(jì)數(shù)器PC發(fā)送存儲(chǔ)器,從存儲(chǔ)器提取當(dāng)前指令。向程序計(jì)數(shù)器加4(因?yàn)槊織l指令的長度為4個(gè)字節(jié)),將程序計(jì)數(shù)器更新到下一個(gè)連續(xù)計(jì)數(shù)器。
此周期操作:a.讀取PC,b.更新PC
2)指令譯碼/寄存器提取周期(ID)
此周期操作:a.將指令譯碼,b.讀取相應(yīng)寄存器,c.判斷是否為分支
這幾點(diǎn)在下面都會(huì)有詳細(xì)解釋
3)執(zhí)行/有效地址周期(EX)
此周期操作(其中之一):a.計(jì)算有效地址(基址寄存器+偏移量)b.在寄存器與寄存器之間進(jìn)行運(yùn)算,c.在寄存器與立即數(shù)之間進(jìn)行運(yùn)算
4)存儲(chǔ)器訪問(MEM)
操作(執(zhí)行其中之一):a.將寄存器寫入存儲(chǔ)器(寫入)b.將存儲(chǔ)器的內(nèi)容讀取到寄存器中(載入)
5)寫回周期(WB)
將程序結(jié)果(來自ALU運(yùn)算或載入指令)寫入寄存器堆
1.3 RISC經(jīng)典五級(jí)流水線
下面這種情況沒有采用流水線結(jié)構(gòu),是簡單的順序執(zhí)行,在執(zhí)行完一個(gè)指令的五個(gè)周期后,才能執(zhí)行下一條指令,如圖所示:
這種方法存在著一個(gè)問題,比如參與運(yùn)算的ALU單元平均在五個(gè)周期種只被使用了一次,硬件資源造成的很大程度上的浪費(fèi)。于是我們采用了流水線結(jié)構(gòu),如下圖所示:
流水線結(jié)構(gòu)在每個(gè)時(shí)鐘周期都會(huì)啟動(dòng)一條指令,其性能會(huì)達(dá)到非流水化處理器的5倍(理想情況下)。比如ALU單元,在每一個(gè)時(shí)鐘周期都被用到了,相比于非流水化大大提高了硬件的利用率。IF ID EX MEM WB值得是指令集的5個(gè)時(shí)鐘周期。
可能很難相信流水線是這么地簡單,實(shí)際上,它的確不是這么簡單。
下圖是流水化形式的RISC數(shù)據(jù)路徑的簡化版本。如圖:
流水線可以看作一系列隨時(shí)間移動(dòng)的數(shù)據(jù)路徑。上圖給出了數(shù)據(jù)路徑不同部分之間的重疊,時(shí)鐘周期數(shù)5(CC5)表示穩(wěn)定狀態(tài),此狀態(tài)下,一個(gè)時(shí)鐘周期內(nèi),運(yùn)行著五條指令的不同部分。寄存器左側(cè)虛線表示寫入,右側(cè)虛線表示讀取。IM表示指令存儲(chǔ)器,DM表示數(shù)據(jù)存儲(chǔ)器,CC表示時(shí)鐘周期。
我們也可以看出來,主要功能單元(如ALU)是在不同周期使用的,因此多條指令的重疊執(zhí)行不會(huì)引發(fā)多少?zèng)_突(實(shí)際上,不可避免會(huì)存在些許沖突即冒險(xiǎn)問題,在后面會(huì)提到及其解決方案)。以下三點(diǎn)可以看出:
1)采用分離的指令存儲(chǔ)器及數(shù)據(jù)存儲(chǔ)器,并采用分離緩存的方式避免二者的訪問沖突。不過相應(yīng)開銷是:存儲(chǔ)器系統(tǒng)必須提供5倍的帶寬。
2)在兩個(gè)階段都使用了寄存器堆(MIPS中由32個(gè)寄存器):一是在ID中進(jìn)行讀取,一是在WB中進(jìn)行寫入。每次時(shí)鐘周期會(huì)執(zhí)行兩次讀取和一次寫入。我們?cè)跁r(shí)鐘的前半周期寫寄存器,后半周期讀寄存器
3)為了每個(gè)時(shí)鐘周期都會(huì)啟動(dòng)一條新指令,必須在IF階段增加一加法器,一邊為下一條指令做準(zhǔn)備。此外,我們會(huì)在ID期間計(jì)算潛在的分支目標(biāo)。
你會(huì)發(fā)現(xiàn)流水線最重要的就是:
1. 確保流水線中的指令不會(huì)試圖在相同時(shí)間使用硬件資源。
2. 不同流水級(jí)中的指令不會(huì)互相干擾
因此在連續(xù)流水級(jí)中引入了流水線寄存器,如圖所示
在流水化處理器中,如果要將中間結(jié)果從一級(jí)傳送到另外一級(jí),而源寄存器與目標(biāo)地址可能并非直接相鄰,這時(shí)候就是流水線寄存器發(fā)揮作用的時(shí)候了。例如:要在存儲(chǔ)指令中存儲(chǔ)的寄存器值是在ID期間進(jìn)行讀取的,但要等到MEM才會(huì)真正用到;他在MEM級(jí)中通過兩個(gè)流水線寄存器傳送到數(shù)據(jù)寄存器。于此類似,ALU指令的結(jié)果是在EX期間計(jì)算的,但要等到WB才會(huì)實(shí)際存儲(chǔ);
所以有必要對(duì)每個(gè)寄存器進(jìn)行命名,稱為:IF/ID,ID/EX,EX/MEM,MEM/WB。
流水化作用:提高了CPU指令吞吐量(單位時(shí)間內(nèi)完成的指令數(shù))。但不會(huì)縮短單條指令的執(zhí)行時(shí)間。實(shí)際上它還會(huì)產(chǎn)生額外的開銷
流水線開銷:流水線寄存器延遲和時(shí)鐘偏差。
二、 流水化冒險(xiǎn)
上面介紹的流水線,我們假定指令之間都沒有相互依賴關(guān)系。可實(shí)際上,流水線中的指令可能是存在依賴關(guān)系的。
若產(chǎn)生了依賴關(guān)系,再按照之前無停頓的順序執(zhí)行,就會(huì)產(chǎn)生冒險(xiǎn)問題。有以下三種冒險(xiǎn):
1)結(jié)構(gòu)冒險(xiǎn):比如兩個(gè)指令都要訪問存儲(chǔ)器端口,可存儲(chǔ)器只有一個(gè)寫端口,這咋辦?這時(shí)候就產(chǎn)生了資源沖突即結(jié)構(gòu)冒險(xiǎn)。
2)數(shù)據(jù)冒險(xiǎn):實(shí)際上,指令是存在一些先后順序的,如果一些指令取決于先前的指令的結(jié)果,就可能導(dǎo)致數(shù)據(jù)冒險(xiǎn)。
3)控制冒險(xiǎn):比如C語言中的if else語句,分支指令及其他改變程序計(jì)數(shù)器的指令實(shí)現(xiàn)流水化時(shí)可能會(huì)導(dǎo)致控制冒險(xiǎn)。
這三種冒險(xiǎn)總結(jié)如下表所示:
2.1 結(jié)構(gòu)冒險(xiǎn)
出現(xiàn)原因:
如CC4階段,同時(shí)對(duì)存儲(chǔ)器進(jìn)行了引用,如果只有一個(gè)存儲(chǔ)器端口,就會(huì)產(chǎn)生沖突。
當(dāng)指令序列遇到這種冒險(xiǎn)時(shí),流水線將會(huì)使這些指令中的一個(gè)停頓,直到所需單元可用為止。這種停頓會(huì)增大CPI的值,使其不再是理想的1。我們把這些停頓稱為流水線氣泡或氣泡。解決流圖如下:
載入指令強(qiáng)占了指令提取周期,導(dǎo)致流水線停頓。雖然浪費(fèi)了流水線中的一個(gè)時(shí)鐘周期,但避免了沖突。
2.2 數(shù)據(jù)冒險(xiǎn)
舉個(gè)栗子,以下指令:
DADD R1,R2,R3 ;R1=R2+R3 DSUB R4,R1,R5 ;R4=R1-R5 AND R6,R1,R7 OR R8,R1,R9 XOR R10,R1,R11DADD之后的指令都用到了DADD指令的結(jié)果。如圖所示:
DADD在WB流水級(jí)中寫入R1的值,但DSUB在其ID中就要讀取這個(gè)值,這個(gè)問題稱為數(shù)據(jù)冒險(xiǎn)。因?yàn)楹竺嫒龡l指令中使用DADD指令的結(jié)果時(shí),由于要等到這些指令讀取寄存器之后才會(huì)向其中寫入,所以會(huì)導(dǎo)致冒險(xiǎn)。
2.2.1 轉(zhuǎn)發(fā)技術(shù)
這一問題,可以采用轉(zhuǎn)發(fā)(forwarding)的簡單硬件來解決(也稱為旁路或短路)。此技術(shù)關(guān)鍵是:認(rèn)識(shí)到DSUB要等到DADD實(shí)際生成結(jié)果之后才會(huì)真正用到它。DADD將此結(jié)果放在流水線寄存器中,然后轉(zhuǎn)發(fā),轉(zhuǎn)發(fā)工作方式如下:
1)來自EX/MEM和MEM/WB流水線寄存器的ALU結(jié)果總是被反饋回ALU的輸入端
2)如果轉(zhuǎn)發(fā)硬件檢測到前一個(gè)ALU操作對(duì)當(dāng)前ALU操作的源寄存器進(jìn)行了寫入操作,則控制邏輯選擇轉(zhuǎn)發(fā)結(jié)果作為ALU的輸入,而不是從寄存器堆中讀取。
如圖所示:
這種情況不需要停頓,但是并非所有的數(shù)據(jù)冒險(xiǎn)都可以通過轉(zhuǎn)發(fā)解決。這就是下面提到的需要停頓的數(shù)據(jù)冒險(xiǎn)
2.2.2 需要停頓的數(shù)據(jù)冒險(xiǎn)
LD R1,0(R2) DSUB R4,R1,R5 AND R6,R1,R7 OR R8,R1,R9這個(gè)例子與上面的不同在于,上面的指令是ALU運(yùn)算指令,其在EX階段就能產(chǎn)生結(jié)果,但是載入指令LD就不能在當(dāng)前周期產(chǎn)生結(jié)果,其必須在MEM周期得到結(jié)果。因此就沒辦法僅通過轉(zhuǎn)發(fā)技術(shù)就消除這一冒險(xiǎn)。我們需要增加一種稱為流水線互鎖以保持正確的執(zhí)行模式。
流水線互鎖會(huì)導(dǎo)致流水線停頓,讓需要使用某一數(shù)據(jù)的指令等待,直到源指令生成該數(shù)據(jù)為止。這種流水線互鎖會(huì)引入一次停頓或者氣泡。如圖:
2.3 分支冒險(xiǎn)(控制冒險(xiǎn))
對(duì)于MIPS流水線,控制冒險(xiǎn)造成的性能損失可能比數(shù)據(jù)冒險(xiǎn)還要大。在執(zhí)行分支時(shí),修改后的程序計(jì)數(shù)器的值可能等于也可能不等于當(dāng)前值加4。介紹一個(gè)概念:
選中分支:如果分支將程序計(jì)數(shù)器改為其目標(biāo)地址,就代表選中分支,否則就是未選中位置。比如指令i是選中分支,通常會(huì)等到ID末尾,完成地址計(jì)算和對(duì)比之后才會(huì)改變程序計(jì)數(shù)器。
處理分支最簡單的方法是:在ID期間(此時(shí)對(duì)指令進(jìn)行譯碼)檢測到分支,就對(duì)分支之后的指令重新取值。第一個(gè)IF周期基本上就是一次停頓,因?yàn)樗鼜膩聿粫?huì)執(zhí)行有用工作。如圖所示:
如果每個(gè)分支產(chǎn)生一個(gè)停頓,竟會(huì)使性能損失10%-20%,具體取決于分支頻率,所以要研究一些用于應(yīng)對(duì)這一損失的技術(shù)。
有多種方法可以處理由分支延遲導(dǎo)致的流水線停頓,我們討論四種簡單的編譯機(jī)制。我也很好奇它為啥會(huì)有這么多解決方案???
2.3.1 凍結(jié)或沖刷流水線
保留或刪除分支之后的所有命令,直到知道目標(biāo)分支為止。這也是上圖的解決方案。這種情況下,開銷是固定的,不能通過軟件來縮減。
2.3.2 預(yù)測未選中機(jī)制
繼續(xù)提取指令。將每一條分支都看作未選中分支,允許硬件繼續(xù)執(zhí)行,就好像分支未被執(zhí)行一樣。如果分支被選中,就需要將已經(jīng)提取的指令轉(zhuǎn)為空操作,重新開始在目標(biāo)地址提取指令。但這時(shí)候必須特別小心,因?yàn)樵诖_切知道分支輸入之前,不要改變處理器狀態(tài)。復(fù)雜性在于:必須知道處理器狀態(tài)可能何時(shí)被指令改變,以及如何撤銷這種改變。實(shí)現(xiàn)過程如圖所示:
2.3.3 預(yù)測選中機(jī)制
將所有分支都看作選中分支。只要對(duì)分支指令進(jìn)行了譯碼并計(jì)算了目標(biāo)地址,我們就假定該分支被選中,開始在目標(biāo)位置提取和執(zhí)行。
2.3.4 延遲分支
這種技術(shù)在RISC處理器種使用的非常廣泛。在延遲分支種,帶有一個(gè)分支延遲的執(zhí)行周期為:
分支指令
依序后續(xù)指令
選中時(shí)的分支目標(biāo)
依序后續(xù)指令位于分支延遲的間隔中。無論分支是否被選中,這一指令都會(huì)執(zhí)行。我們要做的任務(wù)就是讓這些必須進(jìn)行的指令有效且可用。首先看一下延遲分支的行為特性。
盡管分支延遲可能長于1個(gè)時(shí)鐘周期,但在實(shí)際中,幾乎所有具有延遲的分支的處理器都會(huì)只有單個(gè)指令延遲。為了讓這些指令延遲有效并可用,使用了多種優(yōu)化方式,如下:
延遲分支的局限性在于
a. 對(duì)于可排在延遲時(shí)隙中的指令有限制
b. 在編譯時(shí)預(yù)測分支是否可能被選中的能力有限。
這種優(yōu)化也都引入了一種取消或廢除分支。在取消分支中,指令包含了預(yù)測分支的方向。當(dāng)分支的行為與預(yù)期一致時(shí),分支延遲時(shí)隙中的指令就像普通的延遲分支一樣執(zhí)行。不過也有可能把分支預(yù)測錯(cuò)誤,此時(shí),分支延遲時(shí)隙中的指令轉(zhuǎn)為空操作。
這四種方法的不同是:
凍結(jié)或沖刷流水線導(dǎo)致對(duì)分支后續(xù)指令重新取值。此時(shí)會(huì)有一周期停頓;
預(yù)測選中或未選中機(jī)制,導(dǎo)致選中分支目標(biāo)后續(xù)指令變?yōu)榭詹僮鳌?/p>
延遲分支機(jī)制繼續(xù)執(zhí)行,不過采用調(diào)度,使其執(zhí)行的指令盡可能有用。如果調(diào)度錯(cuò)誤會(huì)將該分支轉(zhuǎn)為空操作。
三、流水化的實(shí)現(xiàn)
3.1 MIPS的簡單實(shí)現(xiàn)
首先給出一種簡單的非流水化實(shí)現(xiàn),然后介紹流水化實(shí)現(xiàn)
每種MIPS指令都可以在最多5個(gè)時(shí)鐘周期中實(shí)現(xiàn),分述如下:
1)指令提取周期(IF)
Mem[PC] ==> IR
PC + 4 ==> NPC
操作:送出PC到IR中,將PC遞增4。IR保存將在后續(xù)時(shí)鐘周期中需要的指令。NPC用于保存下一順序PC
2)指令譯碼/寄存器提取周期(ID)
Reg[rs] == > A
Reg[rt] == > B
IR的符號(hào)擴(kuò)展立即數(shù)字段==> Imm
操作:對(duì)該指令進(jìn)行譯碼,并訪問寄存器堆(rs,rt為源寄存器)放到臨時(shí)寄存器A和B中,IR的低16位也進(jìn)行了符號(hào)擴(kuò)展,并存儲(chǔ)到臨時(shí)寄存器Imm中,供下一個(gè)周期使用。
3)執(zhí)行/有效地址周期(EX)
ALU對(duì)前一周期準(zhǔn)備的操作數(shù)進(jìn)行操作,根據(jù)MIPS指令類型執(zhí)行以下4中功能之一
存儲(chǔ)器引用
A + Imm ==> ALUOUTPUT
操作:ALU將操作數(shù)相加,得到實(shí)際地址,并將結(jié)果放在ALUOUTPUT中
寄存器-寄存器ALU指令
A func B ==> ALUOUTPUT
操作:對(duì)A,B中的取值執(zhí)行由功能代碼指定的操作,將結(jié)果放在ALUOUTPUT中
寄存器-立即數(shù)ALU指令
A op Imm ==> ALUOUTPUT
操作:對(duì)A,Imm中的取值執(zhí)行由操作代碼指定的操作,將結(jié)果放在ALUOUTPUT中
分支
NPC + (Imm << 2)==> ALUOUTPUT
(A == 0) ==> Cond
操作:ALU將NPC加到Imm中的符號(hào)擴(kuò)展立即數(shù),將立即數(shù)左移2位,得到一個(gè)字偏移量,以計(jì)算分支目標(biāo)。Cond為0是分支的標(biāo)志。
4)存儲(chǔ)器訪問(MEM)
對(duì)所有的指令更新PC:NPC ==> PC
存儲(chǔ)器引用
Mem[ALUOUTPUT] ==> LMD 或
B ==> Mem[ALUOUTPUT]
操作:訪問寄存器。如果指令為載入指令,則從存儲(chǔ)器返回?cái)?shù)據(jù),將其放入LMD(載入存儲(chǔ)器數(shù)據(jù))寄存器中。其都需要在ALUOUT存放的ALU計(jì)算得到的實(shí)際地址。
分支
If (cond) ALUOUTPUT ==> PC
操作:如果指令為分支指令,則用寄存器ALUOUTPUT中的分支目標(biāo)地址代替PC
5)寫回周期(WB)
寄存器-寄存器ALU指令
ALUOUTPUT ==> Regs[rd]
寄存器-立即數(shù)ALU指令
ALUOUTPUT ==> Regs[rt]
載入指令
LMD ==> Regs[rt]
操作:無論結(jié)果來自存儲(chǔ)器系統(tǒng)(在LMD中)還是ALU,都將其寫到寄存器堆中。
此中,rs,rt為兩個(gè)源寄存器,rd為目的寄存器。
同時(shí)出現(xiàn)一個(gè)問題,在寫回周期的載入指令中,為什么非要通過LMD才能寫回寄存器呢?看下面這個(gè)數(shù)據(jù)流圖就明白了:
因?yàn)榇鎯?chǔ)器數(shù)據(jù)只能容國LMD存儲(chǔ)至寄存器堆
此中,mux為多工器即數(shù)據(jù)選擇器。
3.2 MIPS基本流水線
上圖為順序結(jié)構(gòu),我們幾乎不需要什么改變就可以對(duì)上圖的數(shù)據(jù)路徑實(shí)現(xiàn)流水線。如圖:
流水線寄存器用于從一個(gè)流水級(jí)向下一個(gè)流水級(jí)傳送數(shù)據(jù)和控制。每個(gè)流水級(jí)上的事件如下:
注意:前兩級(jí)的操作與當(dāng)前指令類型無關(guān)。由于要等到ID級(jí)結(jié)束時(shí)才會(huì)對(duì)指令進(jìn)行譯碼,所以前兩級(jí)操作必須與當(dāng)前指令無關(guān)。IF行為取決于EX/MEM中的指令是否為選中分支。如果是,則會(huì)在IF結(jié)束時(shí)將EX/MEM中的分支指令的目標(biāo)地址寫入PC中,如果不是,則寫回遞增后的PC.
分析一下多工器的作用:
ALU級(jí)的兩個(gè)多工器根據(jù)指令類型設(shè)定,由ID/EX寄存器的IR字段規(guī)定。上面的ALU輸入多工器根據(jù)該指令是否為分支來設(shè)定,下面的多工器根據(jù)指令時(shí)寄存器-寄存器操作,還是ALU操作還是任意其他類型的操作來設(shè)定的。IF級(jí)的多工器選擇是遞增PC的值,還是EX/MEM.ALUOUTPUT的值來寫入PC。這個(gè)多工器由EX/MEM.Cond字段控制。第四個(gè)多工器由WB級(jí)的指令是載入指令還是ALU指令來控制。
3.3 處理分支問題
在MIPS中,分支需要對(duì)比兩個(gè)寄存器的值,在ID周期結(jié)束時(shí)完成此判斷。為了充分利用盡早判斷出該分支是否命中懂得優(yōu)勢,都必須盡早計(jì)算PC。在ID期間計(jì)算分支目標(biāo)地址需要一個(gè)加法器。下圖為修改后額流水化數(shù)據(jù)路徑。
增加獨(dú)立的加法器在ID期間做出分支判斷,分支僅需要停頓1個(gè)時(shí)鐘周期
四、交叉問題/記分卡
如果存在不可避免地冒險(xiǎn),冒險(xiǎn)檢測硬件會(huì)使流水線停頓。在清除這種相關(guān)性之前,不會(huì)提取或發(fā)射指令。為了彌補(bǔ)這些性能地?fù)p失,編譯器嘗試調(diào)度指令來避免冒險(xiǎn);這種方法稱為編譯器調(diào)度或靜態(tài)調(diào)度。
目前為止,討論的所有技術(shù)都是使用循序指令發(fā)射,無調(diào)度,這意味著如果一條指令在流水線中停頓,將不能處理后續(xù)指令。在采用循序發(fā)射時(shí),如果兩條指令之間存在冒險(xiǎn),即使后面存在一些不相關(guān)的、不會(huì)停頓的指令,流水線也會(huì)停頓。
在流水線中,結(jié)構(gòu)性冒險(xiǎn)和數(shù)據(jù)冒險(xiǎn)都是在指令譯碼ID期間進(jìn)行檢查的:當(dāng)一條指令可以正確執(zhí)行時(shí),也是從ID發(fā)射出去的。我們必須將發(fā)射過程分為兩部分:檢查結(jié)構(gòu)性冒險(xiǎn)以及等待數(shù)據(jù)冒險(xiǎn)的消失。循序?qū)χ噶钸M(jìn)行譯碼和發(fā)射;但是,我們希望指令在其數(shù)據(jù)操作數(shù)可用是立即開始執(zhí)行。因此流水線是亂序執(zhí)行的,也就暗示是亂序完成的。為了實(shí)現(xiàn)亂序執(zhí)行,我們必須將ID流水級(jí)分為兩級(jí)。
1)發(fā)射:指令譯碼,檢查結(jié)構(gòu)性冒險(xiǎn)
2)讀取操作數(shù):等到?jīng)]有數(shù)據(jù)冒險(xiǎn),隨后讀取操作數(shù)
采用計(jì)分卡的動(dòng)態(tài)調(diào)度
在動(dòng)態(tài)調(diào)度流水線中,所有指令都是循序通過發(fā)射級(jí);但是,它們可能在第二級(jí)讀取操作數(shù)級(jí)停頓,或者繞過其他指令,然后進(jìn)行亂序執(zhí)行狀態(tài)。記分卡技術(shù)再有足夠的資源、沒有數(shù)據(jù)依賴時(shí),允許指令亂序執(zhí)行。這一功能是在CDC 6600記分卡中開發(fā)的,因此而得名。
在介紹記分卡之前先介紹一種亂序執(zhí)行可能會(huì)出現(xiàn)的寫后讀(WAR)數(shù)據(jù)冒險(xiǎn)問題,這在之前循序執(zhí)行指令時(shí)是不會(huì)出現(xiàn)的,情況如下:
DIV.D FO,F2,F4 ADD.D F10,F0,F8 SUB.D F8,F8,F14ADD.D和SUB.D之間存在一種反相關(guān)性:意思就是如果亂序執(zhí)行時(shí)先執(zhí)行了SUB.D就會(huì)導(dǎo)致ADD.D數(shù)據(jù)錯(cuò)誤,這就是讀后寫問題。于此類似,為避免違反輸出相關(guān)性,也必須檢查寫后寫WAW問題。而記分卡通過停頓反相關(guān)中設(shè)計(jì)的后續(xù)指令,避免了兩種冒險(xiǎn)。
記分卡目標(biāo):通過盡早執(zhí)行指令,保持每時(shí)鐘周期1條指令的執(zhí)行速率。
記分卡負(fù)責(zé):指令的發(fā)射與執(zhí)行,包括所有的冒險(xiǎn)檢測任務(wù)
要充分利用亂序執(zhí)行,需要在其EX級(jí)中同時(shí)有多條指令。這一點(diǎn)可以通過多個(gè)功能單元、流水化功能單元或同時(shí)利用兩者來實(shí)現(xiàn)。
CDC6600擁有16個(gè)獨(dú)立的功能單元,包括4個(gè)浮點(diǎn)單元5個(gè)存儲(chǔ)器引用單元和7個(gè)整數(shù)運(yùn)算單元。如圖:
記分卡的功能時(shí)控制指令執(zhí)行。如上圖:共有兩個(gè)浮點(diǎn)乘法器、一個(gè)浮點(diǎn)除法器、一個(gè)浮點(diǎn)加法器和一個(gè)整數(shù)單元。一組總線(兩個(gè)輸入和一個(gè)輸出)充當(dāng)一組功能單元。
每條指令進(jìn)入記分卡,都會(huì)構(gòu)建一條數(shù)據(jù)相關(guān)性記錄;并由記分卡判斷指令什么時(shí)候能夠讀取它的操作數(shù)并開始執(zhí)行。
在詳細(xì)介紹記分卡之前,我們需要知道每條指令都需要經(jīng)歷四個(gè)執(zhí)行步驟:
1)發(fā)射,如果指令的功能單元空閑,并且不存在冒險(xiǎn)時(shí),記分卡向功能單元發(fā)射指令,并更新內(nèi)部數(shù)據(jù)結(jié)構(gòu)。如果存在結(jié)構(gòu)性冒險(xiǎn)或WAW冒險(xiǎn),則指令發(fā)射停頓,在清除這些冒險(xiǎn)之前,不會(huì)再發(fā)射其他指令。當(dāng)發(fā)射級(jí)停頓時(shí),會(huì)導(dǎo)致指令提取與發(fā)射之間的緩沖區(qū)填滿;如果緩沖區(qū)是擁有多條指令的隊(duì)列,則在隊(duì)列填滿后停頓。
2)讀取操作數(shù),記分卡見時(shí)源操作數(shù)的可用性。源操作數(shù)可用時(shí),記分卡告訴功能單元繼續(xù)從寄存器讀取操作數(shù),并開始執(zhí)行。記分卡在這一步動(dòng)態(tài)解決RAW問題,可以發(fā)送指令以進(jìn)行亂序執(zhí)行
3)執(zhí)行,功能單元接收到操作數(shù)開始執(zhí)行。結(jié)果準(zhǔn)備就緒后,通知記分卡已經(jīng)完成執(zhí)行
4)寫結(jié)果,記分卡知道功能單元已經(jīng)完成執(zhí)行,則檢查WAR冒險(xiǎn),并在必要時(shí)停頓正在完成的指令。
一般來說,存在以下情況時(shí),不能允許一條正在執(zhí)行的指令寫入其結(jié)果:
a. 在正在執(zhí)行的指令前邊有一條指令還沒有讀取其操作數(shù)(WAR數(shù)據(jù)冒險(xiǎn))
b. 這些操作數(shù)之一與正在執(zhí)行指令的結(jié)果是同一寄存器(WAW數(shù)據(jù)冒險(xiǎn))
記分卡究竟是怎么執(zhí)行的呢?看一個(gè)例子:
L.D F6,34(R2) L.D F2,45(R3) MUL.D F0,F2,F4 SUB.D F8,F6,F2 DIV.D F10,F0,F6 ADD.D F6,F8,F2記分卡中的信息如下
記分卡共有3個(gè)部分:
1)指令狀態(tài):指出指令位于4個(gè)步驟中的哪一步
2)功能單元狀態(tài):指出功能單元FU的狀態(tài),共有9個(gè)字段
忙:指示該單元是否繁忙。
Op:在此單元中執(zhí)行的運(yùn)算,如加減
Fi:目標(biāo)寄存器
Fj,Fk:源寄存器標(biāo)號(hào)
Qj,Qk:生成源寄存器Fj、Fk的功能單元
Rj,Rk:只是Fj,Fk已準(zhǔn)備就緒尚未讀取的標(biāo)記。在讀取操作數(shù)后將其設(shè)置為否
3)寄存器結(jié)果狀態(tài):如果一條活動(dòng)指令以該寄存器為目標(biāo)寄存器,則指出哪個(gè)功能單元將寫入寄存器。只要沒有向該寄存器寫入的未完成指令,則將此字段設(shè)置為空。
再說明一下每個(gè)執(zhí)行步驟中記分卡都需要做些什么:
記分卡利用ILP(指令級(jí)并行),在最大程度上降低因?yàn)槌绦驍?shù)據(jù)相關(guān)導(dǎo)致的停頓數(shù)目。在消除停頓方面,記分卡受以下幾個(gè)因素的影響。
1)指令間可用并行數(shù):這一因素決定了能否找到要執(zhí)行的獨(dú)立命令
2)記分卡的項(xiàng)數(shù):這一因素決定了流水線為了查找不相關(guān)命令可以向前查找多少條指令。這組作為潛在執(zhí)行對(duì)象的指令被稱為窗口。記分卡的大小決定了窗口的大小。
3)功能單元的數(shù)目和類型:這一因素決定了結(jié)構(gòu)性冒險(xiǎn)的重要性,他可能會(huì)在使用動(dòng)態(tài)調(diào)度是增加。
4)存在反相關(guān)和數(shù)據(jù)相關(guān):它們會(huì)導(dǎo)致WAR和WAW停頓。
啊!睡個(gè)好覺!
總結(jié)
以上是生活随笔為你收集整理的流水线问题--计算机体系结构的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 暗黑2敲石头什么意思 《暗黑破坏神
- 下一篇: scum撬棍怎么做