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

时间:2014-12-02 15:59:41

标签: c openmp

我有以下代码:

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(..);
                    }
                    // ...
            }
        }
    }

效果很好。

无论如何我可以使用我的第一个代码版本而不会出现错误吗?或者我做错了什么?

1 个答案:

答案 0 :(得分:7)

在这种特殊情况下,OpenMP可能会有点混乱。 specification规定(§2.14.3.6):

  

出现在工作共享的减少条款中的列表项   构造必须在任何平行区域中共享   由工作共享构成的工作共享区域绑定。

此外,对于C和C ++,它说(§2.14.1.1),

  

具有自动存储持续时间的变量,这些变量在   建筑是私人的。

在您的情况下,变量sum在函数cicleMkekin的调用范围内声明,并且作为函数参数具有自动存储持续时间。因此,当您从并行区域内调用cicleMkekin时(或者就此而言,从与程序执行一致的隐式顶级并行区域)调用sum时,cicleMkekin被认为是私人变量。因此,您的减少条款确实是非法的,而您收到的错误信息实际上可能是混乱的。

在您已手动内联sum调用的代码版本中,您在并行区域之外声明变量default。在没有reduction子句或所谓的明确确定的变量数据共享属性的情况下,这样的变量确实是共享的(§2.14.1),因此,{{1}}子句在您的代码版本是合法的。