Parallel processing OpenMP调用函数会产生错误的结果

Parallel processing OpenMP调用函数会产生错误的结果,parallel-processing,fortran,openmp,gfortran,Parallel Processing,Fortran,Openmp,Gfortran,嗨,我正在尝试在不同的线程中放置一个do循环。现在,在do循环中,我调用了一个函数,该函数再次调用一些子例程,并添加到一个总和中。现在,如果我把并行函数封装在do循环中,它会给出随机结果,但是我看到,如果我把函数放在临界环境中,它会给出正确的结果。但是这会花费更多的cpu时间,并且根本不会提高速度。 我用一个小测试程序进行测试,并检查我的逻辑是否正确。然而,在一个大程序中(我不能在这里发布),这只在我将函数调用包含在CRITICAL中时起作用。 下面我给出了测试程序:(我的测试程序工作正常并给出

嗨,我正在尝试在不同的线程中放置一个do循环。现在,在do循环中,我调用了一个函数,该函数再次调用一些子例程,并添加到一个总和中。现在,如果我把并行函数封装在do循环中,它会给出随机结果,但是我看到,如果我把函数放在临界环境中,它会给出正确的结果。但是这会花费更多的cpu时间,并且根本不会提高速度。 我用一个小测试程序进行测试,并检查我的逻辑是否正确。然而,在一个大程序中(我不能在这里发布),这只在我将函数调用包含在CRITICAL中时起作用。 下面我给出了测试程序:(我的测试程序工作正常并给出了正确的结果,但是在大程序中,我发现funb不能正确地在不同的线程中使用,除非它在关键环境中。)

如果我在大程序中删除OMP CRITICAL,我会看到不同的线程在不同的线程中使用相同的funb值,这应该是不同的。因此,我的理解是:在并行部分中调用函数有一些限制。如果有人能澄清这个问题,我将不胜感激

函数funb如下所示:

      COMPLEX*16 FUNCTION FUNB(ZAA)

  IMPLICIT COMPLEX*16 (A-H,O-Z)
  real*8 X1,X2
  COMMON/ZVAR/ZA
  COMMON/XVAR/X1,X2
  ZA=ZAA
  call myinvini
  call myinvc(x2,fout)
  funb=fout
  RETURN
  END
myinvini是wl8、xl8的一些数据,但myinvc也是一个子程序:

  subroutine myinvc(x,f2)
  complex*16 dir,dirc,sta,ss,ssc,cn,cnc,f2,ff,ffc,func
  complex*16 f22,ans
  integer igauss,inte,l,m
  double precision x,range,phi,w,z,zz,zr
  double precision st,st0,zint,xbl,a,b,dli,sli
  double precision cpar,zero
  double precision xl8,wl8,xl32,wl32
  dimension zint(51)
  COMMON/iinte/inte  
  complex*16 cbeta
  common /wgauss/ xl8(8),wl8(8),xl32(32),wl32(32)
  common /ccpar/ cpar

  include 'constants.h'
  igauss = 8
  zero=0.0d0
  range=201.0d0
  phi=3.0d0/4.0d0*pi
  dir=dcmplx(dcos(phi),dsin(phi))
  dirc=dcmplx(dcos(phi),-dsin(phi))
  sta=dcmplx(cpar,zero)
  st =dexp(dlog(range)/dble(inte))
  st0=1.0d0
  zint(1)=zero
  do 11 l=1,inte    
     st0 =st0*st
     zint(l+1)=st0-1.0d0
  11    continue

  ss=dcmplx(zero,zero)
  ssc=dcmplx(zero,zero)
  xbl=dlog(x)

  do 23 l=1,inte  ! inte=5
     a=zint(l)
     b=zint(l+1)
     dli=(b-a)/2.d0
     sli=(b+a)/2.d0

  do 24 m=1,igauss
     if(igauss.eq. 8) w=wl8(m)
     if(igauss.eq.32) w=wl32(m)
     if(igauss.eq. 8) zz=xl8(m)
     if(igauss.eq.32) zz=xl32(m)
     z =dli*zz+sli
     cn=sta+z*dir
     cnc=sta+z*dirc

  ff=func(cn)
  ffc=func(cnc)

  ss=ss+ff*dir*exp(-xbl*cn)*w*dli
  ssc=ssc+ffc*dirc*exp(-xbl*cnc)*w*dli
  24    continue
  23    continue
  f2=(ss+ssc)
  return
  end

在没有threadprivate指令的情况下,共享公共块变量。parallel部分中引用的函数修改此类公共块变量,这将导致数据争用,openmp标准不允许


代码对openmp构造中引用的大多数变量使用隐式类型和隐式数据共享属性规范。从编码风格的角度来看,这些是分离的。如图所示的代码有一个可能的变量拼写错误,如果避免了隐式规范,则可能会避免该错误。

请向我们展示函数的代码。请告诉我是什么使函数线程安全。这在这里已经讨论过很多次了。请看@VladimirF,我已经添加了这个函数。这个问题与私有/共享变量的定义有关吗?您有共同的共享数据,这似乎不是您的意图。谢谢您的解释。有没有办法正确地通过公共块?您所指的变量拼写错误是什么?请查看有关threadprivate属性的文档。示例代码中有名为
xcn
xnc
的变量。不要使用隐式类型!!!!
  subroutine myinvc(x,f2)
  complex*16 dir,dirc,sta,ss,ssc,cn,cnc,f2,ff,ffc,func
  complex*16 f22,ans
  integer igauss,inte,l,m
  double precision x,range,phi,w,z,zz,zr
  double precision st,st0,zint,xbl,a,b,dli,sli
  double precision cpar,zero
  double precision xl8,wl8,xl32,wl32
  dimension zint(51)
  COMMON/iinte/inte  
  complex*16 cbeta
  common /wgauss/ xl8(8),wl8(8),xl32(32),wl32(32)
  common /ccpar/ cpar

  include 'constants.h'
  igauss = 8
  zero=0.0d0
  range=201.0d0
  phi=3.0d0/4.0d0*pi
  dir=dcmplx(dcos(phi),dsin(phi))
  dirc=dcmplx(dcos(phi),-dsin(phi))
  sta=dcmplx(cpar,zero)
  st =dexp(dlog(range)/dble(inte))
  st0=1.0d0
  zint(1)=zero
  do 11 l=1,inte    
     st0 =st0*st
     zint(l+1)=st0-1.0d0
  11    continue

  ss=dcmplx(zero,zero)
  ssc=dcmplx(zero,zero)
  xbl=dlog(x)

  do 23 l=1,inte  ! inte=5
     a=zint(l)
     b=zint(l+1)
     dli=(b-a)/2.d0
     sli=(b+a)/2.d0

  do 24 m=1,igauss
     if(igauss.eq. 8) w=wl8(m)
     if(igauss.eq.32) w=wl32(m)
     if(igauss.eq. 8) zz=xl8(m)
     if(igauss.eq.32) zz=xl32(m)
     z =dli*zz+sli
     cn=sta+z*dir
     cnc=sta+z*dirc

  ff=func(cn)
  ffc=func(cnc)

  ss=ss+ff*dir*exp(-xbl*cn)*w*dli
  ssc=ssc+ffc*dirc*exp(-xbl*cnc)*w*dli
  24    continue
  23    continue
  f2=(ss+ssc)
  return
  end