我需要填充二维数组(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;
}
}
}
它在输出端产生竞争条件。我试图通过将所有内部变量(i
,j
,par
和val
)设为私有来避免它,但它没有帮助。
P.S。此代码的串行版本(#threads = 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;
}
}
}