我正在调用嵌套的for循环,如下所示:
do ir = 1,Nr
do iom = iom1, iom2
xyz(1) = xo(1) + xom(iom)*r
xyz(2) = xo(2) + yom(iom)*r
xyz(3) = xo(3) + zom(iom)*r
call FUNSUB(xyz,Nprop,PropXYZ)
enddo
enddo
其中FUNSUB
以下列方式评估属性:
id = 1
do l=0,lmax
do m=-l,l
id = id + 1
Prop(id) = RHO * Ylm(l,m,xl(1),xl(2),xl(3))
enddo
enddo
现在我想尝试将其与形式
并行化!$OMP parallel do reduction(+:Prop) private(ir, l, m, j, iom, r, wrad, xyz, PropOm, PropOm1, PropXYZ)
这里看到的其他一些私有变量是为了简洁而省略了我的示例代码。我故意尝试将l
和m
设为私有,以便在FUNSUB
循环内,独立评估属性。但是,我发现它们是在线程之间共享的。我已经提出了一些调试选项,发现id
不断超出Prop
的范围,并且发现l
也是lmax
以及m
超出(-l,l)
的范围。
我的问题是:我如何确保l
和m
保密,而不是从主程序中共享?似乎问题在于它是一个完全不同的子程序,它保存了这些值,并且不知何故这些变量的私有声明不会延续
答案 0 :(得分:3)
我认为您的问题是在Fortran local subroutine variables can be static中,而!$OMP
不会传播到被调用的函数。
如果您将FUNSUB
复制粘贴到调用循环中,即如果您手动内联它,则代码应按预期工作。
<强>更新强>
在阅读了关于编译器可能会或可能不会实现局部变量的冗余之后,我想你最好的选择是将FUNSUB
声明为RECURSIVE
。这会强制所有局部变量进入堆栈,这意味着调用FUNSUB
的每个OpenMP线程都将拥有自己的私有局部变量集。
答案 1 :(得分:1)
必须调查FUNSUB的完整代码。在OpenMP区域中正确使用外部函数应该不是问题。应该没有理由,也不可能将外部函数范围内的变量声明为私有。
现代Fortran编译器不会创建函数static的局部变量,如果你不告诉它这样做的话。这可以使用编译器开关(并行代码中的大NO NO)或通过将变量声明为SAVE来完成。请注意,所有初始化变量都是隐式SAVE。这意味着:
integer :: local = 0
即使没有SAVE关键字,也会保存,并且将在线程之间共享。
将所有并行调用的函数声明为PURE
是一种很好的做法。我甚至可以至少有效地使用所有非递归函数PURE
。