我是关于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
答案 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