以下是我的代码大纲:
#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时)。
答案 0 :(得分:5)
bar()
,并且每个线程的堆栈中都有一个result
变量,因此有result
个result
变量和线程数。没有线程知道其他人存储他们private
的位置,并且不可能(并且没有意义)将它们一起减少。这就是为什么从并行区域内部调用的函数中的自动变量预定为reduction
并且由于线程不共享堆栈空间而无法更改。这同样适用于在并行区域内声明的变量 - 它们在区域之前不存在,并且仅存在于每个执行线程的堆栈中。 static
仅适用于另一个范围内存在的共享变量,即在并行区域之前声明,或者是{{1}},或者是全局的。
答案 1 :(得分:0)
并行块中定义的Anythig应该是私有的。
您和您提供的链接之间的差异result
已经在链接中的并行块之外定义,因此可以将其声明为共享。