use*_*080 5 c++ multithreading openmp thread-local-storage c++11
为什么thread_local
不能应用于非静态数据成员?这个问题的接受答案是:"制作非静态结构或类成员线程本地没有意义." 老实说,我看到很多很好的理由让非静态数据成员成为线程本地的.
假设我们有一种ComputeEngine
成员函数computeSomething
,它被连续多次调用.成员函数内部的一些工作可以并行完成.为此,每个线程需要某种类型ComputeHelper
,例如,辅助数据结构.所以我们真正想要的是以下内容:
class ComputeEngine {
public:
int computeSomething(Args args) {
int sum = 0;
#pragma omp parallel for reduction(+:sum)
for (int i = 0; i < MAX; ++i) {
// ...
helper.xxx();
// ...
}
return sum;
}
private:
thread_local ComputeHelper helper;
};
Run Code Online (Sandbox Code Playgroud)
不幸的是,这段代码无法编译.我们可以做的是:
class ComputeEngine {
public:
int computeSomething(Args args) {
int sum = 0;
#pragma omp parallel
{
ComputeHelper helper;
#pragma omp for reduction(+:sum)
for (int i = 0; i < MAX; ++i) {
// ...
helper.xxx();
// ...
}
}
return sum;
}
};
Run Code Online (Sandbox Code Playgroud)
但是,这将构造和破坏ComputeHelper
之间的连续调用computeSomething
.假设构造ComputeHelper
昂贵(例如,由于巨大向量的分配和初始化),我们可能希望ComputeHelper
在连续调用之间重用s.这引出了以下样板方法:
class ComputeEngine {
struct ThreadLocalStorage {
ComputeHelper helper;
};
public:
int computeSomething(Args args) {
int sum = 0;
#pragma omp parallel
{
ComputeHelper &helper = tls[omp_get_thread_num()].helper;
#pragma omp for reduction(+:sum)
for (int i = 0; i < MAX; ++i) {
// ...
helper.xxx();
// ...
}
}
return sum;
}
private:
std::vector<ThreadLocalStorage> tls;
};
Run Code Online (Sandbox Code Playgroud)
thread_local
不能应用于非静态数据成员?这种限制背后的理由是什么?我没有给出线程局部非静态数据成员完美意义的好例子吗?至于为什么thread_local
不能应用于非静态数据成员,会破坏此类成员通常的排序保证。也就是说,单个public/private/protected
组内的数据成员必须按照与类声明中相同的顺序在内存中布局。更不用说如果您在堆栈上分配一个类会发生什么——TLS 成员不会进入堆栈。
至于如何解决这个问题,我建议使用boost::thread_specific_ptr
. 您可以将其中之一放入您的类中并获得您想要的行为。
归档时间: |
|
查看次数: |
732 次 |
最近记录: |