2014-09-06 89 views
1

我正在研究一些旨在在32位模式下在x86上運行的代碼。在這種模式下,我明白我只有8個SIMD/AVX2寄存器(YMM0-7)可以自由使用。然而,單獨的一些矢量子程序有時候會使用的寄存器數量超過了這個數量(這意味着它們仍然需要在路上的某個地方 - 大多數情況下並不是那麼晚)。導出寄存器對堆棧的性能影響是什麼?

我的理解是,當編譯器找不到未使用的寄存器時,會將較舊的寄存器導出到堆棧存儲器。但這對性能有多大影響? (例如稍後在每個導出/導入的週期中)。我可以信任大部分駐留在L1-D-Cache中的堆棧內存(Haswell中有2個週期的延遲),還是存在避免這種寄存器到內存(反之亦然)傳輸的顯着性能影響?

到目前爲止,我無法找到答案的這個話題,特別是因爲寄存器保持越來越大(每個寄存器1級的高速緩存行與即將到來的SKYLAKE微架構平臺)。如果你回答的話可以提供資料,這將是很好的。

+3

你的代碼,當然會比較慢。如果您想了解多少,那麼簡單地分析您的代碼,比較32位和64位版本。只有你可以做到這一點。 – 2014-09-06 20:58:53

+0

出於好奇。你爲什麼只限於32位模式? Core2在九年前就出來了。由於Nehalem(2008)的宏觀操作融合工作在64位模式下。明年推出的AVX512將在64位模式下有32個AVX512寄存器,在32位模式下只有8個。爲什麼要限制你的代碼只有32位模式? – 2014-09-07 09:18:01

+0

我同意你們兩個。看起來我需要對它進行基準測試,看看它是否更好地調整我的內涵。需要32位支持,因爲有些工作站仍然只能運行32位操作系統。不過,問題將會是相同的,無論是8個還是16個註冊,都不太嚴重。 – 2014-09-08 09:25:35

回答

1

總是有打記憶產生影響。

寫入通常是緩慢的。然而,如果你只打一級緩存,它接近瞬間(幾乎與將一個寄存器複製到另一個相同)。如果你擊中L2或L3,速度較慢,但​​仍然非常快。如果你打到實際的內存,那就是「死」(相比而言)。所以如果你的L1緩存是12Kb,你的堆棧中可以有多達12Kb的數據,並且仍然工作得很快(儘管記住緩存是在你的數據之間共享的和你正在運行的代碼;它可能是指令緩存和6KB數據6KB包括堆棧)

你會打的主要問題是你有多少內存工作。如果您的輸入數據非常大,那將會產生最大的影響。特別是如果您無法以流式處理方式加載輸入數據,而處理器已經過優化。 (從(eax)讀取X字節,執行eax + X,然後重複)。

請注意,如果你把它寫在彙編中,你必須做的一切,編譯器可以爲您提供零個錯誤和全面優化做的工作。今天的編譯器非常擅長優化(gcc/g ++)。當你壓入堆棧時,它變得特別複雜,改變當前堆棧中所有局部變量的偏移量(除非你使用幀指針)。

作爲另一個細節,編譯器將堆棧視爲從一個函數中必需的所有局部變量的集合。因此訪問堆棧與訪問結構非常相似。

+0

哪個x86微架構與AVX2有一個**統一的** L1緩存12kb?此外,它被稱爲「幀指針」或「基本指針」,而不是「幀緩衝區」。 – EOF 2014-09-07 07:49:34

+0

我將使用C/C++與avx intrinsics相結合。爲了更清楚:用於例如通過例如用於寄存器保存(堆棧)「熱」(駐留在L1中)的存儲器。幾乎所有的時間都在使用?理論上,編譯器供應商應該以這種方式實現它,但我不確定,因爲它容易用avx寄存器填充許多緩存線,特別是當它使用對齊的存儲庫時。 – 2014-09-07 19:43:39

+2

是的,從這個意義上說,99.9%的時間你的籌碼將「熱」。這將取決於操作系統而不是編譯器(即,您可以強制堆棧內存始終寫入RAM)。編譯器可能是一個問題,如果它傳播的數據「超過必要」,但這不太可能是一個問題。你可能會碰到的是讀取代替堆棧在L1緩存中的新數據。現在,具有內在指令的很酷的事情是,您可以使用寄存器的標籤,並且編譯器會自動將CPU寄存器關聯起來,給它一個進一步優化的機會。 – 2014-09-07 22:36:13