程式設計師的 CPU 微架構

指令管線與管線停滯(the instruction pipeline and pipeline stall)

想像一間自助洗衣店在洗好幾批衣服。你可以把一批完整地洗、烘、摺完才開始下一批——或者你可以在第一批還在烘乾時就開始洗第二批。第二種方式讓每台機器都忙著,每小時完成的衣服多得多。中央處理器的管線把這個點子原封不動套到指令上:不是把一條指令完全做完才去抓下一條,而是把它們重疊起來,讓好幾條指令同時處於不同的完成階段。

執行一條指令被拆成若干階段——經典的教學管線有五個:抓取指令、解碼、執行運算、必要時存取記憶體、把結果寫回。真實的中央處理器階段多得多(常為 14 到 20 多級)。在管線化的處理器裡,當第 1 條指令在執行階段時,第 2 條正在被解碼、第 3 條正在被抓取,全在同一個時脈週期內。好處是吞吐量:管線一旦填滿,中央處理器大約每個週期完成一條指令,即使每條指令要花許多週期才能走完整條管。這正是深度管線化的晶片能跑在高時脈的原因。

麻煩在於指令彼此並不獨立,而管線來不及滿足的相依會造成停滯——管線插入一個叫做氣泡(bubble)的空格並等待。這些來自冒險(hazard):資料冒險(第 4 條指令需要第 3 條尚未算完的結果)、控制冒險(一個方向還不知道的分支,所以中央處理器不曉得下一條該抓什麼)、或結構冒險(兩條指令同時需要同一個硬體單元)。停滯浪費週期,所以這個欄位裡幾乎每一項現代技術——前遞(forwarding)、亂序執行、分支預測、超純量發射——都是為了讓管線保持填滿、讓停滯變罕見而存在。

a = b + c; d = a * 2; 那個乘法需要 a,而加法尚未把它寫回,所以一條嚴格的管線會停滯(資料冒險)。硬體前遞把加法的結果直接送到乘法的輸入以避開氣泡;若做不到,你就得吃下閒置週期。

一個管線來不及滿足的相依就變成一個氣泡——前遞的存在就是為了填補它。

管線化改善的是吞吐量,而非單一指令的延遲——一條指令完成所需的週期數一樣多;你只是把許多條重疊起來。更深的管線也讓分支誤測更昂貴,因為有更多正在途中的階段要被清空。

又稱
pipeliningpipeline stagespipeline bubble管線化管線氣泡