【发布时间】:2020-05-30 19:47:25
【问题描述】:
我已经开始学习 OpenMP 几天了。我遇到了这个我无法解决的错误。
我定义了一个 lambda 函数 f,它捕获局部变量 s。现在,如果我在并行 for 循环中更改变量 s(每个线程的私有变量),那么函数 f 不会反映其输出的变化,并且总是给出 0。我可以理解我在范围界定方面出现了一些错误,但找不到错误。
#include <iostream>
#include <omp.h>
int main(int argc, char *argv[])
{
using namespace std;
double s;
auto f =[&]{return s;};
#pragma omp parallel for private(s)
for(int i = 0; i < 4 ; i++)
{
s = 5+i;
double a1 = f();
#pragma omp critical
cout << a1 << endl;
}
return 0;
}
如果我在并行 for 循环中定义 lambda,它实际上可以工作并返回正确的值 s 而不是 0,即
#pragma omp parallel for private(s)
for(int i = 0; i < 4 ; i++)
{
s = 5+i;
double a1 = [&]{return s;}();
#pragma omp critical
cout << a1 << endl;
}
我的猜测是 lambda 函数和捕获的变量需要在同一范围内。 如果 lambda 函数是在并行块之外定义的,如何解决这个问题?
【问题讨论】:
-
我不熟悉 OpenMP,但我猜
private(s)的意思是“给每个线程自己的s副本”。但是f捕获了“真实的”s,即在循环外声明的那个。它不知道那些私人副本。我预测如果你在声明f的地方写double& s_ref = s;,并使用s_ref而不是f(),你将有相同的行为。 lambda 是一条红鲱鱼。 -
回复:如何解决。很难说不知道你最终要达到什么目标。一种方法是让 lambda 以
s作为参数,而不是捕获它。然后每个线程将传递自己的本地副本。 -
@IgorTandetnik 我也考虑过,将
s作为参数。这肯定会奏效。 -
private指令声明数据在每个线程的内存中都有一个单独的副本。换句话说,每个线程都有自己的s副本。你对s所做的事情在外部范围内看不到。如果您想共享s的值,请删除private指令。 -
@Wbuck 我最初在并行 omp for 循环中遇到了这个问题。我希望每个线程都有自己的
s副本。我想我应该更改其中的循环代码
标签: c++ parallel-processing scope openmp