亂序執行會(huì )給CPU帶來(lái)額外開(kāi)銷(xiāo)嗎?
來(lái)源于小伙伴提問(wèn)。
以下是我的一些看法。
在亂序執行的CPU架構中,指令的實(shí)際執行順序與程序中原本的順序可能不一致。CPU可以根據指令之間的依賴(lài)性,在允許的范圍內重新安排指令的執行順序,以提高并行性,從而提升性能。亂序執行通過(guò)這樣的方法減少流水線(xiàn)停頓(stall),從而更好地利用CPU的執行單元。
舉個(gè)例子,代碼A與代碼B的性能對比:
代碼A:經(jīng)過(guò)完美優(yōu)化,沒(méi)有指令間依賴(lài)導致的停頓。在這種情況下,即使亂序執行引擎重排指令,最終的指令順序和原本順序會(huì )大體相同,因為代碼已經(jīng)被優(yōu)化到最小依賴(lài)性。對于代碼A,亂序執行能進(jìn)一步提升的空間較小,因為沒(méi)有額外的指令重排能夠提高并行性。
代碼B:存在依賴(lài),如果按順序執行會(huì )有停頓。亂序執行引擎在處理代碼B時(shí),可以重新安排指令的執行順序,來(lái)隱藏這些依賴(lài)關(guān)系引起的停頓。雖然代碼B原本的順序較差,但是亂序執行可以通過(guò)重排指令使得性能接近代碼A的水平。
因此,在這種假設的情況下(不考慮亂序窗口的限制),代碼B可以通過(guò)亂序執行引擎來(lái)消除其劣勢,最終性能接近代碼A。但是,這并不意味著(zhù)兩者在所有情況下都會(huì )有相同的性能。
因為:
亂序執行的額外開(kāi)銷(xiāo):雖然亂序執行可以提升性能,但重排指令、跟蹤依賴(lài)關(guān)系、硬件重命名寄存器等操作本身是有代價(jià)的。如果代碼A已經(jīng)完美優(yōu)化,在亂序執行時(shí)需要的重排和依賴(lài)處理會(huì )更少,相對來(lái)說(shuō)能更好地利用CPU資源。
亂序窗口的限制:亂序執行有一個(gè)窗口(out-of-order window),只能在窗口范圍內的指令中進(jìn)行重排。如果代碼B的依賴(lài)關(guān)系較為密集,亂序窗口可能不足以完全消除停頓。
1
是否還有必要對匯編代碼進(jìn)行優(yōu)化?
亂序執行雖然能提升CPU指令吞吐量,但手動(dòng)優(yōu)化匯編代碼依然很有意義,原因如下:
減少亂序執行引擎的負擔:手動(dòng)優(yōu)化代碼可以減少亂序執行過(guò)程中對指令重排和依賴(lài)分析的需求,使得CPU執行更為高效。例如,如果能夠手動(dòng)消除依賴(lài)關(guān)系或者調整指令順序,就能減少亂序執行的重排開(kāi)銷(xiāo)。
提升并行性:亂序執行的硬件能力是有限的,手動(dòng)優(yōu)化代碼可以更好地利用多執行單元的并行能力。例如,交錯使用整數運算和浮點(diǎn)運算指令,或者同時(shí)執行內存訪(fǎng)問(wèn)和計算操作。
硬件特性:不同的CPU對亂序執行的支持程度不同,優(yōu)化代碼可以更好地針對特定硬件特性。例如,有些老舊或低功耗CPU的亂序執行能力較弱,這種情況下代碼的手動(dòng)優(yōu)化顯得尤為重要。
2
在亂序執行基礎上進(jìn)一步優(yōu)化的技巧
減少數據依賴(lài)性:盡量減少指令之間的數據依賴(lài),例如通過(guò)增加指令間的運算、緩存臨時(shí)結果到寄存器來(lái)減少對之前指令結果的依賴(lài)。
減少內存訪(fǎng)問(wèn)延遲:內存訪(fǎng)問(wèn)是指令停頓的主要來(lái)源之一,可以通過(guò)軟件預?。╬refetching)、增加緩存命中率(合理使用數據結構)等手段,降低訪(fǎng)問(wèn)延遲。
避免寄存器重命名沖突:亂序執行依賴(lài)寄存器重命名技術(shù)來(lái)消除偽依賴(lài)(false dependency)。可以通過(guò)合理安排寄存器使用,減少重命名沖突。
利用指令并行性:在指令間隙中插入無(wú)關(guān)操作,使得更多的指令可以并行執行。例如,將計算指令與加載指令交錯安排,減少流水線(xiàn)的停頓。
合理使用分支預測:盡量減少分支錯誤預測帶來(lái)的流水線(xiàn)清空,重排代碼或者避免難以預測的分支。
雖然亂序執行可以大大減少流水線(xiàn)停頓,但代碼優(yōu)化仍能顯著(zhù)提升性能。對于追求極致性能的場(chǎng)合,手動(dòng)優(yōu)化匯編代碼依然不可或缺。
*博客內容為網(wǎng)友個(gè)人發(fā)布,僅代表博主個(gè)人觀(guān)點(diǎn),如有侵權請聯(lián)系工作人員刪除。