分支預測器

在電腦架構中，分支預測器是一種數位電路，在分支指令執行結束之前猜測哪一路分支將會被執行，以提高處理器的指令流水線的效能。使用分支預測器的目的，在於改善指令管線化的流程，就像一家公司的員工提前預測公司所需要的東西，即交付不同單位進行準備工作，而那各個部門之間的等待交辦的時間大大地縮短，整個公司的效率就會提高了。現代使用指令管線化處理器的效能能夠提高，分支預測器對於現今的指令流水線微處理器獲得高效能是非常關鍵的技術。簡介.條件分支指令通常具有兩路後續執行分支。即不採取跳轉到另一塊程式記憶體去執行那裡的指令。是否條件跳轉，只有在該分支指令在指令流水線中通過了執行階段才能確定下來。如果沒有分支預測器，處理器將會等待分支指令通過了指令流水線的執行階段，才把下一條指令送入流水線的第一個階段—取指令階段或者分支延遲間隙。這是早期的RISC體系結構處理器採用的應對分支指令的流水線執行的辦法。分支預測器猜測條件運算式兩路分支中哪一路最可能發生，然後推測執行這一路的指令，來避免流水線停頓造成的時間浪費。如果後來發現分支預測錯誤，那麼流水線中推測執行的那些中間結果全部放棄，重新取得正確的分支路線上的指令開始執行，這招致了程式執行的延遲。在分支預測失敗時浪費的時間是從取指令到執行完指令的流水線的級數。現代微處理器趨向採用非常長的流水線，因此分支預測失敗可能會損失10-20個時鐘週期。越長的流水線就需要越好的分支預測。一條條件跳轉指令第一次遇到，還沒有任何資訊可以去預測分支。此後保持這條指令是採取還是不採取跳轉的歷史記錄，就可以作為再遇到這條指令時猜測最可能的分支。分支預測不同於“分支目標預測”相應的跳轉目的碼塊。實現.靜態預測.靜態預測是最簡單的分支預測技術，因為它不依賴於程式碼執行的動態歷史資訊。相反，它僅依賴於分支指令自身。SPARC與MIPS的最早實現才能確定。兩種處理器都會在分支指令進入流水線的執行階段時，插入一個分支延遲間隙。分支指令完成流水線的執行階段，就已經能確定是否跳轉，這時就可以決定是後續的順序出現的指令被繼續執行還是跳轉到的新指令進入流水。更復雜的靜態預測假定向後分支將會發生，向前的分支不會發生。向後分支，是指跳轉到的新地址比當前地址要低。這有助於配合經常出現的程式的迴圈控制結構。一些處理器允許分支預測提示出現在程式碼中。Intel Pentium 4就是如此。但這一特徵在Intel此後的處理器中不再支援。靜態預測也用於某些處理器分支動態預測沒有任何可用資訊時的一個最後的辦法。Motorola MPC7450 (G4e)與Intel Pentium 4都是如此。動態預測.動態預測利用分支指令發生轉移的歷史來進行預測，並根據實際執行情況動態調整預測位，準確率可達90%，現在幾乎所有處理器都採用動態預測。下一行預測.一些超標量處理器(MIPS R8000, Alpha 21264 and Alpha 21464 (EV8))使用此種技術。飽和計數.飽和計數器是一種有4個狀態的狀態機：當一個分支命令被求值，對應的狀態機被修改。分支不採納，則向“強不選擇”方向降低狀態值；如果分支被採納，則向“強選擇”方向提高狀態值。這種方法的優點是，該條件分支指令必須連續選擇某條分支兩次，才能從強狀態翻轉，從而改變了預測的分支。最初的不具有MMX的Intel Pentium處理器使用了這種飽和計數器。雖然實現不夠完美。在SPEC'89 benchmark測評中, 飽和預測達到了93.5%正確率，如果每條條件分支指令都映射了自己的計數器。預測器表使用條件分支指令的地址作為索引。因此處理器可以在分支指令解碼前就給它分配一個預測器。兩級自適應預測器.對於一條分支指令，如果每2次執行發生一次條件跳轉，或者其它的規則發生模式，那麼用上文提到的飽和計數器就很難預測了。如圖所示，一種二級自適應預測器可以記住過去n次執行該指令時的分支情況的歷史，可能的2n種歷史模式的每一種都有1個專用的飽和計數器，用來表示如果剛剛過去的n次執行歷史是此種情況，那麼根據這個飽和計數器應該預測為跳轉還是不跳轉。例如，n = 2。這意味著過去的2次分支情況被儲存在一個2位的移位暫存器中。因此可能有4種不同的分支歷史情況：00, 01, 10, 11。其中0表示未發生跳轉，1表示發生了分支跳轉。現在，設計一個模式歷史表，有4個條目，對應於2n = 4種可能的分支歷史情況。4種歷史情況的每一種都在模式歷史表對應於一個2位飽和計數器。分支歷史暫存器用於選擇哪個飽和計數器供現在使用。如果分支歷史暫存器是00，那麼選擇第一個飽和計數器；如果分支歷史暫存器是11，那麼選擇第4個飽和計數器。假定，例如條件跳轉每隔2次執行就發生一次，即分支情況的歷史序列是001001001...。在這種情況下，00對應的飽和計數器將是狀態“強選擇”，表示在01之後必然是出現一個0。這也同樣適用於10狀態。而11狀態從未使用，因為不可能出現連續兩個1。2級自適應預測器的一般規則是n位分支歷史暫存器，可以預測在所有n週期以內出現的所有的重複序列的模式。2級自適應預測器的優點是能快速學會預測任意的重複模式。此方法1991年被提出。 已經變得非常流行。以此為基礎很多變種方法被用於現代微處理器。區域性分支預測.區域性分支預測對於每個條件跳轉指令都有專用的分支歷史情況緩衝區；模式歷史表可以是專用的，也可以是所有條件分支指令共用。Intel Pentium MMX, Pentium II, Pentium III使用區域性分支預測器，記錄4位的歷史情況，每條條件跳轉指令使用專用的區域性模式歷史表，當然是包含24 = 16個條目。對SPEC'89 benchmark測評，非常大的本地預測器的正確率達到97.1%。全域性分支預測.全域性分支預測器；甚至歷史記錄沒有一位是來自同一個分支指令，如果有太多的不同的分支指令。這種方法只有在歷史緩衝區足夠長，才能發揮出效能。但是模式歷史表的條目數是歷史緩衝區位數的指數量級。因此只能是在所有的條件跳轉指令間共享這個大的模式歷史表。AMD的CPU，以及Intel的Pentium M, Core，Core 2使用了此種方法。SPEC'89 benchmark評測，非常大的gshare預測器達到了96.6%正確率，略低於區域性分支預測。融合分支預測.融合分支預測器起來。VIA Nano處理器可能採用此方法。Agree預測器.Agree預測器是一種兩級自適應全域性預測器，但是附加了一個bias飽和計數器，用來記錄歷次預期的準確度。最終輸出結果是全域性預測與bias飽和計數器的異或。Intel Pentium 4使用了此種方法，但此後的Intel處理器放棄了此種方法。迴圈預測器.程式迴圈的控制部分所對應的條件跳轉指令最好用專門的迴圈控制器來預測分支。將要重複N次的迴圈的底部的條件跳轉指令，前N-1次選擇跳轉，只有一次不跳轉而是順序執行。條件跳轉指令有很多次選擇了一條分支，只有一次選擇另一分支，這種行為將被作為迴圈行為被檢測。這種條件跳轉指令可以用簡單的計數器很容易地檢測出來。迴圈預測器是一種混合預測器，其中元預測器判斷該條件跳轉指令是否具有迴圈行為。許多微處理器現在都有迴圈預測器。間接跳轉預測.間接跳轉指令，這個儲存位置的內容才是要轉去的下一條指令地址。例如codice_1，表示在ZF標誌暫存器為1情況下，跳轉到暫存器EAX所儲存的記憶體地址開始的程式碼快。間接跳轉指令可以選擇多於兩條分支的執行路線。Intel與AMD的更新的處理器使用兩級自適應預測器能預測間接跳轉。間接跳轉指令在歷史緩衝區貢獻了超過1位的表示。沒有這種預測機制的處理器，就簡單地預測間接跳轉指令是否會如同上次一樣選擇同一目標。函式返回的預測.許多處理器有專門用於表示函式呼叫返回地址的"return stack buffer"。overriding分支預測.快速與精確，是分支預測需要平衡的兩個效能指標。有時就設定兩個分支預測器。第一個是簡單且快速。第二個是更慢、更復雜、表更大、可以覆蓋第一個預測器作出的預測。Alpha 21264與Alpha EV8處理器使用一個快速的、單週期的下一行預測器處理分支目標，提供一個簡單快速的分支預測。兩個微處理器都有更復雜的、兩個週期的分支預測期，可以覆蓋下一行預測器的不準確的結果。Intel Core i7有兩個分支目標預測器，可能有兩個或更多分支預測器。神經分支預測器.1999年提出的神經分支預測器。突出優點是能夠利用很長的歷史記錄，僅導致了資源的線性增長。而傳統預測器的資源需要量與歷史長度是指數增長關係。這種方法主要缺點是高延遲。神經分支預測器的準確度非常突出。。Intel在IA-64的模擬器 (2003)中實現了這一方法。歷史.分支預測對於指令流水線、超標量的處理器是非常重要的，如Intel Pentium, DEC Alpha 21064, MIPS R8000, IBM POWER等處理器。這些處理器依賴於1位或2位預測器。