我试图并行化这个循环,但是在PGI编译器中出现了一些错误,我不明白错误
#pragma acc kernels
{
#pragma acc loop independent
for (i = 0;i < k; i++)
{
for(;dt*j <= Ms[i+1].t;j++)
{
w = (j*dt - Ms[i].t)/(Ms[i+1].t-Ms[i].t);
X[j] = Ms[i].x*(1-w)+Ms[i+1].x*w;
Y[j] = Ms[i].y*(1-w)+Ms[i+1].y*w;
}
}
}
错误 85,生成多核代码 87,#pragma acc loop gang 89,加速器限制:Y,X的GPU副本的大小未知 复合环带有Ms-> t,Ms-> x,X->,Ms-> y,Y->的依赖性。防止并行化 循环携带Y-,X->的重复使用。防止并行化 那么我可以做些什么来解决这种依赖性问题呢?
答案 0 :(得分:1)
我在这里看到一些问题。同时给出输出,我假设您正在编译“-ta = multicore,tesla”(即同时针对多核CPU和GPU)
首先,由于“j”未在“i”循环中初始化,因此“j”的起始值将取决于前一次迭代“i”的结束值“j”。因此,循环不可并行化。通过使用“循环独立”,您已经强制在外部循环上进行并行化,但是您将从顺序运行代码中获得不同的答案。您需要重新考虑您的算法。
我建议制作X和Y二维。第一个尺寸为“k”。第二维可以是锯齿状阵列(即每个都具有不同的大小),其大小对应于“Ms [i + 1] .t”值。
我写了一个使用锯齿状数组作为使用OpenACC并行编程一书的章节(#5)的一部分的例子。请参阅:https://github.com/rmfarber/ParallelProgrammingWithOpenACC/blob/master/Chapter05/jagged_array.c
或者,您可以设置“j = Ms [i] .t”,假设设置了“Ms [0] .t”。
for(j=Ms[i].t;dt*j <= Ms[i+1].t;j++)
“加速器限制:Y的GPU副本的大小,X未知”
这告诉您编译器无法隐式复制设备上的X和Y数组。在C / C ++中,无界指针没有大小,因此编译器无法判断这些数组有多大。通常它可以从循环跳闸计数中获取此信息,但由于循环跳闸计数未知(见上文),因此在这种情况下不能。要修复,您需要在“kernels”指令中包含data指令或向代码添加数据区域。例如:
#pragma acc kernels copyout(X[0:size], Y[0:size])
或
#pragma acc data copyout(X[0:size], Y[0:size])
{
...
#pragma acc kernels
...
}
要记住的另一件事是指针别名。在C / C ++中,允许相同类型的指针指向同一对象。因此,如果没有诸如“restrict”属性,“独立”子句或PGI编译器标志“-Msafeptr”之类的附加信息,编译器必须假设您的指针指向同一个对象,使得循环不可并行化。
答案 1 :(得分:0)
这很可能会通过添加独立于内循环的循环或使用collapse子句来平坦循环,同时应用于两者来消失。如果所有数组都使用restrict
传入,但也许不会传入,也可能会消失。