c++ - openmp c ++中并行块内lambda函数的奇怪行为
问题描述
我已经开始学习 OpenMP 几天了。我遇到了这个我无法解决的错误。我定义了一个f
捕获局部变量的 lambda 函数s
。现在,如果我s
在并行 for 循环中更改变量(每个线程的私有变量),那么该函数f
不会反映其输出的变化并给出 always 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
and not的正确值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 函数是在并行块之外定义的,如何解决这个问题?
解决方案
您正在处理多个s
变量。s
(s) 中的变量parallel region
和s
在外部范围中声明的变量。
该private
指令声明数据在每个线程的内存中都有一个单独的副本。因此,每个线程都将拥有自己的副本,该副本驻留在与外部作用域中声明的s
内存位置不同的内存位置。s
double s;
当您更改 in 的值时s
,parallel region
您只是在更改 的线程本地副本s
。
外部范围内的值s
(您ref
在 a中捕获的值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++;
}
}
推荐阅读
- r - R中的指数分布
- ios - IOS 上的 WebRTC 应用程序无法在美国 iPhone 上运行
- c# - 参数值“421.0526000000”超出范围
- javascript - JQuery .on('Click') 只工作一次,而不是多次
- bash - 监控变量与上次读数中的其他 bash 相比是否在增长
- android - Android 数据绑定库 - 未解决的参考
- python - 无法在(Flask-)SQLAlchemy中获得一对多关系
- html - 如何在不更改 HTML 的情况下将单个 UL 拆分为两列布局?
- javascript - 如何使用 Sentry 报告 console.error?
- python - ValueError:期望','分隔符,同时尝试在python3中将字符串加载为json