为什么我不能使用默认值(共享)?

时间:2013-10-17 11:13:27

标签: c parallel-processing openmp

以下是我的代码大纲:

#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++;
}

编译时出现以下错误:

  

减少变量'result'在外部上下文中是私有的

这不应该发生,因为根据IBM compiler documentation reduction子句

  

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

     

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

     
    

减少条款中指定的变量:

  
     
      
  • 必须是适合运营商的类型。
  •   
  • 必须在封闭的上下文中共享。
  •   
  • 不得为const限定。
  •   
  • 不得有指针类型。
  •   

重点补充。由于外部并行区域应该将所有变量都处理为shared,这意味着result一旦找到它就会转换为private。至少虽然它不应该被视为外部范围中的private,因为外部范围已明确告知每个变量为shared。这是我混乱的根源。

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

所以我想我的问题是:为什么OpenMP会处理减少变量。作为私有变量,当它之前被声明为在外部上下文中共享时?

我只有减少这个问题,其他一切都按预期工作(特别是当有example which does the exact same thing时)。

2 个答案:

答案 0 :(得分:5)

每个OpenMP线程独立调用

bar(),并且每个线程的堆栈中都有一个result变量,因此有resultresult变量和线程数。没有线程知道其他人存储他们private的位置,并且不可能(并且没有意义)将它们一起减少。这就是为什么从并行区域内部调用的函数中的自动变量预定为reduction并且由于线程不共享堆栈空间而无法更改。这同样适用于在并行区域内声明的变量 - 它们在区域之前不存在,并且仅存在于每个执行线程的堆栈中。 static仅适用于另一个范围内存在的共享变量,即在并行区域之前声明,或者是{{1}},或者是全局的。

答案 1 :(得分:0)

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

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