2011-04-02 40 views
1

我正在爲我的項目(Linux,ICC,pthreads)優化一些儀器,並希望對此技術提供一些反饋,爲一個線程分配一個唯一的索引,這樣我就可以使用它來索引每個線程的數組數據。我可以使用pthreads分配每個線程的索引嗎?

舊的技術使用基於pthread id的std :: map,但我想避免鎖定和地圖查找(如果可能的話)(它會產生大量的開銷)。

這是我的新技術:

static PerThreadInfo info[MAX_THREADS]; // shared, each index is per thread 

// Allow each thread a unique sequential index, used for indexing into per 
// thread data. 
1:static size_t GetThreadIndex() 
2:{ 
3: static size_t threadCount = 0; 
4: __thread static size_t myThreadIndex = threadCount++; 
5: return myThreadIndex; 
6:} 

在後面的代碼:

// add some info per thread, so it can be aggregated globally 
info[ GetThreadIndex() ] = MyNewInfo(); 

所以:

1)它看起來像4號線可能是,如果兩個線程的競爭條件在同一時間創建。如果是這樣 - 我怎樣才能避免這種情況(最好沒有鎖)?我看不出原子增量會在這裏起到什麼作用。

2)有沒有更好的方法來創建每線程索引莫名其妙?也許通過以某種方式預先生成線程創建的TLS索引?

回答

2

1)原子增量實際上會有幫助,因爲可能的種族是兩個線程讀取併爲自己分配相同的ID,因此確保增量(讀取數量,加1,存儲數量)發生原子性修復該種族條件。在英特爾,一個「lock; inc」可以做到這一點,或者任何你的平臺提供的(例如Windows的InterlockedIncrement())。 2)嗯,實際上你可以讓整個信息線程本地化(「__thread static PerThreadInfo info;」),前提是你的唯一目標是能夠以一個通用的名字輕鬆地訪問每線程的數據。如果你真的希望它是一個全局可訪問的數組,那麼像使用TLS一樣保存索引是一種非常簡單而有效的方法。正如Kromey在他的文章中指出的那樣,您也可以預先計算索引並在創建線程時將它們作爲參數傳遞。

+0

1)當然,謝謝你清理那個。 2)這是真的 - 但不幸的是我想要從任何線程「讀取」信息,定期進行聚合。 – Justicle 2011-04-02 23:12:46

1

爲什麼如此反對使用鎖?解決競爭條件正是他們所設計的......

無論如何,您可以使用pthread_create()中的第4個參數將參數傳遞給線程的啓動例程;通過這種方式,您可以使用主進程在啓動線程時生成遞增計數器,並在創建每個線程時將該計數器傳遞給每個線程,從而爲您提供每個線程的唯一索引。

+0

請參閱此鏈接如何傳遞參數給線程的幾個例子;從這裏滾動一個代碼示例,看起來像你要求的。 https://computing.llnl.gov/tutorials/pthreads/#PassingArguments – Kromey 2011-04-02 00:54:08

+1

爲什麼不鎖定...因爲剖析器顯示鎖佔用了相當長的時間,我相信在這種情況下它們可能是不必要的。 – Justicle 2011-04-02 23:09:44

0

我知道你標記了這個[pthreads],但你也提到了使用std :: map的「舊技術」。這使我相信你是用C++編程的。在C++ 11中,你有std :: thread,並且你可以通過一個普通的函數參數在線程創建時將唯一索引(id)傳遞給你的線程。

下面是一個示例HelloWorld,它創建了N個線程,並通過N-1爲每個索引分配0。每個線程什麼也不做,但說「嗨」,並給它的指數:

#include <iostream> 
#include <thread> 
#include <mutex> 
#include <vector> 

inline void sub_print() {} 

template <class A0, class ...Args> 
void 
sub_print(const A0& a0, const Args& ...args) 
{ 
    std::cout << a0; 
    sub_print(args...); 
} 

std::mutex& 
cout_mut() 
{ 
    static std::mutex m; 
    return m; 
} 

template <class ...Args> 
void 
print(const Args& ...args) 
{ 
    std::lock_guard<std::mutex> _(cout_mut()); 
    sub_print(args...); 
} 

void f(int id) 
{ 
    print("This is thread ", id, "\n"); 
} 

int main() 
{ 
    const int N = 10; 
    std::vector<std::thread> threads; 
    for (int i = 0; i < N; ++i) 
     threads.push_back(std::thread(f, i)); 
    for (auto i = threads.begin(), e = threads.end(); i != e; ++i) 
     i->join(); 
} 

我的輸出:

This is thread 0 
This is thread 1 
This is thread 4 
This is thread 3 
This is thread 5 
This is thread 7 
This is thread 6 
This is thread 2 
This is thread 9 
This is thread 8 
相關問題