我正在尝试使用openmp任务来安排基本jacobi2d计算的平铺执行。在jacobi2d存在来自在openmp中的依赖子句不尊重依赖声明
上A(I,J)的依存A(I,J)
A(I-1,j)的
A(I + 1,J)
A(I, j-1)
A(i,j + 1)。
为了我对depends子句的理解,我正确地声明了依赖关系,但是在执行代码时他们没有被尊重。我已经复制下面的简化代码片段。最初我的猜测是某些图块的越界范围可能会导致这个问题,所以我纠正了这个问题,但问题仍然存在(我没有复制更长的代码和更正后的图块范围,因为那部分只是一堆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,然后才执行第二个。但是如果你执行代码,它会混合订单。
为什么不在循环中使用工作共享?在第一个循环中,您从“B”读取,但是写入“A”。在第二个循环中,您写入'A'并从'B'读取。因此,第1部分先并行,然后第2部分并行。只要确保你同步part1和part2之间的线程(无论如何,除非你使用'nowait',否则应该是隐含的)。 –
当然,条件都是错的? ( “如果((ⅱ!= 0 || II!= N-1)||(JJ!= 0 || JJ!= N-1))”。考虑二== 0,仍然会由于0执行! = N-1,但你不希望它因为它产生出界访问... –
@Zboson - 是的,这是可以做到很好,它只是用任务给你一个稍微更有效地利用作为理想小任务给你一个更高的并行性和更少的同步是必需的。 @吉姆。是的,你是对的,那就是与代码中的错误,关键是依赖的问题仍然存在。我使用跟踪依赖和执行顺序在2内部ii和jj for循环之前单个打印,并且打印语句的顺序不正确。我采取了预防措施,把这个印刷品放在重要的杂注里,否则印刷品可能会非常不正确。 – hajmola