C++ 类声明自己(*this)private以避免竞争条件/放弃对gcc中threadprivate的追求
我想避免并行代码中的竞争条件。问题是,我的类包含几个全局变量,为了简单起见,假设只有一个C++ 类声明自己(*this)private以避免竞争条件/放弃对gcc中threadprivate的追求,c++,gcc,openmp,C++,Gcc,Openmp,我想避免并行代码中的竞争条件。问题是,我的类包含几个全局变量,为了简单起见,假设只有一个x,还有一个for循环,我希望使其并行。实际代码还有一个方法,该方法将指向类的指针(在本例中为类本身)作为其参数,访问更多全局变量。因此,让整个实例threadprivate可能是有意义的。我正在使用OpenMP。MWE是 #include <iostream> #include <omp.h> class lotswork { public: int x; int f
x
,还有一个for
循环,我希望使其并行。实际代码还有一个方法,该方法将指向类的指针(在本例中为类本身)作为其参数,访问更多全局变量。因此,让整个实例threadprivate可能是有意义的。
我正在使用OpenMP。MWE是
#include <iostream>
#include <omp.h>
class lotswork {
public:
int x;
int f[10];
lotswork(int i = 0) { x = i; };
void addInt(int y) { x = x + y; }
void carryout(){
#pragma omp parallel for
for (int n = 0; n < 10; ++n) {
this->addInt(n);
f[n] = x;
}
for(int j=0;j<10;++j){
std::cout << " array at " << j << " = " << f[j] << std::endl;
}
std::cout << "End result = " << x << std::endl;
}
};
int main() {
lotswork production(0);
#pragma omp threadprivate(production)
production.carryout();
}
因此,基于定义的这段代码应该可以做到这一点,但不知何故它无法编译。有人能帮我把这段代码放在一起,这样它就能实现所需的线程安全和编译,同时考虑到threadprivate不是非英特尔编译器人员的选项这一约束条件吗?非常感谢您的帮助。这是GCC长期缺失的一项功能:
thread\u local
有望工作,不过:
int main() {
thread_local lotswork production(0);
production.carryout();
}
但是,我认为这在您的情况下不起作用,因为
carrout
中的并行循环仍将在单个lotswork
实例上运行。我相信这也适用于使用threadprivate
的原始代码。您可能需要将并行循环移到执行
成员函数之外。这里似乎对OpenMP构造有一些混淆threadprivate
与thread\u local非常相似,用于创建静态生存期对象的每个线程副本,可以是全局变量,也可以是静态变量。如前所述,这存在一些实现问题,但即使实现可以处理该类,对非静态局部变量使用threadprivate
也会产生错误
至于错误,很难说没有输出,但可能有多种原因:
{
放置在pragma行的末尾不会打开块,它需要位于下一行#pragma omp parallel
{
lotswork tmp(*this);
// do things with private version
}
但是请注意,整个内容都是私有的,因此这意味着原始副本中的f
将不会更新,除非您在私有副本上执行addInt
等同物,然后在原始副本上执行f[n]
赋值
编辑:我最初提到使用default(firstprivate)
子句,但是
default子句仅为FORTRAN提供private和first private
C++中的相同效果,将上面的和复制构造成每个新实例,
或者默认情况下使用带有capture by value的lambda,然后使用firstprivate,*this
需要c++17才能工作,但完全符合要求:
auto fn = [=,*this](){
// do things with private copies
// all updates to persist in shared state through pointers
};
#pragma omp parallel firstprivate(fn)
fn();
我对这个问题做了大量的研究,似乎很多人都关心这个问题。与其匿名地、毫无帮助地提供downvote,为什么不提供应该改进的建议呢?不是downvoter,但如果您包含一个,足以使您认为应该改进的自包含、正确的代码片段可编译但不公平。我稍微改变了这个问题。你能解释一下为什么你想在并行区域之间保存私有变量吗?我通常能找到一个解决办法,我几乎不需要线程私有。解释你想做什么。你确定你不会把<代码>私有< /代码>与C++对应。“能见度"在类层次结构和OpenMP的
private
(对应于在每个线程的基础上进行复制)中,这两个概念都是完全正交的。到目前为止,我真的不明白您的问题是什么,以及您试图实现什么…感谢您指出这一点。我可能会咬紧牙关,声明一个关于f我的一个微不足道的地区的私有变量。“默认值(firstprivate)”不起作用,或者至少CLion抱怨说它期望“无”或“共享”。我将阅读OpenMP文档以了解您的建议,“有可能将私有或firstprivate设为默认值”所以我检查了一下,您所说的仅在Fortran中是正确的,请看这里,尽管有一条神秘的提示“[h]无论如何,实际实现可能会提供此选项。”是的,不会编译,并给出错误“在“firstprivate”之前预期为“non”或“shared”我猜LLNL的好人指的是OpenMP的定制版本?你说得很对。即使是我们这些帮助编写东西的人有时也会犯这些错误。回答编辑。
auto fn = [=,*this](){
// do things with private copies
// all updates to persist in shared state through pointers
};
#pragma omp parallel firstprivate(fn)
fn();