管線化與危障
管線停頓(pipeline stall)
在裝配線上,有時唯一誠實的做法就是暫停:下一站需要的零件就是還沒好,所以你把未完成的工作留在原處,等一拍。管線停頓正是這樣——硬體把一條或多條指令凍結在原地一個(或數個)週期,因為放它們前進就會讀到錯的值或搶到忙碌的資源。它是萬用、蠻力的解法,在沒有更聰明的辦法時對任何危障都管用。
機制上,停頓凍結管線前端。處於停頓階段及更前面的指令不前進——程式計數器與前段管線暫存器維持原內容而非載入新值——而已經越過停頓點的指令照常前進。在它們後面開出的空隙裡,硬體注入一條什麼都不做的指令,一個氣泡,好讓後段階段有無害的東西可處理。偵測危障並施加凍結的電路叫互鎖:一個危障偵測單元注意到例如載入-使用衝突,便發訊號令管線恰好停頓一個週期。
停頓正確但昂貴:每個停頓週期都是沒有有用指令完成的週期,所以停頓直接把有效的每指令週期數抬高到理想值一之上。這就是為什麼架構師如此費力地避免它們——前饋以閃避資料危障、加硬體以閃避結構危障、預測以閃避控制危障。停頓是只有在那些都幫不上時才動用的退路,最著名的就是載入-使用危障那一次無可避免的停頓。好的程式碼與好的編譯器會用獨立的工作填滿停頓槽,讓凍結不花成本。
lw x1, 0(x2) 接著 add x3, x1, x4。載入的 x1 要到 MEM 之後才備妥,但 add 早一個週期就在 EX 要它。互鎖偵測到這點,讓 add 停頓一個週期、插入一個氣泡;接著前饋恰好準時遞交 x1。代價:恰好一個浪費的週期。
當危障無法被藏起時,互鎖凍結管線前端並插入氣泡——這裡是無可避免的載入-使用停頓。
停頓與氣泡是同一件事的兩種看法:停頓是施加在較早指令上的凍結;氣泡是往後段階段流動的那個空槽。兩者付出相同的一個吞吐量週期。
又稱
另見