簡體   English   中英

x86匯編pushad / popad,它的速度有多快?

[英]x86 Assembly pushad/popad, How fast it is?

我只是想嘗試在x86程序集中進行非常快速的基於計算的程序,但我需要在調用程序之前推送累加器,計數器和數據寄存器。 手動推動它們的速度更快:

push eax
push ecx
push edx

或者只是使用,

pushad

與彈出一樣。 謝謝

如果你關心性能, pusha / popa幾乎從來popa 它們僅在以速度為代價優化代碼大小時才有用,例如在函數周圍保存/恢復寄存器。 但是對於非void函數來說非常不方便,因為它們會重新加載所有寄存器,因此你必須將返回值存儲在內存中(例如,在將被加載到eax的堆棧槽中,或者在popad之后重新加載的其他地方)。

只推送需要保存的寄存器 ,或者想要作為函數args傳遞的寄存器 或者, ,只需讓編譯器通過為任何臨時寄存器聲明"=r"(dummy1)虛擬輸出操作數來管理寄存器,或者在特定寄存器上使用clobbers。 通常情況下,編譯器可以選擇它可以讓你破壞但不保存的寄存器。 (或者在笨重的MSVC樣式的內聯asm中,編譯器無法為您分配寄存器,因此您必須手動選擇。編譯器解析您的asm以查找clobbers。)

您通常不需要保存/恢復eax ; 對於性能,你可能應該移動mov esi, eax / call /使用esi的值,如果你不能首先計算esi中的值。 即使用調用保留寄存器來獲取需要在call存活的值 ,因此重要值的存儲/重新加載不在關鍵路徑上。 相反,存儲/重新加載位於調用者的一個調用保留寄存器的關鍵路徑上,您(或編譯器)在任何循環之外push / pop整個函數。


即使您確實想要推送所有8個整數寄存器(包括esp !) ,在現代CPU上使用8個單獨的push指令實際上更快。 pusha / popa是微編碼的, 這可能是前端的問題 (雖然8個單字節指令也可能是uop-cache的一個問題。但在實際代碼中,你通常只需要推幾個寄存器,而不是所有寄存器。)

如果您正在優化過時的CPU(如原始的有序Pentium和Pentium II / III),pusha / popa的速度與8 push r或8 pop r一樣快,實際上更少的uops,因為它們沒有堆棧引擎消除ESP更新uops。

來自Agner Fog的指令表 :現代CPU具有單uop push regpop reg ,因為這些指令一直被編譯器使用,因此對性能很重要。 推/彈吞吐量通常匹配存儲/負載吞吐量(通常每個時鍾1個存儲或每個時鍾2個負載)。 popa器不使用pusha / popa ,因此CPU設計人員沒有特別的支持來使它們快速。 如果運行popa popa吞吐量僅限於每個時鍾1個負載。 (我認為在Intel CPU上,測量性能最可能的解釋是popa不使用堆棧引擎,所以它依賴於esp 。)

英特爾:

  • Skylake: pusha :11 uops,8c吞吐量。 popa :18 popa / 8c吞吐量。
  • Sandybridge: pusha :16 uops / 8c吞吐量。 popa :18 popa / 9c吞吐量。
  • Nehalem: pusha :18 uops / 8c吞吐量。 popa :10 popa / 8c吞吐量。
  • Silvermont / KNL: pusha :10 uops / 10c吞吐量。 popa :17 popa / 14c吞吐量。
  • Pentium4: pusha :4/10 uops / 19c吞吐量。 popa :4/16 popa / 14c吞吐量。
  • P5奔騰1 / MMX:5-9個循環,不可配對。 “如果SP可被4整除(不完美的配對),則為9。”

AMD: pusha / popa在一些AMD CPU上出奇的好,尤其是K8。

  • Ryzen: pusha :9 uops,8c吞吐量。 popa :9 popa4c吞吐量 (與英特爾不同,AMD的新設計popa並不比8倍pop差。)
  • 美洲虎: pusha :9 uops / 8c吞吐量。 popa :9 popa / 8c吞吐量。 (捷豹每個時鍾通常只能負載一次。)
  • 打樁機: pusha :9 uops / 9c吞吐量。 popa :14 popa / 8c吞吐量。 (Agner將Bulldozer系列的常規pop reg吞吐量列為每時鍾1個,雖然我認為它們確實有堆棧引擎並且每個時鍾可以執行2次加載。也許堆棧引擎一次只能處理一個堆棧指令?)
  • K8: pusha :9 uops / 4c吞吐量!! (IDK如何可能,這是表中的錯誤或拼寫錯誤,或者K8合並32位寄存器並執行四個64位存儲)。 popa :9 popa / 4c吞吐量。 這些數字似乎確實是真實的: InstLatx86測量結果與Clawhammer(第一代K8微體系結構)上的pushad / popad 4c吞吐量一致。 顯然,AMD在優化pushad方面付出了一些努力。

您標記了此 通常你應該避免在inline-asm中使用call ,所以C編譯器知道這個調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM