本文將討論處理器的一個(gè)重要的基礎(chǔ)知識(shí):“流水線”。熟悉計(jì)算機(jī)體系結(jié)構(gòu)的讀者一定知道,言及處理器微架構(gòu),幾乎必談其流水線。處理器的流水線結(jié)構(gòu)是處理器微架構(gòu)最基本的一個(gè)要素,猶如汽車底盤對(duì)于汽車一般具有基石性的作用,它承載并決定了處理器其他微架構(gòu)的細(xì)節(jié)。本文將簡要介紹處理器的一些常見流水線結(jié)構(gòu),讓您真正讀懂處理器流水線。
1 從經(jīng)典的五級(jí)流水線說起
流水線的概念來源于工業(yè)制造領(lǐng)域,以汽車裝配為例來解釋流水線的工作方式,假設(shè)裝配一輛汽車需要四個(gè)步驟:
第一步?jīng)_壓:制作車身外殼和底盤等部件。
第二步焊接:將沖壓成形后的各部件焊接成車身。
第三步涂裝:將車身等主要部件清洗、化學(xué)處理、打磨、噴漆和烘干。
第四步總裝:將各部件(包括發(fā)動(dòng)機(jī)和向外采購的零部件)組裝成車。
汽車裝配則同時(shí)對(duì)應(yīng)需要沖壓、焊接、涂裝和總裝四個(gè)工人。最簡單的方法是一輛汽車依次經(jīng)過上述四個(gè)步驟裝配完成之后,下一輛汽車才開始進(jìn)行裝配,最早期的工業(yè)制造就是采用的這種原始的方式,即同一時(shí)刻只有一輛汽車在裝配。不久之后人們發(fā)現(xiàn),某個(gè)時(shí)段中一輛汽車在進(jìn)行裝配時(shí),其它三個(gè)工人都處于閑置狀態(tài),顯然這是對(duì)資源的極大浪費(fèi),于是思考出能有效利用資源的新方法,即在第一輛汽車經(jīng)過沖壓進(jìn)入焊接工序的時(shí)候,立刻開始進(jìn)行第二輛汽車的沖壓,而不是等到第一輛汽車經(jīng)過全部四個(gè)工序后才開始,這樣在后續(xù)生產(chǎn)中就能夠保證四個(gè)工人一直處于運(yùn)行狀態(tài),不會(huì)造成人員的閑置。這樣的生產(chǎn)方式就好似流水川流不息,因此被稱為流水線。
計(jì)算機(jī)體系結(jié)構(gòu)教材中被提及最多的經(jīng)典MIPS五級(jí)流水線如圖1所示。在此流水線中一條指令的生命周期分為:
取指:
指令取指(Instruction Fetch)是指將指令從存儲(chǔ)器中讀取出來的過程。
譯碼:
指令譯碼(Instruction Decode)是指將存儲(chǔ)器中取出的指令進(jìn)行翻譯的過程。經(jīng)過譯碼之后得到指令需要的操作數(shù)寄存器索引,可以使用此索引從通用寄存器組(Register File,Regfile)中將操作數(shù)讀出。
執(zhí)行:
指令譯碼之后所需要進(jìn)行的計(jì)算類型都已得知,并且已經(jīng)從通用寄存器組中讀取出了所需的操作數(shù),那么接下來便進(jìn)行指令執(zhí)行(Instruction Execute)。指令執(zhí)行是指對(duì)指令進(jìn)行真正運(yùn)算的過程。譬如,如果指令是一條加法運(yùn)算指令,則對(duì)操作數(shù)進(jìn)行加法操作;如果是減法運(yùn)算指令,則進(jìn)行減法操作。
在“執(zhí)行”階段的最常見部件為算術(shù)邏輯部件運(yùn)算器(Arithmetic Logical Unit,ALU),作為實(shí)施具體運(yùn)算的硬件功能單元。
訪存:
存儲(chǔ)器訪問指令往往是指令集中最重要的指令類型之一,訪存(Memory Access)是指存儲(chǔ)器訪問指令將數(shù)據(jù)從存儲(chǔ)器中讀出,或者寫入存儲(chǔ)器的過程。
寫回:
寫回(Write-Back)是指將指令執(zhí)行的結(jié)果寫回通用寄存器組的過程。如果是普通運(yùn)算指令,該結(jié)果值來自于“執(zhí)行”階段計(jì)算的結(jié)果;如果是存儲(chǔ)器讀指令,該結(jié)果來自于“訪存”階段從存儲(chǔ)器中讀取出來的數(shù)據(jù)。
在工業(yè)制造中采用流水線可以提高單位時(shí)間的生產(chǎn)量,同樣在處理器中采用流水線設(shè)計(jì)也有助于提高處理器的性能。以上述的五級(jí)流水線為例,由于前一條指令在完成了“取指”進(jìn)入“譯碼”階段后,下一條指令馬上就可以進(jìn)入“取指”階段,依次類推,如圖2所示,如果流水線沒有停頓,理論上可以取得每個(gè)時(shí)鐘周期都完成一條指令的性能。
圖1 MIPS五級(jí)流水線結(jié)構(gòu)圖
圖2 MIPS五級(jí)流水線運(yùn)行圖
2 可不可以不要流水線——流水線和狀態(tài)機(jī)的關(guān)系
言及處理器微架構(gòu),幾乎必談流水線。那么,我們能否挑戰(zhàn)一下權(quán)威提出一個(gè)有意思的問題:處理器難道就一定需要流水線嗎?可否不要流水線呢?
在回答這個(gè)問題之前,我們先探討下流水線的本質(zhì):
流水線并不限于處理器設(shè)計(jì),在所有的ASIC電路實(shí)現(xiàn)中都廣泛采用流水線的思想。流水線本質(zhì)上可以理解為是一種以面積換性能(Trade Area for Performance)、以空間換時(shí)間(Trade Space for Timing)的手段。
譬如,以5級(jí)流水線為例,其增加了5組寄存器,每一個(gè)流水線級(jí)數(shù)內(nèi)部都有各自的組合邏輯數(shù)據(jù)通路,彼此之間沒有復(fù)用資源,因此,其面積開銷是比較大的,但是由于可以讓不同的流水線級(jí)數(shù)同時(shí)做不同的事情,而達(dá)到流水的效果,提高了性能,優(yōu)化了時(shí)序,增加了吞吐率。
與流水線相對(duì)應(yīng)的另外一種策略是狀態(tài)機(jī),狀態(tài)機(jī)是流水線的“取反”,同樣在所有的ASIC電路實(shí)現(xiàn)中都廣泛采用。狀態(tài)機(jī)本質(zhì)上可以理解為是一種以性能換面積(Trade Performance for Area)、以時(shí)間換空間(Trade Timing for Space)的手段。
“流水線”和“狀態(tài)機(jī)”的關(guān)系,還有一種說法稱之為“展開”和“折疊”的關(guān)系。本質(zhì)上都是一種電路設(shè)計(jì)時(shí),選擇側(cè)重時(shí)間(性能)還是空間(面積)的一種取舍。
通過上述分析,假設(shè)處理器不采用流水線,而是使用一個(gè)狀態(tài)機(jī)來完成,則需要多個(gè)時(shí)鐘周期才能完成一條指令的所有操作,每個(gè)時(shí)鐘周期完成狀態(tài)機(jī)的一個(gè)狀態(tài)(譬如分別為取指、譯碼、執(zhí)行、訪存和寫回)。通過使用狀態(tài)機(jī),可以省掉上述流水線中的寄存器開銷,還可以復(fù)用組合邏輯數(shù)據(jù)通路,因此面積開銷比較小,但是每條指令都需要5個(gè)周期才能完成,吞吐率和性能很差。
談及此處,就不得不提及8位單片機(jī)時(shí)代的傳奇老炮兒8051內(nèi)核,早期原始的8051內(nèi)核微架構(gòu)就是采用了類似狀態(tài)機(jī)的實(shí)現(xiàn)方式而不是流水線。因此,回到最開始我們提出的問題,處理器可否不要流水線,答案是:當(dāng)然可以,傳奇老炮兒8051內(nèi)核就沒有流水線。
所以說從功能能上來講,處理器完全可以不使用流水線,而使用狀態(tài)機(jī)的方式來實(shí)現(xiàn),只不過由于這種方式性能比較差,在現(xiàn)代處理器設(shè)計(jì)中比較罕見而已。
3 深處種菱淺種稻,不深不淺種荷花——流水線的深度
流水線的級(jí)數(shù)(又稱深度)多少最好呢?要回答這個(gè)問題,就需要了解流水線的深淺各自的優(yōu)劣。此處有一個(gè)常見面試題,題目便是:處理器的流水線是否越深越好?在此我們給出答案:
早期的經(jīng)典流水線是5級(jí)流水線,分別為取指、譯碼、執(zhí)行、訪存和寫回。現(xiàn)代的處理器往往具有極深的流水線級(jí)數(shù),譬如高達(dá)十幾級(jí),或者二十幾級(jí)的深度。流水線就像一根黃瓜,切五刀下去得到的每一截長度和切二十到下去得到的每一截長度肯定是不一樣的。當(dāng)流水線的級(jí)數(shù)越多,那么意味著流水線被切的很細(xì),每一級(jí)流水線內(nèi)容納的硬件邏輯便越少,熟悉數(shù)字同步電路設(shè)計(jì)的讀者應(yīng)該比較熟悉,在兩級(jí)寄存器(每一級(jí)流水線由寄存器組成)之間的硬件邏輯越少,則意味能夠運(yùn)行到更高的主頻。因此現(xiàn)代的處理器流水線極深主要是由于處理器追求高頻的指標(biāo)所驅(qū)使,高端的ARM Cortex-A系列由于有十幾級(jí)的流水線,所以能夠運(yùn)行到高達(dá)2GHz的主頻,而Intel的x86處理器甚至采用幾十級(jí)的流水線深度將主頻推到3-4GHz的高度。主頻越高也意味著流水線的吞吐率越高從而性能越高,這是流水線加深的正面意義。
由于每一級(jí)流水線都由寄存器組成,那么意味著更多的流水線級(jí)數(shù)要消耗更多的寄存器,也意味著更多的面積開銷。這是流水線加深的負(fù)面意義。
同時(shí)流水線越深,由于每一級(jí)流水線需要進(jìn)行握手,流水線最后一級(jí)的反壓信號(hào)可能會(huì)一直串?dāng)_到最前一級(jí)造成嚴(yán)重的時(shí)序問題,需要使用一些比較高級(jí)的技巧來解決此類反壓時(shí)序問題。這是流水線加深的負(fù)面意義。
較深的處理器流水線還有一個(gè)問題,由于在流水線的取指令階段無法得知條件跳轉(zhuǎn)的結(jié)果是跳還是不跳,因此只能進(jìn)行預(yù)測,而到了流水線的末端才能夠通過實(shí)際的運(yùn)算得知該分支是真的該跳還是不該跳,如果發(fā)現(xiàn)真實(shí)的結(jié)果(譬如該跳)與之前預(yù)測的結(jié)果(譬如預(yù)測為不跳)不相符,則意味著預(yù)測失敗,需要將所有預(yù)取的錯(cuò)誤指令流全部丟棄掉,而重新取正確的指令流,這個(gè)過程叫做流水線沖刷(Pipeline Flush),雖然可以使用分支預(yù)測器來保證前期的分支預(yù)測盡可能的準(zhǔn)確,但是也無法做到萬無一失。那么,流水線的深度越深,則意味著已經(jīng)預(yù)取了很多的錯(cuò)誤指令流,需要將其全部拋棄然后重啟,不僅白白的浪費(fèi)了功耗,還造成了性能的損失。流水線越深則意味著浪費(fèi)和損失越嚴(yán)重,流水線越淺則浪費(fèi)和損失越少。這是流水線加深的另一個(gè)主要的負(fù)面意義。
綜上,所謂深處種菱淺種稻,不深不淺種荷花,流水線的不同深度皆有其優(yōu)缺點(diǎn),需要根據(jù)不同的應(yīng)用背景合理地進(jìn)行選擇。
由于處理器流水線深淺的不同優(yōu)劣,根據(jù)不同的應(yīng)用場景,當(dāng)今處理器的流水線深度在向著兩個(gè)不同的極端發(fā)展,一方面級(jí)數(shù)越來越深,另一方面又越來越淺,下面我們結(jié)合不同的商用處理器例子予以探討。
評(píng)論