2012-02-19 81 views
9

我有幾個類遭受緩存爭用,並與「新」運營商分配。我可以以某種方式確保「新」返回與緩存行對齊的地址嗎?C++中的假共享

我正在使用GCC(如果它不是可移植的)。

+1

緩存行通常是64個字節。你必須有一些非常小的類,因此必須執行很多很小的動態分配? – 2012-02-19 19:16:19

+0

有些很小,但大部分重疊(在緩存行中)。 – jk4736 2012-02-19 19:18:02

+0

你是單獨分配還是分配數組? – dasblinkenlight 2012-02-19 19:19:42

回答

1

您可以使用placement new構造一個對象到給定內存區域:

// Instantiate object into a pre-allocated buffer 
    obj = new (buf) TheClass(); 

爲了得到一個對齊的緩衝,buf,您可以使用memalignsbrkmmap

+0

我看不出問題與'mmap'之間的關係。爲什麼'mmap'? – Frunsi 2012-02-19 19:59:43

+2

您可以使用mmap分配一段對齊的內存塊... – mfontanini 2012-02-19 20:55:39

3

對於glibc或windows CRT系統,您可以分別使用memalign_aligned_alloc。你甚至可以使用像nedmalloc這樣的自定義分配器並讓它對齊塊,這也可以給你一些額外的獎勵。

你也應該用__attribute__((aligned(64)))來標記它們,以防萬一它們被靜態分配。

2

解決這個問題的最簡單方法是讓對象足夠大,以免共享緩存線。使用gcc你可以設置類的對齊(我假設你的對象是小然後高速緩存行,因爲你爭苦):

class foo {} __attribute__((aligned(2 * CL))); 

你需要插入正確的Cachelinesize您的架構,當然CL (或者把它放到一個宏中,並在那裏使用)。我使用了兩倍大小的緩存行,因爲從我記得的new不能保證它實際上會確保對齊被保留。由於該對象因此不能保證在高速緩存行的開始處開始,所以仍然可以在同一高速緩存行中獲得不同對象的部分(即一個對象的結尾,以及另一個的開始)。如果始終保持對齊,則__attribute__((aligned(CL)))就可以。當然這需要你改變你的結構並浪費很多空間。

您也可以根據memalign編寫自己的new(請查看here瞭解如何操作)。對於更加類似的解決方案,您也可以直接使用memalign,並使用placement new將對象放入分配的空間中。當然,它使得使用這些對象的代碼不太好。