Я прочитал как Calling an internal subroutine inside OpenMP region, так и Global Variables in Fortran OpenMP. Мое понимание (from here) таково:Подпрограмма внутри OpenMP PARALLEL DO - сбой программы
- Переменные в списке аргументов наследуют свой атрибут области данных от вызывающей процедуры.
- Общие блоки или переменные модуля в Fortran являются общими, если не объявлено THREADPRIVATE.
- Переменные SAVE в Fortran являются общими.
- Все остальные локальные переменные являются частными.
Ниже представлена упрощенная версия моего кода:
!$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(j,dummy1,dummy2,dummy3,dummy4)
DO j=1,ntotal
dummy1 = 0.0d0
dummy2 = foo(j)
CALL kernel(dummy1,dummy1,dummy2,dummy3,dummy4)
Variable(j) = dummy3 + dummy4
END DO
!$OMP END PARALLEL DO
Ядро подпрограммы затем принимает dummy1 и dummy2 и тушит dummy3 и dummy4. Я компилирую с:
-fopenmp -fno-automatic -fcheck=all
я получаю:
Fortran runtime error: Recursive call to nonrecursive procedure 'kernel'
Какой из here я понимаю, как ожидается. Когда я компилирую без -fcheck, иногда код передает вызов подпрограммы без инцидентов, но большую часть времени он будет сбой без ошибок. Я предполагаю, что это потому, что моя подпрограмма не является потокобезопасной. Все аргументы, переданные подпрограмме, должны быть частными и индивидуальными для каждого потока. Урезана подпрограммой выглядит следующим образом:
SUBROUTINE kernel(r,dx,hsml,w,dwdx)
USE Initial_Parameters
IMPLICIT NONE
! DATA DICTIONARY: DECLARE CALLING PARAMETER TYPES AND DEFINITIONS
REAL(KIND=dp), INTENT(IN) :: r
REAL(KIND=dp), DIMENSION(dim), INTENT(IN) :: dx
REAL(KIND=dp), INTENT(IN) :: hsml
REAL(KIND=dp), INTENT(OUT) :: w
REAL(KIND=dp), DIMENSION(dim), INTENT(OUT):: dwdx
! DATA DICTIONARY: DECLARE LOCAL VARIABLE TYPES AND DEFINITIONS
INTEGER :: i, d
REAL(KIND=dp) :: q, dw
REAL(KIND=dp) :: factor
! Kernel functions are funcitons of q, the distance between particles
! divided by the smoothing length
q = r/hsml
! Preset the kernel to zero
w = 0.e0
! Preset the derivative of the kernel to zero
DO d=1,dim
dwdx(d) = 0.e0
END DO
IF (skf == 1) THEN
! If the problem is one dimensional then,
IF (dim == 1) THEN
! The coefficient, alpha = factor is given by:
factor = 1.e0/hsml
! If the problem is two dimensional then,
ELSE IF (dim == 2) THEN
! The coefficient, alpha = factor is given by:
factor = 15.e0/(7.e0*pi*hsml*hsml)
! If the problem is two dimensional then,
ELSE IF (dim == 3) THEN
! The coefficient, alpha = factor is given by:
factor = 3.e0/(2.e0*pi*hsml*hsml*hsml)
! If the dimension value is not 1, 2 or 3 then there is a problem.
ELSE
WRITE(*,*)' >>> Error <<< : Wrong dimension: Dim =',dim
STOP
END IF
! Smoothing function for 1st range of q.
IF (q >= 0 .AND. q <= 1.e0) THEN
! The smoothing function is given by:
w = factor * (2./3. - q*q + q*q*q/2.)
! For each dimension work out the gradient of the smoothing function
DO d = 1, dim
dwdx(d) = factor * (-2.+3./2.*q)/hsml**2 * dx(d)
END DO
! Smoothing function for 2nd range of q.
ELSE IF (q > 1.e0 .AND. q <= 2) THEN
! Smoothing function is equal to:
w = factor * 1.e0/6.e0 * (2.-q)**3
! Gadient of the smoothing function in each dimension.
DO d = 1, dim
dwdx(d) =-factor * 1.e0/6.e0 * 3.*(2.-q)**2/hsml * (dx(d)/r)
END DO
! Smoothing function and gradient for all other values of q is zero.
ELSE
! Smoothing function is equal to:
w=0.
! Gadient of the smoothing function in each dimension.
DO d= 1, dim
dwdx(d) = 0.
END DO
END IF
END SUBROUTINE kernel
Локальные переменные должны быть частными и все argumets которые прошли частные. Параметры модуля разделены, но это нормально. Не могли бы вы объяснить, почему это происходит?
Это продукт минимального примера. Для этого примера код 1D (dim = 1), поэтому он, надеюсь, не должен иметь значения. Ядро не находится в модуле, это автономная подпрограмма. – 1QuickQuestion
@ 1QuickQuestion Если я пытаюсь скомпилировать что-то похожее на это, я получаю 'Предупреждение: несоответствие ранга в аргументе 'b' at (1) (rank-1 и scalar)', но если я поместил 'подпрограмму' внутри' contains' (т. е. существует интерфейс), это становится «Ошибка: несоответствие ранга в аргументе« b »в (1) (ранг-1 и скаляр)), поэтому я был бы осторожен с этим подходом. –
Без '-fno-automatic' код будет компилироваться, но не запускаться вообще. @ d_1999 Я исследую это дальше. – 1QuickQuestion