如何在子程序中保持变量私有,这些子程序在openmp的并行部分中调用?

时间:2012-06-23 16:05:01

标签: multithreading fortran openmp private

我正在调用嵌套的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)

这里看到的其他一些私有变量是为了简洁而省略了我的示例代码。我故意尝试将lm设为私有,以便在FUNSUB循环内,独立评估属性。但是,我发现它们是在线程之间共享的。我已经提出了一些调试选项,发现id不断超出Prop的范围,并且发现l也是lmax以及m超出(-l,l)的范围。

我的问题是:我如何确保lm保密,而不是从主程序中共享?似乎问题在于它是一个完全不同的子程序,它保存了这些值,并且不知何故这些变量的私有声明不会延续

2 个答案:

答案 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