我有一些关于在Fortran中使用并行编程中的公共块的问题。
我的子程序有公共块。我是否必须声明并行do区域中的所有公共块和threadprivate?
他们如何传递信息?我想为每个线程分别使用公共时钟,并希望它们通过并行区域的末尾传递信息。它会在这里发生吗?
我的Ford
子例程更改了公共块中的一些变量,Condact
子例程再次覆盖它们,但该函数使用Condact
子例程中的值。第二个子例程和函数是否复制了每个线程的前一个子例程中的变量?
program
...
! Loop which I want to parallelize
!$OMP parallel DO
!do I need to declear all common block and threadprivate them here?
I = 1, N
...
call FORD(i,j)
...
!$OMP END parallel DO
end program
subroutine FORD(i,j)
dimension zl(3),zg(3)
common /ellip/ b1,c1,f1,g1,h1,d1,
. b2,c2,f2,g2,h2,p2,q2,r2,d2
common /root/ root1,root2
!$OMP threadprivate (/ellip/,/root/)
!this subroutine rewrite values of b1, c1 and f1 variable.
CALL CONDACT(genflg,lapflg)
return
end subroutine
SUBROUTINE CONDACT(genflg,lapflg)
common /ellip/ b1,c1,f1,g1,h1,d1,b2,c2,f2,g2,h2,p2,q2,r2,d2
!$OMP threadprivate (/ellip/)
! this subroutine rewrite b1, c1 and f1 again
call function f(x)
RETURN
END
function f(x)
common /ellip/ b1,c1,f1,g1,h1,d1,
. b2,c2,f2,g2,h2,p2,q2,r2,d2
!$OMP threadprivate (/ellip/)
! here the function uses the value of b1, c1, f1 from CONDAT subroutine.
end
答案 0 :(得分:1)
首先,正如上面的评论所说,我强烈建议不要使用common
,特别是在现代代码中,混合全局数据和并行性只是要求一个痛苦的世界 - 实际上全球数据只是一个坏事想法完全停止。
好的,你的问题:
- 我的子程序有常见的块。我必须申报所有的 并行do区域中的公共块和threadprivate?
醇>
不,threadprivate
是一个声明性指令,只能在代码的声明部分使用,并且必须在每次声明后出现。
- 他们如何传递信息?我想要每个人都有一个共同的时钟 线程并希望它们通过并行结束传递信息 区域。它会在这里发生吗?
醇>
您怀疑每个线程都会获得自己的common
块版本。当您进入第一个并行区域时,块中的值将是未定义的,除非您使用copyin
来广播主线程中的值。对于后续并行区域,只要每个区域中使用的线程数相同,就会保留这些值。在区域之间,公共块中的值将是主线程的值。
- 是否可以通过子程序访问这些公共块?我的Ford子程序在common block和Condat中重写了一些变量 子程序再次重写它们,但函数使用这些值 来自Condat子程序。这可能是重写并传递共同点 在这里使用threadprivate阻塞变量?
醇>
我不得不承认我不确定你在这里问的是什么。但是,如果您在询问OpenMP代码中是否可以使用common来传递不同子程序之间的变量,答案是肯定的,就像在串行Fortran中一样(注意大写)
答案 1 :(得分:0)
如何将公共块转换为模块?
将common /root/ root1, root2
更改为use gammax
,然后制作包含以下内容的新文件root.f
:
module root
implicit none
save
real :: root1, root2
!$omp threadprivate( root1, root2 )
end module root