并行子程序的性能不佳

时间:2017-06-13 20:48:38

标签: fortran openmp

我试图并行化以下代码;然而,当它在主程序上执行时,似乎没有显着的加速。我在另一个程序上测试了相同的子程序,运行时间比串行代码要长。

      SUBROUTINE rotate(r,qt,n,np,i,a,b)
      IMPLICIT NONE
      INTEGER n,np,i
      DOUBLE PRECISION a,b,r(np,np),qt(np,np)
      INTEGER j
      DOUBLE PRECISION c,fact,s,w,y
      if(a.eq.0.d0)then
        c=0.d0
        s=sign(1.d0,b)
      else if(abs(a).gt.abs(b))then
        fact=b/a
        c=sign(1.d0/sqrt(1.d0+fact**2),a)
        s=fact*c
      else
        fact=a/b
        s=sign(1.d0/sqrt(1.d0+fact**2),b)
        c=fact*s
      endif
!$omp parallel shared(i,n,c,s,r,qt) private(y,w,j)
!$omp do schedule(static,2)

      do 11 j=i,n
        y=r(i,j)
        w=r(i+1,j)
        r(i,j)=c*y-s*w
        r(i+1,j)=s*y+c*w
 11   continue

!$omp do schedule(static,2)  

      do 12 j=1,n
        y=qt(i,j)
        w=qt(i+1,j)
        qt(i,j)=c*y-s*w
        qt(i+1,j)=s*y+c*w
 12   continue
!$omp end parallel
      return
      END
C  (C) Copr. 1986-92 Numerical Recipes Software Vs94z&):9+X%1j49#:`*.

然而,当我使用Linux中的内置函数来测量时间时,我得到了:

real 0m12.160s

user 4m49.894s

sys 0m0.880s

与串行代码的时间相比,这是荒谬的:

real 0m2.078s

user 0m2.068s

sys 0m0.000s

1 个答案:

答案 0 :(得分:1)

所以你有类似

的东西
do i=1,n
  do j=1,n
    do k=1,n
      call rotate()
    end do
  end do
end do

表示n = 100并且您正在rotate内部并行化两个简单的循环。

那是没有希望的。如果你想要不错的性能,你必须并行化尽可能最外层的循环。

rotate内的循环中根本没有足够的工作,并且它被调用了太多次。你称它为1000000次,因此线程必须同步或重新启动2000000次。这需要你所有的运行时间。您看到的所有运行时间增加都是此同步。