关于fortran中嵌套循环和openmp的麻烦

时间:2015-08-21 11:56:24

标签: fortran openmp

我很难将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的明确的教程吗?提前谢谢

2 个答案:

答案 0 :(得分:2)

显式并行化的循环是外部循环(irow循环)。这种并行化使得每个线程可以具有不相交的索引集irow。对于其他索引iparmjrow,每个线程在某个时刻都会获得jrow = 1,这意味着所有线程集zvec(1)zvec分享,你肯定会得到一个奇怪的结果。因为你永远不会知道zvec(1)中的内容。同样适用于iparmbrx。正如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的故事也是如此。先尝试一下,然后告诉我们。