一文讀懂處理器流水線

2021-09-12 03:35:36 字數 3875 閱讀 1750

本文將討論處理器的乙個重要的基礎知識:「流水線」。熟悉計算機體系結構的讀者一定知道,言及處理器微架構,幾乎必談其流水線。處理器的流水線結構是處理器微架構最基本的乙個要素,猶如汽車底盤對於汽車一般具有基石性的作用,它承載並決定了處理器其他微架構的細節。本文將簡要介紹處理器的一些常見流水線結構,讓您真正讀懂處理器流水線。

1 從經典的五級流水線說起

第一步沖壓:製作車身外殼和底盤等部件。

第二步焊接:將沖壓成形後的各部件焊接成車身。

第三步塗裝:將車身等主要部件清洗、化學處理、打磨、噴漆和烘乾。

第四步**:將各部件(包括發動機和向外採購的零部件)組裝成車。

汽車裝配則同時對應需要沖壓、焊接、塗裝和**四個工人。最簡單的方法是一輛汽車依次經過上述四個步驟裝配完成之後,下一輛汽車才開始進行裝配,最早期的工業製造就是採用的這種原始的方式,即同一時刻只有一輛汽車在裝配。不久之後人們發現,某個時段中一輛汽車在進行裝配時,其它三個工人都處於閒置狀態,顯然這是對資源的極大浪費,於是思考出能有效利用資源的新方法,即在第一輛汽車經過沖壓進入焊接工序的時候,立刻開始進行第二輛汽車的沖壓,而不是等到第一輛汽車經過全部四個工序後才開始,這樣在後續生產中就能夠保證四個工人一直處於執行狀態,不會造**員的閒置。這樣的生產方式就好似流水川流不息,因此被稱為流水線。

計算機體系結構教材中被提及最多的經典mips五級流水線如圖1所示。在此流水線中一條指令的生命週期分為:

取指:指令取指(instruction fetch)是指將指令從儲存器中讀取出來的過程。

解碼:指令解碼(instruction decode)是指將儲存器中取出的指令進行翻譯的過程。經過解碼之後得到指令需要的運算元暫存器索引,可以使用此索引從通用暫存器組(register file,regfile)中將運算元讀出。

執行:指令解碼之後所需要進行的計算型別都已得知,並且已經從通用暫存器組中讀取出了所需的運算元,那麼接下來便進行指令執行(instruction execute)。指令執行是指對指令進行真正運算的過程。譬如,如果指令是一條加法運算指令,則對運算元進行加法操作;如果是減法運算指令,則進行減法操作。

在「執行」階段的最常見部件為算術邏輯部件運算器(arithmetic logical unit,alu),作為實施具體運算的硬體功能單元。

訪存:儲存器訪問指令往往是指令集中最重要的指令型別之一,訪存(memory access)是指儲存器訪問指令將資料從儲存器中讀出,或者寫入儲存器的過程。

寫回:寫回(write-back)是指將指令執行的結果寫回通用暫存器組的過程。如果是普通運算指令,該結果值來自於「執行」階段計算的結果;如果是儲存器讀指令,該結果來自於「訪存」階段從儲存器中讀取出來的資料。

在工業製造中採用流水線可以提高單位時間的生產量,同樣在處理器中採用流水線設計也有助於提高處理器的效能。以上述的五級流水線為例,由於前一條指令在完成了「取指」進入「解碼」階段後,下一條指令馬上就可以進入「取指」階段,依次類推,如圖2所示,如果流水線沒有停頓,理論上可以取得每個時鐘週期都完成一條指令的效能。

一文讀懂處理器流水線

圖1 mips五級流水線結構圖

一文讀懂處理器流水線

圖2 mips五級流水線執行圖

2 可不可以不要流水線——流水線和狀態機的關係

言及處理器微架構,幾乎必談流水線。那麼,我們能否挑戰一下權威提出乙個有意思的問題:處理器難道就一定需要流水線嗎?可否不要流水線呢?

在回答這個問題之前,我們先**下流水線的本質:

流水線並不限於處理器設計,在所有的asic電路實現中都廣泛採用流水線的思想。流水線本質上可以理解為是一種以面積換效能(trade area for performance)、以空間換時間(trade space for timing)的手段。

譬如,以5級流水線為例,其增加了5組暫存器,每乙個流水線級數內部都有各自的組合邏輯資料通路,彼此之間沒有復用資源,因此,其面積開銷是比較大的,但是由於可以讓不同的流水線級數同時做不同的事情,而達到流水的效果,提高了效能,優化了時序,增加了吞吐率。

與流水線相對應的另外一種策略是狀態機,狀態機是流水線的「取反」,同樣在所有的asic電路實現中都廣泛採用。狀態機本質上可以理解為是一種以效能換面積(trade performance for area)、以時間換空間(trade timing for space)的手段。

「流水線」和「狀態機」的關係,還有一種說法稱之為「展開」和「摺疊」的關係。本質上都是一種電路設計時,選擇側重時間(效能)還是空間(面積)的一種取捨。

