Parallele Programmierung mit OpenMP - Eine kurze Einführung - 11.06.2003 RRZN Kolloquium SS 2003 1
Gliederung 1. Grundlagen 2. Programmiermodell 3. Sprachkonstrukte 4. Vergleich MPI und OpenMP 11.06.2003 RRZN Kolloquium SS 2003 2
Was ist OpenMP? Abkürzung für Open Multi Processing Modell für die parallele Programmierung Shared Memory Architekturen CPU 1 CPU 2 a=3 c=a*a a 11.06.2003 RRZN Kolloquium SS 2003 3
Was ist OpenMP? Abkürzung für Open Multi Processing Modell für die parallele Programmierung Shared Memory Architekturen Standard seit 1997 Erweiterungen für Fortran, C und C++ portabel und skalierbar inkrementelle Parallelisierung Programme bleiben seriell lauffähig 11.06.2003 RRZN Kolloquium SS 2003 4
Grundlagen compilerbasiert OpenMP Sprachmittel: Compilerdirektiven Bibliotheksroutinen Umgebungsvariablen hauptsächlich Parallelisierung von Schleifen Kommunikation über gemeinsame Variablen Programmiermodell: Fork-Join-Modell 11.06.2003 RRZN Kolloquium SS 2003 5
Fork-Join-Modell serieller Bereich 0 parallele Region 0 1 2 3 Team of Threads serieller Bereich 0 Master Thread parallele Region 0 1 2 3 Team of Threads serieller Bereich 0 Master Thread 11.06.2003 RRZN Kolloquium SS 2003 6
Syntax der Direktiven Fortran: Behandlung als Kommentare!$omp Name [clauses] keine Unterscheidung von Groß- und Kleinschreibung C/C++: #pragma Direktiven #pragma omp Name [clauses] Unterscheidung von Groß- und Kleinschreibung include Datei <omp.h> für Bibliotheksroutinen 11.06.2003 RRZN Kolloquium SS 2003 7
Parallel Direktive Fortran:!$omp parallel [clause] Block!$omp end parallel C/C++: #pragma omp parallel [clause] strukturierter Block /* omp end parallel */ clause kann sein: shared, private, firstprivate, lastprivate 11.06.2003 RRZN Kolloquium SS 2003 8
Parallel Direktive (Beispiel) Fortran: integer omp_get_thread_num()!$omp parallel write(*,*) Threadnummer:,omp_get_thread_num()!$omp end parallel C/C+: #include <omp.h> #inlcude <stdio.h> #pragma omp parallel printf( Threadnummer: %d\n,omp_get_thread_num()); /* omp end parallel */ 11.06.2003 RRZN Kolloquium SS 2003 9
Parallel Direktive (Beispiel) Fortran: integer omp_get_thread_num()!$omp parallel write(*,*) Threadnummer: omp_get_thread_num()!$omp end parallel E10K: f90 openmp prog.f HLRN: xlf_r qsmp=omp prog.f export OMP_NUM_THREADS=4./a.out C/C++: #include <omp.h> #inlcude <stdio.h> #pragma omp parallel printf( Threadnummer: %d\n,omp_get_thread_num()); /* omp end parallel */ E10K: cc xopenmp prog.c HLRN: xlc_r qsmp=omp prog.c export OMP_NUM_THREADS=4./a.out 11.06.2003 RRZN Kolloquium SS 2003 10
Parallel Direktive (Beispiel) Fortran integer omp_get_thread_num()!$omp parallel Threadnummer: 2 write(*,*) Threadnummer: Threadnummer: 3 omp_get_thread_num() Threadnummer: 0!$omp end Threadnummer: parallel 1 Threadnummer: 0 Threadnummer: 1 Threadnummer: 2 E10k: f90 openmp prog.f Threadnummer: 3 HLRN: xlf_r qsmp=omp prog.f C/C++ #include <omp.h> #inlcude <stdio.h> Threadnummer: #pragma 0omp parallel Threadnummer: printf( 3 Threadnummer: /* end parallel 2 */ Threadnummer: 1 Threadnummer: 2 Threadnummer: 0 Threadnummer: 1 Threandummer: E10K: 3 cc opemnp prog.f HLRN: xlc_r qsmp=omp prog.f 11.06.2003 RRZN Kolloquium SS 2003 11
Parallel Direktive (Beispiel 2) Fortran: do i=1,20 a(i)= i + b(i) end do C/C++: for (i=0;i<20;i++) a[i] = i + b[i]; 11.06.2003 RRZN Kolloquium SS 2003 12
Parallel Direktive: (Beispiel) Fortran:!$omp parallel do i=1,20 a(i)= i + b(i) end do!$omp end parallel C/C++: #pragma omp parallel for (i=0;i<20;i++) a[i] = i + b[i]; /*omp end parallel */ 11.06.2003 RRZN Kolloquium SS 2003 13
Work-Sharing-Direktiven Aufteilung der Arbeit in der parallelen Region auf die Mitglieder des Thread-Teams müssen dynamisch in der parallelen Region liegen starten keine neuen Threads keine implizite Barrier beim Eintritt Synchronisation am Ende der Direktive wichtige Direktivenarten: do-direktive (Fortran) for-direktive (C/C++) 11.06.2003 RRZN Kolloquium SS 2003 14
Do/For-Direktive die unmittelbar folgende Schleife wird parallel ausgeführt nur einen Eintritts- und einen Austrittspunkt Anzahl der gesamten Schleifendurchläufe muß vorher bekannt sein Fortran:!$ omp do[clause] for-schleife!$omp end do C/C++: #pragma omp for [clause] new line for-schleife for-schleife muß kanonische Form haben: for (i=0;i<20;i++) 11.06.2003 RRZN Kolloquium SS 2003 15
Do/For-Direktive (Beispiel) Fortran:!$omp parallel!$omp do do i=1,20 a(i)= i + b(i) end do!$omp end do!$omp end parallel C/C++: #pragma omp parallel #pragma omp for for (i=0;i<20;i++) a[i] = i + b[i]; /*omp end parallel */ 11.06.2003 RRZN Kolloquium SS 2003 16
For-Direktive i=0 i=0!$omp parallel!$omp do do i=1,20 a(i)=b(i)+i i=1,5 i= 6,10 i= 11,15 i= 16,20 end do!$omp end do a(i)= b(i)+i a(i)= b(i)+i a(i)= b(i)+i a(i)= b(i)+i!$omp end parallel i=0 11.06.2003 RRZN Kolloquium SS 2003 17
Do/For-Direktive (Beispiel) Fortran: do i=1,20 x=i*i a(i)= x + b(i) end do C/C++: for (i=0;i<20;i++) { x=i*i; a[i] = x+b[i]; } 11.06.2003 RRZN Kolloquium SS 2003 18
Do/For-Direktive (Beispiel) Fortran: C/C++:!$omp parallel do do i=1,20 x=i*i a(i)= x + b(i) end do!$omp end parallel do #pragma omp parallel for for (i=0;i<20;i++) {x=i*i; a[i] = x +b[i];} /*omp end parallel */ 11.06.2003 RRZN Kolloquium SS 2003 19
Do/For-Direktive (Beispiel) Fortran: C/C++:!$omp parallel for do i=1,20 x=i*i a(i)= x + b(i) end do!$omp end parallel #pragma omp parallel for for (i=0;i<20;i++) {x=i*i; a[i] = x +b[i];} /*omp end parallel */ liefert falsche Ergebnisse 11.06.2003 RRZN Kolloquium SS 2003 20
Do/For-Direktive (private) Fortran: C/C++:!$omp parallel do private(x) do i=1,20 x=i*i a(i)= x + b(i) end do!$omp end parallel do #pragma omp parallel for private(x) for (i=0;i<20;i++){ x=i*i; a[i] = x +b[i];} /*omp end parallel */ 11.06.2003 RRZN Kolloquium SS 2003 21
Data scope clauses charakterisieren die Eigenschaften der Variablen shared (list): default nur einen Speicherplatz für alle CPUs innerhalb des Teams Ausnahme: Schleifenindizes sind immer private private (list): jeder Thread hat eine lokale Kopie der Variablen firstprivate (list): Initialisierung wird in Schleife übernommen lastprivate (list): Master Thread übernimmt Werte aus der Schleife 11.06.2003 RRZN Kolloquium SS 2003 22
Beispiel: Summenbildung Fortran: sum=0.0 do i=1,20 sum=sum+a(i) end do C/C++: sum=0.0; for (i=0;i<20;i++) sum=sum+a[i]; 11.06.2003 RRZN Kolloquium SS 2003 23
Beispiel: Summenbildung Fortran: C/C++:!$omp parallel do sum=0.0 do i=1,20 sum=sum+a(i) end do!$omp end parallel do #pragma omp parallel for sum=0.0; for (i=0;i<20;i++) sum=sum+a[i]; /* end parallel for */ liefert falsche Ergebnisse 11.06.2003 RRZN Kolloquium SS 2003 24
Reduction clause reduction (operator:list) führt Operation mit den Variablen in list durch Variablen in list müssen shared sein (haben aber sowohl private als auch shared Eigenschaften) operator kann sein: Fortran: +,*,-,.and.,.or.,.eqv.,.neqv, max, min C/C++: +, *, -, &, &&, am Schleifenende wird globale Operation mit den Variablen in list durchgeführt 11.06.2003 RRZN Kolloquium SS 2003 25
Beispiel: reduction clause Fortran: sum=0 $!omp parallel do reduction(+:sum) do i=1,20 sum=sum+a(i) end do!$omp end parallel do 11.06.2003 RRZN Kolloquium SS 2003 26
Beispiel: Summenbildung Fortran: sum=0 sum=0!omp parallel do!$omp& reduction(+:sum) do i=1,20 i=1,5 i= 6,10 i= 11,15 i= 16,20 sum=sum+a(i) end do sum= 10 sum= 20 sum= 30 sum= 40!$omp end parallel do sum= 100 11.06.2003 RRZN Kolloquium SS 2003 27
Beispiel: MD-Code!$omp parallel do!$omp& private(i,j,k,rij,d)!$omp& reduction(+ : pot, kin) do i=1,np f(1:nd,i) = 0.0 do j=1,np if (i.ne. j) then call dist(nd,box,pos(1,i),pos(1,j),rij,d) pot = pot + 0.5*v(d) do k=1,nd f(k,i) = f(k,i) - rij(k)*dv(d)/d enddo endif enddo kin = kin + dotr8(nd,vel(1,i),vel(1,i)) enddo!$omp end parallel do kin = kin*0.5*mass!$omp parallel do!$omp& private(i,j) do i = 1,np do j = 1,nd pos(j,i) = pos(j,i) + vel(j,i)*dt + 0.5*dt*dt*a(j,i) vel(j,i) = vel(j,i) + 0.5*dt*(f(j,i)*rmass + a(j,i)) a(j,i) = f(j,i)*rmass enddo enddo!$omp end parallel do 11.06.2003 RRZN Kolloquium SS 2003 28
MD-Code: Auswertung E(n)=T(1)/(T(n)*n), E(n)=Effizienz T(1) = serielle CPU-Zeit 11.06.2003 T(n) = parallele CPU-Zeit
OpenMP: Fehlerquellen race conditions: - Programmergebnis hängt vom genauen zeitlichen Verhalten der Threads ab - häufige Ursache: unbeabsichtigt gemeinsame Variablen deadlocks Verklemmungen Threads werden eingesperrt, indem sie auf gesperrte Daten warten, die nie freigegeben werden 11.06.2003 RRZN Kolloquium SS 2003 30
OpenMP: Mehr als parallele Schleifen auch einzelne Programmsegmente können auf verschiedene Threads verteilt werden: single Direktive: nur ein Thread arbeitet sections Direktive: Aufgaben für je einen Thread Synchronisationsmöglichkeiten: barrier Direktive: Synchronisation nowait clause: Aufhebung der expliziten Synchronisation Scheduling-Verhalten veränderbar.. 11.06.2003 RRZN Kolloquium SS 2003 31
Weitere Informationen OpenMP Homepage: http://www.openmp.org OpenMP am HLRS: http://www.hlrs.de/organization/tsc/services/models/openmp Parallel Programming in OpenMP: R. Chandra et al: Academic Press 2001 OpenMP Shared Memory Parallel Programming: R. Eigemann, M. Voss (eds.): Springer LNCS, 2001 11.06.2003 RRZN Kolloquium SS 2003 32
OpenMP: Zusammenfassung Standard für shared memory Programmierung inkrementeller Ansatz für Parallelisierung Fork-Join-Modell compilerbasiert wichtige Konstrukte für Schleifenparallelisierung: parallel-direktive, do/for-direktive, reduction- u. private-clause 11.06.2003 RRZN Kolloquium SS 2003 33
Vergleich: OpenMP und MPI Hardware Sprachen Kommunikation Aufwand Implementation Serialität bleibt erhalten Besonderheiten OpenMP Shared Memory Fortran, C und C++ Gemeinsame Variablen Je nach Ziel Compilerdirektiven Ja Inkrementelle Parallelisierung MPI Shared und Distributed Memory Fortran, C und C++ Message Passing Erheblich Bibliotheksfunktionen Nein auf sehr hohe CPU- Anzahlen skalierbar 11.06.2003 RRZN Kolloquium SS 2003 34
Vielen Dank für Ihre Aufmerksamkeit 11.06.2003 RRZN Kolloquium SS 2003 35