天天看點

CPU的流水線指令設計

為什麼小小一個CPU,有那麼多周期(Cycle)?

程式的性能=指令數×CPI×時鐘周期,和周期相關的隻有一個時鐘周期,即CPU主頻的倒數。

一個CPU的時鐘周期可以認為是可以完成一條最簡單的計算機指令的時間。

那為何構造CPU時,有那麼多周期?

單指令周期處理器

一條CPU指令的執行,由FDE三步組成。這個執行過程,至少需花費一個時鐘周期。因為在取指令的時候,我們需要通過時鐘周期的信号,來決定計數器的自增。

很自然,我們希望能確定讓這樣一整條指令的執行,在一個時鐘周期内完成。

這樣,一個時鐘周期可執行一條指令,CPI=1,看着就比執行一條指令要多個時鐘周期性能好。

這就是單指令周期處理器(Single Cycle Processor):一個時鐘周期内,處理器正好能處理一條指令。

但時鐘周期固定,指令的電路複雜程度不同,是以實際一條指令執行時間不同。

随門電路層數增加,由于門延遲,位數多、計算複雜指令需執行更久。

不同指令執行時間不同,但要讓所有指令都在一個時鐘周期内完成,隻好把時鐘周期和執行時間最長的那個指令一樣。不然就會導緻快速執行完成的指令,需等待滿一個時鐘周期,才能執行下一條指令。

雖然CPI能夠保持在1,但時鐘頻率卻沒法太高。太高,有些複雜指令沒法在一個時鐘周期内完成。在下個時鐘周期到來,開始執行下條指令時,前一條指令執行結果可能還沒寫入寄存器。下一條指令讀取的資料就不準确了。

  • 前一條指令的寫入,在後一條指令的讀取之前
    CPU的流水線指令設計

    一個CPU時鐘周期,可認為是完成一條簡單指令的時間。

    為什麼單指令周期處理器,反而變成執行一條最複雜的指令的時間?

    無論是Intel CPU or ARM CPU,都不是單指令周期處理器,而是采用一種叫作指令流水線(Instruction Pipeline)的技術。

現代處理器的流水線設計

指令執行過程會拆分成“取指令、譯碼、執行”三步。

更細分,執行的過程,還包含從寄存器或記憶體讀資料,通過ALU運算,把結果寫回寄存器或記憶體。

CPU的指令執行過程,其實也是由各電路子產品組成:

  • 取指令時,需要譯碼器,把資料從記憶體取出來,寫入寄存器
  • 指令譯碼時,需要另外一個譯碼器,把指令解析成對應控制信号、記憶體位址和資料
  • 指令執行時,需要一個完成計算工作的ALU。這些都是一個一個獨立的組合邏輯電路,我們可以把它們看作一個團隊裡面的産品經理、後端工程師和用戶端工程師,共同協作來完成任務。
  • 流水線執行示意圖
    CPU的流水線指令設計

    這就不用把時鐘周期設定成整條指令執行的時間,而是拆分成完成這樣的一個一個小步驟需要的時間。同時,每一個階段的電路在完成對應的任務之後,也不需要等待整個指令執行完成,而是可以直接執行下一條指令的對應階段。

    這樣的協作模式,就是指令流水線。這裡每個獨立步驟,稱為流水線階段或流水線級(Pipeline Stage)。

把一個指令拆分成“取指令-指令譯碼-執行指令”三部分,那這就是一個三級流水線。

進一步把“執行指令”拆分成“ALU計算(指令執行)-記憶體通路-資料寫回”,就變成一個五級流水線。

五級流水線:同一時鐘周期裡,同時運作五條指令的不同階段。這時,雖然執行一條指令的時鐘周期變成5,但可提高CPU的主頻。

無需確定最複雜那條指令在時鐘周期裡執行完成,隻要保障一個最複雜的流水線級操作,在一個時鐘周期内完成即可。

若某一操作步驟時間太長,可考慮把該步驟拆分成更多步驟,讓所有步驟需執行時間盡量差不多長。這就可解決在單指令周期處理器中遇到的,性能瓶頸來自最複雜的指令的問題。

像ARM或IntelCPU,流水線級數都已到14級。

雖然不能通過流水線,減少單條指令執行的“延時”名額,但通過同時在執行多條指令的不同階段,提升了CPU的“吞吐率”。

外部看來,我們的CPU好像“一心多用”,同一時間,同時執行5條不同指令的不同階段。

CPU内部,就像生産線,不同分工的元件不斷處理上遊傳遞下來的内容,而無需等待單件商品生産完成後,再啟動下一件商品的生産。

超長流水線的性能瓶頸

你說流水線能增加 CPU 吞吐率,流水線級數就越深越好咯?

增加流水線深度,是有性能成本的。

同步時鐘周期的,不再是指令級别,而是流水線階段級别。

每一級流水線對應的輸出,都要放到流水線寄存器(Pipeline Register),然後在下一個時鐘周期,交給下一個流水線級去處理。

是以,每增加一級流水線,就要多一級寫入到流水線寄存器的操作。

雖然流水線寄存器非常快,比如隻有20皮秒(ps,

1

12

10^{-12}

10−12秒)。

CPU的流水線指令設計

但不斷加深流水線,這些操作占整個指令的執行時間的比例就會不斷增加。最後,性能瓶頸就會出現在這些overhead。

若指令執行有3ns=3000ps:

  • 20級流水線,則流水線寄存器寫入就要400ps,占超過10%
  • 50級流水線,就要多花費1ns在流水線寄存器上,占到25%

這意味着,單純增加流水線級數,不僅不能提升性能,反而會有更多overhead開銷。是以,設計合理的流水線級數也是現代CPU中非常重要的一點。

總結

  • 《深入了解計算機系統》的4.4章節
  • 《計算機組成與設計 硬體/軟體接口》的4.5章節