在给定子程序GAUSSLEG的并行化do循环中,变量(私有和共享)的正确分配是什么?

时间:2015-05-27 06:42:30

标签: openmp private shared reduction

我是关于openmp的新手。我试图在子程序GAUSSLEG中并行化do循环。变量Xg,Wg和Ng取自模块matric。我得到了意想不到的结果。我对正确分配变量(私有和共享)感到困惑。有人可以帮帮我吗?

SUBROUTINE GAUSSLEG(f,a,b,s)
     USE OMP_LIB
     USE MATRIC , ONLY : XG ,WG , NG
     IMPLICIT DOUBLE PRECISION(A-H,O-Z)
     external f
     xm = 0.5d0*(b+a)
     xl = 0.5d0*(b-a)
     s = 0.d0
    !$omp parallel do reduction ( + : s) default(none)
    !$omp private(j) shared(xm,xl,wg,xg,ng,dx)

     do  j=1,ng
         dx = xl*xg(j)
         s = s + wg(j)*(func(xm+dx)+func(xm-dx))
     end do
   !$omp end parallel do

    s = xl*s/2.0
    return
  END

嗨,我已经使用子程序gaussleg来计算sin(x)从0到pi的积分,我得到相同的结果(2.5464790894),无论我是dx私有还是共享,但确切的结果是2.0。我还尝试直接放入xl * xg(j)并删除dx,仍然得到与上面相同的结果。在编译中没有-openmp选项,我得到了确切的结果2.0。这是整个程序。

  MODULE MATRIC
   IMPLICIT NONE
    INTEGER , PARAMETER :: NG = 40
    DOUBLE PRECISION , PARAMETER :: PI=2.0D0*ACOS(0.0D0)
    DOUBLE PRECISION ::  XG(60) , WG(60)
  END MODULE MATRIC
  program gauss
   use matric, only : xg,wg,pi
   implicit none
   double precision :: x1,x2,a,b,ans
   external :: f
   x1 = -1.0d0 ; x2 = 1.0d0
   a  = 0.0    ; b  = PI
   call gauleg(x1,x2)
   call gaussleg(f,a,b,ans)
   write(*,*)ans
  end program gauss
  !function to be integrated
  double precision function f(x)
        implicit none
        double precision, intent(in) :: x
        f = sin(x)
  end function f
  SUBROUTINE GAUSSLEG(func,a,b,ss)
     USE OMP_LIB
     USE MATRIC , ONLY : XG ,WG , NG
     double precision,intent(in) :: a , b
     double precision,intent(out)::ss
     double precision :: xm , xl , dx
     integer :: j
     double precision,external::func
     xm = 0.5d0*(b+a)
     xl = 0.5d0*(b-a)
     ss = 0.d0
    !$OMP PARALLEL DO REDUCTION( + : ss) default(none) &
    !$OMP PRIVATE(j,dx) SHARED(xm,xl,xg,wg)
       do  j=1,ng
           dx = xl*xg(j)
           ss = ss + wg(j)*(func(xm+dx)+func(xm-dx))
       end do
    !$OMP END PARALLEL DO
      ss = xl*ss/2.0
      return
      END

2 个答案:

答案 0 :(得分:0)

您的代码包含规范数据竞赛。您已声明dx已共享,然后已写入

         dx = xl*xg(j)

这样所有线程都可以更新相同的共享变量,而无需任何协调。我想,但是你有责任检查一下,你可以让dx私有,并让每个线程都看看它自己的变量值。

顺便提及。不要使用implicit打字,你只是在寻找麻烦。在尝试学习如何使用OpenMP时要求麻烦只是,好吧,要求更多麻烦。使用implicit none。并且不要回复哦,我只是更新使用隐式类型的现有代码库。如果这就是你正在做的事情,那就做好吧。

答案 1 :(得分:0)

以下列方式得到确切的结果。

SUBROUTINE QGAUSSP(func,a,b,ss)

     USE OMP_LIB
     USE MATRIC , ONLY : XG ,WG , NG
     implicit none
     double precision, intent(in) :: a , b
     double precision, intent(out):: ss
     double precision :: xm , xl , dx , xgd , wgd
     double precision :: s(NG)
     integer :: j,tid
     double precision,external::func
     xm = 0.5d0*(b+a)
     xl = 0.5d0*(b-a)
     ss = 0.d0
  !$omp parallel do private(j,xgd,wgd,dx) shared(xm,xl,xg,wg,s) num_threads(15) 
   do  j=1,ng
       xgd=xg(j)
       wgd=wg(j)
       dx = xl*xgd
       s(j)=wgd*(func(xm+dx)+func(xm-dx))
   end do
  !$omp end parallel do
   ss=sum(s) *xl/2.0
   return
  END