5.5 CPU指令流水線
一. 流水線
-
流水線
(1)流水線:
指令從取值到真正執行的過程划分成多個小步驟,cpu真正開始執行指令序列時,一步壓一步的執行,減少其等待時間。
(2)流水線級數越多,工作效率越高。intel處理器的流水線級數遠超過嵌入式cpu的流水線級數
(3)流水線的效率:
a. 並非指令每一步的操作時間都是等長的。長節拍的步驟會導致流水線效率下降(短節拍的步驟要等待長節拍的步驟執行完畢)
b. 解決辦法:
i. 拆分長節拍
ii. 增加長節拍的處理單元:使得同時間產生多個長節拍的執行結果,供短節拍的動作使用。
eg:長節拍是短節拍執行時間的3倍,則可以增加為3個長節拍執行單元,1個短節拍執行單元 -
ARM7的三級流水線:
ARM7把知道指令執行的時間分為3個步驟:取指IF,譯碼ID,執行EX
-
經典的MIPS5級流水線
(1)處理器內部有很多程序員可見的 通用寄存 器,這些通用寄存器組成了寄存器堆register file
(2)為了讓不同流水線之間的數據不會互相打擾,cpu在每個階段會把通用寄存器中的值拷貝到流水線寄存器中,使得各個節拍的工作不會亂序。
(3)匯編語言中,ALU執行單元直接訪問通用寄存器,而在硬件實現中,通用寄存器的值先拷貝到ALU輸入寄存器中(一個流水線寄存器),然后再送回通用寄存器
(4)MIPS在3級流水線的基礎上,增加了2個階段,1個是從內存獲取數據的mem階段,另一個是把ALU計算后的數據導出到通用寄存器堆的WB階段
IF -> ID -> EX -> MEM -> WB
-
DSP對三級流水線的深層次擴展
(1)DSP處理器把取指,譯碼,執行的三大步驟細分為多個小步驟
(2)MIPS處理器把MEM和ALU計算放在不同階段,寫回通用寄存器也單獨形成一個階段。而DSP把MEM和WB階段都放在了指令執行階段,更符合程序員的視角。
三. 流水線思想的冒險
-
結構冒險:不同階段的執行步驟由於硬件資源沖突不能同時進行
MIPS處理器的流水線中,IF階段需要訪問存儲器拿指令,MEM階段需要訪問存儲器拿數據,這兩個動作都要訪問存儲器,造成存儲器和寄存器之間的總線沖突,而不能同時進行。但是,現代處理器,程序被存儲在L1P Cache中,數據被存在L1D Cache中,所以不會沖突。
-
數據冒險
(1)流水線使得原先有先后順序的指令同時處理,當出現某些指令組合時,可能會導致使用了錯誤的數據。
(2)因此,cpu采用直通(forwarding)來解決:如果當前指令的源操作數在EX/MEM的流水線寄存器中,就直接將流水線寄存器中的值傳遞給ALU輸入,不去通用寄存器堆取值
(3)但不是所有數據沖突都能采用直通解決,要配置cycle等待
sub指令的R1,最早也要在cycle4中才能到MEM/EX流水線寄存器,所以仍要掩飾一個周期 -
控制冒險:
(1)當一條流水線中的指令出現跳轉操作時,其他流水線提前做出的操作是根據pc+1進行取指的,跳轉操作使得這些流水線上的操作全部無效
(2)流水線等級越深,跳轉指令造成的效率下降約嚴重
四. 流水線的分支預測
- 1-bit預測算法:
如果該指令上次發生跳轉,則預測這一次也會發生跳轉 -
2-bit預測算法:
每個指令的預測狀態信息從1bit加到2bit,如果這個跳轉執行了,就+1,加到3就不加了,如果跳轉信息不執行就-1,減到0就不減了。如果計數器值為0/1,就預測不執行,計數器為2/3,就預測執行。 -
Intel的分支預測實現
(1)前面2個是算法思想,Intel在此基礎上進行了一系列的設計。Intel分支預測包含3個單元:Branch Target Buffer(BTB),The Static Predictor,Return Stack
五. 指令的亂序執行
-
亂序執行
指令在執行時,常常因為一些限制而等待。例如,MEM階段訪問的數據不在cache中,需要從外部存儲器獲取,這個動作需要幾十個cycle,如果順序執行,后面的指令MEM都要等待這個指令操作完成。亂序執行是說,先執行后面不依賴該數據的指令。 -
指令相關性
(1)寄存器相關:當2條指令公用寄存器時,他們就有可能相關。
a. 先讀后讀ADD BX,AX ADD CX,AX #2條指令先后讀取AX寄存器
b. 先寫后讀 (RAW:Read after Write)
ADD BX,AX ADD CX,BX #后面的指令依賴前面的指令。先寫BX,后讀BX,指令間存在數據流動
c. 先讀后寫 (WAR:Write after read)
ADD BX,AX MOV AX,CX #指令1讀AX,指令2寫AX,邏輯上本沒有相關性,但X86cpu的寄存器太少,指令要公用寄存器,導致指令相關
d. 先寫后寫(WAW)
MOV AX,BX MOV AX,CX #輸出到同一個寄存器
【注】:WAR和WAW在2條指令間沒有數據流動,被稱為偽相關。
-
控制相關:
前一條指令是跳轉指令,而后一條指令的執行需要跳轉指令的結果,這就是控制相關
三. 去除指令相關
-
去除數據相關
去除數據相關的動作不是由cpu進行的,而是由編譯器和程序員進行處理的x = a + b y = x + c z = y + d // x,y,z產生深度相關 // 改造后 x = a + b y = b + c z = x + y // 此時去除了x,y間的相關性
-
去除控制相關
投機執行:cpu會根據跳轉預測的結果,可能會提前把跳轉后的指令放到跳轉指令前面執行,是一種預測的投機行為。現代分支預測的准確性能達到98%以上,所以可以一定程度上去除控制相關 -
去除偽相關:WAW,WAR
(1)處理器的ISA寄存器數目通常較少(暴露給程序員的寄存器),因此會導致多個變量映射到同一個寄存器中,這樣即使指令邏輯上是不相關的,也會因為使用了同一個寄存器而產生相關。
(2)通過把相同的ISA寄存器,映射到不同的物理寄存器來解決偽相關(名字相關)
(3)映射策略:- 將每條指令的目的寄存器映射到新的物理寄存器
- 將指令的源寄存器映射到ISA寄存器最近映射到的那個物理寄存器上
- 本條指令執行后,該目的寄存器映射的更早的物理寄存器就可以釋放了
- 一開始R1,R2,R3,R4分別映射到F1,F2,F3,F4寄存器
- 第一條指令R3是目的寄存器,映射到新物理寄存器F5
- 這種方式會把物理寄存器用光,所以每次映射完畢都要實時釋放:R4寄存器開始映射到F4寄存器,指令2結束后,R4映射到F6寄存器,此時,原先的F4寄存器就可以釋放了
四.CPU如何進行亂序執行
-
Buffer
CPU內部要提供能夠緩存多條指令的Buffer,才能達到亂序執行的效果 -
指令調度
(1)指令有操作數和操作碼,操作碼描述指令做什么(cpu分配什么樣的執行單元);而寄存器重命名后,目的寄存器總是新的,所以指令能否執行,和目的操作數已經無關,和操作碼和源操作數有關
(2)指令可以被執行的2個條件,除了這2個條件,指令不用再等待前面的指令執行完畢- cpu中是否有空閑的執行單元執行這條指令(操作碼)
- 該指令的源操作數是否已經准備好
-
指令結果順序提交
(1)指令執行順序雖然是亂序的,但是指令結果的提交順序一定要是順序的。因為“精確中斷”的存在
(2)精確中斷:指令執行過程中,來了一個中斷,此時cpu要將ISA寄存器壓棧,執行中斷服務程序,然后執行中斷后面的指令。而精確中斷要求終端錢的指令全部執行,中斷后的指令一個都不執行。而在亂序執行內核中,終端后面的指令可能放在中斷前面的指令執行
(3)所以,cpu引入重排序緩沖區,用來緩沖指令的執行結果,這些結果會被順序的提交到寄存器中,來實現精確中斷。
五. 處理器並行架構
-
Flynn分類
1966年,Flynn將處理器系統結構分成4類
(1)SISD:處理器有一次處理一條指令,每條指令處理一份數據 (single instruction single data)
(2)SIMD:一次處理一條數據,一條指令可以處理多分數據(數據並行)
(3)MISD:一次處理多條指令,每條指令處理一份數據(此設計無用)
(4)MIMD:一次處理多條指令,每條指令可以處理多分數據 -
指令並行
(1)發射單元一次發射多條指令,就能達到指令並行(multi issue)
(2)multi-issue的2種方式
i. SuperScalar:超標量(硬件)
a. 超標量是cpu內部增加一個硬件單元,負責把穿行指令輸入進行並行化處理。
b. 奔騰4采用超標量進行指令並行
ii. VLIW:超長指令字(軟件)
a. 超長指令字是編譯器或程序員在匯編語言中聲明多條指令要在一個cycle內執行。||符號鏈接2條指令
b. TI C6000 DSP采用超長指令字進行指令並行
(3)超標量由於需要增加電路設計,增大了功耗,超標量在執行階段制定並行。x86為了保證程序兼容性,不能不采用超標量,而后來的RISC處理器,則可以采用超長指令字VIEW結構
(4)並行性上來講,VIEW更勝一籌,因為他從源頭實現了指令並行,擅長於數據密集型運算。但發生cache miss,執行跳轉時,VIEW無能為力,采用亂序執行+超標量處理器則能將后面的指令提前執行,因此亂序+超標量適合負責的控制類程序。 -
數據並行
(1)多媒體程序有一個特點:同一個操作應用於多個數據,於是SIMD產生出來
(2)Intel的MMD,SSE2,SSE3,SSE4.1,SSE4.2,AVX指令集都是SIMD的。AMD的3DNOW!,SSE5指令集也是SIMD
(3)MMX指令一次可處理64bit數據,SSX指令一次可處理128bit數據
(4)幾種不同的SSE指令
(a) 垂直計算
SSE指令把需要操作的2個寄存器中的數划分成對應的幾個段,2個寄存器對應段中的數據進行操作
(b) 水平計算
2個源操作數來自於同一個寄存器
(c) 標量計算
a. 類似於垂直計算的2個寄存器分段,不同的是標量計算可以只計算2個寄存器中對應的1個段,而其他段保持不變
b. 如下,只有x0和y0進行操作,而其他段保持不練
-
線程並行
(1)軟件多線程:時分復用操作系統
(2)硬件多線程
(a) 粗粒度硬件多線程:
當處理器發現一個線程被長時間阻塞,eg:cache miss,發射器就發射另一個線程的指令
(b) 細粒度硬件多線程
處理器每個cycle發送不同線程的指令
(c) 同時多線程
超標量處理器同一時間可以發送多條指令,這些指令來自於不同線程
(3)多核處理器架構
i. p:processor處理核心,c:cache緩存,s:switch用於核間通信。線條表示通信路徑
ii. Bus Multicore結構多核:設計簡單,但任意兩個核心通信都要占用總線,導致其他核心不能通信,降低效率。 iii. Swich Multicore結構多核:任意兩個核心間右獨立的通信連線。1,2核心通信不會阻塞3,4核心通信。但這種方式消耗大量互聯資源,4核心時通常使用SwitchMulticore,核心數量再多則資源浪費
v. Ring Multicore結構多核:改進了Bus結構,1和3通信要經過2,相鄰的兩個核心通信速度最快.通常8核心使采用這種結構vi. Mesh Multicore結構多核:類似於二維的Ring結構。核心太多時,switch結構就會導致連線過於復雜。Mesh結構利於擴展,效率高。64核心等眾核可以采用這個設計。
(4)各種硬件多線程的對比
(a)圖形解釋: 每行代表一個cycle
(b)每列代表一個功能單元
i. 第一個是單線程處理器,大量功能單元空閑,有時if,id階段的所有控制單元空閑
ii. 細粒度多線程:每個cycle發送不同線程的指令
iii. 粗粒度多線程:當cpu發現線程阻塞時(cache miss),就發射另一個線程的指令
iv. 多核心技術:每個核心2個功能單元,沒有硬件多線程,2個核心分別處理2個不同的線程
V. 同時多線程:功能單元的利用率最高,超標量cpu同時發送多個線程的指令,每個線程使用不同的功能單元