2011-12-12 20 views
50

在用C++編寫 見梅德Vyukov的優秀界MPMC隊列:http://www.1024cores.net/home/lock-free-algorithms/queues/bounded-mpmc-queue如何以及何時對齊緩存行大小?

他補充一些填充變量。我認爲這是爲了使其與高速緩存線對齊以獲得性能。

我有一些問題。

  1. 爲什麼這樣做?
  2. 它是一個便攜式的方法,將 總是工作
  3. 在什麼情況下,這將是最好使用__attribute__ ((aligned (64)))代替。
  4. 爲什麼在緩衝區指針幫助執行之前填充?不僅僅是加載到緩存中的指針,所以它只是指針的大小?

    static size_t const  cacheline_size = 64; 
    typedef char   cacheline_pad_t [cacheline_size]; 
    
    cacheline_pad_t   pad0_; 
    cell_t* const   buffer_; 
    size_t const   buffer_mask_; 
    cacheline_pad_t   pad1_; 
    std::atomic<size_t>  enqueue_pos_; 
    cacheline_pad_t   pad2_; 
    std::atomic<size_t>  dequeue_pos_; 
    cacheline_pad_t   pad3_; 
    

將根據海灣合作委員會這個概念適用於C代碼?

回答

34

這樣做是爲了讓修改不同字段的不同內核不必在其緩存之間彈出包含它們的緩存行。通常,對於處理器訪問內存中的某些數據,包含它的整個緩存行必須位於該處理器的本地緩存中。如果正在修改該數據,則該緩存條目通常必須是系統中任何緩存中的唯一副本(MESI/MOESI風格緩存一致性協議中的獨佔模式)。當單獨的內核嘗試修改發生在同一緩存行上的不同數據並因此浪費時間來回移動整行時,這就是所謂的虛假共享

在你給,一個芯可以被入隊的條目的特定示例(讀取(共享)buffer_和寫入(不含)僅enqueue_pos_),而另一出隊(共享buffer_和獨佔dequeue_pos_),而不任一芯上的高速緩存線失速由另一方擁有。

開頭處的填充意味着buffer_buffer_mask_最終位於同一高速緩存行,而不是分成兩行,因此需要雙倍的內存訪問量才能訪問。

我不確定這項技術是否完全可移植。 假設每個 cacheline_pad_t本身都會對齊到一個64字節(它的大小)的緩存行邊界,因此它會在下一個緩存行中進行任何操作。據我所知,C和C++語言標準只需要整個結構的這種標準,這樣他們就可以很好地生活在陣列中,而不會違反其任何成員的對齊要求。

attribute方法會更具體編譯器,但可能會將此結構的大小減半,因爲填充限制爲將每個元素四捨五入到完整的緩存行。如果有很多這些,這可能是非常有益的。

相同的概念適用於C以及C++。

+0

@Novelcrat - 好吧,這很有意義。那麼問題2和3呢? – Matt

+9

@MattH:爲便於攜帶,C++ 11引入了'std :: aligned_storage',它允許您要求存儲已定義的大小和對齊方式。否則,'char [N]'的默認對齊方式爲'1'。 –

+1

爲什麼鏈接器不優化填充變量如果不使用? – RishiD

相關問題