我有以下代码:
void simulation (MD *md){
double sum;
#pragma omp parallel private (move)
{
for(move = 0; move < maxIterations; ++move)
{
cicleDoMove(md);
cicleForces(md);
cicleMkekin(md,sum);
// ...
}
}
}
其中:
void cicleMkekin(Md *md, double sum){
#pragma omp for reduction(+ : sum)
for (i = 0; i < md->mdsize; i++)
{
sum += mkekin(..);
}
// ..
}
我收到以下错误:
"reduction variable 'sum' is private in outer context"
变量sum不是私有的,实际上如果我将模拟代码更改为:
void simulation (MD *md){
double sum;
#pragma omp parallel private (move)
{
for(move = 0; move < maxIterations; ++move)
{
cicleDoMove(md);
cicleForces(md);
#pragma omp for reduction(+ : sum)
for (i = 0; i < md->mdsize; i++)
{
sum += mkekin(..);
}
// ...
}
}
}
效果很好。
无论如何我可以使用我的第一个代码版本而不会出现错误吗?或者我做错了什么?
答案 0 :(得分:7)
出现在工作共享的减少条款中的列表项 构造必须在任何平行区域中共享 由工作共享构成的工作共享区域绑定。
此外,对于C和C ++,它说(§2.14.1.1),
具有自动存储持续时间的变量,这些变量在 建筑是私人的。
在您的情况下,变量sum
在函数cicleMkekin
的调用范围内声明,并且作为函数参数具有自动存储持续时间。因此,当您从并行区域内调用cicleMkekin
时(或者就此而言,从与程序执行一致的隐式顶级并行区域)调用sum
时,cicleMkekin
被认为是私人变量。因此,您的减少条款确实是非法的,而您收到的错误信息实际上可能是混乱的。
在您已手动内联sum
调用的代码版本中,您在并行区域之外声明变量default
。在没有reduction
子句或所谓的明确确定的变量数据共享属性的情况下,这样的变量确实是共享的(§2.14.1),因此,{{1}}子句在您的代码版本是合法的。