我想加速这些嵌套循环。由于v的维数(NMAX = MAX(NX1,NX2,NX3)),我知道这可能是两个外部循环并行化的冲突。我尝试使用 private 子句:
static double **v;
if (v == NULL) {
v = ARRAY_2D(NMAX_POINT, NVAR, double);
}
#pragma acc parallel loop present(V, U) private(v[:NMAX_POINT][:NVAR])
for (k = kbeg; k <= kend; k++){ g_k = k;
#pragma acc loop
for (j = jbeg; j <= jend; j++){ g_j = j;
#pragma acc loop collapse(2)
for (i = ibeg; i <= iend; i++) {
for (nv = 0; nv < NVAR; nv++){
v[i][nv] = V[nv][k][j][i];
}}
#pragma acc routine(PrimToCons) seq
PrimToCons (v, U[k][j], ibeg, iend);
}}
我得到这些错误:
Generating present(V[:][:][:][:],U[:][:][:][:])
Generating Tesla code
144, #pragma acc loop seq
146, #pragma acc loop seq
151, #pragma acc loop gang, vector(128) collapse(2) /* blockIdx.x threadIdx.x */
154, /* blockIdx.x threadIdx.x collapsed */
144, Accelerator restriction: induction variable live-out from loop: g_k
Complex loop carried dependence of v->-> prevents parallelization
146, Accelerator restriction: induction variable live-out from loop: g_j
Loop carried dependence due to exposed use of v prevents parallelization
Complex loop carried dependence of V->->->->,v->-> prevents parallelization
g_k 和 g_j 是 extern int 。我以前从未见过消息“ 归纳变量从循环中退出”。
编辑: 我按照建议修改了循环,但它仍然无法工作
#pragma acc parallel loop collapse(2) present(U, V) private(v[:NMAX_POINT][:NVAR])
for (k = kbeg; k <= kend; k++){
for (j = jbeg; j <= jend; j++){
#pragma acc loop collapse(2)
for (i = ibeg; i <= iend; i++) {
for (nv = 0; nv < NVAR; nv++){
v[i][nv] = V[nv][k][j][i];
}}
PrimToCons (v, U[k][j], ibeg, iend, g_gamma);
}}
我收到此错误:
Failing in Thread:1
call to cuStreamSynchronize returned error 700: Illegal address during kernel execution
好像编译器找不到v,U或V,但是在主函数中我使用了以下指令:
#pragma acc enter data copyin(data)
#pragma acc enter data copyin(data.Vc[:NVAR][:NX3_TOT][:NX2_TOT][NX1_TOT], data.Uc[:NX3_TOT][:NX2_TOT][NX1_TOT][:NVAR])
data.Vc和data.Uc是我要并行化的例程中的V和U。
答案 0 :(得分:0)
g_k和g_j是extern int。我从未看过“归纳 变量从循环中退出”。
并行运行时,执行循环迭代的顺序是不确定的。因此,一旦退出循环,g_k和g_j的值就是发生在最后的迭代。这会产生依赖性,因为为了获得正确的答案(即与串行运行时的答案一致的答案),必须依次运行“ k”和“ j”循环。
如果“ g_k”和“ g_j”是局部变量,则编译器将隐式私有化它们以消除此依赖性。但是,由于它们是全局变量,因此必须假定代码的其他部分使用结果,因此不能假定可以将它们设为私有。如果您知道这些变量未在其他地方使用,则可以通过将其添加到“ private”子句中来解决此问题。请注意,这些变量似乎并没有在循环本身中使用,因此可以将其删除,而在循环外部仅为其分配值“ kend”和“ jend”。
除非在“ PrimToCons”子例程中使用了“ g_k”和“ g_j”?在那种情况下,您有一个更大的问题,因为这将导致争用情况,因为变量值可能会被其他线程更新,而不再是子例程期望的值。在这种情况下,解决方法是将“ k”和“ j”作为参数传递给“ PrimToCons”,而不使用“ g_k”和“ g_j”。
至于“ v”,它也应该对“ j”循环专用,而不仅仅是“ k”循环。要解决此问题,我建议在“ k”循环的编译指示中添加“ collapse(2)”子句,并删除有关“ j”循环的循环指令。