簡體   English   中英

C ++使用`.reserve()`來填充`std :: vector`s,以防止多線程高速緩存失效和錯誤共享

[英]C++ Using `.reserve()` to pad `std::vector`s as a way of protecting against multithreading cache invalidation and false sharing

我有一個程序,其結構如下所示。 基本上,我有一個對象矢量。 每個對象都有成員向量,其中一個是包含更多向量的結構向量。 通過多線程,對象被並行操作,進行涉及訪問和修改成員向量元素的計算。 一個對象一次僅被一個線程攻擊,並被復制到該線程的堆棧以進行處理。

問題是該程序無法擴展到16個核心。 我懷疑並且被告知該問題可能是虛假共享和/或緩存失效。 如果這是真的,似乎原因必須是矢量分配內存彼此太接近,因為我的理解是兩個問題(簡單來說)是由不同處理器同時訪問的近端內存地址引起的。 這種推理是否有意義,是否可能發生這種情況? 如果是這樣,似乎我可以通過使用.reserve()填充成員向量來解決這個問題,以增加額外的容量,在向量數組之間留下大的空內存空間。 那么,這一切都有意義嗎? 我完全在這里吃午飯嗎?

struct str{
    vector <float> a;   vector <int> b;      vector <bool> c;  };

class objects{
    vector <str> a;     vector <int> b;      vector <float> c;  
    //more vectors, etc ...
    void DoWork();            //heavy use of vectors
};    

main(){
    vector <object> objs;
    vector <object> p_objs = &objs;

    //...make `thread_list` and `attr`
    for(int q=0; q<NUM_THREADS; q++)
        pthread_create(&thread_list[q], &attr, Consumer, p_objs );
    //...
}

void* Consumer(void* argument){
     vector <object>* p_objs = (vector <object>*) argument ;
     while(1){
         index = queued++;  //imagine queued is thread-safe global
         object obj = (*p_objs)[index]        
         obj.DoWork();
         (*p_objs)[index] = obj;
}

那么,在線程0中復制的最后一個向量是objs[0].c 在線程1中復制的第一個向量是objs[1].a[0].a 因此,如果它們的兩個分配數據塊都碰巧占用相同的高速緩存行(64個字節,或者它實際上是該CPU的任何內容),那么你就會有錯誤的共享。

當然,涉及的任何兩個向量也是如此,但僅僅為了一個具體的例子,我假裝線程0首先運行並在線程1開始分配之前進行分配,並且分配器傾向於使連續分配相鄰。

reserve()可能會阻止您實際操作的塊的部分占用相同的緩存行。 另一種選擇是每線程內存分配 - 如果這些向量的塊是從不同的池分配的,那么它們不可能占用相同的行,除非池有。

如果你沒有每線程分配器,那么問題可能是內存分配器上的爭用,如果DoWork重新分配了這些向量。 或者它可能是DoWork使用的任何其他共享資源的爭用。 基本上,假設每個線程花費1 / K的時間做一些需要全局獨占訪問的事情。 然后它似乎可以合理地並行化到一定數量J <= K,此時獲取獨占訪問顯着地加速到加速,因為核心在空閑時間上花費了相當大的時間。 除了K核之外,額外核心幾乎沒有任何改進,因為共享資源無法更快地工作。

在荒謬的一端,想象一下花費1 / K的時間進行全局鎖定的工作,以及等待I / O的時間(K-1)/ K. 然后問題看起來幾乎與K個線程(無論核心數量)並行地令人尷尬地平行,此時它停止了。

所以,在你排除真正的分享之前,不要專注於虛假分享;-)

暫無
暫無

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

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