2014-09-02 5 views
1

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

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

EDIT: Полный код здесь: 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 дочерним подпрограммам.

+2

Невозможно ответить, если вы не добавили остальную часть кода. Может быть, 'b' не является безопасным потоком, но кто знает. –

+1

Правило большого пальца есть, если вам нужно объяснить в нескольких предложениях, как выглядит код, не объяснять его, размещать код. –

+0

Какие у вас параметры компилятора? '-openmp' должен принудительно использовать« рекурсивный », но некоторые другие варианты могут испортить его. –

ответ

3

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

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

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

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

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


По IanH:.

«Ссылка на I внутри внутренней подпрограммы в регионе, но не в конструкции ли я именуются оригинальный я до параллели действительно построить или закрытый экземпляр вызывается как «неуказанный» в OpenMP 4.0 и ранее ».

Соответствующий раздел из Specifiction является (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. 

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

+0

Спасибо за разъяснение. –

+0

Это было очень полезно. Благодаря! – Michael

Смежные вопросы