我已经开始学习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函数在并行块之外定义,该如何解决?
private
指令声明数据在每个线程的内存中具有单独的副本。因此,每个线程将拥有自己的s
副本,该副本与外部范围s
中声明的double s;
驻留在不同的内存位置。[在s
中更改parallel region
的值时,您仅在更改s
的线程本地副本。
[您的外部示波器中的s
的值(您正在ref
中的lambda
捕获])不会更改。外部s
位于不同的存储位置。
附带说明,您应该初始化外部s
变量:double s{ 0 };
。
// This value of x will remain unchanged.
int x = 5;
#pragma omp parallel private( x )
{
// What happens in the `parallel block` stays in the
// in the `parallel block`. In other words, incrementing this
// local value of x will not change the value of x declared in the
// outer scope. That's because this `parallel block` has its own copy of x.
x++;
}
// This value of x will change.
int x = 5;
#pragma omp parallel
{
// The x variable is now shared between each thread. What you
// do to x here changes the value of x in the outer scope.
#pragma omp critical
{
x++;
}
}