我有包含动态3d数组的类。该类的对象调用一个函数进行一些计算以填充1d数组,最后用1d数组数据填充对象的3d数组.1d数组的大小与3d数组相同。
我正在使用Openmp来加强计算。单线程执行给出了正确的结果,但是一旦我转到多个线程,我得到了奇怪的结果。
示例代码如下。请帮助解决问题。
class A (
void func(float *buf);
void populateRes(*t);
private:
float ***res;
};
A a[n];
int nthrd = omp_get_num_threads();
float *buf;
while (cnt < nz)
{
#pragma omp parallel shared(cnt) private(buf, tid, omp_i)
{
if(cnt == 0 )
buf = new float[x*y*z];
#pragma omp for
for(omp_i=0; omp_i<n; omp_i++)
{
a[omp_i].func(buf);
a[omp_i].populateRes(buf);
}
}
cnt++;
if(cnt >= nz)
delete []buf;
}
答案 0 :(得分:1)
OpenMP不会将不同条目之间的private
变量值保存到同一个parallel
区域,就像在函数的不同调用之间不保留自动局部变量的值一样(除非它们声明static
)。实际上,在大多数OpenMP实现中,parallel
区域是单独的函数,private
变量是自动的。
这会使您的代码出错,因为buf
只会在循环的第一次迭代中分配,但在下一次迭代中,您的代码将在新的未初始化的本地副本上运行。可能会(通过纯粹的机会)发生特定线程的堆栈内容未更改,因此buf
保留其值。同样删除buf
区域之外的parallel
会忽略对new
进行多次调用的事实。
如果您只想分配buf
一次,则应将while
循环放在parallel
区域内,反之亦然。这也可以提高性能,因为parallel
区域只输入一次,并且每个条目都有相关的开销。
A a[n];
#pragma omp parallel
{
float *buf = new float[x*y*z];
for (int cnt = 0; cnt < nz; cnt++)
{
#pragma omp for
for (int i = 0; i < n; i++)
{
a[i].func(buf);
a[i].populateRes(buf);
}
}
delete [] buf;
}
(我没有在内部使用tid
所以我冒昧地将其从private
变量列表中删除了
更改两个循环的嵌套是可能的,因为for
工作共享结构的末尾有一个隐式屏障。我不知道是否有其他代码你已经省略但是给出了问题的代码,cnt
循环甚至可以嵌套在工作共享结构中,即:
#pragma omp parallel
{
float *buf = new float[x*y*z];
#pragma omp for
for (int i = 0; i < n; i++)
{
for (int cnt = 0; cnt < nz; cnt++)
{
a[i].func(buf);
a[i].populateRes(buf);
}
}
delete [] buf;
}