使用OpenMP进行竞争条件

时间:2012-01-25 16:09:05

标签: openmp race-condition

我需要填充二维数组(tmp[Ny][Nx]),同时数组的每个单元格作为自由参数的函数得到一个整数(某个函数)。由于我处理了一个非常大的数组(这里我简化了我的情况),我需要使用OpenMP并行性来加速我的计算。这里我使用简单的#pragma omp parallel for指令。

不使用#pragma omp parallel for,代码执行完美。但是添加parallel指令会在输出中产生竞争条件。

我试图通过制作private(i,j,par)来治愈它,它没有帮助。

P.S。我使用VS2008 Professional和OpenMP 2.0以及WIndows 7 OS

这是我的代码:(简短的样本)

testfunc(const double* var, const double* par)
{
    // here is some simple function to be integrated over
    // var[0] and var[1] and two free parameters par[0] and par[1]
    return ....
}

#define Nx 10000
#define Ny 10000
static double tmp[Ny][Nx];

int main()
{    
    double par[2]; // parameters
    double xmin[]={0,0} // limits of 2D integration
    double xmax[]={1,1};// limits of 2D integration

    double val,Tol=1e-7,AbsTol=1e-7;
    int i,j,NDim=2,NEval=1e5;

#pragma omp parallel for private(i,j,par,val) 
    for (i=0;i<Nx;i++)
    {
        for (j=0;j<Ny;j++)
        {
            par[0]=i;
            par[1]=j*j;
            adapt_integrate(testfunc,par, NDim, xmin, xmax,
                            NEval, Tol, AbsTol, &val, &err);
            // adapt_integrate - receives my integrand, performs
            // integration and returns a result through "val"
            tmp[i][j] = val;
        }
    }
}  

它在输出端产生竞争条件。我试图通过将所有内部变量(ijparval)设为私有来避免它,但它没有帮助。

P.S。此代码的串行版本(#threads = 1)正常运行。

1 个答案:

答案 0 :(得分:0)

(在问题中回答。转换为社区wiki答案。请参阅Question with no answers, but issue solved in the comments (or extended in chat)

OP写道:

  

问题解决了!

     

我将集成参数定义为全局,并使用#pragma omp threadprivate(parGlob)指令。现在它就像一个魅力。我一直认为private()threadprivate()具有相同的含义,只是不同的实现方式,但它们没有。

     

因此,使用这些指令可能会给出正确的答案。另一个问题是在第一个i循环中定义迭代器for可以使性能提高20%-30%。因此,代码的最快版本现在看起来像:

testfunc(const double* var, const double* par)
    {
       .......
    }

    #define Nx 10000
    #define Ny 10000
    static double tmp[Ny][Nx];
    double parGlob[2]; //<- Here are they!!!
    #pragma omp threadprivate(parGlob)  // <-Magic directive!!!!

    int main()
    {    
 // Not here !!!! ->       double par[2]; // parameters
        double xmin[]={0,0} // limits of 2D integration
        double xmax[]={1,1};// limits of 2D integration

        double val,Tol=1e-7,AbsTol=1e-7;
        int j,NDim=2,NEval=1e5;

    #pragma omp parallel for private(j,val)  // no `i` inside `private` clause
        for (int i=0;i<Nx;i++)
        {
            for (j=0;j<Ny;j++)
            {
                parGlob[0]=i;
                parGlob[1]=j*j;
                adapt_integrate(testfunc,par, NDim, xmin, xmax,
                                NEval, Tol, AbsTol, &val, &err);
                tmp[i][j] = val;
            }
        }
    }