我正在尝试使用openmp任务来安排基本jacobi2d计算的平铺执行。在jacobi2d中,存在对A(i,j)的依赖
A(i,j)
A(i-1,j)
A(i + 1,j)
A(i,j-1)
A(i,j + 1)。
据我对Dependent子句的理解,我正确地声明了依赖关系,但是在执行代码时并未遵守它们。我已经在下面复制了简化的代码段。最初我的猜测是某些图块的范围超出范围可能会导致此问题,因此我纠正了该问题,但问题仍然存在。(我没有复制具有更正图块范围的较长代码,因为那部分只是一堆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,然后仅执行第二个printf。但是,如果执行代码,它将混合顺序。
最佳答案
因此,我终于弄清楚了这个问题,即使OpenMP规范说Dependent子句应该以起点和范围来实现,但尚未在gcc中实现。因此,当前它仅比较从属子句(depend(in:A [i-1:b + 2] [j-1:b + 2]))A [i-1] [j-1]中的起点这个案例。
最初,我是比较处于不同相对图块位置的元素。例如,将(0,0)元素与图块的最后一个元素进行比较,这与依赖关系没有冲突,因此,各种任务的执行顺序是随机的。
当前的gcc实现根本不关心该子句中提供的范围。
关于openmp - openmp中的从属子句不尊重声明的独立性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/36322638/