2016-08-28 4 views
1

Ich denke mein Problem ist verwandt oder sogar identisch mit dem beschriebenen Problem here. Aber ich verstehe nicht, was tatsächlich passiert.Unterroutine in paralleler Umgebung aufrufen

Ich verwende OpenMP mit dem gfortran Compiler und ich habe die folgende Aufgabe zu tun: Ich habe eine Dichteverteilung F(X, Y) auf einer zweidimensionalen Fläche mit x-Koordinaten und XY y-Koordinaten. Die Matrix F hat die Größe Nx x Ny.

Ich habe jetzt eine Reihe von Koordinaten Xp(i) und Yp(i) und ich muss die Dichte F auf diese Punkte interpolieren. Dieses Problem wurde für die Parallelisierung gemacht.

!$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(i) 
    do i=1, Nmax 

     ! Some stuff to be done here 

     Fint(i) = interp2d(Xp(i), Yp(i), X, Y, F, Nx, Ny) 

     ! Some other stuff to be done here 

    end do 
!$OMP END PARALLEL DO 

Alles ist geteilt außer i. Die Funktion interp2d führt eine einfache lineare Interpolation durch.

Das funktioniert gut mit einem Thread aber schlägt mit Multithreading fehl. Ich verfolgte das Problem auf die hunt-Unterroutine aus Numerical Recipes, die von interp2d aufgerufen wird. Die hunt -Unterroutine berechnet grundsätzlich den Index ix so, dass X(ix) <= Xp(i) < X(ix+1). Dies wird benötigt, um den Startpunkt für die Interpolation zu erhalten.

Mit ihm Multithreading passiert ab und zu, dass ein Threads den richtigen Index ix von hunt und den Faden bekommt, die hunt nächste bekommt exakt die gleichen Index aufruft, obwohl Xp(i) bis zu diesem Zeitpunkt nicht einmal in der Nähe ist.

Ich kann dies verhindern, indem die CRITICAL-Umgebung:

!$OMP PARALLEL DO DEFAULT(SHARED) PRIVATE(i) 
    do i=1, Nmax 

     ! Some stuff to be done here 

    !$OMP CRITICAL 
     Fint(i) = interp2d(Xp(i), Yp(i), X, Y, F, Nx, Ny) 
    !$OMP END CRITICAL 

     ! Some other stuff to be done here 

    end do 
!$OMP END PARALLEL DO 

Aber dies die Effizienz verringert. Wenn ich zum Beispiel drei Threads verwende, habe ich einen Lastdurchschnitt von 1,5 mit der CRITICAL Umgebung. Ohne habe ich einen Lastdurchschnitt von 2,75, aber falsche Ergebnisse und manchmal sogar einen SIGSEGV Laufzeitfehler.

Was genau passiert hier? Es scheint mir, dass alle Threads die gleiche hunt -subroutine aufrufen und wenn sie es gleichzeitig tun, gibt es einen Konflikt. Ist das sinnvoll?

Wie kann ich das verhindern?

+1

Es sieht so aus, als wäre das 'hunt'-Unterprogramm nicht Thread-sicher. Verschieben Sie einfach Ihre 'critical' Direktive weg von dem Aufruf zu' interp2d' runter zum Aufruf 'jagen' innerhalb von 'interp2d' (oder so niedrig wie möglich). – Gilles

+1

Könnten Sie den Code der Routinen 'interp2d' und' hunt' posten? Normalerweise, wenn Sie ein 'critical' benötigen, damit ein Code funktioniert, liegt das daran, dass Sie eine gemeinsam genutzte Ressource (z. B. eine Variable) haben, die von mehreren Threads gleichzeitig gelesen und geschrieben wird. – smateo

+0

Ich bin mir nicht sicher, ob ich das Unterprogramm von Numerical Recipes hier veröffentlichen kann. Aber ich werde später etwas vereinfachtes veröffentlichen. Mittlerweile denke ich, dass alle Threads auf den gleichen Stapel zugreifen und manchmal, abhängig von der Ausführungszeit der Routinen, lesen sie nicht die Dummy-Variablen in der richtigen Reihenfolge vom Stapel. Macht das irgendeinen Sinn? Kann ich jeden Thread zwingen, einen eigenen privaten Stack zu haben? – Sebastian

Antwort

1

variable Erklärung und Initialisierung in Fortran 90+ hat den Nebeneffekt des Gebens die Variable die SAVE Attribut zu kombinieren.

integer :: i = 0 

entspricht in etwa:

integer, save :: i 

if (first_invocation) then 
    i = 0 
end if 

SAVE ‚d Variablen ihren Wert zwischen mehreren Aufrufen der Routine erhalten und werden daher häufig als statische Variablen implementiert. Nach den Regeln für die impliziten Klassen für den Datenaustausch in OpenMP werden diese Variablen gemeinsam genutzt, sofern sie nicht in einer threadprivate-Direktive aufgeführt sind.

OpenMP schreibt vor, dass kompatible Compiler die obige Semantik anwenden sollten, selbst wenn die zugrunde liegende Sprache Fortran 77 ist.

Verwandte Themen