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?
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
@ 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. –
Ohne '-fno-automatic' wird der Code kompiliert, aber überhaupt nicht ausgeführt. @ d_1999 Ich werde das weiter untersuchen. – 1QuickQuestion