У меня есть модуль, который содержит подпрограмму, содержащую другую подпрограмму. Внешняя подпрограмма имеет параллельную область 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
, это даст следующее:
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
дочерним подпрограммам.
Невозможно ответить, если вы не добавили остальную часть кода. Может быть, 'b' не является безопасным потоком, но кто знает. –
Правило большого пальца есть, если вам нужно объяснить в нескольких предложениях, как выглядит код, не объяснять его, размещать код. –
Какие у вас параметры компилятора? '-openmp' должен принудительно использовать« рекурсивный », но некоторые другие варианты могут испортить его. –