指令流水線總結


5.5 CPU指令流水線

一. 流水線

  1. 流水線
    (1)流水線:
    指令從取值到真正執行的過程划分成多個小步驟,cpu真正開始執行指令序列時,一步壓一步的執行,減少其等待時間。
    (2)流水線級數越多,工作效率越高。intel處理器的流水線級數遠超過嵌入式cpu的流水線級數
    (3)流水線的效率:
        a. 並非指令每一步的操作時間都是等長的。長節拍的步驟會導致流水線效率下降(短節拍的步驟要等待長節拍的步驟執行完畢)
        b. 解決辦法:
            i. 拆分長節拍
            
            ii. 增加長節拍的處理單元:使得同時間產生多個長節拍的執行結果,供短節拍的動作使用。
            
            eg:長節拍是短節拍執行時間的3倍,則可以增加為3個長節拍執行單元,1個短節拍執行單元

  2. ARM7的三級流水線:
    ARM7把知道指令執行的時間分為3個步驟:取指IF,譯碼ID,執行EX
         

  3. 經典的MIPS5級流水線
    (1)處理器內部有很多程序員可見的 通用寄存 器,這些通用寄存器組成了寄存器堆register file
    (2)為了讓不同流水線之間的數據不會互相打擾,cpu在每個階段會把通用寄存器中的值拷貝到流水線寄存器中,使得各個節拍的工作不會亂序。
    (3)匯編語言中,ALU執行單元直接訪問通用寄存器,而在硬件實現中,通用寄存器的值先拷貝到ALU輸入寄存器中(一個流水線寄存器),然后再送回通用寄存器
    (4)MIPS在3級流水線的基礎上,增加了2個階段,1個是從內存獲取數據的mem階段,另一個是把ALU計算后的數據導出到通用寄存器堆的WB階段
    IF -> ID -> EX -> MEM -> WB
         

  4. DSP對三級流水線的深層次擴展
    (1)DSP處理器把取指,譯碼,執行的三大步驟細分為多個小步驟
    (2)MIPS處理器把MEM和ALU計算放在不同階段,寫回通用寄存器也單獨形成一個階段。而DSP把MEM和WB階段都放在了指令執行階段,更符合程序員的視角。
         

三. 流水線思想的冒險

  1. 結構冒險:不同階段的執行步驟由於硬件資源沖突不能同時進行
    MIPS處理器的流水線中,IF階段需要訪問存儲器拿指令,MEM階段需要訪問存儲器拿數據,這兩個動作都要訪問存儲器,造成存儲器和寄存器之間的總線沖突,而不能同時進行。但是,現代處理器,程序被存儲在L1P Cache中,數據被存在L1D Cache中,所以不會沖突。
         

  2. 數據冒險
    (1)流水線使得原先有先后順序的指令同時處理,當出現某些指令組合時,可能會導致使用了錯誤的數據。
         
    (2)因此,cpu采用直通(forwarding)來解決:如果當前指令的源操作數在EX/MEM的流水線寄存器中,就直接將流水線寄存器中的值傳遞給ALU輸入,不去通用寄存器堆取值
    (3)但不是所有數據沖突都能采用直通解決,要配置cycle等待
    sub指令的R1,最早也要在cycle4中才能到MEM/EX流水線寄存器,所以仍要掩飾一個周期

  3. 控制冒險
    (1)當一條流水線中的指令出現跳轉操作時,其他流水線提前做出的操作是根據pc+1進行取指的,跳轉操作使得這些流水線上的操作全部無效
    (2)流水線等級越深,跳轉指令造成的效率下降約嚴重

四. 流水線的分支預測

  1. 1-bit預測算法:
    如果該指令上次發生跳轉,則預測這一次也會發生跳轉
  2. 2-bit預測算法:
    每個指令的預測狀態信息從1bit加到2bit,如果這個跳轉執行了,就+1,加到3就不加了,如果跳轉信息不執行就-1,減到0就不減了。如果計數器值為0/1,就預測不執行,計數器為2/3,就預測執行。

  3. Intel的分支預測實現
    (1)前面2個是算法思想,Intel在此基礎上進行了一系列的設計。Intel分支預測包含3個單元:Branch Target Buffer(BTB),The Static Predictor,Return Stack

