Вызов внутренней подпрограммы внутри региона OpenMP

У меня есть модуль, который содержит подпрограмму, которая содержит другую подпрограмму. Внешняя подпрограмма имеет параллельную область 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

Если я запускаю отладчик Intelidb, он покажет мне SIGSEGV внутриsubroutine b, Теперь, если я вручную заменю содержимоеsubroutine b внутриsubroutine a вместо того, чтобы вызывать его и сохранять предложения OMP, он не будет выдавать ошибку SIGSEGV, и результаты теперь верны.

РЕДАКТИРОВАТЬ: Полный код здесь:https://github.com/mikolchon/cfd/blob/master/cfd2/calcRHS.f90 Это модуль, содержащий подпрограмму для решения уравнений жидкости Эйлера. Если я бегуidb, это даст следующее:

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 своим дочерним подпрограммам.

 Vladimir F02 сент. 2014 г., 18:25
На это невозможно ответить, если вы не добавили остальную часть кода. Может бытьb не нить безопасна, но кто знает.
 Vladimir F02 сент. 2014 г., 20:38
Каковы ваши варианты компилятора?-openmp должен обеспечивать соблюдениеrecursive но некоторые другие варианты могут испортить его.
 Vladimir F02 сент. 2014 г., 18:27
Практическое правило заключается в том, что если вам нужно в нескольких предложениях объяснить, как выглядит код, не объясняйте его, опубликуйте код.
 Michael02 сент. 2014 г., 21:07
Просто удалось воспроизвести ошибку на меньшем примере. Я добавил это к вопросу.
 Vladimir F02 сент. 2014 г., 20:44
Попробуйте уменьшить код и добавить основную программу, которая его вызывает, чтобы мы могли ее протестировать.

Ответы на вопрос(1)

Решение Вопроса

https://software.intel.com/en-us/forums/topic/297424 также есть некоторые сомнения. Возможно, это просто неправильно реализовано в Intel Fortran, но нужно будет внимательно прочитать официальные спецификации.

В вашем случае я бы избежал необходимости в ассоциации хостов, вставив код процедуры непосредственно в цикл, как вы тоже пытались.

Другой вариант - передать приватные переменные в качестве фиктивных аргументов, как предлагается в ссылочном потоке, который также избегает ассоциации хоста.

Я не уверен, поможет ли использование одного достаточно высокого уровня оптимизации, вероятно, небезопасно встраивать.

Я также получаю ту же ошибку с Oracle Solaris Studio 12.4beta.

Согласно IanH:

«Ссылка на i внутри внутренней подпрограммы находится в регионе, но не в конструкции. Независимо от того, ссылается ли на i оригинал i перед конструкцией параллельного do, или частная копия вызывается как« неопределенная »в 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.

Это означает, что такого использования следует избегать.

 Michael03 сент. 2014 г., 03:43
Это было очень полезно. Спасибо!
 Vladimir F02 сент. 2014 г., 23:20
Спасибо за разъяснения.

Ваш ответ на вопрос