分支預測器(Branch Predictor) 彙總介紹

        當包含流水線技術的處理器處理分支指令時就會遇到一個問題,根據判定條件的真/假的不同,有可能會產生轉跳,而這會打斷流水線中指令的處理,因爲處理器無法確定該指令的下一條指令,直到分支執行完畢。流水線越長,處理器等待的時間便越長,因爲它必須等待分支指令處理完畢,才能確定下一條進入流水線的指令。

  分支預測技術便是爲解決這一問題而出現的。

  分支預測技術包含編譯時進行的靜態分支預測和硬件在執行時進行的動態分支預測


靜態分支預測:


  最簡單的靜態分支預測方法就是任選一條分支。1)認爲branch一定會token;2)認爲branch一定不會token;這樣平均命中率爲50%。更精確的辦法是根據原先運行的結果進行統計從而嘗試預測分支是否會跳轉。

  任何一種分支預測策略的效果都取決於該策略本身的精確度和條件分支的頻率。

       SPARCMIPS的最早實現(作爲第一代商用RISC體系結構處理器)使用單方向靜態分支預測:總是預測條件跳轉不發生,因此總是順序取下一條指令投機執行。僅當條件跳轉指令被求值確實發生了跳轉,則非順序的代碼地址被加載執行。兩種CPU都是在解碼階段評價分支指令,取指令佔用1個週期。因此分支目標需要兩個週期(即經過了去指令、解碼兩個週期)才能確定。兩種處理器都會在分支指令進入流水線的執行階段時,插入一個分支延遲間隙。分支指令完成流水線的執行階段,就已經能確定是否跳轉,這時就可以決定是後續的順序出現的指令被繼續執行還是跳轉到的新指令進入流水。

    更復雜的靜態預測假定向後分支將會發生,向前的分支不會發生。向後分支,是指跳轉到的新地址比當前地址要低。這有助於配合經常出現的程序的循環控制結構。

    一些處理器允許分支預測提示出現在代碼中。Intel Pentium 4就是如此。但這一特徵在Intel此後的處理器中不再支持。

    靜態預測也用於某些處理器分支動態預測沒有任何可用信息時的一個最後的辦法。Motorola MPC7450 


動態分支預測:


    動態分支預測是近來的處理器已經嘗試採用的的技術。最簡單的動態分支預測策略是分支預測緩衝區(Branch Prediction Buff)或分支歷史表(branch history table)。

     BHT——Branch History Table,顧名思義,這是記錄分支歷史信息的表格,用於判定一條分支指令是否token;這兒記錄的是跳轉信息,簡單點的,可以用1bit位記錄,例如1表示跳轉,0表示不跳轉,而這個表格的索引是指令PC值;考慮在32位系統中,如果要記錄完整32位的branch history,則需要4Gbit的存儲器,這超出了系統提供的硬件支持能力;所以一般就用指令的後12位作爲BHT表格的索引,這樣用4Kbit的一個表格,就可以記錄branch history了。當然,通過大夥的不懈努力和分析,發現在BHT中用1bit位記錄分支是否跳轉還不夠準確,用2bit位記錄就非常好了,而用3bit或者更多位記錄,效果與2bit類似。所以在BHT中,一般就用2bit位記錄分支是否跳轉:例如11和10表示這條分支會跳轉;01和00表示分支不會跳轉。這個2bit計數器大夥叫做飽和計數器。


    BTB——用於記錄一條分支指令的跳轉地址,由於這兒存儲的是指令地址,例如32位地址,因此,這個表格就不能做到存儲BHT那樣多的內容了,如果也支持4K條指令,則需要128Kbit的存儲空間,這幾乎可以趕上一個L1Cache的容量了,所以BTB一般很小,就32項或者64項。由於這個BTB容量小,並且其用於是記錄分支指令的跳轉地址,因此,如果這條指令不跳轉,即其下一條指令就是PC+4,則不會在BTB中記錄的。


      基於BTB和BHT的分支預測就很簡單了:
      1)在取指階段利用PC尋址BTB,如果命中,則說明這是一條跳轉指令,利用從BTB中獲取到的地址去取icache;
      2)由於BTB中保存的內容不夠多,因此BHT的準確率更高,這個時候索引BHT表格,如果發現BHT也跳轉,則說明這條指令預測是跳轉的;如果BHT不跳轉,則說明不跳轉,這個時候就取消BTB中的指令地址,重新PC+4去取icache;

  


