4

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

whereFUNSUB以下列方式评估属性:

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不断超出.Propllmaxm(-l,l)

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

4

2 回答 2

3

我认为您的问题是在 Fortran 中,局部子程序变量可以是静态的,!$OMP并且不会传播到被调用的函数。

如果您将代码复制粘贴FUNSUB到调用循环中,即如果您手动内联它,您的代码应该可以按预期工作。

更新

在阅读了一些关于编译器可能会或可能不会实现局部变量的疯狂之后,我想你最好的选择是声明FUNSUBRECURSIVE. 这会将所有局部变量强制到堆栈上,这意味着调用的每个 OpenMP 线程都FUNSUB将拥有自己的一组私有的局部变量。

于 2012-06-23T16:30:36.490 回答
1

必须调查 FUNSUB 的完整代码。在 OpenMP 区域中正确使用外部函数应该不是问题。应该没有理由,也不可能将外部函数范围内的变量声明为私有的。

如果您不告诉它这样做,现代 Fortran 编译器将不会创建函数静态的局部变量。这可以使用编译器开关(并行代码中的大 NO NO)或通过将变量声明为已保存的 SAVE 来完成。请注意,所有初始化的变量都是隐式保存的。这意味着:

   integer :: local = 0

即使没有 SAVE 关键字也是 SAVE 并将在线程之间共享。

将所有并行调用的函数声明为PURE. 我什至至少有效地拥有所有非递归函数PURE

于 2012-06-23T19:21:27.003 回答