指令層級平行與亂序執行
分支預測(branch prediction)
分支預測器是對「你會走哪條岔路」的一個猜測。程式充滿分支——if 敘述、迴圈、函式呼叫——在每一個分支處,CPU 都必須決定接下來提取哪些指令。但一個分支是否會跳,往往要好幾個週期後才知道,而深管線等不起。所以硬體立刻猜出方向(與目標)並繼續往下走,賭它在偶爾猜錯時能廉價地自我修正。
具體來說,分支預測器觀察過去分支的歷史,賭未來像過去。最簡單的方案為每個分支記住上次往哪走。更好的方案為每個分支用一個小型飽和計數器(兩位元預測器)、把某分支的行為與其他分支近期的結果關聯(關聯式預測器),或同時跑好幾個預測器、逐分支學會該信哪一個(競賽式預測器)。至於跳躍分支的目標位址,分支目標緩衝區會快取該分支上次去了哪裡,好讓下一次提取直接從那裡開始、不必等待。現代預測器好得驚人——在典型程式碼上往往遠超過 95% 的準確率。
在一顆深、寬、推測的核心裡,準確率就是一切,因為誤測代價高昂:錯誤路徑上每一道推測執行的指令都得被壓掉,管線得從正確路徑重新填滿,每次或許花上十多個甚至更多週期。所以即使只有百分之幾的誤測,也會明顯削弱效能。誠實的提醒是:方向基本上隨機(以無法預測的方式依賴資料)的分支,會擊敗任何預測器——而預測品質正是一顆核心究竟能維持多少 ILP 的實務限制之一。
一個跑 1000 次的迴圈,其回邊分支跳 999 次、不跳 1 次(出口)。預測器很快學會「跳」,於是 1000 次分支中有 999 次預測正確,只有最後的出口付出一次誤測代價。
賭未來像過去;只在猜錯時付出重填的代價。
沒有預測器能贏過真正隨機的分支——準確率取決於程式碼是否可預測。而良好預測所開啟的那份推測,正是 Spectre 的根基,所以高準確率是雙面刃。
又称
另见