c语言 - 为什么我不能在默认(共享)的情况下使用缩减?



这是我的代码大纲:

#pragma omp parallel default(shared)
{
for(i; i<lim; i++)
    do_work();
}

过了一会儿:

do_work(){
    foo();
    bar();
}
foo(){
    #pragma omp for //etc
    for(i;i<l;i++) //your typical loop
}
bar(){ //here's the interesting part
    int i;
    int result;
    #pragma omp for reduction(+:result) private(i)
    for(i=0; i<lim; i++)
        result++;
}

编译时出现以下错误:

归约变量"结果"在外部上下文中是私有

这不应该发生,因为根据 IBM 编译器文档,reduction 子句

使用指定的运算符对列表中的所有标量变量执行缩减。列表中的缩减变量用逗号分隔。

为每个线程创建列表中每个变量的私有副本。在语句块的末尾,以适合运算符的方式组合归约变量的所有私有副本的最终值,并将结果放回共享归约变量的原始值。

归约子句中指定的变量:

  • 必须是适合操作员的类型。
  • 必须在封闭上下文中共享。
  • 不得符合恒量标准。
  • 不得具有指针类型。

强调添加。因为外平行区域应该以shared的方式处理所有变量,这意味着一旦发现result的约化,它就应该被转换为private。至少,虽然它不应该被视为在外部作用域中private,因为外部作用域已经明确告诉每个变量都要shared。这就是我困惑的根源。

当然,我使用的是GCC而不是IBM编译器,但是在这种情况下有什么区别吗?

所以我想我的问题是:为什么 OpenMP 将缩减变量视为私有变量,而它之前在外部上下文中声明为共享?

我只有减少的问题,其他一切都按预期工作(特别是当有一个示例做完全相同的事情时)。

bar()

每个 OpenMP 线程独立调用,并且每个线程的堆栈中都有一个result变量,因此result变量的数量与线程数一样多。没有线程知道其他线程将他们的result存储在哪里,并且不可能(也没有意义)将它们一起减少。这就是为什么从并行区域内调用的函数中的自动变量被预先确定为private并且由于线程不共享堆栈空间而无法更改的原因。这同样适用于在并行区域内声明的变量 - 它们在区域之前不存在,仅存在于每个执行线程的堆栈上。 reduction仅适用于存在于其他作用域中的共享变量,即要么在并行区域之前声明,要么static,要么是全局的。

在并行块中定义的 Anythig 应该是私有的。

和您提供的链接之间的区别是result已经在链接中的并行块之外定义,因此可以将其声明为共享。

最新更新