Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
558 views
in Technique[技术] by (71.8m points)

fortran - Calling an internal subroutine inside OpenMP region

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:

<code>idb</code> message

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

1.4m articles

1.4m replys

5 comments

57.0k users

...