五. 指令的亂序執行

  1. 亂序執行
    指令在執行時,常常因為一些限制而等待。例如,MEM階段訪問的數據不在cache中,需要從外部存儲器獲取,這個動作需要幾十個cycle,如果順序執行,后面的指令MEM都要等待這個指令操作完成。亂序執行是說,先執行后面不依賴該數據的指令

  2. 指令相關性
    (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條指令間沒有數據流動,被稱為偽相關。

  3. 控制相關
    前一條指令是跳轉指令,而后一條指令的執行需要跳轉指令的結果,這就是控制相關

三. 去除指令相關

  1. 去除數據相關
    去除數據相關的動作不是由cpu進行的,而是由編譯器和程序員進行處理的

    x = a + b y = x + c z = y + d // x,y,z產生深度相關 // 改造后 x = a + b y = b + c z = x + y // 此時去除了x,y間的相關性
  2. 去除控制相關
    投機執行:cpu會根據跳轉預測的結果,可能會提前把跳轉后的指令放到跳轉指令前面執行,是一種預測的投機行為。現代分支預測的准確性能達到98%以上,所以可以一定程度上去除控制相關

  3. 去除偽相關:WAW,WAR
    (1)處理器的ISA寄存器數目通常較少(暴露給程序員的寄存器),因此會導致多個變量映射到同一個寄存器中,這樣即使指令邏輯上是不相關的,也會因為使用了同一個寄存器而產生相關。
    (2)通過把相同的ISA寄存器,映射到不同的物理寄存器來解決偽相關(名字相關)
    (3)映射策略:

    1. 將每條指令的目的寄存器映射到新的物理寄存器
    2. 將指令的源寄存器映射到ISA寄存器最近映射到的那個物理寄存器上
    3. 本條指令執行后,該目的寄存器映射的更早的物理寄存器就可以釋放了
       
    4. 一開始R1,R2,R3,R4分別映射到F1,F2,F3,F4寄存器
    5. 第一條指令R3是目的寄存器,映射到新物理寄存器F5
    6. 這種方式會把物理寄存器用光,所以每次映射完畢都要實時釋放:R4寄存器開始映射到F4寄存器,指令2結束后,R4映射到F6寄存器,此時,原先的F4寄存器就可以釋放了

四.CPU如何進行亂序執行

  1. Buffer
    CPU內部要提供能夠緩存多條指令的Buffer,才能達到亂序執行的效果

  2. 指令調度
    (1)指令有操作數和操作碼,操作碼描述指令做什么(cpu分配什么樣的執行單元);而寄存器重命名后,目的寄存器總是新的,所以指令能否執行,和目的操作數已經無關,和操作碼和源操作數有關
    (2)指令可以被執行的2個條件,除了這2個條件,指令不用再等待前面的指令執行完畢

    1. cpu中是否有空閑的執行單元執行這條指令(操作碼)
    2. 該指令的源操作數是否已經准備好
  3. 指令結果順序提交
    (1)指令執行順序雖然是亂序的,但是指令結果的提交順序一定要是順序的。因為“精確中斷”的存在
    (2)精確中斷:指令執行過程中,來了一個中斷,此時cpu要將ISA寄存器壓棧,執行中斷服務程序,然后執行中斷后面的指令。而精確中斷要求終端錢的指令全部執行,中斷后的指令一個都不執行。而在亂序執行內核中,終端后面的指令可能放在中斷前面的指令執行
    (3)所以,cpu引入重排序緩沖區,用來緩沖指令的執行結果,這些結果會被順序的提交到寄存器中,來實現精確中斷。

五. 處理器並行架構

  1. Flynn分類
    1966年,Flynn將處理器系統結構分成4類
    (1)SISD:處理器有一次處理一條指令,每條指令處理一份數據 (single instruction single data)
    (2)SIMD:一次處理一條數據,一條指令可以處理多分數據(數據並行)
    (3)MISD:一次處理多條指令,每條指令處理一份數據(此設計無用)
    (4)MIMD:一次處理多條指令,每條指令可以處理多分數據

  2. 指令並行
    (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無能為力,采用亂序執行+超標量處理器則能將后面的指令提前執行,因此亂序+超標量適合負責的控制類程序。

  3. 數據並行
    (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進行操作,而其他段保持不練
        

  4. 線程並行
    (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同時發送多個線程的指令,每個線程使用不同的功能單元


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM