0

这是我的代码的大纲:

#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子句

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

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

减少子句中指定的变量:

  • 必须是适合操作员的类型。
  • 必须在封闭的上下文中共享。
  • 不能是 const 限定的。
  • 不能有指针类型。

重点补充。由于外部并行区域应该将所有变量处理为shared,这意味着一旦发现它的减少就result应该转换为。private至少不应该private在外部范围内考虑它,因为外部范围已明确告诉每个变量都是shared. 这就是我困惑的根源。

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

所以我想我的问题是:为什么 OpenMP 对待归约 var。当它先前在外部上下文中声明为共享时作为私有变量?

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

4

2 回答 2

5

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

于 2013-10-17T12:25:23.987 回答
0

在并行块中定义的任何东西都应该是私有的。

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

于 2013-10-17T11:53:02.407 回答