在OpenMP区域内调用一个内部子例程 [英] Calling an internal subroutine inside OpenMP region

查看:435
本文介绍了在OpenMP区域内调用一个内部子例程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

  module my_module 
包含
子程序a(...)
* ...某些变量*
!$ OMP PARALLEL DO默认(私有)共享(...)
* ...做一些工作*
调用b(...)

!$ OMP END PARALLEL DO
包含
子程序b(...)
* ...某些变量*
* ...做一些工作*
结束子程序b
结束子程序a
结束我的模块
idb ,它会在子程序中显示一个SIGSEGV b $ b / code>。现在,如果我手动替换子程序a 中的子程序b 的内容而不是调用它,并保留OMP子句,它不会抛出SIGSEGV错误,并且结果现在是正确的。



编辑:完整的代码在这里:也有一些疑虑。也许这只是由英特尔Fortran错误实施,但必须仔细阅读官方规格。



在您的情况下,我会通过粘贴来避免需要主机关联直接进入循环的代码,就像你也尝试过一样。



另一种选择是将私有变量作为伪参数传递,就像在被引用的线程中所建议的那样,这也可以避免主机关联。



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

FWIW我也遇到了与Oracle Solaris Studio 12.4beta相同的错误。




根据IanH:

在内部子程序中对i的引用是在一个区域中,而不是在一个构造中。我被引用的是否是原来的i在前并行结构或私有副本被称为OpenMP 4.0中的未指定 。



来自specifiction的相关部分是(OpenMP 4.0 2.14.3.3。 14):


 对应的原始列表项。在构造内部,所有对原始
列表项的引用被对新列表项的引用所替代。在该地区的其他地区,未指定是否为新的清单项目或原始清单项目的


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


I have a module that contains a subroutine that contains another subroutine. The outer subroutine has a parallel OpenMP region in which I call the inner subroutine. The code compiles and runs without any error but the results are not correct.

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

If I run the Intel Debugger idb, it will show me a SIGSEGV inside subroutine b. Now, if I manually replace the content of subroutine b inside subroutine a instead of calling it, and keeping the OMP clauses, it will not throw SIGSEGV error and the results are now correct.

EDIT: Full code is here: https://github.com/mikolchon/cfd/blob/master/cfd2/calcRHS.f90 It's a module containing a subroutine to solve Euler fluid equations. If I run the idb, it will give the following:

EDIT2: Just managed to write a smaller example that reproduces this error:

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

The program should print 1.000000 1.000000 1.000000 1.000000 1.000000. The following are different compilation flags I tried: (compiler is ifort 14.0.2)

ifort name.f90 -check bounds -traceback -O0 - works fine without OpenMP

ifort name.f90 -openmp -check bounds -traceback -O0 - gives array index out of bound.

ifort name.f90 -openmp -check bounds -traceback - will work

So basically, the error will show when I use -O0. However, that doesn't mean that the error is absent when I don't use -O0 (I say this because my original code will give wrong results). Also, if I pass the index i explicitly, that is:

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

and then compile with -O0, it will work again. So my suspicion is that OpenMP is having trouble inheriting the variable i to its child subroutines.

解决方案

I am not sure if this is allowed by the OpenMP specifications. This thread https://software.intel.com/en-us/forums/topic/297424 also has some doubts. Maybe it is just wrongly implemented by Intel Fortran, but one would have to carefully read the official specifications.

In your case I would avoid the need for the host association by pasting the code of the procedure directly into the loop as you also tried.

The other option is to pass the private variables as dummy arguments, as is suggested in the referenced thread, which also avoids the host association.

I am unsure whether using high enough optimization level alone will help, it is probably unsafe to need the inlining.

FWIW I am getting the same error also with the Oracle Solaris Studio 12.4beta.


According to IanH:

"The reference to i inside the internal subroutine is in a region but not in a construct. Whether the i being referred to is the original i prior to the parallel do construct or a private copy is called out as being "unspecified "in OpenMP 4.0 and earlier."

The relevant section from the specifiction is (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.

This means this usage should be avoided.

这篇关于在OpenMP区域内调用一个内部子例程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