我想进行以下填充A矩阵的并行循环。对于每个计算的A [i] [j]元素,我希望A [i-1] [j],A [i-1] [j -1]和A [i0] [j-1]中的价格为先计算出来。因此,我的线程必须等待这些位置的线程计算出它们的结果。我试图做到这一点:
#pragma omp parallel for num_threads(threadcnt) \
default(none) shared(A, lenx, leny) private(j)
for (i=1; i<lenx; i++)
{
for (j=1; j<leny; j++)
{
do
{
} while (A[i-1][j-1] == -1 || A[i-1][j] == -1 || A[i][j-1] == -1);
A[i][j] = max(A[i-1][j-1]+1,A[i-1][j]-1, A[i][j-1] -1);
}
}
我的A矩阵以-1初始化,因此,如果A [] []等于-1,则此单元格中的操作未完成。不过,它比串行程序要花费更多的时间。.有什么想法可以避免while循环吗?
答案 0 :(得分:1)
等待循环似乎不理想。除了燃烧等待旋转的内核外,您还需要大量适当放置的flush
指令才能使此代码正常工作。
一种选择,尤其是在更通用的并行化方案中,将使用任务和任务依赖关系来建模不同数组元素之间的依赖关系:
#pragma omp parallel
#pragma omp single
for (i=1; i<lenx; i++) {
for (j=1; j<leny; j++) {
#pragma omp task depend(in:A[i-1][j-1],A[i-1][j],A[i][j-1]) depend(out:A[i][j])
A[i][j] = max(A[i-1][j-1]+1,A[i-1][j]-1, A[i][j-1] -1);
}
}
您可能想考虑阻止矩阵更新,以便每个任务都收到一个矩阵块而不是单个元素,但是总体思路将保持不变。
另一种有用的OpenMP功能可能是ordered
构造,它能够完全遵守这种数据依赖关系:
#pragma omp parallel for
for (int i=1; i<lenx; i++) {
for (int j=1; j<leny; j++) {
#pragma omp ordered depend(source)
#pragma omp ordered depend(sink:i-1,j-1)
A[i][j] = max(A[i-1][j-1]+1,A[i-1][j]-1, A[i][j-1] -1);
}
}
PS:上面的代码未经测试,但应该可以理解。