2016-06-01 11 views
2

Ich habe beide Calling an internal subroutine inside OpenMP region und Global Variables in Fortran OpenMP gelesen. Mein Verständnis (from here) ist, dass:Unterprogramm in OpenMP PARALLEL DO - Programmabsturz

  • Variablen in der Argumentliste Attribut von der rufenden Routine ihres Datenumfang erben.
  • COMMON-Blöcke oder Modulvariablen in Fortran werden gemeinsam genutzt, sofern sie nicht als THREADPRIVATE deklariert sind.
  • SAVE Variablen in Fortran sind geteilt.
  • Alle anderen lokalen Variablen sind privat.

Das Folgende ist eine vereinfachte Version von meinem Code:

!$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 

Das Unterprogramm Kernel nimmt dann IN dummy1 und dummy2 und setzt OUT dummy3 und dummy4. Ich kompilieren mit:

-fopenmp -fno-automatic -fcheck=all 

ich:

Fortran runtime error: Recursive call to nonrecursive procedure 'kernel' 

Welche von here Ich verstehe, wird erwartet. Wenn ich ohne das -fcheck kompiliere, übergibt der Code manchmal den Subroutinenaufruf ohne Vorfall, aber die meiste Zeit wird er ohne Fehler abstürzen. Ich vermute, das liegt daran, dass meine Subroutine nicht Thread-sicher ist. Alle an die Subroutine übergebenen Argumente sollten für jeden Thread privat und individuell sein. Die abgespeckte Unterprogramm ist wie folgt:

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 

Die lokalen Variablen privat sein sollte und alle argumets, die sind privat geführt worden sind. Die Modulparameter sind geteilt, aber das ist in Ordnung. Könntest du bitte erklären, warum das abstürzt?

Antwort

3

Mit -fno-automatic werden die lokalen Variablen in kernel implizit SAVE d. Die Beschreibung here

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

Als solche stellt fest, kernel ist in der Tat nicht-Thread-sicher (wie ich es verstehe).

Beachten Sie auch in Ihrem Beispiel passieren Sie dummy1 als das erste und das zweite Argument zu kernel, aber Ihre Definition dieser Routine gibt das erste Argument (r) in einem Skalar, während das zweite (dx) ist ein Array der Länge dim. Ich bin mir nicht sicher, ob dies nur ein Produkt Ihres minimalen Beispiels oder Ihres echten Codes ist, aber dies könnte Probleme verursachen. Deklarieren Sie kernel in einem Modul und verwenden Sie dann das Modul? Dies wird Schnittstellen generieren, die dazu beitragen sollten, solche Dinge zu erfassen.

+0

Es ist ein Produkt des minimalen Beispiels. Für dieses Beispiel ist der Code 1D (dim = 1), also sollte es hoffentlich keinen Unterschied machen. Kernel ist nicht in einem Modul, es ist eine eigenständige Subroutine. – 1QuickQuestion

+1

@ 1QuickQuestion Wenn ich versuche, etwas zu kompilieren, das so aussieht, bekomme ich 'Warnung: Rank mismatch in Argument 'b' bei (1) (Rang-1 und Skalar)' aber wenn ich die 'Unterroutine' in ein' contains' setze Abschnitt (dh eine Schnittstelle existiert) wird dies zu 'Fehler: Rank mismatch in argument' b 'unter (1) (Rang-1 und Skalar) 'also wäre ich vorsichtig mit diesem Ansatz. –

+0

Ohne '-fno-automatic' wird der Code kompiliert, aber überhaupt nicht ausgeführt. @ d_1999 Ich werde das weiter untersuchen. – 1QuickQuestion