一些典型預測器介紹:

飽和計數

    飽和計數其(saturating counter)或者稱雙模態預測其(bimodal predictor)是一種有4個狀態的狀態機


    2位飽和計數器

·         強不選擇Strongly not taken

·         弱不選擇Weakly not taken

·         弱選擇Weakly taken

·         強選擇Strongly taken

當一個分支命令被求值,對應的狀態機被修改。分支不採納,則向強不選擇方向降低狀態值;如果分支被採納,則向強選擇方向提高狀態值。這種方法的優點是,該條件分支指令必須連續選擇某條分支兩次,才能從強狀態翻轉,從而改變了預測的分支。

最初的不具有MMXIntel Pentium處理器使用了這種飽和計數器。雖然實現不夠完美。

SPEC'89 benchmark測評中飽和預測達到了93.5%正確率,如果每條條件分支指令都映射了自己的計數器。

預測器表使用條件分支指令的地址作爲索引。因此處理器可以在分支指令解碼前就給它分配一個預測器。


兩級自適應預測器:

 

    兩級自適應預測器。pattern history table中的每個條目是上文的2位飽和計數器。

    對於一條分支指令,如果每2次執行發生一次條件跳轉,或者其它的規則發生模式,那麼用上文提到的飽和計數器就很難預測了。如圖所示,一種二級自適應預測器可以記住過去n次執行該指令時的分支情況的歷史,可能的2n種歷史模式的每一種都有1個專用的飽和計數器,用來表示如果剛剛過去的n次執行歷史是此種情況,那麼根據這個飽和計數器應該預測爲跳轉還是不跳轉。

    例如,n = 2。這意味着過去的2次分支情況被保存在一個2位的移位寄存器中。因此可能有4種不能的分支歷史情況:00, 01, 10, 11。其中0表示未發生跳轉,1表示發生了分支跳轉。現在,設計一個模式歷史表(pattern history table),有4個條目,對應於2n= 4種可能的分支歷史情況。4中歷史情況的每一種都在模式歷史表對應於一個2位飽和計數器。分支歷史寄存器用於選擇哪個飽和計數器供現在使用。如果分支歷史寄存器是00,那麼選擇第一個飽和計數器;如果分支歷史寄存器是11,那麼選擇第4個飽和計數器。

    假定,例如條件跳轉每隔2次執行就發生一次,即分支情況的歷史串行是001001001...。在這種情況下,00對應的飽和計數器將是狀態強選擇strongly taken),表明在兩個0之後必然是出現一個101對應的飽和計數器將是狀態強不選擇strongly not taken),表示在01之後必然是出現一個0。這也同樣適用於10狀態。而11狀態從未使用,因爲不可能出現連續兩個1

      2級自適應預測器的一般規則是n位分支歷史寄存器,可以預測在所有n週期以內出現的所有的重複串行的模式。

      2級自適應預測器的優點是能快速學會預測任意的重複模式。此方法1991年被提出。 已經變得非常流行。以此爲基礎很多變種方法被用於現代微處理。


本地分支預測:

本地分支預測(local branch predictor)對於每個條件跳轉指令都有專用的分支歷史情況緩衝區;模式歷史表可以是專用的,也可以是所有條件分支指令共用。

Intel Pentium MMX, Pentium II, Pentium III使用本地分支預測器,記錄4位的歷史情況,每條條件跳轉指令使用專用的本地模式歷史表,當然是包含24= 16個條目。

SPEC'89 benchmark測評,非常大的本地預測器的正確率達到97.1%


全局分支預測:

全局分支預測器(global branch predictor)並不爲每條條件跳轉指令保持專用的歷史記錄。相反,它保持一份所有條件跳轉指令的共用的歷史記錄。優點是能識別出不同的跳轉指令之間的相關性。缺點是歷史記錄被不相關的不同的條件跳轉指令的執行情況稀釋了(diluted);甚至歷史記錄沒有一位是來自同一個分支指令,如果有太多的不同的分支指令。

這種方法只有在歷史緩衝區足夠長,才能發揮出性能。但是模式歷史表的條目數是歷史緩衝區位數的指數量級。因此只能是在所有的條件跳轉指令間共享這個大的模式歷史表。

AMDCPU,以及IntelPentium M, CoreCore 2使用了此種方法。

