lampda函数在openmp c ++中的并行块内的奇怪行为

问题描述 投票:0回答:2

我已经开始学习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函数在并行块之外定义,该如何解决?

c++ parallel-processing scope openmp
2个回答
1
投票
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++; } }


0
投票
© www.soinside.com 2019 - 2024. All rights reserved.