こんにちはを与えます。今度はdoループの中で、再びサブルーチンを呼び出して総和を加算する関数を呼び出しています。私はループを囲む平行に置けば今、それはランダムな結果を与えているが、私はCRITICAL環境内で機能を置けば、それは正しい結果を与えていることがわかります。しかし、これはより多くのCPU時間を要し、速度をまったく改善しない。 私は小さなテストプログラムでテストされ、私のロジックが正しいことを確認してください。しかし、大きなプログラム(ここでは投稿できません)では、これは関数呼び出しをCRITICALで囲む場合にのみ機能します。 私はテストプログラム与える以下:(。私のテストプログラムが動作し、私はそれがクリティカルな環境でない限り、funbが正しく異なるスレッドで撮影されていないことがわかり、大きなプログラムでただし、正しい結果が得られる)OpenMPのは、私は別のスレッドで実行するループを入れしようとしています間違った結果に
sum=0d0
!$OMP PARALLEL PRIVATE(i,j,sum1,xcn,fun)
ithrd=OMP_GET_THREAD_NUM()
!$OMP DO
do i=1,5
sum1=0d0
do j=1,3
xcn=i+j+xx
!$OMP CRITICAL
fun=funb(xnc)
write(*,*)fun
!$OMP END CRITICAL
sum1=sum1+fun
enddo
enddo
!$OMP END DO
!$OMP CRITICAL
sum=sum+sum1
!$OMP END CRITICAL
!$OMP END PARALLEL
write(*,*)sum
場合をI別のスレッドが異なっている必要があります異なるスレッドでfunbに対して同じ値を取っていることを私が見る大きなプログラムでOMP CRITICALを削除します。したがって、私の理解です:PARALLELセクションで呼び出される関数にいくつかの制限があります。誰かが問題を明らかにすることができれば感謝しています。
として与えられる関数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はXL8、WL8のためにいくつかのデータであるが、サブルーチンが再び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
注釈は、私たちに機能のコードを示します。そして、関数をスレッドセーフなものにしてください*。これは以前何度もここで議論されていました。 –
https://stackoverflow.com/questions/35347944/fortran-openmp-with-subroutines-and-functionsを参照してください。 –
@VladimirF私はこの機能を追加しました。問題はプライベート/シェア変数の定義に関連していますか? –