SPEC'89 benchmark評測,非常大的gshare預測器達到了96.6%正確率,略低於本地分支預測。


融合分支預測:

    融合分支預測器(alloyed branch predictor組合了本地與全局預測原理,把本地與全局的分支歷史情況連接(concatenating)起來。VIA Nano處理器可能採用此方法。

    Tournament預測器:整體局部自適應預測器
    Tournament預測器通過使用多個預測器-----其中一個基於全局信息,另一個基於局部信息,通過一個選擇器將二者結合,而將這種方法又向前推進了一步。




    Tournament預測器的先進性在於,它可以爲特定的轉移選擇正確的預測器,而這一點對於定點基準測試程序來說十分關鍵。Alpha的Tournament預測器由局部轉移地址索引的4K個2bit計數器,在全局預測器和局部預測器間進行選擇。

    全局預測器共有4K個入口,由最近執行的12個轉移進行索引:其中每個入口爲一個標準2bit預測器。局部預測器由兩層組成。上層是由1024個10bit入口組成的局部歷史表;每一個10bit入口對應這個轉移最近10次的執行情況。

    局部歷史表中被選中的入口用來對一個表進行索引,這個表由1K個入口組成,每個入口爲3bit飽和計數器,該計數器用來進行局部預測。這種組合共使用了4K*2 +4K*2+1K*10 + 1K*3=29K bit。錯誤率在1.6%~4%之間。



Agree預測器:

Agree預測器是一種兩級自適應全局預測器,但是附加了一個bias飽和計數器,用來記錄歷次預期的準確度。最終輸出結果是全局預測與bias飽和計數器的異或Intel Pentium 4使用了此種方法,但此後的Intel處理器放棄了此種方法。


循環預測器:

    程序循環的控制部分所對應的條件跳轉指令最好用專門的循環控制器來預測分支。將要重複N次的循環的底部的條件跳轉指令,前N-1次選擇跳轉,只有一次不跳轉而是順序執行。條件跳轉指令有很多次選擇了一條分支,只有一次選擇另一分支,這種行爲將被作爲循環行爲被檢測。這種條件跳轉指令可以用簡單的計數器很容易地檢測出來。循環預測器是一種混合預測器,其中元預測器判斷該條件跳轉指令是否具有循環行爲。許多微處理器現在都有循環預測器。


間接跳轉預測:

    間接跳轉指令(indirect jump)是指操作數不是要轉去的下一條指令地址(這是直接跳轉),而是一個存儲位置(寄存器或者內存),這個存儲位置的內容纔是要轉去的下一條指令地址。例如je EAX,表示在ZF標誌寄存器爲1情況下,跳轉到寄存器EAX所保存的內存地址開始的代碼快。

    間接跳轉指令可以選擇多於兩條分支的執行路線。IntelAMD的更新的處理器使用兩級自適應預測器能預測間接跳轉。間接跳轉指令在歷史緩衝區貢獻了超過1位的表示。沒有這種預測機制的處理器,就簡單地預測間接跳轉指令是否會如同上次一樣選擇同一目標。


函數返回的預測:

    許多處理器有專門用於表示函數調用返回地址的return stack buffer


overriding分支預測:

    快速與精確,是分支預測需要平衡的兩個性能指標。有時就設置兩個分支預測器。第一個是簡單且快速。第二個是更慢、更復雜、表更大、可以覆蓋第一個預測器作出的預測。

      Alpha 21264Alpha EV8處理器使用一個快速的、單週期的下一行(next line)預測器處理分支目標,提供一個簡單快速的分支預測。兩個微處理器都有更復雜的、兩個週期的分支預測其,可以覆蓋下一行預測器的不準確的結果。

      Intel Core i7有兩個分支目標預測器(Branch target predictor),可能有兩個或更多分支預測器。


神經分支預測器:

      1999年提出的神經分支預測器(neural branch predictor。突出優點是能夠利用很長的歷史記錄,僅導致了資源的線性增長。而傳統預測器的資源需要量與歷史長度是指數增長關係。這種方法主要缺點是高延遲。

   神經分支預測器的準確度非常突出。(參見Intel's "Championship Branch Prediction Competition" )。IntelIA-64的模擬器 (2003)中實現了這一方法。


其它總結性文獻可參考論文: 《處理器分支預測研究的歷史和現狀》———馮子軍 肖俊華 章隆兵





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章