我很难将openmp应用到Fortran中的嵌套循环,如下所示:
!$omp parallel do default(none) private(irow,mm,iparm,jrow) shared(nsrow,nparm,zvec,bvec,brx,zdense)
do irow = 2, nsrow
mm = irow -1
do iparm = 1, nparm
do jrow = 1, mm
zvec(jrow) = zdense( ijdense(jrow,irow,nsrow) )
end do
bvec(iparm) = ddot( mm, zvec, 1, brx(:,iparm), 1)
end do
brx(irow,:) = (brx(irow,:)-bvec)/zdense(ijdense(irow,irow,nsrow))
end do
!$omp end parallel do
当我将串口与openmp版本进行比较时,最后一个得到了奇怪的结果。你知道为什么或者可以指出一个关于嵌套循环和openmp的明确的教程吗?提前谢谢
答案 0 :(得分:2)
显式并行化的循环是外部循环(irow
循环)。这种并行化使得每个线程可以具有不相交的索引集irow
。对于其他索引iparm
和jrow
,每个线程在某个时刻都会获得jrow = 1
,这意味着所有线程集zvec(1)
和zvec
分享,你肯定会得到一个奇怪的结果。因为你永远不会知道zvec(1)
中的内容。同样适用于iparm
和brx
。正如Gilles建议的那样,zvec
必须是私有的才能获得与顺序运行相同的结果。
在我看到iparm
循环时,最好将iparm
循环并行化并保持brx
共享。或者在brx
上有减少条款,但它仍然会很棘手。
do irow = 2, nsrow
mm = irow -1
!$omp parallel do default(none) private(irow,mm,iparm,jrow,zvec) shared(nsrow,nparm,bvec,brx,zdense)
do iparm = 1, nparm
do jrow = 1, mm
zvec(jrow) = zdense( ijdense(jrow,irow,nsrow) )
end do
bvec(iparm) = ddot( mm, zvec, 1, brx(:,iparm), 1)
end do
!$omp end parallel do
brx(irow,:) = (brx(irow,:)-bvec)/zdense(ijdense(irow,irow,nsrow))
end do
答案 1 :(得分:0)
我在这里看到的第一件事是zvec
是共享的,而它应该是私有的。我想bvec
的故事也是如此。先尝试一下,然后告诉我们。