Shared Memory Programmierung: Übungen Zugang Daten-Attribute Race condition Parallelisierungs-Overhead Lastverteilung mit SCHEDULE Prozedur-übergreifende Parallelisierung Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP Zugang Einloggen auf gwdk032.gwdg.de Kopieren der Übungsbeispiele mit cp -r ~ohaan/Uebungen . Editieren, Übersetzen, Binden und Starten von Programmen auf dem Knoten gwdk032 Bearbeitung der Programme auf gwdk030,gwdk032 (interaktiv) gwdk061 – gwdk064 (Batch) Verzeichniswechsel cd Uebungen/Start Compilieren von hello.f xlf_r -qsmp=omp hello.f bzw. hello.c xlc_r -qsmp=omp hello.c Starten im Dialog a.out Starten im Batch llsubmit lljob Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP Batch-Verarbeitung Jobfile lljob #!/bin/ksh # @ job_type = parallel # @ job_name=kurs # @ wall_clock_limit = 00:10:00,00:10:00 # @ output = out.$(jobid) # @ error = err.$(jobid) # @ class = sp_kurs # @ node = 1,1 # @ tasks_per_node = 1 # @ node_usage = not_shared # @ network.MPI = switch,shared,US # @ queue a.out Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP Batch-Verarbeitung Starten: llsubmit <lljob> Job-Abfrage: llq, llall Abbrechen: llcancel <jobid> Status-Abfrage llstatus Ergebnisse in out.<jobid> und err.<jobid> Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP Aufgabe 1: hello Modifizieren Sie hello.f, so, daß anstelle von –1 die Thread-ID ausgegeben wird. Hinweis: Verwenden Sie die Laufzeitroutine OMP_GET_THREAD_NUM() und das Daten-Attribut PRIVATE Verändern Sie die Anzahl der verwendeten Threads Hinweis: Verwenden Sie dieUmgebungsvariable OMP_NUM_THREADS oder die Laufzeitroutine OMP_SET_NUM_THREADS(nthr) Shared Memory Programmierung: OpenMP
Daten-Attribute in parallelen Regionen Default Attribut ist SHARED Default Attribut für Iterationsvariable in paralleler do-Schleife ist PRIVATE Variablen, die in jedem Thread separat modifiziert werden, müssen explizit als PRIVAT deklariert werden, z.B.: alle skalaren Variablen, die in der parallelen Region gesetzt werden alle Felder, deren lokale Indexmengen gemeinsame Elemente haben Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP Aufgabe 2: matmul Wechseln Sie in das Verzeichnis Attribute Ergänzen Sie in matmul.f die notwendigen Attribute für die PARALLEL DO Direktive Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP FIRSTPRIVATE Beispiel: associate.f a,b,c=1 !$OMP PARALLEL PRIVATE(a), FIRSTPRIVATE(b) das lokale a ist nicht mit dem globalen a assoziiert alle lokalen b‘s sind mit dem Wert des globalen b initialisiert !$OMP END PARALLEL Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP LASTPRIVATE Beispiel: associate.f !$OMP DO do i = 1 , n Nach der parallelen Region ist der Iterationsindex i nicht mehr mit dem i aus der Schleife assoziiert !$OMP DO LASTPRIVATE(i) Nach der parallelen Region hat der Iterationsindex i den Wert n+1 Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP race condition Bei unsynchronisiertem Modifizierung von gemeinsamen Variablen kann das Ergebnis unvorhersehbar sein z. B.: Programm in Datei sum_race.f do i = ia , ie globsum = globsum + a(i) end do Jeder Thread hat eigene Iterationsgrenzen ia, ie, globsum ist eine Variable mit dem Attribut SHARED Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP Aufgabe 3: sum_race Wechseln Sie in das Verzeichnis Attribute Übersetzen Sie sum_race.f mit Hilfe des Makefiles Verifizieren Sie das Auftreten der race condition durch mehrmaligen Aufruf des ausführbaren Programms mit den Eingaben aus der Datei inp sum < inp Modifizieren Sie das Programm so, dass die race condition nicht mehr auftritt Hinweis: Verwendung Sie die Direktiven !$OMP ATOMIC oder !$OMP CRITICAL / !OMP END CRITICAL Shared Memory Programmierung: OpenMP
Aufgabe 4: sum_race mit LOCK Beheben Sie die race condition mit locks Hinweis: Programmstruktur mit LOCK-Routinen integer lck call OMP_INIT_LOCK(lck) ... call OMP_SET_LOCK(lck) geschützter Bereich call OMP_UNSET_LOCK(lck) call OMP_DESTROY_LOCK(lck) lck muss das Attribut SHARED haben! Shared Memory Programmierung: OpenMP
Aufgabe 5: sum_reduction Vereinfachen Sie das Programm sum_race durch Verwendung der Direktiven !$OMP PARALLEL DO Hinweis: die Summationsvariable globsum muss als Reduktionsvariable deklariert werden durch Verwendung des Attributes REDUCTION(+:globsum) Shared Memory Programmierung: OpenMP
Overhead durch Parallelisierung Die wichtigsten Quellen für Leistungsverluste durch Parallelisierung sind Thread-Erzeugung zu Beginn der parallelen Region Synchronisation zu Ende der parallelen Region Jede weitere Synchronisation mit BARRIER oder FLUSH Exklusive Zugriffe auf gemeinsame Variablen Ungleiche Lastverteilung Overhead für Parallele Schleife auf IBM Winterhawk2: ca 20 microsec = 7500 Zyklen ( bei 375 MHz Taktrate) Shared Memory Programmierung: OpenMP
SMP Summe auf IBM Winterhawk2 Shared Memory Programmierung: OpenMP
SMP Summe auf IBM Regatta Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP Aufgabe 6: Zeitmessung Wechseln Sie in das Verzeichnis Zeitmessung Compilieren Sie das Programm in synch.f : xlf_r -qsmp=omp synch.f Starten Sie das Programm mit 1,2,3 und 4 Threads Hinweis: Zahl der Threads auf nthr setzen mit export OMP_NUM_THREADS=nthr Shared Memory Programmierung: OpenMP
Lastverteilung in einer Schleife OpenMP stellt drei Methoden zur Verteilung von Iterationen einer Schleife auf die Threads zur Verfügung: SCHEDULE(STATIC,n) SCHEDULE(DYNAMIC,n) SCHEDULE(GUIDED,n) Mit SCHEDULE(RUNTIME) kann die Verteilung zur Laufzeit gewählt werden : export OMP_SCHEDULE=“method,n“ Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP Aufgabe 7: sched.f Wechseln Sie in das Verzeichnis Schedule Testen Sie durch Modifikation von sched.f die Verteilung der Schleifeniterationen bei verschiedenen SCHEDULE-Methoden Shared Memory Programmierung: OpenMP
Shared Memory Programmierung: OpenMP Aufgabe 8: force.f Wechseln Sie in das Verzeichnis Schedule Das Programm force.f enthält die Schleife für die Kraftberechnung in einem System von n Lennard-Jones-Molekülen. Übersetzen Sie mit make Setzen Sie die Umgebungsvariable OMP_SCHEDULE Finden Sie für n=5000 die günstigste Methode für SCHEDULE Shared Memory Programmierung: OpenMP
Prozedur-übergreifende Parallelisierung OpenMP-Direktiven sind über Prozedurgrenzen gültig subroutine work(sum) integer tid, sum integer OMP_GET_THREAD_NUM ... tid = OMP_GET_THREAD_NUM() !$OMP CRITICAL sum = sum + tid !$OMP END CRITICAL program a ... !$OMP PARALLEL call work(sum) !$OMP END PARALLEL statischer Gültigkeitsbereich (static extent) verwaiste Direktiven (orphaned directives) dynamischer Gültigkeitsbereich (dynamic extent) Shared Memory Programmierung: OpenMP
Daten-Attribute bei Prozedur-übergreifender Parallelisierung Attribute in Direktiven gelten nur im statischen Geltungsbereich, außer für Variable, die als Argumente in Prozeduraufrufen übergeben werden Lokale Variable ohne SAVE Attribut in Prozeduren, die aus einer parallele Region gerufen werden, haben implizit das Attribut PRIVATE Lokale Variable mit SAVE Attribut, COMMON Blöcke und MODULE Daten in Prozeduren, die aus einer parallele Region gerufen werden, haben implizit das Attribut SHARED Als THREADPRIVATE deklarierte COMMON Blöcke haben in Prozeduren, die aus einer parallele Region gerufen werden, haben implizit das Attribut PRIVATE Shared Memory Programmierung: OpenMP
Compiler Flags und Daten-Attribute Fortran77 Compiler (xlf, xlf_r) hat Default -qsave: alle lokalen Variablen sind SHARED -qnosave muss beim Compilieren gesetzt werden Fortran90 Compiler (xlf90, xlf90_r) hat Default -qnosave: alle lokalen Variablen sind PRIVATE Speicherplatzreservierung -bmaxdata:<n Bytes> reserviert Platz für Daten mit Attribut SHARED -bmaxstack:<n Bytes> reserviert Platz für Daten mit Attribut PRIVATE, maximaler Wert für Stack in 32bit Compilierung ist 256 MB Shared Memory Programmierung: OpenMP