通過上述分析,假設處理器不採用流水線,而是使用乙個狀態機來完成,則需要多個時鐘週期才能完成一條指令的所有操作,每個時鐘週期完成狀態機的乙個狀態(譬如分別為取指、解碼、執行、訪存和寫回)。通過使用狀態機,可以省掉上述流水線中的暫存器開銷,還可以復用組合邏輯資料通路,因此面積開銷比較小,但是每條指令都需要5個週期才能完成,吞吐率和效能很差。

談及此處,就不得不提及8位微控制器時代的傳奇老炮兒8051核心,早期原始的8051核心微架構就是採用了類似狀態機的實現方式而不是流水線。因此,回到最開始我們提出的問題,處理器可否不要流水線,答案是:當然可以,傳奇老炮兒8051核心就沒有流水線。

所以說從功能能上來講,處理器完全可以不使用流水線,而使用狀態機的方式來實現,只不過由於這種方式效能比較差,在現代處理器設計中比較罕見而已。

3 深處種菱淺種稻,不深不淺種荷花——流水線的深度

流水線的級數(又稱深度)多少最好呢?要回答這個問題,就需要了解流水線的深淺各自的優劣。此處有乙個常見面試題,題目便是:處理器的流水線是否越深越好?在此我們給出答案:

早期的經典流水線是5級流水線,分別為取指、解碼、執行、訪存和寫回。現代的處理器往往具有極深的流水線級數,譬如高達十幾級,或者二十幾級的深度。流水線就像一根黃瓜,切五刀下去得到的每一截長度和切二十到下去得到的每一截長度肯定是不一樣的。當流水線的級數越多,那麼意味著流水線被切的很細,每一級流水線內容納的硬體邏輯便越少,熟悉數字同步電路設計的讀者應該比較熟悉,在兩級暫存器(每一級流水線由暫存器組成)之間的硬體邏輯越少,則意味能夠執行到更高的主頻。因此現代的處理器流水線極深主要是由於處理器追求高頻的指標所驅使,高階的arm cortex-a系列由於有十幾級的流水線,所以能夠執行到高達2ghz的主頻,而intel的x86處理器甚至採用幾十級的流水線深度將主頻推到3-4ghz的高度。主頻越高也意味著流水線的吞吐率越高從而效能越高,這是流水線加深的正面意義。

由於每一級流水線都由暫存器組成,那麼意味著更多的流水線級數要消耗更多的暫存器,也意味著更多的面積開銷。這是流水線加深的負面意義。

同時流水線越深,由於每一級流水線需要進行握手,流水線最後一級的反壓訊號可能會一直串擾到最前一級造成嚴重的時序問題,需要使用一些比較高階的技巧來解決此類反壓時序問題。這是流水線加深的負面意義。

較深的處理器流水線還有乙個問題,由於在流水線的取指令階段無法得知條件跳轉的結果是跳還是不跳,因此只能進行**,而到了流水線的末端才能夠通過實際的運算得知該分支是真的該跳還是不該跳,如果發現真實的結果(譬如該跳)與之前**的結果(譬如**為不跳)不相符,則意味著**失敗,需要將所有預取的錯誤指令流全部丟棄掉,而重新取正確的指令流,這個過程叫做流水線沖刷(pipeline flush),雖然可以使用分支**器來保證前期的分支**盡可能的準確,但是也無法做到萬無一失。那麼,流水線的深度越深,則意味著已經預取了很多的錯誤指令流,需要將其全部拋棄然後重啟,不僅白白的浪費了功耗,還造成了效能的損失。流水線越深則意味著浪費和損失越嚴重,流水線越淺則浪費和損失越少。這是流水線加深的另乙個主要的負面意義。

綜上,所謂深處種菱淺種稻,不深不淺種荷花,流水線的不同深度皆有其優缺點,需要根據不同的應用背景合理地進行選擇。

由於處理器流水線深淺的不同優劣,根據不同的應用場景,當今處理器的流水線深度在向著兩個不同的極端發展,一方面級數越來越深,另一方面又越來越淺,下面我們結合不同的商用處理器例子予以**。

處理器執行流水線優化之多Warp切換

處理器的執行流水線通常分為5個階段,分別為 取指 解碼 訪存 執行和寫回。這裡的訪存指的是訪問暫存器。假設每個階段只占用乙個時鐘週期,那麼這個5級流水線的處理器每個時鐘週期可以執行一條指令。如下圖,如果前一條指令的目的暫存器是當前指令的源暫存器,如 圖中,指令0的執行結果在寫回的同時,連同指令1的其...

瀏覽器渲染流水線解析(一)

layer compositor 圖層合成器 接收 blink 的輸入,負責圖層樹的管理,圖層的滾動,旋轉等矩陣變幻,圖層的分塊,光柵化,紋理上傳等任務 display compositor 接收 layer compositor 的輸入,負責輸出最終的 opengl 繪製指令,將網頁內容通過 gl...

計算機組成第六周 流水線處理器

流水線的特點 超級流水線 流水線的級數越多,流水線暫存器的延遲所佔比例越高,所以不是級數越多越好 超標量流水線 標量流水線和超標量流水線 如果指令和資料放在同乙個儲存器中,則不能同時讀儲存器 解決方案 流水線停頓,產生空泡 指令和資料放在不同的儲存器中 如果讀暫存器和寫暫存器同時發生 解決方案 一條...