2016-06-01 3 views
2

Я прочитал как 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 которые прошли частные. Параметры модуля разделены, но это нормально. Не могли бы вы объяснить, почему это происходит?

ответ

3

С -fno-automatic локальные переменные в kernel будут неявно SAVE d. Описание here отмечает

Local variables with the SAVE attribute declared in procedures called from a parallel region are implicitly SHARED.

как таковой, kernel действительно не поточно- (как я понимаю).

Обратите внимание также в вашем примере вы передаете dummy1 в качестве первого и второго аргументов kernel, но ваше определение этой процедуры задает первый аргумент (r) в скаляр в то время как второй (dx) представляет собой массив длины dim. Я не уверен, что это всего лишь продукт вашего минимального примера или вашего реального кода, но это может вызвать проблемы. Вы объявляете kernel внутри модуля, а затем используете модуль? Это создаст интерфейсы, которые должны помочь поймать подобные вещи.

+0

Это продукт минимального примера. Для этого примера код 1D (dim = 1), поэтому он, надеюсь, не должен иметь значения. Ядро не находится в модуле, это автономная подпрограмма. – 1QuickQuestion

+1

@ 1QuickQuestion Если я пытаюсь скомпилировать что-то похожее на это, я получаю 'Предупреждение: несоответствие ранга в аргументе 'b' at (1) (rank-1 и scalar)', но если я поместил 'подпрограмму' внутри' contains' (т. е. существует интерфейс), это становится «Ошибка: несоответствие ранга в аргументе« b »в (1) (ранг-1 и скаляр)), поэтому я был бы осторожен с этим подходом. –

+0

Без '-fno-automatic' код будет компилироваться, но не запускаться вообще. @ d_1999 Я исследую это дальше. – 1QuickQuestion