2011-04-14 90 views

回答

12

大多數現代處理器prefetch指令,甚至speculatively execute他們之前,代碼流已經達到了該指令。有一個分支意味着突然有兩個不同的指令可能是下一條指令。有至少三種可能的方式,這可以與預取相互作用:

  • 分支之後的指令不被預取。 instruction pipeline變空,處理器必須等待下一個指令在最後一刻被取出,從而導致性能下降。
  • 處理器可以猜想哪個分支將被採取(branch prediction)並預取並執行相應的指令。如果它猜到了錯誤的分支,它將不得不放棄已完成的工作,並等待正確的指令被提取。
  • 處理器可以獲取並執行兩個分支,然後丟棄未採取分支的結果。

根據處理器和特定代碼的不同,與沒有分支的等效代碼相比,分支可能會或可能不會產生顯着的性能影響。如果執行代碼的處理器使用分支預測(大多數情況下)並且大部分都是針對特定代碼正確猜測的,那麼它可能不會對性能產生重大影響。另一方面,如果它大多猜錯了,它可能會導致巨大的減速。

可能很難預測某個特定代碼是否移除分支會顯着加速代碼。當微觀優化時,最好測量兩種方法的性能而不是猜測。

1

因爲處理器不知道它應該預取哪些指令來執行,如果你給它的可能性。在分支以不是預期的方式運行的情況下,它必須刷新指令流水線,因爲那些加載的指令現在是錯誤的,並且使其週期變慢...

2

這很壞,因爲它會干擾instruction prefetch。現代處理器可以開始加載下一個命令的字節,同時仍然處理第一個字節,以便運行更快。當一個分支發生時,被預取的「下一個命令」必須被丟棄,這浪費了時間。在一個緊密的循環或類似的內部,這些錯過的預取可以加起來。

1

除了預取的問題,如果你跳,你沒有做其他工作......

0

如果你仔細想想的汽車組裝線,你聽到這樣的話汽車的X號脫落一天中的線路。這並不意味着原材料從生產線開始,X數量在一天內完成了整個運行。誰知道它可能不會,但每輛車開始和結束可能需要幾天,這就是裝配線的重點。想象一下,如果出於某種原因,你有一個製造變更,你基本上不得不沖洗線上的所有車輛,並在其他時間將其廢棄或打撈其他車輛。要裝配這條裝配線需要一段時間,並且每天返回X輛汽車。

處理器中的指令流水線工作方式完全相同,流水線中沒有數百個步驟,但概念是相同的,即每個時鐘週期執行一個或多個指令的執行速率(X個汽車數日),你需要保持這條管道平穩運行。所以你預取,燒了一個內存循環,這通常是緩慢的,但層緩存幫助。解碼,需要另一個時鐘,執行,可能需要很多時鐘,特別是像x86一樣的CISC。當你執行一個分支時,在大多數處理器上,如果你考慮一般的簡化流水線,你必須丟棄指令執行和預取,基本上是你的流水線的2/3。然後,您必須等待這些時鐘才能進行提取,並在您恢復平穩執行之前進行解碼。除此之外,根據定義,取指不是下一條指令,某些百分比的時間不僅僅是一條緩存線,還有一些時間百分比,這意味着從內存或更高層的緩存中獲取更多時鐘週期比如果你線性執行。另一個常見的解決方案是一些處理器聲明不管分支指令之後的指令是什麼,或者有時在分支指令之後的兩條指令總是被執行。通過這種方式,您可以在刷新管道時執行此操作,一個好的編譯器會安排這些指令,以便每個分支之後的其他內容都是nop。懶惰的方法是在每個分支之後放置一兩個nop,創建另一個性能命中,但對於該平臺,大多數人都會使用它。第三種方式是ARM執行條件執行。簡而言之,前向分支並非都不常見,而是如果條件爲分支,則標記您要分支的幾條指令,如果不是條件,則執行它們,然後執行解碼並執行,並執行爲nops和管道繼續前進。 ARM依靠傳統的沖洗和重新填充更長或更後的分支。

舊版x86(8088/86)手冊以及其他舊版處理器手冊以及微控制器手冊(新舊版本)仍將發佈每個指令執行的時鐘週期。對於分支指令,如果分支發生,它會說增加x個時鐘。你現代的x86,甚至是ARM和其他處理器,用於運行Windows,Linux或其他(笨重和慢速)的操作系統都不用麻煩,他們經常只是說它每時鐘運行一條指令,或者談論mips到兆赫或類似的東西,而不一定每條指令有一個時鐘表。你只假設一個,並記住它就像一輛汽車每天,它最後執行時鐘而不是其他時鐘到達那裏。微控制器人員特別處理每條指令不一個時鐘,並且必須比普通桌面應用程序更多地意識到執行時間。看看其中一些Microchip PIC(不是PIC32,這是mips),msp430,絕對是8051的規格,雖然那些是或由許多不同的公司製造的,但它們的時序規格差異很大。底線,對於桌面應用程序甚至操作系統上的內核驅動程序,編譯器效率不高,操作系統增加了更多的開銷,您幾乎不會注意到時鐘節省。切換到微控制器並放入太多分支,代碼速度降低2到3倍。即使使用編譯器而不使用匯編器。如果使用編譯器(不用匯編語言編寫),則可以使代碼慢2到3倍,因此必須在開發,維護和可移植性與性能之間取得平衡。

+0

非常好的總結! – 2011-04-14 14:35:26