天天看點

什麼是分支預測

聽說這個屬于cpu的範疇,CPU中,為了提高執行的性能,CPU的多個單元會同時執行多條指令。例如當取址單元正在尋找下一條指令前,上一條指令的譯碼和執行已經在進行中了,這一套機制被稱作CPU流水線(pipeline)。

CPU流水線架構把指令的執行分為了多個階段,每個單元隻負責完成指令執行過程中的一個階段,而中間結果由專門的流水線寄存器暫存。這樣理論上,一條指令的執行假設被分為5個階段,那麼當5個單元同時運作一段時間後,理論上相同時間可以同時執行5條指令,當然這隻是最簡單的情況,實際的情況要複雜得多。

流水線的引入相當于程式中引入了并發,相應的,會帶來很多額外的問題。例如為了更好地讓指令流水般地執行,不涉及順序一緻性的指令會被重排序。這裡不詳細讨論太多流水線的技術細節,隻要知道指令并不是一條一條順序執行的,那樣會嚴重阻礙處理器的性能。

CPU流水線引入的目的在于,希望能夠在每個CPU的時鐘周期都發射一條新的指令,這樣理論上可以達到最高效率。但這有一個前提:如果指令的執行是“每個時鐘周期”一條,那麼指令的取值也必須達到每個時鐘周期一條,如此,當你在取址階段拿到要執行的指令時,下一條指令的位址必須被确定了,否則下一個時鐘周期便無法取出對應的指令。

這将引發一個問題:

對于條件跳轉指令(彙編層面是JMP等,代碼層面例如if),需要等目前的指令執行完才知道結果是true還是false,也就是說,要等待若幹個時鐘周期後,CPU才可以确定下一條要執行的指令究竟是哪個分支的。

難道這段時間就隻能幹等着嗎?當然不是,這裡CPU就會采取「分支預測」的方式,預測下一條要執行的分支指令,并預先執行,如果if執行完後發現和預測的分支一緻,那就中大獎了,整個執行階段一點都沒有暫停。但如果悲劇地預測錯誤,那麼這時候必須從取址開始,重新執行另一個分支的指令。

從中顯然可以看出,預測錯誤消耗的代價要比幹等着更大。

為了提高CPU預測的正确性,有多種算法,但是我們可以先思考一下最簡單的方案。

首先,從常理上來考慮,如果遇到一個if分支,那麼很有可能某一個分支的執行機率要大于另一個。這跟我們的編碼風格有關,例如在校驗參數是否合法的過程中,有的人喜歡嵌套if一直到滿足一個最嚴格的條件,然後執行,這種情況對應了if為true的情況;另一種人喜歡先把其它條件都排除掉,例如null判斷等,等不合法的都被排除後,這時候再執行,這種情況對應if為false的情況。

總之這就是CPU的分支預測,其他内容詳見:https://yq.aliyun.com/articles/26556?do=login&accounttraceid=0b86ac89-9e23-4513-885b-b7eb773357c8。

繼續閱讀