簡體   English   中英

對齊數據成員和成員函數以提高性能

[英]Alignment of data members and member functions for performance

對齊結構/類的數據成員是否真的不再產生它曾經使用過的好處,尤其是在因硬件改進而導致的Nehalem上? 如果是這樣,那么對齊是否仍會始終提供更好的性能,與過去的CPU相比,只有很小的顯着改進?

成員變量的對齊是否擴展到成員函數? 我相信我曾經讀過(可能在Wikibooks“ C ++ performance”上),有規則將成員函數“打包”到各種“單元”(即源文件)中,以便最佳地加載到指令緩存中? (如果我在這里用錯了術語,請糾正我)。

處理器仍然比RAM可以提供的速度快得多,因此它們仍然需要緩存。 緩存仍然由固定大小的緩存行組成。 同樣,主存儲器以頁交付,並且使用轉換后備緩沖區訪問頁面。 同樣,此緩沖區具有固定大小的緩存。

這意味着空間和時間的局部性都非常重要 (例如,如何打包東西以及如何訪問東西)。 很好地包裝結構(按填充/對齊要求排序),而不是按某種偶然的順序包裝它們,通常會導致結構尺寸更小。

較小的結構尺寸意味着,如果您有大量數據:

  • 一條緩存​​行中可容納更多結構(緩存未命中= 50-200個周期)
  • 需要的頁面更少(頁面錯誤= 10-20百萬個CPU周期)
  • 需要更少的TLB條目,更少的TLB丟失(TLB丟失= 50-500個周期)

線性處理幾千兆字節的緊密打包的SoA數據,比天真地采用不良布局/打包方式進行相同操作要快3個數量級(如果涉及頁面錯誤,則要快8-10個數量級)。

無論您是否手動將單個 4字節或2字節值(例如,典型的intshort )對齊為2或4字節,在最近的Intel CPU上差異都很小(很難注意到)。 就此而言,似乎似乎很想“對此進行優化”,但我強烈建議不要這樣做。
通常這是最好的事情,不用擔心,讓編譯器找出來。 如果沒有其他原因,那么說這種增益充其量是微不足道的,但是如果您弄錯了,其他一些處理器體系結構將引發異常。 因此,如果您試圖變得太聰明,那么在其他體系結構上進行編譯時,您將突然發生無法解釋的崩潰。 發生這種情況時,您會感到抱歉。

當然,如果您沒有至少幾十兆的數據要處理,則根本不需要關心。

對齊數據以適合處理器永遠不會受到傷害,但是某些處理器將比其他處理器具有更多明顯的缺點,我認為這是回答此問題的最佳方法。

將功能對齊到高速緩存行單元中對我來說似乎有點紅鯡魚。 對於小型函數,如果可能的話,您真正想要的是內聯。 如果無法內聯代碼,則無論如何它可能比高速緩存行大。 [當然,除非它是一個虛擬函數]。 我認為這不是一個很大的因素-要么代碼通常被調用,因此通常在緩存中被調用,或者它不經常被調用,並且在緩存中不被頻繁調用。 我敢肯定有可能提供一些代碼來調用一個函數,func1()也會將func2()拖入緩存,因此,如果您總是短時間連續調用func1()和func2(),它將一些好處。 但是,除非您有很多具有成對的或成對的函數組(稱為緊密函數)的函數,否則,這並不是什么好處。 [順便說一下,我不認為編譯器可以保證將函數代碼以任何特定順序放置,無論您將其放在源文件中的順序如何]。

緩存對齊稍有不同,因為如果正確和錯誤,緩存行仍然會產生巨大的影響。 對於多線程而言,這比常規的“加載數據”更為重要。 關鍵是要避免在處理器之間的同一緩存行中共享數據。 在大約10年前我從事的項目中,一個基准測試具有一個函數,該函數使用兩個整數組成的數組來計算每個線程進行的迭代次數。 當將其分成兩個單獨的緩存行時,基准測試從單個處理器上運行的0.6倍提高到一個處理器上的1.98倍。 即使它們的速度更快,也會在現代CPU上產生相同的效果-效果可能不完全相同,但是會大大減慢速度(並且共享數據的處理器越多,效果就越好,因此四核系統比雙核更糟糕,等等)。 這是因為每次處理器更新高速緩存行中的某些內容時,所有已讀取該高速緩存行的其他處理器都必須從更新它的處理器(或從過去的內存)中重新加載它。

暫無
暫無

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

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