2015-03-30 64 views
0

假設我有一個非常大的數據結構,它比我硬件的緩存行(見下面的示例)大得多。讓我們假設我想在大數據結構上緩存行檢索和性能

  1. 讀寫memb_one_位於第一高速緩存行
  2. 然後我想讀,寫後位於memb_forty_ 2高速緩存行。
  3. 現在我可能還想讀寫位於第二緩存行中的成員,即中間行memb_ten_中的成員。這並不總是發生。

所以我需要經常執行第1步和第2步,但不總是第3步。不幸的是,我無法更改結構的佈局。

我的問題如下:在步驟1和步驟2之後,是第二個緩存行,即中間的一個從內存中檢索到L1?

據我所知,在L1中檢索到的緩存行只是通過讀/寫位於其中的結構成員而「感動」的。這實際上意味着只有一部分結構的實例可以在L1中獲得。

如果我的理解是正確的,有沒有辦法強制所有3個緩存行的請求?我想避免在需要時通過寫入第二個緩存行來獲取緩存缺失。

如果沒有這樣的機制,您認爲我可以從共享相同緩存的後臺線程中受益,並頻繁閱讀這些實例以保持緩存行「熱」嗎?該線程永遠不會寫入,以避免錯誤的共享效應或過多的數據總線流量。

struct VeryBigStruct 
{ 
    // first cahce line.. 
    int memb_one_; 
    ... 

    // second cahce line.. 
    int memb_ten_; 
    ... 

    // third cache line 
    int memb_forty_; 
    ... 
} 

我在Linux上使用g++ 4.7 and 4.9

回答

1

不,第二個緩存行不能保證在第一個和第三個第一個緩存中。但如果訪問頻率足夠高,它可能就在那裏。

如果後臺線程運行在與主線程相同的物理內核中,那麼後臺線程可能只能幫助您將數據存入L1緩存。你可以爲你的線程設置CPU親和力來達到這個效果。

在GCC有一個內置函數預取的內存地址緩存, 它被稱爲是這樣的:

__builtin_prefetch(&your_struct_ptr->memb_ten_, 1, 3); 

或者你可以這樣做:

#include <xmmintrin.h> 
... 
_mm_prefetch(&your_struct_ptr->memb_ten_, _MM_HINT_ET0); 

在這裏看到:https://gcc.gnu.org/onlinedocs/gcc/Other-Builtins.html 和這裏:https://software.intel.com/en-us/node/524263

[我認爲你使用x86或x86-64架構。 ]

+0

@Alexey:非常感謝!我在想,我晚上把這個調用放在一個現有的線程中(在同一個核心上),它試圖通過'try_lock'來獲取互斥鎖。如果try_lock沒有成功,它會調用__builtin_prefetch – 2015-03-31 07:27:51

+0

如果先調用Prefetch,那麼Prefetch的效果最好,然後在其他某些東西上花費幾個CPU週期,讓CPU有時間在後臺執行請求,然後再回到真正的使用預取數據。 – 2015-03-31 10:19:15

+0

@Akexet:酷信息!非常感謝! – 2015-03-31 10:45:08