openmp 中的 Depend 子句不尊重声明的依赖性
Depend clause in openmp is not respecting dependence declared
我正在尝试使用 openmp 任务来安排基本 jacobi2d 计算的平铺执行。在 jacobi2d 中,存在对来自
的 A(i,j) 的依赖
A(i, j)
A(i-1, j)
A(i+1, j)
A(i, j-1)
A(我,j + 1)。
根据我对 depend 子句的理解,我正确地声明了依赖关系,但在执行代码时没有遵守它们。我已经复制了下面的简化代码片段。最初我的猜测是某些图块的越界范围可能导致了这个问题,所以我纠正了这个问题,但问题仍然存在。(我没有复制带有更正图块范围的较长代码,因为那部分只是一堆 ifs +最大值)
int n=8,tsteps=2,b=4; //n - size of matrix, tsteps - time iterations, b - tile size or block size
#pragma omp parallel
{
#pragma omp master
for (t=0; t<tsteps; ++t)
{
for (i=0; i<n; i+=b)
for (j=0; j<n; j+=b)
{
#pragma omp task firstprivate(t,i,j) depend(in:A[i-1:b+2][j-1:b+2]) depend(out:B[i:b][j:b])
{
#pragma omp critical
printf("t-%d i-%d j-%d --A",t,i,j); //Prints out time loop, i,j
}
}
for (i=0; i<n; i+=b)
for (j=0; j<n; j+=b)
{
#pragma omp task firstprivate(t,i,j) depend(in:B[i-1:b+2][j-1:b+2]) depend(out:A[i:b][j:b])
{
#pragma omp critical
printf("t-%d i-%d j-%d --B",t,i,j); //Prints out time loop, i,j
}
}
}
}
}
因此,声明从 i-1 和 j-1 开始且范围为 (b+2) 的依赖关系的想法是,相邻的图块也会影响您当前的图块计算。类似地,对于第二组循环,只有在相邻的图块使用了这些值后,才应覆盖 A 中的值。
正在使用支持 openmp 4.0 的 gcc 5.3 编译代码。
ps: 上面声明数组范围的方式表示起始位置和创建依赖图时要考虑的索引数。
编辑(基于 Zulan 的评论)- 将内部代码更改为简单的打印语句,因为这足以检查任务执行的顺序。理想情况下,对于上述值(因为只有 4 个图块),所有图块都应完成第一个 printf,然后仅执行第二个。但是如果你执行代码,它会混合顺序。
所以我终于想通了这个问题,尽管OpenMP规范说depend子句应该用一个起点和范围来实现,但在gcc中还没有实现。所以目前它只比较依赖子句的起点 (depend(in:A[i-1:b+2][j-1:b+2])) A[i-1][j-1] in这个案例。
最初我是在比较不同相对图块位置的元素。例如,将 (0,0) 元素与图块的最后一个元素进行比较,这与依赖性没有冲突,因此各种任务的执行顺序是随机的。
当前的 gcc 实现根本不关心子句中提供的范围。
我正在尝试使用 openmp 任务来安排基本 jacobi2d 计算的平铺执行。在 jacobi2d 中,存在对来自
的 A(i,j) 的依赖A(i, j)
A(i-1, j)
A(i+1, j)
A(i, j-1)
A(我,j + 1)。
根据我对 depend 子句的理解,我正确地声明了依赖关系,但在执行代码时没有遵守它们。我已经复制了下面的简化代码片段。最初我的猜测是某些图块的越界范围可能导致了这个问题,所以我纠正了这个问题,但问题仍然存在。(我没有复制带有更正图块范围的较长代码,因为那部分只是一堆 ifs +最大值)
int n=8,tsteps=2,b=4; //n - size of matrix, tsteps - time iterations, b - tile size or block size
#pragma omp parallel
{
#pragma omp master
for (t=0; t<tsteps; ++t)
{
for (i=0; i<n; i+=b)
for (j=0; j<n; j+=b)
{
#pragma omp task firstprivate(t,i,j) depend(in:A[i-1:b+2][j-1:b+2]) depend(out:B[i:b][j:b])
{
#pragma omp critical
printf("t-%d i-%d j-%d --A",t,i,j); //Prints out time loop, i,j
}
}
for (i=0; i<n; i+=b)
for (j=0; j<n; j+=b)
{
#pragma omp task firstprivate(t,i,j) depend(in:B[i-1:b+2][j-1:b+2]) depend(out:A[i:b][j:b])
{
#pragma omp critical
printf("t-%d i-%d j-%d --B",t,i,j); //Prints out time loop, i,j
}
}
}
}
}
因此,声明从 i-1 和 j-1 开始且范围为 (b+2) 的依赖关系的想法是,相邻的图块也会影响您当前的图块计算。类似地,对于第二组循环,只有在相邻的图块使用了这些值后,才应覆盖 A 中的值。
正在使用支持 openmp 4.0 的 gcc 5.3 编译代码。
ps: 上面声明数组范围的方式表示起始位置和创建依赖图时要考虑的索引数。
编辑(基于 Zulan 的评论)- 将内部代码更改为简单的打印语句,因为这足以检查任务执行的顺序。理想情况下,对于上述值(因为只有 4 个图块),所有图块都应完成第一个 printf,然后仅执行第二个。但是如果你执行代码,它会混合顺序。
所以我终于想通了这个问题,尽管OpenMP规范说depend子句应该用一个起点和范围来实现,但在gcc中还没有实现。所以目前它只比较依赖子句的起点 (depend(in:A[i-1:b+2][j-1:b+2])) A[i-1][j-1] in这个案例。
最初我是在比较不同相对图块位置的元素。例如,将 (0,0) 元素与图块的最后一个元素进行比较,这与依赖性没有冲突,因此各种任务的执行顺序是随机的。
当前的 gcc 实现根本不关心子句中提供的范围。