2012-09-19 23 views
14

我總是聽說未對齊的訪問是不好的,因爲它們會導致運行時錯誤並導致程序崩潰或內存訪問速度緩慢。不過,我無法找到任何有關他們會減慢速度的實際數據。x86上成功的未對齊訪問的實際效果是什麼?

假設我在x86上並且有一些(未知的)未分配的訪問份額 - 實際上可能的最差放緩是什麼,以及如何估計它,而不消除所有未對齊的訪問並比較兩個版本的代碼的運行時間?

+0

憑經驗:未對齊的讀取大多數的架構導致〜2倍的性能命中相比,對齊的讀,因爲它需要兩個讀週期來獲取數據,並確定了。寫入有點複雜。 –

回答

13

這取決於指令,對於大多數x86 SSE加載/存儲指令(不包括未對齊的變體),它將導致錯誤,這意味着它可能會導致程序崩潰或導致大量往返你的異常處理程序(這意味着幾乎或全部的性能丟失)。未對齊的加載/存儲變量運行的週期數是IIRC的兩倍,因爲它們執行部分讀取/寫入操作,所以需要2個才能執行操作(除非您幸運並且它在緩存中,這大大減少了懲罰)。

對於一般的x86加載/存儲指令,懲罰是速度,因爲讀或寫需要更多的週期。未對齊也可能會影響緩存,導致緩存線分裂,並導致緩存邊界跨越。它還可以防止讀寫的原子性(這對於x86的所有對齊的讀/寫都是有保證的,障礙和傳播是另一回事,但是在未對齊的數據上使用LOCK'ed指令可能導致和異常,或者大大增加已經大規模的處罰bu鎖定發生),這對於併發編程來說是不允許的。

Intels x86 & x64 optimizations manual對每個上述問題,它們的副作用以及如何補救它們進行了詳細說明。

Agner Fog' optimization manuals應具有您正在尋找的原始循環吞吐量的確切數字。

+0

看過Agner Fog論文,但找不到具體的數字。你能指出我在正確的頁面/表格嗎? –

+0

@NitsanWakart:未對齊SSE指令,這裏列出:http://www.agner.org/optimize/instruction_tables.pdf,你需要諮詢的開發手冊中的相應英特爾章罰則正常指令的處罰(第8或9 IIRC,至少,未對齊的讀取需要雙倍的週期) – Necrolis

+0

我特別在使用最近的(後Core2)cpus查找未對齊(而非cacheline straddling)訪問上的MOV的處罰。在Agner的指令表中,我找不到任何懲罰,除了一般性建議以調整數據外,我無法在英特爾手冊中找到相關參考。 –

2

現代處理器的速度估計通常非常複雜。這不僅適用於未對齊的訪問,而且通常也適用。

現代處理器具有流水線架構,無序並且可能並行執行指令以及可能影響執行的許多其他事情。

如果不支持未對齊的訪問,則會發生異常。但是,如果支持,您可能會或可能不會放慢取決於許多因素。這些因素包括您在未對齊指令之前和之後執行的其他指令(因爲處理器可能能夠在執行先前指令時開始獲取數據,或繼續執行並在等待時執行後續指令)。

另一個非常重要的區別是,如果跨越緩存行邊界發生未對齊訪問。一般情況下,對於未對齊的訪問,可能發生兩次訪問高速緩存的情況,真正的減速是如果訪問跨越緩存行邊界並導致雙緩存未命中。在最糟糕的情況下,2字節未對齊的讀取可能需要處理器將兩條緩存線清除到內存,然後從內存中讀取2條線。這是一大堆數據移動。

優化的一般規則也適用於這裏:第一個代碼,然後測量,然後當且僅當有問題找出解決方案。

5

在某些英特爾微架構上,由緩存行邊界分割的負載需要比平常長數十個週期,而由頁邊界分割的負載需要長200個週期。如果負載在循環中始終未對齊,那麼這是非常糟糕的,值得做兩個對齊的負載並手動合併結果,即使palignr不是一個選項。即使SSE的未經調整的負荷也不會救你,除非他們完全分開。

在AMD的這從來就不是一個問題,問題主要集中在Nehalem的消失,但仍有大量的Core2的離開那裏了。

相關問題