gpt4 book ai didi

fortran - 在 OpenMP 区域内调用内部子程序

转载 作者:行者123 更新时间:2023-12-05 04:16:56 24 4
gpt4 key购买 nike

我有一个模块包含一个包含另一个子例程的子例程。外部子例程有一个并行的 OpenMP 区域,我在其中调用内部子例程。代码编译运行没有任何错误,但结果不正确。

module my_module
contains
subroutine a(...)
*...some variables*
!$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(...)
*...do some work*
call b(...)

!$OMP END PARALLEL DO
contains
subroutine b(...)
*...some variables*
*...do some work*
end subroutine b
end subroutine a
end my module

如果我运行英特尔调试器 idb,它会在 子程序 b 中显示一个 SIGSEGV。现在,如果我在 subroutine a 中手动替换 subroutine b 的内容而不是调用它,并保留 OMP 子句,它不会抛出 SIGSEGV 错误,结果现在是正确。

编辑:完整代码在这里:https://github.com/mikolchon/cfd/blob/master/cfd2/calcRHS.f90它是一个包含用于求解欧拉流体方程的子程序的模块。如果我运行 idb,它将给出以下内容:

<code>idb</code> message

EDIT2:刚刚设法编写了一个较小的示例来重现此错误:

module some_module
implicit none
contains
subroutine sub0()
real :: a(5)
integer :: i
a(:) = 0
!$OMP PARALLEL DO DEFAULT(PRIVATE) SHARED(a)
do i = 1, 5
call sub1()
end do
!$OMP END PARALLEL DO
print*, a(:)
contains
subroutine sub1()
a(i) = a(i) + 1
end subroutine sub1
end subroutine sub0
end module some_module

program main
use some_module
implicit none
call sub0()
end program main

程序应该打印 1.000000 1.000000 1.000000 1.000000 1.000000。以下是我尝试过的不同编译标志:(编译器是ifort 14.0.2)

ifort name.f90 -check bounds -traceback -O0 - 在没有 OpenMP 的情况下工作正常

ifort name.f90 -openmp -check bounds -traceback -O0 - 给出超出范围的数组索引。

ifort name.f90 -openmp -check bounds -traceback - 会起作用

基本上,当我使用 -O0 时,错误就会显示出来。但是,这并不意味着当我不使用 -O0 时错误不存在(我这样说是因为我的原始代码会给出错误的结果)。此外,如果我显式传递索引 i,即:

....
call sub1(i)
....
contains
subroutine sub1(i)
integer i
....

然后用-O0编译,又可以了。所以我怀疑 OpenMP 在将变量 i 继承给它的子程序时遇到了问题。

最佳答案

我不确定 OpenMP 规范是否允许这样做。本帖https://software.intel.com/en-us/forums/topic/297424也有些疑惑。也许它只是被 Intel Fortran 错误地实现了,但必须仔细阅读官方规范。

在您的情况下,我会像您也尝试过的那样,通过将过程代码直接粘贴到循环中来避免主机关联的需要。

另一种选择是将私有(private)变量作为伪参数传递,正如引用线程中所建议的那样,这也避免了主机关联。

我不确定单独使用足够高的优化级别是否会有帮助,需要内联可能是不安全的。

FWIW 我在 Oracle Solaris Studio 12.4beta 上也遇到了同样的错误。


根据 IanH 的说法:

“内部子程序中对 i 的引用在一个区域中,但不在构造中。被引用的 i 是并行 do 构造之前的原始 i 还是私有(private)副本被称为“未指定”在 OpenMP 4.0 及更早版本中。”

规范中的相关部分是 (OpenMP 4.0 2.14.3.3.14):

The corresponding original list item. Inside the construct, all references to the original
list item are replaced by references to the new list item. In the rest of the region, it is
unspecified whether references are to the new list item or the original list item.

这意味着应该避免这种用法。

关于fortran - 在 OpenMP 区域内调用内部子程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25628034/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com