2011-04-02 60 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 
相关问题