Parallele Programmierung. Parallele Programmierung Memory-Rechner mit OpenMP
|
|
|
- Ingeborg Dunkle
- vor 6 Jahren
- Abrufe
Transkript
1 Parallele Programmierung für Shared-Memory Memory-Rechner mit OpenMP Dieter an Mey Rechen- und Kommunikationszentrum der RWTH Aachen 21. Januar 2002 rz.rwth-aachen.de [/hpc hpc] OpenMP-Kurs Dieter an Mey Parallele Programmierung für Shared-Memory Memory-Rechner mit OpenMP Einleitung Automatische Parallelisierung Explizite Parallelisierung mit OpenMP Debugging mit Assure und TotalView Performance Tools GuideView, WorkShop Hybride Parallelisierung 2 OpenMP-Kurs Dieter an Mey
2 Mehrprozessorsystem mit Shared Memory Uniform Memory Access (UMA) Memory (interleaved) Crossbar / Bus Cache Cache Cache Cache Proc Proc Proc Proc 3 OpenMP-Kurs Dieter an Mey SMP-Compute Server mit OpenMP sunc00 sunc15 - Sun Fire 6800 SMP-Cluster Cluster, 24 Prozessoren, US-III, 750/900 MHz (UMA) 1H2002: sunc16 sunc19 - Sun Fire 15K SMP-Cluster Cluster, 72 Prozessoren, US-III, 900 MHz (ccnuma( ccnuma) hpc4 - HP V-ClassV Class,, 16 Prozessoren, PA 8200, 240 MHz (UMA) hpc6 - HP J-ClassJ Class,, 4 Prozessoren, PA 8500, 440 MHz (UMA) sgic3 - SGI Origin 200, 4 Prozessoren, MIPS R10000, 180 MHz (ccnuma( ccnuma) sgic5 - SGI Origin 200, 2 Prozessoren, MIPS R10000, 180 MHz (UMA) hpcline - SMP-Cluster aus 16 PIII, 800 MHz Doppelprozessoren linuxcxx- PIII Doppelprozessoren unterschiedlicher Taktung 4 OpenMP-Kurs Dieter an Mey
3 Was heißt Shared-Memory Memory-Parallelisierung? Prozessoren do i = 1, 100 a(i) = b(i) + c(i) do i = 1, 25 a(i) = b(i) + c(i) do i = 26, 50 a(i) = b(i) + c(i) do i = 51, 75 a(i) = b(i) + c(i) do i = 76, 100 a(i) = b(i) + c(i) Speicher A(1)... A(100) B(1)... B(100) C(1)... C(100) 5 OpenMP-Kurs Dieter an Mey Und was nun? do i = 1, 100 s = s + a(i) Prozessoren Arbeitsteilung (worksharing) do i = 1, 25 s = s + a(i) do i = 26, 50 s = s + a(i) do i = 51, 75 s = s + a(i) do i = 76, 100 s = s + a(i) Speicher S A(1)... A(100) Alle Prozessoren wollen gleichzeitig S lesen und schreiben! 6 OpenMP-Kurs Dieter an Mey
4 Parallele Programmierung für Shared-Memory Memory-Rechner mit OpenMP Automatische Parallelisierung Explizite Parallelisierung mit OpenMP Debugging mit Assure und TotalView Performance Tools GuideView, WorkShop Hybride Parallelisierung 7 OpenMP-Kurs Dieter an Mey Automatische Parallelisierung Sun (Forte Developer 6 U2 = WorkShop 6 U2) Übersetzen und Binden f90 / f95 / f77 -autopar abkürzend für -xautopar depend xo3 bzw. cc -xautopar xdepend xo4 Parallelisierung von Reduktionen unter Zulassen der Vertauschung der arithmetischen Reihenfolge durch -reduction bzw. -xreduction Ausgabe von Compilerinformationen zur Parallelisierung: -loopinfo bzw. -xloopinfo Angabe der Prozessorzahl bei Ausführung export OMP_NUM_THREADS=n 8 OpenMP-Kurs Dieter an Mey
5 Automatische Parallelisierung Linux (PGI-Compiler) Übersetzen und Binden pgf90 / pgf77 / pgcc / pgcc -O2 -Mconcur[=option,option,] Unbedingte parallele Ausführung oder in Abhängigkeit von der Schleifendurchlaufzahl (alternate coding) -Mconcur=altcode:n -Mconcur= noaltcode Verteilung der Schleifenindizes auf die Prozessoren -Mconcur=dist:block -Mconcur=dist: cyclic Keine Vertauschung der arithmetischen Reihenfolge (Reduktionen!) -Mconcur=noassoc Ausgabe von Compilerinformationen: -Minfo -Mneginfo=concur Angabe der Prozessorzahl bei Ausführung export NCPUS=n Steuerung der Parallelisierung durch Direktiven!PGI$<scope> NODEPCHK #pragma <scope> nodepchk scope: g r l scope: global routine loop 9 OpenMP-Kurs Dieter an Mey Automatische Parallelisierung HP Übersetzen und Binden f90 / c89 / acc +DA2.0 +DS2.0 +Odataprefetch +O3 +O[no]parallel Unbedingte parallele Ausführung oder in Abhängigkeit von der Schleifendurchlaufzahl +O[no]dynsel Schalten der Automatischen Parallelisierung +O[no]autopar Keine Vertauschung der arithmetischen Reihenfolge (Reduktionen!) +Ofltacc Ausgabe von Compilerinformationen: +O[no]info +O[no]report Angabe der Prozessorzahl bei Ausführung export MP_NUMBER_OF_THREADS=n ( MLIB_NUMBER_OF_THREADS bei Verwendung der MathLIBrary) Steuerung der Parallelisierung durch Direktiven!$DIR PREFER_PARALLEL #pragma _CNX prefer_parallel!$dir NO_LOOP_DEPENDENCE[(arraylist)] 10 OpenMP-Kurs Dieter an Mey
6 Automatische Parallelisierung SGI (MIPSpro( MIPSpro-Compiler) Übersetzen und Binden f90 / f77 / cc / CC -n32 -mips4 -O3 -apo -mp Verteilung der Schleifenindizes auf die Prozessoren -mp_schedtype=dynamic GSS INTERLEAVE RUNTIME SIMPLE Ausgabe von mit OpenMP-Direktiven angereichertem Programm: -apo -mp list Angabe der Prozessorzahl bei Ausführung export OMP_NUM_THREADS=n Steuerung der Parallelisierung durch Direktiven!*$*ASSERT DO (CONCURRENT) #pragma prefer concurrent manual pages pe_environ environ 11 OpenMP-Kurs Dieter an Mey Automatische Parallelisierung Visual KAP for OpenMP (NT) Präprozesor /kai/vkomp36/bin/vkapomp.exe -WKkeep -WKonly -WK,-fuse -WK, -fuselevel=1 -WK,-noarclimit -WK,-conc -WK,-so=0 -WK,-o=3 -WK,-r=3 -WK,-noparallelrtl -WKonly -WK,-heap=64 -WK,-nointl -WK,-suppress=w -WK,-lo=lkopst -WK,-mc=0 simpeq.f Steuerung der Parallelisierung durch Direktiven!*$*concurrentize 12 OpenMP-Kurs Dieter an Mey
7 Visual KAP for OpenMP (NT) Fortran90 Präprozessor Auto-parallelization, gererating OpenMP directives no unrolling 13 OpenMP-Kurs Dieter an Mey Bedingungen für die automatische Parallelisierung (Sun) Kandidaten für die Parallelisierung: Explizite DO-Schleifen oder implizite Schleifen (IF-Schleifen, Feldsyntax) Bedingungen für die Parallelisierung (Auswahl): Es dürfen in einer Iteration keine Feldkomponenten geändert werden, die in einer anderen Iteration benötigt (gelesen oder geschrieben) werden. (Auch nicht in Unterprogrammen, die in der Schleife gerufen werden.) Es dürfen keine skalaren Variablen geändert werden, die nach der Schleife noch gelesen werden. Es dürfen in einer Iteration keine skalaren Variablen geändert werden, die in einer anderen Iteration benötigt (gelesen oder geschrieben) werden. Der Overhead der Parallelisierung darf im Vergleich zur Rechenarbeit in der Schleife nicht zu hoch sein. 14 OpenMP-Kurs Dieter an Mey
8 Problemfälle der (automatischen) Parallelisierung do i = ilow, ihigh! Abhängigkeit der Feldelemente von A a(i) = a(i+k) + b(i)! zwischen verschiedenen Iterationen! (Bei positivem k ist Vektorisierung möglich) do i = 1, n a(ind(i)) = b(i)! Ist nur dann parallelisierbar, wenn alle! ind(1:n) paarweise verschieden sind. t = x do i = 1, n! Die skalare Variable t wird in einer a(i) = t + b(i)! Iteration geschrieben und in t = c(i)! einer anderen (der folgenden) gelesen y = t! Die skalare Variable t wird nach der Schleife gelesen 15 OpenMP-Kurs Dieter an Mey Parallele Programmierung für Shared-Memory Memory-Rechner mit OpenMP Automatische Parallelisierung Explizite Parallelisierung mit OpenMP Debugging mit Assure und TotalView Performance Tools GuideView, PerView, CXperf,, Puma Hybride Parallelisierung 16 OpenMP-Kurs Dieter an Mey
9 OpenMP - Gliederung Einleitung: Geschichte, Compiler, OpenMP-Struktur Einführung in OpenMP Format der Direktiven Laufzeitfunktionen Parallele Regionen Arbeitsteilung (worksharing) Verwaisen (orphaning) Daten-Geltungsbereiche (data scope) Synchronisation Überblick über alle Kompontenten von OpenMP Ein Beispiel (Berechnung von Pi) Strategien, Performance Klassifizierung von Variablen Parallelisierung auf Schleifenebene Grobgranulare Arbeitsteilung SPMD OpenMP versus MPI Anwendungsbeispiele Jacobi, Panta 17 OpenMP-Kurs Dieter an Mey OpenMP - Geschichte : OpenMP Version 1.0 für Fortran Standard für die Shared-Memory Memory-Programmierung inzwischen für alle namhaften SMP-Rechner verfügbar löst im techn.-wiss. Rechnen die proprietären Direktiven und die unmittelbare Verwendung der [p]threads ab 1998: OpenMP V1.0 für C und C : OpenMP V1.1 für Fortran (Fehler korrigiert, Erläuterungen eingearbeitet) 2000: OpenMP V2.0 für Fortran (Unterstützung von Fortran90-Modules) 2001: OpenMP V2.0 für C und C++ Draft 18 OpenMP-Kurs Dieter an Mey
10 Compiler für OpenMP SUN: f77 / f90 / f95 openmp [ -R/ R/usr/lib/lwp lwp ] cc xopenmp [ -R/ R/usr/lib/lwplwp ] guidef77 / guidef90 / guidecc / guidec++ Linux: pgf77 / pgf90 / pgcc / pgcc mp guidecc / guidec++ HP: f90 openmp guidef77 / guidef90 / guidecc / guidec++ SGI: f77 / f90 / cc / CC mp 19 OpenMP-Kurs Dieter an Mey Die Komponenten von OpenMP (Fortran) Umgebungsvariable, Direktiven, Laufzeitbibliothek #!/bin/ksh # Shell-Script f90 openmp test.f90 export OMP_NUM_THREADS=4 a.out Umgebungsvariable Direktiven (besondere Kommentarzeilen) Laufzeitbibliothek! Source file test.f90 program main integer omp_get_thread_num!$omp parallel print *, 'me: ', omp_get_thread_num()!$omp end parallel end program me: 0 me: 3 me: 2 me: 1 20 OpenMP-Kurs Dieter an Mey
11 Die Komponenten von OpenMP (C) Umgebungsvariable, Direktiven, Laufzeitbibliothek #!/bin/csh # Shell-Script cc xopenmp test.f90 setenv OMP_NUM_THREADS 4 a.out /* Source file test.c */ #include <stdio.h> #include <omp.h> Umgebungsvariable Direktiven (besondere Kommentarzeilen) Laufzeitbibliothek int main(void) { #pragma omp parallel { printf("me: %d\n",omp_get_thread_num()); me: 0 me: 3 me: 2 me: 1 21 OpenMP-Kurs Dieter an Mey Die Komponenten von OpenMP - schematisch Nutzer Shell OpenMP-Programm Umgebungsvariablen Direktiven Laufzeitfunktionen OpenMP-Laufzeitsystem Betriebsystem - Threads 22 OpenMP-Kurs Dieter an Mey
12 OpenMP - Gliederung Einleitung: Geschichte, Compiler, OpenMP-Struktur Einführung in OpenMP Format der Direktiven Laufzeitfunktionen Parallele Regionen Arbeitsteilung (worksharing( worksharing) Verwaisen (orphaning( orphaning) Daten-Geltungsbereiche (data( scope) Synchronisation Überblick über alle Kompontenten von OpenMP Ein Beispiel (Berechnung von Pi) Strategien, Performance Klassifizierung von Variablen Parallelisierung auf Schleifenebene Grobgranulare Arbeitsteilung SPMD OpenMP versus MPI Anwendungsbeispiele Jacobi, Panta 23 OpenMP-Kurs Dieter an Mey Format der Direktiven Fortran77: C*** OpenMP-Direktive C$OMP directive [clause[[,] clause ] ] **** OpenMP-Direktive *$OMP directive [clause[[,] clause ] ] C*** OpenMP-Direktive mit Fortsetzungzeile C$OMP directive clause clause C$OMP+clause Fortran90:!*** OpenMP-Direktive!$OMP directive [clause[,]]!*** OpenMP-Direktive mit Fortsetzungzeile!$OMP directive clause clause &!$OMP& clause C: /*** OpenMP-Direktive */ #pragma omp directive [clause..]!*** OpenMP-Direktive mit Fortsetzungzeile #pragma omp directive clause \ clause 24 OpenMP-Kurs Dieter an Mey
13 Verschiedenes Bedingte Übersetzung Äquivalent: C C$ wird ersetzt durch 2 Blanks C$ 10 IAM = OMP_GET_THREAD_NUM()+ C$ & INDEX #ifdef _OPENMP 10 IAM = OMP_GET_THREAD_NUM()+ & INDEX #endif #ifdef _OPENMP iam=omp_get_thread_num()+index; #endif!$ wird ersetzt durch 2 Blanks!$ IAM = OMP_GET_THREAD_NUM()+ &!$ INDEX 25 OpenMP-Kurs Dieter an Mey Laufzeitfunktionen program simple implicit integer (a-z) logical omp_in_parallel Serielle Region export OMP_NUM_THREADS=3 write (*,*) "inside parallel region? ", omp_in_parallel() write (*,*) "number of available processors ", omp_get_num_procs() write (*,*) "maximum number of threads ", omp_get_max_threads() call omp_set_num_threads ( max(1,omp_get_max_threads()-1) )!$omp parallel Parallele write (*,*) "inside parallel region? ", omp_in_parallel() write (*,*) "number of threads in the team ", omp_get_num_threads() Region write (*,*) "my thread id ", omp_get_thread_num()!$omp end parallel end program inside parallel region? F number of available processors 16 maximum number of threads 3 Redundante Ausführung! inside parallel region? T number of threads in the team 2 my thread id 0 inside parallel region? T number of threads in the team 2 26 OpenMP-Kurs Dieter an Mey my thread id
14 Serielle Region Parallele Regionen (1) program simple implicit integer (a-z) write (*,*) Region A: ", omp_get_thread_num() export OMP_NUM_THREADS=4 Parallele!$omp parallel write (*,*) Region B: ", omp_get_thread_num() Region!$omp end parallel write (*,*) Region C: ", omp_get_thread_num() Serielle Region call omp_set_num_threads(2) Parallele!$omp parallel write (*,*) Region D: ", omp_get_thread_num() Region!$omp end parallel Serielle Region write (*,*) Region E: ", omp_get_thread_num() Parallele!$omp parallel num_threads(3) Region write (*,*) Region F: ", omp_get_thread_num()!$omp end parallel Serielle Region write (*,*) Region G: ", omp_get_thread_num() end program Region A: 0 Region B: 0 Region B: 3 Region B: 1 Region B: 2 Region C: 0 Region D: 1 Region D: 0 Region E: 0 Region F: 2 Region F: 0 Region F: 1 Region G: 0 27 OpenMP-Kurs Dieter an Mey Parallele Regionen (2) Master Thread Slave Threads Slave Threads Slave Threads Parallele Region Serielle Region Das OpenMP-Program Program beginnt wie ein serielles : single threaded Region A: 0 Am Anfang der Parallelen Region B: 0 Region B: 3 Region werden die Slave Region B: 1 Threads gestartet. Sie bilden Region B: 2 mit dem Master ein Team. Region C: 0 Zwischen den Parallelen Regionen schlafen die Slave Threads. Region D: 1 Region D: 0 Region E: 0 Region F: 2 Region F: 0 Region F: 1 Region G: 0 28 OpenMP-Kurs Dieter an Mey
15 Parallele Regionen (3) - Sun Master Thread Slave Threads Slave Threads Slave Threads Parallele Region Serielle Region Zwischen den Parallelen Regionen schlafen die Slave Threads. Die Tiefe des Schlafes kann durch die Umgebungsvariable SUMW_MP_THR_IDLE beeinflusst werden: SUMW_MP_THR_IDLE=spin (default) busy waiting die schlafenden Threads geben ihre CPU nicht ab SUMW_MP_THR_IDLE=sleep idle waiting die schlafenden Threads geben ihre CPU nicht ab SUMW_MP_THR_IDLE=ns s (Sekunden) SUMW_MP_THR_IDLE=nms (Millisekunden) Kompromiss die schlafenden Threads geben ihre CPU nach einer gewissen Zeit ab 29 OpenMP-Kurs Dieter an Mey Arbeitsteilung (1) - Prinzip Prozessoren do i = 1, 100 a(i) = b(i) + c(i) Arbeitsteilung (worksharing) do i = 1, 25 a(i) = b(i) + c(i) do i = 26, 50 a(i) = b(i) + c(i) do i = 51, 75 a(i) = b(i) + c(i) do i = 76, 100 a(i) = b(i) + c(i) Speicher A(1)... A(100) B(1)... B(100) C(1)... C(100) 30 OpenMP-Kurs Dieter an Mey
16 Arbeitsteilung (2) mit omp_get get_thread_num C Fortran77 C$omp parallel if ( omp_get_thread_num() == 0 ) do i = 1, 25 a(i) = b(i) + c(i)! Fortran 90!$omp parallel else if ( omp_get_thread_num() == 1 ) select case ( omp_get_thread_num() ) do i = 26, 50 case ( 0 ) a(i) = b(i) + c(i) a(1:25) = b(1:25) + c(1:25) case (1) else if ( omp_get_thread_num() == 2 ) a(26:50) = b(26:50) + c(26:50) do i = 51, 75 case(2) a(i) = b(i) + c(i) a(51:75) = b(51:75) + c(51:75) case (3) else if ( omp_get_thread_num() == 3 ) a(76:100) = b(76:100) + c(76:100) do i = 76, 100 end select a(i) = b(i) + c(i)!$omp end parallel end if C$omp end parallel 31 OpenMP-Kurs Dieter an Mey Arbeitsteilung (3) parallel sections C Fortran77 C$omp parallel C$omp sections C$omp section do i = 1, 25 a(i) = b(i) + c(i) Die end Kurzschreibweise do ist C$omp nur möglich, section wenn in der Parallelen do i = 26, Region 50 nur das Parallel a(i) = b(i) Sections + c(i) Worksharing Construct /* C, verkürzte Schreibweise */ #pragma omp parallel sections for ( i=1; i<25; i++ ) { a[i] = b[i] + c[i] ; #pragma omp section for ( i=26; i<50; i++ ) { a[i] = b[i] + c[i] ; #pragma omp section for ( i=51; i<75; i++ ) { a[i] = b[i] + c[i] ; #pragma omp section for ( i=76; i<100; i++ ) { a[i] = b[i] + c[i] ; #pragma omp end parallel sections C$omp enthalten section ist.! Fortran 90, verkürzte Schreibweise do i = 51, 75!$omp parallel sections a(i) = b(i) + c(i) a(1:25) = b(1:25) + c(1:25)!$omp section C$omp section a(26:50) = b(26:50) + c(26:50) do i = 76, 100!$omp section a(i) = b(i) + c(i) a(51:75) = b(51:75) + c(51:75)!$omp section C$omp end sections a(76:100) = b(76:100) + c(76:100) C$omp 32 end parallel OpenMP-Kurs!$omp Dieter an end Mey parallel sections
17 Arbeitsteilung (4) parallel do C Fortran77 C$omp parallel C$omp do do i = 1, 100 a(i) = b(i) + c(i) C$omp C$omp end Die parallel Kurzschreibweise ist nur möglich, wenn in der /* C */ Parallelen Region nur das #pragma omp parallel Parallel Sections Do { Worksharing Construct #pragma omp enthalten for ist. { for ( i=1; i<100; i++ ) { a[i] = b[i] + c[i] ;! Fortran90, verkürzte Schreibweise!$omp parallel do do i = 1, 100 a(i) = b(i) + c(i) /* C, verkürzte Schreibweise */ #pragma omp parallel for for ( i=1; i<100; i++ ) { a[i] = b[i] + c[i] ; 33 OpenMP-Kurs Dieter an Mey Arbeitsteilung (5) parallel workshare neu in OpenMP V2.0! Nur in Fortran90!$omp parallel!$omp workshare a(1:100) = b(1:100) + c(1:100) d(2:99) = a(1:98) + a(3:100)!$omp end workshare!$omp end parallel! Nur in Fortran90, Kurzschreibweise!$omp parallel workshare a(1:100) = b(1:100) + c(1:100) d(2:99) = a(1:98) + a(3:100)!$omp end parallel workshare Achtung: versteckte Barrieren 34 OpenMP-Kurs Dieter an Mey
18 Arbeitsteilung? single!$omp parallel!$omp single print *, nur einer!$omp end single!$omp end parallel #pragma omp parallel { #pragma omp single { printf nur einer\n ; 35 OpenMP-Kurs Dieter an Mey Verwaisen orphaning!$omp parallel call work ( 100, a, b, c )!$omp end parallel call work ( 100, a, b, c ) subroutine work ( n, a, b, c ) real a(n), b(n), c(n)!$omp do do i = 1, 100 a(i) = b(i) + c(i)!$omp return end subroutine work Statischer Bereich der Parallelen Region (static/lexical extent) Die Direktiven, die zu einer Parallelen Region gehören, müssen nicht in ein und dynamischer Bereich demselben Programmmodul der Parallelen Region stehen. (dynamic extent) Wird hier das Unterprogramm in der Parallelen Region aufgerufen, so wirkt das Verwaiste worksharing-konstrukt, (orphaned) anderenfalls wird es ignoriert. Direktive 36 OpenMP-Kurs Dieter an Mey
19 Geltungsbereich der Variablen (0) Intro shared private global local Gültig für alle Threads und in allen Modulen Gültig für alle Threads aber lokal im jeweiligen Modul Privat für alle Threads aber gültig in allen Modulen Privat für alle Threads und gültig im jeweiligen Modulen 37 OpenMP-Kurs Dieter an Mey Geltungsbereich der Variablen (1) data scope do i = 1, 100 a(i) = b(i) + c(i)!$omp parallel do!$omp& default(none) private(i) shared(a,b,c) do i = 1, 100 a(i) = b(i) + c(i)!$omp end parallel do #pragma omp parallel for \ default(none) private(i) shared(a,b,c) { for ( i=1; i<100; i++ ) { a[i] = b[i] + c[i] ; Normalerweise sind alle Variablen (im statischen Bereich der Parallelen Region) von allen Threads gleichermaßen zugänglich, sie sind shared. Eine Ausnahme bilden die Laufindizes der parallelisierten Schleifen, sie sind standardmäßig private. Die Voreinstellung kann geändert werden durch: default (shared private none) Die default-klausel wirkt nur auf die Variablen des Statischen Bereiches! 38 OpenMP-Kurs Dieter an Mey
20 Geltungsbereich der Variablen (2) defaults Das Shared-Memory-Programmiermodell: Normalerweise sind alle Variablen shared. Globale Variablen sind shared: Fortran: common-blöcke Fortran: Variable mit dem save-attribute Fortran: Modul-Variable falls sie nicht als threadprivate vereinbart sind C: Variable, deren Geltungsbereich sich auf die ganze Quelldatei erstreckt C: Variable mit dem static oder extern Attribut Ausnahme: Die Schleifenindizes von parallelisierten Zählschleifen sind private. ACHTUNG: Variablen in Unterprogrammen, die in einer Parallelen Region gerufen werden, und auf dem Stack abgelegt werden (Normalfall!) sind private. Variablen in Unterprogrammen, die in einer Parallelen Region gerufen werden und das save-attribut (C: static) haben, sind shared. 39 OpenMP-Kurs Dieter an Mey Geltungsbereich der Variablen (3) defaults program main integer n common / comblk / n double precision pi!$omp parallel do call calc_pi ( pi )!$omp end parallel end program Main shared subroutine calc_pi ( pi ) integer :: i, n common / comblk / n double precision, save :: sum, h double precision :: a,x,f, pi pi = private return end subroutine calc_pi 40 OpenMP-Kurs Dieter an Mey
21 Geltungsbereich der Variablen (4) private #include <stdio.h> #include <omp.h> eine nicht initialisierte Kopie wird für jeden Thread angelegt int main(void) { int i; i = 42; printf( before parallel region: i=%d\n", i); # pragma omp parallel private(i) { printf("(%d): i=%d\n",omp_get_thread_num(),i); i += omp_get_thread_num(); printf("(%d): i:%d\n",omp_get_thread_num(),i); printf( after parallel region: i=%d\n", i); Output: before PR: i=42 (1): i=0 (3): i=0 (1): i: 1 (2): i=0 (3): i: 3 (0): i=0 (0): i: 0 (2): i: 2 after PR: i=42 return 1; 41 OpenMP-Kurs Dieter an Mey Geltungsbereich der Variablen (5) firstprivate #include <stdio.h> #include <omp.h> int main(void) { int i; i = 42; printf( before parallel region: i=%d\n", i); # pragma omp parallel firstprivate(i) { Die private Kopie wird mit dem Originalwert initialisiert printf("(%d): i=%d\n",omp_get_thread_num(),i); i += omp_get_thread_num(); printf("(%d): i:%d\n",omp_get_thread_num(),i); printf( after parallel region: i=%d\n", i); Output: before PR: i=42 (1): i=42 (3): i=42 (1): i: 43 (2): i=42 (3): i: 45 (0): i=42 (0): i: 42 (2): i: 44 after PR: i=42 return 1; 42 OpenMP-Kurs Dieter an Mey
22 Lastprivate - Beispiel!$omp parallel default(none) shared(a,b,c)!$omp do lastprivate(i) do i = 1, 100 a(i) = b(i) + c(i)!$omp!$omp end parallel print *, i! 101 i erhält den Wert des letzten (seriellen) Schleifendurchlaufs 43 OpenMP-Kurs Dieter an Mey Geltungsbereich der Variablen (5) threadprivate #include <stdio.h> #include <omp.h> int t_private; #pragma omp threadprivate(t_private) void foo(void) { printf("(foo) thread(%d): t_private=%d\n", omp_get_thread_num(),t_private); main(){ int priv; #pragma omp parallel { t_private = omp_get_thread_num(); foo(); Output: (foo) thread(0): t_private=0 (foo) thread(3): t_private=3 (foo) thread(2): t_private=2 (foo) thread(1): t_private=1 Globale Daten werden durch die threadprivate-direktive privatisiert. Sie können durch die copyin-klausel initialisiert werden. 44 OpenMP-Kurs Dieter an Mey
23 Geltungsbereich der Variablen (6) Übersicht shared private global local (static extend) F: common F: module + use C: file scope default shared-klausel Die Verwaltung des Heap muss synchronisiert F: common werden. + threadprivate Das F: häufige module Anlegen + use + von threadprivate dynamischen Variablen C: file mit scope malloc/new + threadprivate kann daher zu Performance-Einbußen führen. Verbesserung durch binden mit private-klausel cc xopenmp -lmtalloc local (dynamic extend) F: save C: static, extern C: heap (malloc, new) der Pointer kann auch private sein. default (f90 stackvar ) C: automatic variables 45 OpenMP-Kurs Dieter an Mey Kritische Region (1) do i = 1, 100 s = s + a(i) Prozessoren Arbeitsteilung (worksharing) do i = 1, 25 s = s + a(i) do i = 26, 50 s = s + a(i) do i = 51, 75 s = s + a(i) do i = 76, 100 s = s + a(i) Speicher S A(1)... A(100) Alle Prozessoren wollen gleichzeitig S lesen und schreiben! 46 OpenMP-Kurs Dieter an Mey
24 Kritische Region (2) do i = 1, 100 s = s + a(i) Prozessoren Arbeitsteilung (worksharing) do i = 1, 25 s = s + a(i) do i = 26, 50 s = s + a(i) do i = 51, 75 s = s + a(i) do i = 76, 100 s = s + a(i) Speicher S A(1)... A(100) Zu einer Zeit darf nur ein Prozessor die kritische Region betreten => Performance? 47 OpenMP-Kurs Dieter an Mey Kritische Region (3) critical / end critical do i = 1, 100 s = s + a(i)!$omp parallel do private(i) do i = 1, 100!$omp critical s = s + a(i)!$omp end critical!$omp end parallel do #pragma omp parallel for private(i) { for ( i=1; i<100; i++ ) { #pragma omp critical { s += a[i]; Die Kritischen Regionen dürfen zu einer Zeit nur von einem Thread ausgeführt werden. Da hier die Schleifenkörper nur noch aus der kritischen Region bestehen, wird das Programm drastisch langsamer. 48 OpenMP-Kurs Dieter an Mey
25 Kritische Region (4) do i = 1, 100 s = s + a(i) Prozessoren Die Kritische Arbeitsteilung Region wird (worksharing) aus der Schleife herausgezogen => Performance? do i = 1, 25 s1 = s1 + a(i) s = s + s1 do i = 26, 50 s2 = s2 + a(i) s = s + s2 do i = 51, 75 s3 = s3 + a(i) s = s + s3 do i = 76, 100 s4 = s4 + a(i) s = s + s4 Speicher S A(1)... A(100) S1 S3 S2 S4 49 OpenMP-Kurs Dieter an Mey Kritische Region (5) critical / end critical!$omp parallel private(i,s_local) s_local = 0.0!$omp do do i = 1, 100 s_local = s_local + a(i)!$omp!$omp critical s = s + s_local!$omp end critical!$omp end parallel #pragma omp parallel private(i,s_local) { s_local = 0.0; #pragma omp for { for ( i=1; i<100; i++ ) { s_local += a[i]; #pragma omp critical { s += s_local; 50 OpenMP-Kurs Dieter an Mey Jetzt werden die Teilsummen parallel berechnet. Die Kritischen Regionen wird nur noch einmal von jedem Thread durchlaufen.
26 Kritische Region (6) named critical region!$omp parallel private(i,s_local) s_local = 0.0!$omp do do i = 1, 100 s_local = s_local + a(i)!$omp!$omp critical (sum) s = s + s_local!$omp end critical (sum)!$omp end parallel #pragma omp parallel private(i,s_local) { s_local = 0.0; #pragma omp for { for ( i=1; i<100; i++ ) { s_local += a[i]; #pragma omp critical (sum) { s += s_local; 51 OpenMP-Kurs Dieter an Mey Kritische Regionen können benannt werden. Das ist dann von Vorteil, wenn in einer Parallelen Region mehrere Kritische Regionen auftreten. Der Namen ist eine globale Größe. Kritische Region (7) atomic!$omp parallel private(i,s_local) s_local = 0.0!$omp do do i = 1, 100 s_local = s_local + a(i)!$omp!$omp atomic s = s + s_local!$omp end parallel #pragma omp parallel for private(i,s_local) { s_local = 0.0; #pragma omp for { for ( i=1; i<100; i++ ) { s_local += a[i]; #pragma omp atomic { s += s_local; 52 OpenMP-Kurs Dieter an Mey Wenn die Kritischen Region nur aus einem Statement mit einfacher Struktur besteht var = var op expression oder var = intrinsic ( var,expression ) bzw. var binop= expression; oder var++; var--; ++var;--var so kann ist die atomic-direktive verwendet werden, die auf schnelle Hardware-Mechanismen abgebildet werden kann.
27 Reduktionen reduction clause do i = 1, 100 s = s + a(i)!$omp parallel do private(i) reduction(+:s) do i = 1, 100 s = s + a(i)!$omp end parallel do #pragma omp parallel for private(i) \ reduction(+:s) { for ( i=1; i<100; i++ ) { s += a[i]; Genau für diesen häufig auftretenden Fall gibt es die Reduktionsklausel. reduction({op intrinsic:list) mit op = { + * -.and..or..eqv..neqv. oder intrinsic = { max, min, iand, ior, ieor bzw. op = { + * - & ^ && list ist eine Komma-separierte Liste von Variablen 53 OpenMP-Kurs Dieter an Mey Reduktionen unterschiedliche Rundungsfehler Bei der Parallelisierung von solchen Rekursionen ist mit einer Änderung des Rundungsfehlerverhaltens zu rechnen Unterschiedliche Rundungsfehler: seriell seriell (verschiedene Compileroptionen) seriell parallel (OpenMP oder Autoparallel) parallel parallel (aufeinanderfolgende Rechenläufe) parallel parallel (Unterschiedliche Prozessorzahl) Abhilfe: Reduzierung der seriellen Optimierung: -fsimple=0 -xnolibmopt Partielle Parallelisierung Autoparallelisierung mit noreduction 54 OpenMP-Kurs Dieter an Mey !$omp parallel do reduction(+:s) do i = 1, 100 s = s + a(i) * b(i) / c(i)!$omp end parallel do!$omp parallel do do i = 1, 100 tmp(i) = a(i) * b(i) / c(i)!$omp end parallel do do i = 1, 100 s = s + tmp(i)
28 Synchronisation barrier Jeder Thread wartet an der Barriere, bis alle Threads des Teams diese Barriere erreicht haben!$omp parallel print *, bin schon da \n ;!$omp barrier print *, gemeinsam geht s weiter ;!$omp end parallel #pragma omp parallel { printf bin schon da \n ; #pragma omp barrier printf gemeinsam geht s weiter\n ; Folgende Konstrukte haben eine implizite Barriere, falls diese nicht durch eine nowait Klausel abgeschaltet wird: end parallel end sections end single end workshare 55 OpenMP-Kurs Dieter an Mey Synchronisation master Nur der Master-Thread führt diese Programmsegment durch, alle anderen überspringen es.!$omp parallel!$omp master print *, nur der Meister! ;!$omp end master!$omp end parallel!$omp parallel if ( omp_get_thread_num() == 0 ) print *, so geht s auch. der Meister! ;!$omp end parallel #pragma omp parallel { #pragma omp master printf nur der Meister!\n ; Im Gegensatz zur single-direktive: Keine implizite Barriere am Ende! 56 OpenMP-Kurs Dieter an Mey
29 Synchronisation nowait Mit der nowait-klausel können überflüssige Barrieren eingespart werden. Barrieren sind die wesentlichen Bremsen, die den Speedup reduzieren.!$omp parallel!$omp do schedule(static) do i = 1, 100 a(i) =!$omp nowait!$omp do schedule(static) do i = 1, 100 b(i) = a(i) **2!$omp nowait ACHTUNG: bei schedule(dynamic) kann es schief gehen!!$omp end parallel 57 OpenMP-Kurs Dieter an Mey program main implicit integer (a-z)!$omp parallel Synchonisation - ordered!$omp do do i = 1, omp_get_num_threads()!$omp print *, 'me: ', omp_get_thread_num(), ' i: ', i!$omp do ordered do i = 1, omp_get_num_threads()!$omp ordered!$omp end ordered!$omp!$omp end parallel end print *, 'me: ', omp_get_thread_num(), ' i: ', i 58 OpenMP-Kurs Dieter an Mey me: 0 i: 1 me: 3 i: 4 me: 2 i: 3 me: 1 i: 2 me: 1 i: 1 me: 0 i: 2 me: 2 i: 3 me: 3 i: 4
30 Synchronisation - flush!$omp flush [(list)] Die flush-direktive sorgt dafür, dass alle Speicheroperationen [ bzgl. der angegebenen Liste der Variablen ] abgeschlossen werden, und anschließend bei Bedarf wieder aus dem Speicher geladen werden. Betroffen sind shared Variablen. Folgende Konstrukte implizieren eine flush-direktive: barrier critical und end critical ABER: Kein implizites flush bei do end sections master und end master end single sections end workshare single ordered und end ordered workshare parallel und end parallel end {do sections single nowait 59 OpenMP-Kurs Dieter an Mey Geordnete Ausgabe ohne ordered-klausel - flush program ordered integer me, ticket, omp_get_thread_num!$omp parallel private(me) shared(ticket) me = omp_get_thread_num()!$omp single ticket = 0!$OMP end single do while ( ticket < me )!$OMP flush(ticket) Warteschleife call work(me)! do ordered work here ticket = ticket + 1!$OMP flush(ticket) write (*,*) me!$omp end parallel end program flush 60 OpenMP-Kurs Dieter an Mey
31 OpenMP - Gliederung Einleitung: Geschichte, Compiler, OpenMP-Struktur Einführung in OpenMP Format der Direktiven Laufzeitfunktionen Parallele Regionen Arbeitsteilung (worksharing( worksharing) Verwaisen (orphaning( orphaning) Daten-Geltungsbereiche (data( scope) Synchronisation Überblick über alle Kompontenten von OpenMP Ein Beispiel (Berechnung von Pi) Strategien, Performance Klassifizierung von Variablen Parallelisierung auf Schleifenebene Grobgranulare Arbeitsteilung SPMD OpenMP versus MPI Anwendungsbeispiele Jacobi, Panta 61 OpenMP-Kurs Dieter an Mey OpenMP Directives Runtime Library Binding Conditional Compilation Nesting Environment Variables Control Constructs Parallel Region Data Constructs ThreadPrivate Synchonization Constructs Master Work Sharing Do Sections Schedule Ordered Data Scope Shared Private Reduction FirstPrivate LastPrivate Copyin Single Default 62 OpenMP-Kurs Dieter an Mey Critical Barrier Atomic Ordered Flush
32 OpenMP Directives Environment Variables OMP_SCHEDULE OMP_NUM_THREADS OMP_DYNAMIC OMP_NESTED Lock Functions Runtime Library Environment Functions OMP_GET/SET_NUM_THREADS OMP_GET_MAX_THREADS OMP_GET_THREAD_NUM OMP_GET_NUM_PROCS OMP_IN_PARALLEL OMP_GET/SET_DYNAMIC OMP_GET/SET_NESTED OMP_INIT_LOCK OMP_DESTROY_LOCK OMP_[UN]SET_LOCK OMP_TEST_LOCK 63 OpenMP-Kurs Dieter an Mey Direktiven Parallel Region Construct!$omp parallel [clause[[,] clause] ] block!$omp end parallel mit clause aus private (list) shared (list) default ( private shared none ) firstprivate (list) reduction ({op intrinsic:list) copyin (list) if ( logexp ) num_threads ( intexp ) neu in OpenMP V2.0 Parallele Ausführung des Programmsegmentes block Der (Master-) Thread, der auf die Parallele Region trifft, spaltet ein Team von (Slave-)Threads ab, die alle dasselbe Programmsegment ausführen. Die Anzahl der Threads (Master + Slaves) wird durch die Umgebungsvariable OMP_NUM_THREADS oder durch die Laufzeitfunktion omp_set_num_threads oder durch die num_threads-klausel spezifiziert, es sei denn, dass dem Laufzeitsystem explizit die dynamische Steuerung der Threadzahl durch die Umgebungsvariable OMP_DYNAMIC oder die Laufzeitfunktion omp_set_dynamic überlassen wurde. Wenn die if-klausel den Wert.FALSE. besitzt, so wird block seriell ausgeführt. Die end parallel-direktive enthält implizit eine Barriere. 64 OpenMP-Kurs Dieter an Mey
33 Direktiven Work-sharing Constructs - do!$omp do [clause[[,] clause] ] do_loop!$omp [nowait] mit clause aus private (list) firstprivate (list) lastprivate (list) reduction ({op intrinsic:list) schedule (type[,chunk] ) ordered Die Ausführung der Zählschleife, die unmittelbar der do-direktive folgt wird auf die beteiligten Threads aufgeteilt, so wie durch die schedule-klausel angegeben. Die ordered-klausel muss hinzugefügt werden, wenn innerhalb der Zählschleife eine ordered-direktive verwendet werden soll. Die -Direktive enthält implizit eine Barriere, falls nicht die nowait-klausel hinzugefügt wird. 65 OpenMP-Kurs Dieter an Mey Direktiven Work-sharing Constructs do - scheduling schedule (static[,chunk]) Die Iterationen werden gleichmäßig in Blöcken (chunks) der Größe chunk reihum auf die Threads aufgeteilt. Wird chunk nicht angegeben, so ist die Blockgröße gleich der Anzahl der Iterationen dividiert durch die Anzahl der Threads. schedule (dynamic [,chunk]) Die Iterationen werden in Blöcken (chunks) der Größe chunk auf die Threads aufgeteilt. Der Thread, der seinen Block abgearbeitet hat, bekommt einen neuen zugewiesen. Wird chunk nicht angegeben, so ist die Blockgröße gleich 1. schedule (guided [,chunk]) Die Iterationen werden in Blöcken (chunks) auf die Threads aufgeteilt, deren Größe exponentiell abnimmt. Der Thread, der seinen Block abgearbeitet hat, bekommt einen neuen zugewiesen. Mit chunk wird die minimale Blockgröße angegeben. Wird chunk nicht angegeben, so ist die minimale Blockgröße gleich 1. schedule (runtime) Das Schleifen-Scheduling kann zur Laufzeit durch die Umgebungsvariable OMP_SCHEDULE festgelegt werden. Die Voreinstellungen sind implementationsabhängig. Meist ist schedule (static) voreingestellt 66 OpenMP-Kurs Dieter an Mey
34 Direktiven Work-sharing Constructs - sections!$omp sections [clause[[,] clause] ] [!$omp section] block [!$omp section block]!$omp end sections [nowait] Die Ausführung der einzelnen Programmsegmente block, wird auf die Threads verteilt. Die end sections-direktive enthält implizit eine Barriere, falls nicht die nowait-klausel hinzugefügt wird. mit clause aus private (list) firstprivate (list) lastprivate (list) reduction ({op intrinsic:list) 67 OpenMP-Kurs Dieter an Mey Direktiven Work-sharing Constructs - single!$omp single [clause[[,] clause] ] block!$omp end single { [nowait] [copyprivate (list)] mit clause aus private (list) firstprivate (list) neu in OpenMP V2.0 Das Programmsegment block wird nur von einem Thread des Teams ausgeführt. Die end single-direktive enthält implizit eine Barriere, falls nicht die nowait-klausel hinzugefügt wird. Dort warten ggfls. alle anderen Threads. Mit der copyprivate-klausel können private Variablen an die anderen Threads weitergegeben werden (broadcast, z.b. nach einer Eingabe in block.) copyprivate und nowait schließen einander aus. 68 OpenMP-Kurs Dieter an Mey
35 Direktiven Work-sharing Constructs - workshare neu in OpenMP V2.0 (nur Fortran90)!$omp workshare block!$omp end workshare [nowait] Die Ausführung Fortran90-Feldzuweisungen, wird auf die beteiligten Threads aufgeteilt. Zwischen den Statements werden u.u. implizite Barrieren eingefügt Die end workshare-direktive enthält implizit eine Barriere, falls nicht die nowait-klausel hinzugefügt wird. 69 OpenMP-Kurs Dieter an Mey Direktiven Besonderheiten von C / C++ #pragma omp parallel [clause[ clause] ] { structured block #pragma omp for [clause[ clause] ] { for-loop #pragma omp sections [clause[[,] clause] ] { [#pragma omp section] { structured block [#pragma omp section { structured block ] Die default-klausel kann nur die Werte shared oder none enthalten. Das for-statement muss einfach sein. Der Verzicht auf die Barriere am Ende des for-work-sharing-konstruktes wird durch eine nowait-klausel bei dem for-pragma spezifiziert. Der Verzicht auf die Barriere am Ende des sections-work-sharing-konstruktes wird durch eine nowait-klausel bei dem sections-pragma spezifiziert. 70 OpenMP-Kurs Dieter an Mey
36 Direktiven Kombinierte Parallel Work-sharing Constructs!$omp parallel do [clause[[,] clause] ] do_loop!$omp end parallel do!$omp parallel sections [clause[[,] clause] ] [!$omp section] block [!$omp section block]!$omp end parallel sections Abkürzende Schreibweisen für Parallele Regionen, die nur ein Work-sharing-Konstrukt beinhalten. Es können alle die Klauseln verwendet werden, die zu der parallel-direktive oder zu dem Work-sharing-Konstrukt gehören.!$omp parallel workshare [clause[[,] clause] ] block neu in OpenMP V2.0 (Fortran90)!$omp end parallel workshare 71 OpenMP-Kurs Dieter an Mey Direktiven Synchronization Constructs!$omp master block!$omp end master!$omp critical [(name)] block!$omp end critical [(name)]!$omp barrier!$omp atomic!$omp flush [(list)]!$omp ordered block!$omp end ordered Das Programmsegment block wird nur vom Master-Thread ausgeführt. Das Konstrukt enthält keine implizite Barriere! Kritische Bereiche (block) mit gleichem Namen werden zu einer Zeit nur von einem Thread des Teams ausgeführt. Das Konstrukt enthält keine implizite Barriere! Die Barriere synchronisiert alle Threads eines Teams. Jeder Thread wartet, bis alle anderen Threads des Teams diesen Punkt erreicht haben. Die atomic-direktive stellt sicher, dass eine Speicherzelle atomar, d.h. ungestört von anderen schreibenden Zugriffen geändert werden kann. Die (explizite oder implizite) flush-direktive sorgt dafür, dass alle Threads ein konsistentes Bild von allen oder einer Liste list von Variablen besitzen. Das Programmsegment block wird in der Reihenfolge ausgeführt, in der es im seriellen Fall ausgeführt würde. Die zugehörge do-direktive muß die ordered-klausel besitzen. Es wird zu einer Zeit nur von einem Thread des Teams durchlaufen. 72 OpenMP-Kurs Dieter an Mey
37 threadprivate (list) Direktiven Data Scope Die threadprivate-direktive privatisiert benannte common-blöcke oder Variablen, globalisiert sie aber innerhalb eines jeden Threads. ( In C / C++: externe/globale Variable) Diese Direktive gehört überall dort in den Anweisungsteil wo auch die common-blöcke bzw. die Variablen deklariert werden. In den seriellen Regionen und den master-bereichen werden auf die common-blöcke bzw. die Variablen des Master-Threads zugegriffen. Am Anfang der ersten Parallelen Region, werden die als threadprivate vereinbarten Variablen bzw. common-blöcke angelegt. Werden sie in einer copyin-klausel einer parallel-direktive aufgeführt, so werden sie initialisiert mit dem Inhalt der entsprechenden Variablen bzw. des entsprechenden common-blocks des Master-Threads. Wird die Anzahl der Threads nicht dynamischen gesteuert, so bleiben Inhalte und Zustände zwischen Parallelen Regionen erhalten. 73 OpenMP-Kurs Dieter an Mey Klauseln Data Scope (1) private (list) shared (list) Für jeden Thread werden neue private Objekte angelegt, deren Inhalte anfangs nicht definiert sind. Die entsprechenden (shared) Objekte haben am Ende des Konstuktes keinen wohl definierten Wert. Alle Threads greifen auf denselben Speicherbereich zu. Aufgrund der Verwendung von Registern und Caches werden Änderungen durch einen Thread nicht sofort bei den anderen Threads wahrgenommen, es sei denn eine flush-direktive wird verwendet. default ( private shared none ) Die standardmäßige Voreinstellung des Datengeltungsbereiches auf shared kann verändert werden firstprivate (list) lastprivate (list) Wie mit der private-direktive werden private Objekte für jeden Thread erzeugt. Diese werden zusätzlich mit dem Wert des entsprechenden ursprünglichen Objektes initialisiert. Wie mit der private-direktive werden private Objekte für jeden Thread erzeugt. Zusätzlich werd die Werte der seriell letzten Iteration bzw. der lexikalisch letzten section auf die entsprechenden ursprünglichen Objekte übertragen. 74 OpenMP-Kurs Dieter an Mey
38 Klauseln Data Scope (2) reduction ({op intrinsic:list) Es wird eine Reduktion mit dem Operator op intrinsic auf die Variablen in der Liste list ausgeführt. ACHTUNG: Die Reihenfolge der Berechnungen ist zufällig, daher treten unterschiedliche Rundungsfehlereinflüsse auf! Die Variablen der Liste müssen im umgebenden Kontext shared sein. Es wird dann eine private Kopie für die Zwischenergebnisse angelegt, die in Abhängigkeit von der gewählten Operation sinnvoll initialisiert wird. Das Endergebnis der Reduktion steht erst nach der nächsten Barriere zur Verfügung (bei Verwendung von nowait) Fortran: op = { + * -.and..or..eqv..neqv. intrinsic = { max, min, iand, ior, ieor. C / C++: op = { + * - & ^ && list ist eine Komma-separierte Liste von Variablen 75 OpenMP-Kurs Dieter an Mey Klauseln Data Scope (3) copyin (list) Variablen, common-blöcke oder Variablen in common-blöcken, die als threadprivate deklariert wurden, können am Anfang einer Parallelen Region initialisiert werden, in dem sie den Wert des entsprechenden Objektes des Master-Threads erhalten. neu in OpenMP V2.0 : copyprivate (list) Mit dieser Klausel der end critical-direktive kann der Wert einer privaten Variablen an die anderen Threads übermittelt werden (broadcast) 76 OpenMP-Kurs Dieter an Mey
39 Laufzeitroutinen integer function omp_get_num_threads () subroutine omp_set_num_threads ( intexp ) integer function omp_get_max_threads () integer function omp_get_thread_num () integer function omp_get_num_procs () logical function omp_in_parallel () logical function omp_get_dynamic () subroutine omp_set_dynamic ( logexp ) logical function omp_get_nested () subroutine omp_set_nested ( logexp ) neu in OpenMP V2.0: double precision function omp_get_wtime () double precision function omp_get_wtick () Setzen / Abfragen der Threadanzahl Abfragen der maximalen Threadzahl Abfragen der aktuellen Threadzahl Abfragen der Anzahl der Prozessoren (HW) In einer Parallelen Region? Abfragen / Setzen des Dynamisches Schleifen-Schedulings Abfragen / Setzen der geschachtelten Parallelisierung Echtzeit in Sekunden Abstand zwischen zwei Ticks in Sekunden 77 OpenMP-Kurs Dieter an Mey Laufzeitfunktionen - locks integer (kind=omp_lock_kind) :: svar subroutine omp_init_lock (svar) subroutine omp_destroy_lock (svar) subroutine omp_set_lock (svar) subroutine omp_unset_lock (svar) subroutine omp_test_lock (svar) neu im OpenMP Fortran API V2.0, im OpenMP C / C++ API V1.0 schon enthalten : integer (kind=omp_nest_lock_kind) :: nvar subroutine omp_init_nest_lock (nvar) subroutine omp_destroy_ nest_ lock (nvar) subroutine omp_set_ nest_ lock (nvar) subroutine omp_unset_ nest_ lock (nvar) subroutine omp_test_ nest_ lock (nvar) 78 OpenMP-Kurs Dieter an Mey integer*4/*8 bei 32-/ 64-Bit Adressierung Anmelden Abmelden Setzen (ggfls. nach Warten) Freigeben Testen und Setzen eines Locks mit dem Namen svar Nestable Locks können von einem Thread mehrfach gesperrt werden
40 Umgebungsvariablen OMP_SCHEDULE = { static dynamic guided [,chunk] OMP_NUM_THREADS = int OMP_DYNAMIC = {FALSE TRUE Spezifizieren der Aufteilung der Schleifendurchläufe auf die Threads, falls in der do-direktive die Klausel schedule(runtime) angegeben wurde. Spezifizieren der Anzahl der zu verwendenden Threads, falls diese nicht explizit durch die Laufzeitfunktion omp_set_num_threads oder die num_threads-klausel der parallel-direktive gesetzt wird. Bei dynamischem Schleifen- Scheduling ist dies das Maximum der Threadzahl Default: Sun-Compiler: 1, Guide: max Ein-/Ausschalten der dynamischen Einstellung der Threadzahl durch das Laufzeitsystem im Abhängigkeit von der aktuellen Maschinenauslastung Default: Sun-Compiler: TRUE, Guide: FALSE OMP_NESTED = {FALSE TRUE Ein-/Ausschalten der geschachtelten (nested) Parallelisierung. Parallele Regionen innerhalb von Parallelen Regionen werden durch die derzeitigen OpenMP-Compiler serialisiert. 79 OpenMP-Kurs Dieter an Mey OpenMP - Gliederung Einleitung: Geschichte, Compiler, OpenMP-Struktur Einführung in OpenMP Format der Direktiven Laufzeitfunktionen Parallele Regionen Arbeitsteilung (worksharing( worksharing) Verwaisen (orphaning( orphaning) Daten-Geltungsbereiche (data( scope) Synchronisation Überblick über alle Kompontenten von OpenMP Ein Beispiel (Berechnung von Pi) Strategien, Performance Klassifizierung von Variablen Parallelisierung auf Schleifenebene Grobgranulare Arbeitsteilung SPMD OpenMP versus MPI Anwendungsbeispiele Jacobi, Panta 80 OpenMP-Kurs Dieter an Mey
41 Problemstellung und C-ProgrammkernC Die Kreiszahl π kann berechnet werden als Integral: 1 π = f(x)dx, mit f(x) = 4 /(1 + x 2 ) 0 Dieses Integral kann numerisch mit einer Quadraturformel (Mittelpunktsregel) angenähert werden: n π 1/n f(x i ), mit x i = (i-½)/ n für i=1,,n i=1 double f(double x) { return (double)4.0/(1.0+(x*x)); h = 1.0/(double)n; sum = 0.0; for(i=1;i<=n;i++) { x = h*((double)i - 0.5); /* Stützstelle */ sum += f(x); pi = h*sum; 81 OpenMP-Kurs Dieter an Mey Serielles Fortran90-Programm program main integer :: i,n double precision,parameter :: pi25dt= d0 double precision :: a,h,pi,sum,x double precision :: f f(a) = 4.d0 / (1.d0+a*a)! statement function do read (5,10001) n; if (n <= 0) exit h = 1.0d0 / n sum = 0.0d0 do i = 1, n x = h * (DBLE(i)-0.5d0) sum = sum + f(x) pi = h * sum write (6,10002) pi, ABS(pi-pi25dt) end program main 82 OpenMP-Kurs Dieter an Mey
42 OpenMP-Programm Programm 1. Version in Fortran90 (Auszug) do read (5,10001) n if (n <= 0) exit allocate (fx(n),stat=ierror) h = 1.0d0 / n sum = 0.0d0!$omp parallel private(i,x) shared(h,fx)!$omp do do i = 1,n x = h * (DBLE(i)-0.5d0) fx(i) = f(x)!$omp!$omp end parallel do i = 1,n sum = sum + fx(i) pi = h * sum write (6,10002) pi, ABS(pi-pi25dt) deallocate (fx) 83 OpenMP-Kurs Dieter an Mey OpenMP-Programm Programm 2. Version in Fortran90 (Auszug) do read (5,10001) n if (n <= 0) exit sum = 0.0d0!$omp parallel!$omp do private(i,x) do i = 1,n x = h * (DBLE(i)-0.5d0)!$omp critical sum = sum + f(x)!$omp end critical!$omp!$omp end parallel pi = h * sum write (6,10002) pi, ABS(pi-pi25dt) 84 OpenMP-Kurs Dieter an Mey
43 OpenMP-Programm Programm 3. Version in Fortran90 double precision :: sum_local do read (5,10001) n if (n <= 0) exit h = 1.0d0 / n sum = 0.0d0 sum=0!$omp parallel private(i,x,sum_local) sum_local = 0.0d0!$omp do do i = 1,n x = h * (DBLE(i)-0.5d0) sum_local = sum_local + f(x)!$omp!$omp critical sum = sum + sum_local!$omp end critical!$omp end parallel pi = h * sum write (6,10002) pi, ABS(pi-pi25dt) Thread 0 Lese n (z.b. n=6) sum_local=0 i=1 sum_local+=f(x i ) i=2 sum_local+=f(x i ) warten sum+=sum_local pi = h*sum Drucke pi Thread 1 sum_local=0 i=3 sum_local+=f(x i ) i=4 sum_local+=f(x i ) sum+=sum_local Thread 2 sum_local=0 i=5 sum_local+=f(x i ) i=6 sum_local+=f(x i ) warten warten sum+=sum_local 85 OpenMP-Kurs Dieter an Mey OpenMP-Programm Programm 4. Version in Fortran90 (Auszug) do read (5,10001) n if (n <= 0) exit h = 1.0d0 / n sum = 0.0d0!$omp parallel private(i,x)!$omp do parallel reduction(+:sum) do private(i,x) reduction(+:sum) do i = 1,n x = h * (DBLE(i)-0.5d0) sum = sum + f(x)!$omp!$omp end parallel pi = h * sum write (6,10002) pi, ABS(pi-pi25dt) 86 OpenMP-Kurs Dieter an Mey
44 OpenMP-Programm Programm 5. Version in Fortran90 (Auszug)!$omp parallel private(i,x) do!$omp single read (5,10001) n!$omp end single if (n <= 0) exit h = 1.0d0 / n! Wird redundant von jedem Thread ausgeführt sum = 0.0d0! Wird redundant von jedem Thread ausgeführt!$omp barrier! Wichtig, nicht vergessen!$omp do reduction(+:sum) do i = 1,n x = h * (DBLE(i)-0.5d0) sum = sum + f(x)!$omp!$omp single pi = h * sum write (6,10002) pi, ABS(pi-pi25dt)!$omp end single!$omp end parallel 87 OpenMP-Kurs Dieter an Mey OpenMP-Programm Programm 5. Version in C (Auszug) int main(int argc, char *argv[]) { long, n, i; double h, pi, sum, x; # pragma omp parallel private (i,x) { for (;;) { # pragma omp single { printf("enter the number of intervals:(0 quits)");scanf("%u",&n); if (n==0) break; h = 1.0/(double)n; /* Wird redundant von jedem Thread ausgeführt */ sum = 0.0; /* Wird redundant von jedem Thread ausgeführt */ # pragma omp barrier /* Wichtig, nicht vergessen */ # pragma omp for reduction (+:sum) for(i=1;i<=n;i++) { x = h*((double)i-0.5); sum += f(x); # pragma omp single { pi = h*sum; printf(" ",pi,fabs(pi-pi)); 88 OpenMP-Kurs Dieter an Mey
45 OpenMP-Programm Programm 6. Version in Fortran90 (Auszug) program main!$omp parallel do!!$omp single write (6,10000) read (5,10001) n!$omp end single if (n <= 0) exit call calc_pi (n, pi)!$omp single subroutine calc_pi (n, pi) integer, intent(in) :: n double precision, intent(out) :: pi double precision, save :: sum, h integer :: i double precision :: a,x,f f(a) = 4.d0 / (1.d0+a*a)!$omp single h = 1.0d0 / n sum = 0.0d0!$omp end single write (6,10002) pi, ABS(pi-pi25dt)!$omp do reduction(+:sum) private(i,x)!$omp end single do i = 1,n x = h * (DBLE(i)-0.5d0)!$omp end parallel sum = sum + f(x) end program Main!$omp!$omp single pi = h * sum!$omp end single return 89 OpenMP-Kurs Dieter end an subroutine Mey calc_pi OpenMP-Programm Programm 7. Version in Fortran90 (Auszug) program main!$omp parallel do!!$omp single write (6,10000) read (5,10001) n!$omp end single if (n <= 0) exit call calc_pi (n, pi)!$omp single subroutine calc_pi (n, pi) double precision, save :: sum, h integer :: omp_get_thread_num,omp_get_num_threads integer :: myid,numthreads double precision :: sum_local myid = omp_get_thread_num() numthreads = omp_get_num_threads()!$omp single h = 1.0d0 / n sum = 0.0d0!$omp end single do i = myid+1, n, numthreads write (6,10002) pi, ABS(pi-pi25dt) x = h * (DBLE(i)-0.5d0)!$omp end single!$omp end parallel end program Main sum_local = sum_local + f(x)!$omp critical sum = sum + sum_local!$omp end critical!$omp barrier!$omp single pi = h * sum!$omp end single 90 OpenMP-Kurs return Dieter an Mey end subroutine calc_pi
46 #include <omp.h> #define SIZE template <typename T,int size> class Array { private: T data[size]; public: Array() /* Default constructor */ { ~Array() /* Array destructor */ { Array(const T& r) /* Regular constructor */ { #pragma omp parallel for for (int i=0 ; i<size ; i++) data[i]=r; Array(const Array& rhs) /* Copy constructor end */ do { #pragma omp parallel for for (int i=0 ; i<size ; i++) data[i]=rhs[i]; // Read only and read/write subscript operators const T& operator[](int i) const { return data[i]; T& operator[](int i) { return data[i]; C++ - Beispiel Array& operator=(const Array& rhs) /* Assignment operator */ { #pragma omp parallel for for (int i=0 ; i<size ; i++) data[i]=rhs[i]; return *this; ; //-- Operators template <typename T,int size> Array<T,size> operator+(const Array<T,size>& a,const Array<T,s Array<T,size> ret; #pragma omp parallel for for (int i=0 ; i<size ; i++) ret[i] = a[i]+b[i]; return ret; void do_it(int repeat) { Array<double,SIZE> a(1.0),b(2.0), c(3.0),d(4.0),res(5.0); for (int i=0; i<repeat; i++) res = a * b - c + d;! Analoges Fortran90 Programm subroutine do_it ( repeat ) integer, intent(in) :: repeat integer, parameter :: SIZE=10000 real*8, dimension(size) :: a=1.0,b=2.0,c=3.0,d=4.0,res=5.0!$omp parallel workshare do i = 0, repeat-1 res = a * b c + d end subroutine 91 OpenMP-Kurs Dieter an Mey OpenMP - Gliederung Einleitung: Geschichte, Compiler, OpenMP-Struktur Einführung in OpenMP Format der Direktiven Laufzeitfunktionen Parallele Regionen Arbeitsteilung (worksharing( worksharing) Verwaisen (orphaning( orphaning) Daten-Geltungsbereiche (data( scope) Synchronisation Überblick über alle Kompontenten von OpenMP Ein Beispiel (Berechnung von Pi) Vertiefung, Strategien, Performance Klassifizierung von Variablen Parallelisierung auf Schleifenebene Grobgranulare Arbeitsteilung SPMD OpenMP versus MPI Anwendungsbeispiele Jacobi, Panta 92 OpenMP-Kurs Dieter an Mey
47 Klassifizierung von Variablen (1) Beachte Zugriffsart: Variable wird nur gelesen => shared Variable wird zuerst gelesen und dann Variable wird zuerst modifiziert und dann gelesen => evtl. private Variable wird nur modifiziert => evtl. lastprivate!$omp parallel do do i = 1, n a(i) = b(i) * PI s = 0.0!$omp parallel do reduction(+:s) modifiziert => evtl. reduction, firstprivate? do i = 1, n s = s + a(i) print *, s!$omp parallel do private(t) do i = 1, n Mögliches Vorgehen: t = a(i) + b(i) c(i) = t * t einfach Work-sharing-Konstrukt einsetzen und mit Assure überprüfen diesen Vorgang wiederholen, bis Assure kein Problem mehr meldet einen möglichst kleinen Testfall aussuchen, der dennoch typisch ist. Assure benötigt viel mehr Speicherplatz und Laufzeit! 93 OpenMP-Kurs Dieter an Mey Klassifizierung von Variablen (2) Beachte Zugriffsart: Variable wird in der Parallelen Region modifiziert: Empfehlungen ohne Garantie! sie wird mit dem Index der parallelen Schleife indiziert => shared sie wird global, aber nur innerhalb der Parallelen Region benutzt => threadprivate sie wird nur temporär genutzt => private sie ist lokal in einem Unterprogramm (dynamic extend) mit dem save / static Attribut => threadprivate sonst per default => private (Sun: f90 stackvar / HP: f90 nosave ) im common-block/modul => threadprivate? Initialisierung mit copyin? anderenfalls Modifikationen in kritischen Regionen schützen Enthält ein common-block Variablen mit unterschiedlichen Eigenschaften, so muss er u.u. gespalten werden. 94 OpenMP-Kurs Dieter an Mey
48 Welche Schleife soll parallelisiert werden? Wähle die am weitesten außen stehende Schleife (gröbst mögliche Parallelität) Ignoriere dabei Schleifen über Zeitschritte oder Iterationen (Rekursivität) Ignoriere Schleifen mit nur wenigen Iterationen Ignoriere Schleifen die nur unwichtige Unterprogramme aufrufen Vorsicht bei der Parallelisierung von Schleifen, in denen gemeinsame Daten modifiziert werden von Schleifen, die verlinkte Listen durchlaufen von Schleifen, die Ein-/Ausgabe enthalten 95 OpenMP-Kurs Dieter an Mey Was tun, bei mehreren parallelisierbaren Schleifen? Geschachtelte parallelisierbare Schleifen sind gut Obwohl die derzeitigen Compiler nested parallelism noch nicht unterstützen Wähle die am einfachsten parallelisierbare Schleife oder die mit den meisten Iterationen Achte auf Datenlokalität (False Sharing) Nutze die IF-Klausel zur dynamischen Auswahl der besten Schleife Kann die äußere Schleife zusätzlich mit MPI parallelisiert werden? Nicht geschachtelte parallelisierbare Schleifen Fasse Schleifen zusammen (Loop Fusion), Lokalität? Kann der dazwischen liegenden Code redundant ausgeführt werden? 96 OpenMP-Kurs Dieter an Mey
49 Parallelisierung auf Schleifenebene (fein-granular granular) Vorteile: Jede einzelne Schleife wird parallel ausgeführt. Einfache schrittweise Vorgehensweise geringfügige Änderung des bestehenden Codes Nur eine Code-Version Kann ggfls. mit automatische Parallelisierung kombiniert werden Nachteile: Hoher Overhead durch häufigen Thread-Start und Synchronisierung Der Anteil an nicht parallelisiertem Code kann schnell dominieren, daher skaliert dieser Ansatz meist schlecht (Amdahl s Law). Die Datenverteilung kann sich von Schleife zu Schleife ändern (Daten wandern zwischen den Caches) 97 OpenMP-Kurs Dieter an Mey Verbesserung der Parallelisierung auf Schleifenebene Zusammenfassen mehrer Schleifen zu einer Parallele Region dadurch Verringerung des Overheads, die Schleifengrenzen für das Worksharing muss weiterhin jeweils berechnet werden Falls möglich Einsparung von Synchronisationspunkten durch NOWAIT häufig nur bei SCHEDULE(STATIC) möglich. Vergrößern der Parallelen Regionen durch Orphaning Ausführen des Codes zwischen den parallelisierbaren Schleifen in SINGLE oder MASTER Bereichen, oder redundante Ausführung mit allen Threads. 98 OpenMP-Kurs Dieter an Mey
50 Grob-granulare Parallelisierung Gebietszerlegung Im Falle von zahlreichen ähnlichen parallelisierbaren Schleifen können die Schleifengrenzen vorher explizit berechnet werden. Allgemeinerer Ansatz: Gebietszerlegung, Jeder Thread erhält ein Teilgebiet zur Bearbeitung Erhöhter Programmieraufwand Grob-granularer Ansatz: Eine Parallele Region für das gesamte Programm Höhere Skalierbarkeit SPMD-Ansatz: Single Program, Multiple Data Alle zum Teilgebiet gehörenden Daten sind privat 99 OpenMP-Kurs Dieter an Mey Verwalten globaler Daten Globale Daten überspannen das gesamte Gebiet Felder sind meist Shared, jeder Thread nutzt ein anderes Teilfeld Änderung gemeinsamer Daten erfordert Synchronisation durch SINGLE- oder ATOMIC-Konstrukte Vereinbare private COMMON-Blöcke oder Daten mit globalem Geltungsbreich als THREADPRIVATE 100 OpenMP-Kurs Dieter an Mey
51 SPMD-Programmierung Programmierung Vergleich von OpenMP und MPI Derselbe Algorithmus, einfachere Implementierung Die Modifikation von Shared Daten erfordert Synchronisation Keine expliziter Datentransfer, keine Notwendigkeit von Ghost Cells Die Parallelisierung kann sich auf den rechenintensiven Teil beschränken (Präund Postprosessing kann seriell bleiben) 101 OpenMP-Kurs Dieter an Mey Kombination von MPI und OpenMP auf SMP- Clustern OpenMP innerhalb eines SMP-Knotens, MPI über Knotengrenzen hinweg Mehrere MPI-Tasks können auch innerhalb eines SMP-Knotens gestartet werden. Grob-granulare Parallelisierung mit MPI und fein-granulare Parallelisierung mit OpenMP 102 OpenMP-Kurs Dieter an Mey
52 Performance-Gesichtspunkte Bei der SPMD-Programmierung sind die meisten Daten privat: Verwende DEFAULT(PRIVATE) Common-Blöcke sind häufig THREADPRIVATE Privatisiere möglichst viele Variablen zur Vermeidung von False Sharing Vermeide unnötige Barrieren Häufig müssen nur einzelne Threads miteinander synchronisiert werden, Barrieren synchronisieren aber alle Threads 103 OpenMP-Kurs Dieter an Mey Punkt-zu zu-punkt-synchronisation Der Produzent berechnet seinen Teil des gemeinsamen Feldes und setzt anschliessend eine Flagge (entspricht dem MPI_Send beim MPI-Ansatz) Der Verbraucher benötigt einen Teil des Feldes des Produzenten und wartet auf seine Flagge (entspricht dem MPI_Receive beim MPI-Ansatz) 104 OpenMP-Kurs Dieter an Mey
53 Gezielte Synchronisation einzelner Tasks - Flush program flush implicit integer (a-z) logical allocatable, dimension(:) :: done allocate (done(omp_get_max_threads()))!$omp parallel default(private) shared(done) me = omp_get_thread_num() if ( me > 0 ) neighbor = me - 1 done(me)=.false. $!OMP barrier call do_my_work() done(me)=.true. $!OMP flush(done) do while (.not. done(neighbor)) call do_some_more_useful_work() $!OMP flush(done) call do_synchronized_work() $!OMP end parallel end program flush 105 OpenMP-Kurs Dieter an Mey OpenMP - Gliederung Einleitung: Geschichte, Compiler, OpenMP-Struktur Einführung in OpenMP Format der Direktiven Laufzeitfunktionen Parallele Regionen Arbeitsteilung (worksharing( worksharing) Verwaisen (orphaning( orphaning) Daten-Geltungsbereiche (data( scope) Synchronisation Überblick über alle Kompontenten von OpenMP Ein Beispiel (Berechnung von Pi) Strategien, Performance Klassifizierung von Variablen Parallelisierung auf Schleifenebene Grobgranulare Arbeitsteilung SPMD OpenMP versus MPI Anwendungsbeispiele Jacobi, Panta 106 OpenMP-Kurs Dieter an Mey
54 CFD-Programm PANTA auf HP V-ClassV Programmkern!$omp parallel do lastprivate(ine,iee,ise,isw,iww,inw,iue,iuw,ide,idw,inu,ind,isu,isd)!$omp & renbpe,resbme,resbpe,reubme,reubpe,rkdbmk,rkdbpk,rknbmk, private( & &!$omp & aece,aee,aeebe,aewbe,akck,akebk,akk,akwbk,!$omp & rknbpk,rksbmk,rksbpk,rkubmk,rkubpk,rtdbme,rtdbpe,rtnbme, &!$omp & amueec,amuegc,amuekc,amuelc,amuetc,asonsq,atce,ate,!$omp & rtnbpe,rtsbme,rtsbpe,rtubme,rtubpe,rudbme,rudbmx,rudbmy, & &!$omp & atebe,atwbe,auce,aucx,aucy,aucz,aue,auebe,!$omp & & rudbmz,rudbpe,rudbpx,rudbpy,rudbpz,runbme,runbmx,runbmy, &!$omp & auebx,aueby,auebz,auwbe,auwbx,auwby,auwbz,aux,!$omp & runbmz,runbpe,runbpx,runbpy,runbpz,rusbme,rusbmx,rusbmy, & &!$omp & auy,auz,avce,avcx,avcy,avcz,ave,avebe,!$omp & & rusbmz,rusbpe,rusbpx,rusbpy,rusbpz,ruubme,ruubmx,ruubmy, &!$omp & avebx,aveby,avebz,avwbe,avwbx,avwby,avwbz,avx,!$omp & ruubmz,ruubpe,ruubpx,ruubpy,ruubpz,rvdbme,rvdbmx,rvdbmy, & &!$omp & avy,avz,awce,awcx,awcy,awcz,awe,awebe,!$omp & & rvdbmz,rvdbpe,rvdbpx,rvdbpy,rvdbpz,rvnbme,rvnbmx,rvnbmy, &!$omp & awebx,aweby,awebz,awwbe,awwbx,awwby,awwbz,awx,!$omp & rvnbmz,rvnbpe,rvnbpx,rvnbpy,rvnbpz,rvsbme,rvsbmx,rvsbmy, & &!$omp & awy,awz,bedbe,benbe,besbe,beube,bkdbk,bknbk,!$omp & rvsbmz,rvsbpe,rvsbpx,rvsbpy,rvsbpz,rvubme,rvubmx,rvubmy, & &!$omp & bksbk,bkubk,btdbe,btnbe,btsbe,btube,budbe,budbx,!$omp & rvubmz,rvubpe,rvubpx,rvubpy,rvubpz,rwdbme,rwdbmx,rwdbmy, & &!$omp & budby,budbz,bunbe,bunbx,bunby,bunbz,busbe,busbx,!$omp & rwdbmz,rwdbpe,rwdbpx,rwdbpy,rwdbpz,rwnbme,rwnbmx,rwnbmy, & &!$omp & busby,busbz,buube,buubx,buuby,buubz,bvdbe,bvdbx,!$omp & rwnbmz,rwnbpe,rwnbpx,rwnbpy,rwnbpz,rwsbme,rwsbmx,rwsbmy, & &!$omp & bvdby,bvdbz,bvnbe,bvnbx,bvnby,bvnbz,bvsbe,bvsbx,!$omp & rwsbmz,rwsbpe,rwsbpx,rwsbpy,rwsbpz,rwubme,rwubmx,rwubmy, & &!$omp & bvsby,bvsbz,bvube,bvubx,bvuby,bvubz,bwdbe,bwdbx,!$omp & rwubmz,rwubpe,rwubpx,rwubpy,rwubpz,tc,tdb,tdbm, & &!$omp & bwdby,bwdbz,bwnbe,bwnbx,bwnby,bwnbz,bwsbe,bwsbx,!$omp & tdbp,teb,tkc,tkdb,tkdbm,tkdbp,tkeb,tknb, & &!$omp & bwsby,bwsbz,bwube,bwubx,bwuby,bwubz,caqden,dedq1,!$omp & tknbm,tknbp,tksb,tksbm,tksbp,tkub,tkubm,tkubp, & &!$omp & dedq7,diffe,diffre,diffrk,diffru,diffrv,diffrw,dkdq1,!$omp & tkwb,tnb,tnbm,tnbp,tsb,tsbm,tsbp,tub, & &!$omp & dkdq6,dmtdq6,dmtdq7,dtdq1,dtdq2,dtdq3,dtdq4,dtdq5,!$omp & tubm,tubp,twb,uc,udb,udbm,udbp,ueb, & &!$omp & dtdq6,dudq1,dudq2,dvdq1,dvdq3,dwdq1,dwdq4,ec,!$omp & unb,unbm,unbp,usb,usbm,usbp,uub,uubm, & &!$omp & edb,edbm,edbp,eeb,enb,enbm,enbp,esb,!$omp & & uubp,uwb,vc,vdb,vdbm,vdbp,veb,velosq, &!$omp & esbm,esbp,eub,eubm,eubp,ewb,gedb,genb,!$omp & & vnb,vnbm,vnbp,vsb,vsbm,vsbp,vub,vubm, &!$omp & gesb,geub,gkdb,gknb,gksb,gkub,gtdb,gtnb,!$omp & & vubp,vwb,wc,wdb,wdbm,wdbp,web,wnb, &!$omp & gtsb,gtub,gudb,gunb,gusb,guub,gvdb,gvnb,!$omp & & wnbm,wnbp,wsb,wsbm,wsbp,wub,wubm,wubp, &!$omp & gvsb,gvub,gwdb,gwnb,gwsb,gwub,lijk,omegay,!$omp & wwb,xiaxc,xiaxeb,xiaxwb,xiayc,xiayeb,xiaywb,xiazc, &!$omp & omegaz,prode,qdens,qjc,qmqc,redbme,redbpe,renbme,!$omp & xiazeb,xiazwb,xibxc,xibxnb,xibxsb,xibynb,xibysb,xibznb, & &!$omp & omegaz,prode,qdens,qjc,qmqc,redbme,redbpe,renbme,!$omp & xibzsb,xicxc,xicxdb,xicxub,xicydb,xicyub,xiczdb,xiczub) & do i = is,ie! lines omitted 107 OpenMP-Kurs Dieter an Mey percent of the CPU time spent in one loop nest Attention: when parallelizing this loop do n = 1,7 recursion: RHS(l,m) this loop is usually auto-parallelized do m = 1,7 only 7 iterations many iterations! do l = LSS(itsub),LEE(itsub) (vector loop) i = IG(l) j = JG(l) k = KG(l) lijk = L2IJK(l) RHS(l,m) = RHS(l,m)- & FJAC(lijk,lm00,m,n)*DQCO(i-1,j,k,n,NB)*FM00(l) - & FJAC(lijk,lp00,m,n)*DQCO(i+1,j,k,n,NB)*FP00(l) - & FJAC(lijk,l0m0,m,n)*DQCO(i,j-1,k,n,NB)*F0M0(l) - & FJAC(lijk,l0p0,m,n)*DQCO(i,j+1,k,n,NB)*F0P0(l) - & FJAC(lijk,l00m,m,n)*DQCO(i,j,k-1,n,NB)*F00M(l) - & FJAC(lijk,l00p,m,n)*DQCO(i,j,k+1,n,NB)*F00P(l) 108 OpenMP-Kurs Dieter an Mey
55 Visual KAP for OpenMP on WinNT (KAI) Generating OpenMP Directives!$OMP PARALLEL SHARED SHARED (ITSUB,LSS,II15,RHS,II14,L2IJK,FJAC,NB,KG,JG,IG,DQCO&!$OMP&,FM00,II13,FP00,II12,F0M0,II11,F0P0,II10,F00M,II9,F00P,LM00,LP00,L0M0&!$OMP&,L0P0,L00M,L00P,LEE,LFJ) PRIVATE PRIVATE (II2,II1,N1,M,L,II16,II4,RR1,II3,& (II2,II1,N1,M,L,II16,II4,RR1,II3,&!$OMP&I,J,K,LIJK,II17,II18,II20,II21,II22,II23,II24,II25,N,NM,II19,II32,&!$OMP&I,J,K,LIJK,II17,II18,II20,II21,II22,II23,II24,II25,N,NM,II19,II32,&!$OMP&II26,II27,II28,II29,II30,II31,II6,II5)!$OMP&II26,II27,II28,II29,II30,II31,II6,II5) DO!$OMP DO II1=LSS(ITSUB),II15,64 II2 = MIN (II15,II1+63) DO II1=LSS(ITSUB),II15,64 DO N1=1,7 DO II2 M=1,7 = MIN (II15,II1+63) long loop splitted DO N1=1,7 L=II1,II2,1 DO RHS(L,M) M=1,7 = RHS(L,M) - FJAC(L2IJK(L),II14,M,N1) * DQCO(IG(L)-1& &,JG(L),KG(L),N1,NB) * FM00(L) - FJAC(L2IJK(L),II13,M,N1) * DQCO(IG& &(L)+1,JG(L),KG(L),N1,NB) DO L=II1,II2,1 * FP00(L) - FJAC(L2IJK(L),II12,M,N1) * DQCO& &(IG(L),JG(L)-1,KG(L),N1,NB) RHS(L,M) = RHS(L,M) *-F0M0(L) FJAC(L2IJK(L),II14,M,N1) - FJAC(L2IJK(L),II11,M,N1) * DQCO(IG(L)-1& & &* &,JG(L),KG(L),N1,NB) DQCO(IG(L),JG(L)+1,KG(L),N1,NB) * FM00(L) * -F0P0(L) FJAC(L2IJK(L),II13,M,N1) - FJAC(L2IJK(L),II10,& * DQCO(IG& &M,N1) * DQCO(IG(L),JG(L),KG(L)-1,N1,NB) * F00M(L) - FJAC(L2IJK(L)& &(L)+1,JG(L),KG(L),N1,NB) * FP00(L) - FJAC(L2IJK(L),II12,M,N1) * DQCO& &,II9,M,N1) * DQCO(IG(L),JG(L),KG(L)+1,N1,NB) * F00P(L) &(IG(L),JG(L)-1,KG(L),N1,NB) END DO * F0M0(L) - FJAC(L2IJK(L),II11,M,N1) & &* END DQCO(IG(L),JG(L)+1,KG(L),N1,NB) DO * F0P0(L) - FJAC(L2IJK(L),II10,& &M,N1) END DO * DQCO(IG(L),JG(L),KG(L)-1,N1,NB) * F00M(L) - FJAC(L2IJK(L)& END DO!$OMP END &,II9,M,N1) DO NOWAIT * DQCO(IG(L),JG(L),KG(L)+1,N1,NB) * F00P(L)!$OMP BARRIER END DO END DO END DO END DO!$OMP 109 END DO NOWAIT OpenMP-Kurs Dieter an Mey !$OMP BARRIER Visual KAP for OpenMP on WinNT (KAI) Detailled Listing LR NV SO INF do n = 1, LR NV SO NVS NC: do m = 1, LR NV SO NVS :! do l = LSS(itsub),LEE(itsub) Abbreviations Used :!: :!: i = IG(l) j = JG(l) STD standardized :!: 47 k = KG(l) NO not optimized :!: 48 lijk = L2IJK(l) SO :!: 49 RHS(l,m) = & LR loop reordering :!: 50 RHS(l,m) - FJAC(lijk,lm00,m,n)*DQCO(i-1, NV not vectorized :!: 51 FJAC(lijk,lp00,m,n)*DQCO(i+1,j,k,n,NB)*F SO scalar optimization :!: 52 FJAC(lijk,l0m0,m,n)*DQCO(i,j-1,k,n,NB)*F NVS non-vector-stmt :!: 53 FJAC(lijk,l0p0,m,n)*DQCO(i,j+1,k,n,NB)*F :!: 54 FJAC(lijk,l00m,m,n)*DQCO(i,j,k-1,n,NB)*F INF informational :!: 55 FJAC(lijk,l00p,m,n)*DQCO(i,j,k+1,n,NB)*F C 1 concurrentized SO :!: 56 NC not concurrentized :! 57 : 58 Footnote List 1: scalar optimization Statement deleted because of scalar optimization. 2: not vectorized Not an inner loop. 3: not concurrentized Too little concurrentizable code. 4: informational Unrolling of this loop was not done because heuristic says size is o 5: scalar optimization Loop is empty or is zero-trip. 6: informational Unrolling of this loop was not done because no executable statements 7: scalar optimization Strip loop for strip mining with block size 64. 8: scalar optimization Block loop for strip mining with block size OpenMP-Kurs Dieter an Mey
56 Manual Parallelization with OpenMP Compilation with the guidef90 Preprocessor (KAI)!$omp parallel private(n,m,l,i,j,k,lijk) do n = 1,7 do m = 1,7!$omp do do l = LSS(itsub),LEE(itsub) partitioning the long loop i = IG(l) j = JG(l) k = KG(l) lijk = L2IJK(l) RHS(l,m) = RHS(l,m)- & FJAC(lijk,lm00,m,n)*DQCO(i-1,j,k,n,NB)*FM00(l) - & FJAC(lijk,lp00,m,n)*DQCO(i+1,j,k,n,NB)*FP00(l) - & FJAC(lijk,l0m0,m,n)*DQCO(i,j-1,k,n,NB)*F0M0(l) - & FJAC(lijk,l0p0,m,n)*DQCO(i,j+1,k,n,NB)*F0P0(l) - & FJAC(lijk,l00m,m,n)*DQCO(i,j,k-1,n,NB)*F00M(l) - & FJAC(lijk,l00p,m,n)*DQCO(i,j,k+1,n,NB)*F00P(l)!$omp do nowait!omp end parallel no barrier, no overhead 111 OpenMP-Kurs Dieter an Mey Paralleler Speedup des Programmkernes (HP V Class) OMP parallel inner loop without barrier OMP splitting loop over l (VisKAP) AUTO parallel over m speedup CPUs out of 16 busy processors 112 OpenMP-Kurs Dieter an Mey
57 Finites Differenzenverfahren Zur Lösung der zweidimensionalen Helmholtzdifferentialgleichung u + κu = f mit homogenen Dirichlet-Randbedingungen dient ein Finites Differenzenverfahren. Bei der Diskretisierung des Laplace-Operators mit dem zentralen 5-Punkte-Differenzenstern entsteht ein lineares Gleichunssystem mit Bandstruktur, daß mit dem Jacobi- oder Gesamtschrittverfahren iterativ gelöst werden kann. Das Jacobi-Verfahren ist einfach parallelisierbar und auch vektorisierbar. 113 OpenMP-Kurs Dieter an Mey Jacobi-Verfahren - Gebietszerlegung P1 P2 Shared Memory Parallelisierung 114 OpenMP-Kurs Dieter an Mey
58 Jacobi-Verfahren - Gebietszerlegung P1 P2 Shared Memory Parallelisierung P1 Überlappbereiche P2 Distributed Memory Parallelisierung 115 OpenMP-Kurs Dieter an Mey Jacobi-Verfahren - 1. OpenMP Version k = 1 do while (k.le.maxit.and. error.gt. tol) error = 0.0!$omp parallel do do j=1,m do i=1,n; uold(i,j) = u(i,j); enddo enddo!$omp end parallel do!$omp parallel do private(resid) reduction(+:error) do j = 2,m-1 do i = 2,n-1 resid = (ax*(uold(i-1,j) + uold(i+1,j) u(i,j) = uold(i,j) - omega * resid error = error + resid*resid enddo!$omp end parallel do k = k + 1 error = sqrt(error)/dble(n*m) enddo 116 OpenMP-Kurs Dieter an Mey
59 Jacobi-Verfahren - 2. OpenMP Version k = 1 do while (k.le.maxit.and. error.gt. tol) error = 0.0!$omp parallel!$omp do do j=1,m do i=1,n; uold(i,j) = u(i,j); enddo enddo!$omp!$omp do private(resid) reduction(+:error) do j = 2,m-1 do i = 2,n-1 resid = (ax*(uold(i-1,j) + uold(i+1,j) u(i,j) = uold(i,j) - omega * resid error = error + resid*resid enddo!$omp nowait!$omp end parallel k = k + 1 error = sqrt(error)/dble(n*m) enddo 117 OpenMP-Kurs Dieter an Mey Jacobi-Verfahren - 3. OpenMP Version!$omp parallel private(resid,k_local) k_local = 1 do while (k_local.le.maxit.and. error.gt.tol)!$omp do do j=1,m; do i=1,n; uold(i,j) = u(i,j); enddo; enddo!$omp single error = 0.0!$omp end single!$omp do reduction(+:error) do j..;do i..;resid=..;u(i,j)=..;error=..;enddo;enddo!$omp single error = sqrt(error)/dble(n*m)!$omp end single k_local = k_local + 1 enddo!$omp master k = k_local!$omp end master!$omp end parallel 118 OpenMP-Kurs Dieter an Mey
60 Jacobi-Verfahren Parallelisierung mit Visual KAP for OpenMP DO WHILE ( K.LE. MAXIT.AND. ERROR.GT. TOL ) ERROR = 0D0 C$OMP PARALLEL IF (M.GT. 83) SHARED (M,N,UOLD,U) PRIVATE (J,I) C$OMP DO DO J=1,M; DO I=1,N; UOLD(I,J) = U(I,J); END DO; END DO C$OMP END DO NOWAIT C$OMP END PARALLEL II1 = II3; IF (II1.GT. 0) THEN; II2 = M - 2; IF (II2.GT. 0) THEN; DD2 = 1 / B C$OMP PARALLEL SHARED (M,DD2,N,AX,UOLD,F,AY,B,U,OMEGA,ERROR) PRIVATE ( C$OMP& DD1,J,I,RESID,ERROR1) ERROR1 = 0D0 C$OMP DO DO J=2,M-1; DD1 = DD2; DO I=2,N-1 RESID = U(I,J) = UOLD(I,J) - OMEGA * RESID ERROR1 = ERROR1 + RESID * RESID END DO; END DO C$OMP END DO NOWAIT C$OMP CRITICAL (II4) ERROR = ERROR + ERROR1 C$OMP END CRITICAL (II4) C$OMP END PARALLEL END IF; END IF K = K + 1; ERROR = SQRT (ERROR) * DD3 END DO 119 OpenMP-Kurs Dieter an Mey Jacobi-Verfahren Automatische Parallelisierung (Linux( Linux-PGI) Übersetzen mit automatischer Parallelisierung und Erzeugen einer Ausgabeliste (in jacobi.w2f.f): pgf90 -Mlist -Mconcur -Minfo -Mneginfo=concur -fast jacobi.f90 jacobi: 43, Loop not parallelized: multiple exits 49, Parallel code for non-innermost loop generated; block distribution 50, Loop unrolled 10 times 57, Parallel code for non-innermost loop generated; block distribution 120 OpenMP-Kurs Dieter an Mey
61 Parallele Programmierung für Shared-Memory Memory-Rechner mit OpenMP Automatische Parallelisierung Explizite Parallelisierung mit OpenMP Debugging mit Assure und TotalView Performance Tools GuideView, PerView, CXperf,, Puma Hybride Parallelisierung 121 OpenMP-Kurs Dieter an Mey Debugging OpenMP Programs - The Error!$omp parallel private(resid,k_local) k_local = 1 do while (k_local.le.maxit.and. error.gt.tol)!$omp do do j=1,m; do i=1,n; uold(i,j) = u(i,j); enddo; enddo!$omp single error = 0.0!$omp end single!$omp do reduction(+:error) do j..;do i..;resid=..;u(i,j)=..;error=..;enddo;enddo!$omp single error = sqrt(error)/dble(n*m)!$omp end single k_local = k_local + 1 enddo!$omp master k = k_local!$omp end master!$omp end parallel 122 OpenMP-Kurs Dieter an Mey
62 Debugging OpenMP Programs - The Error!$omp parallel private(resid,k_local) k_local = 1 do while (k_local.le.maxit.and. error.gt.tol)!$omp do do j=1,m; do i=1,n; uold(i,j) = u(i,j); enddo; enddo error = 0.0!$omp do reduction(+:error) do j..;do i..;resid=..;u(i,j)=..;error=..;enddo;enddo!$omp single error = sqrt(error)/dble(n*m)!$omp end single k_local = k_local + 1 enddo!$omp master k = k_local!$omp end master!$omp end parallel 123 OpenMP-Kurs Dieter an Mey Debugging OpenMP Programs - ASSURE 124 OpenMP-Kurs Dieter an Mey
63 Debugging OpenMP Programs - ASSURE 125 OpenMP-Kurs Dieter an Mey Debugging von OpenMP-Programmen Programmen mit TotalView (1) - generell Zum Verständnis (vgl. TotalView User s Guide): Jede Parallele Region wird in (mindestens) eine Routine ausgelagert ert (outlining) Die Namen der ausgelagerten Routinen basieren auf dem Namen der ursprünlichen Routine Normalerweise werden die globalen (shared( shared) ) Variablen in der Originalroutine verwaltet und die privaten in der ausgelagerten. Wenn der Master-Thread die Parallele Region betritt, werden die Slave- Threads generiert Beim Debugging kann man nicht schrittweise (s) die Parallele Region betreten, sondern nur in dem man auf einen zuvor gesetzten Breakpoint läuft (g) Beim Setzen des Breakpoints sollten man in der Regel in dem erscheinenden Dialog-Fenster All und OK anklicken. 126 OpenMP-Kurs Dieter an Mey
64 Debugging von OpenMP-Programmen Programmen mit TotalView (2) - Sun TotalView unterstützt derzeit nur Forte Developer 6 U1 Im Parallel Mode schalten die Sun-Compiler automatisch die Optimierungsstufe 3 ein, so dass ein Debugging nicht mehr möglich ist: Ausweg: Guide #!/bin/ksh. Forte61.init. totalview.init guidef90 c WG,-cmpo=i g prog.f90 guidef90 o a.out WG,-cmpo=i g prog.o export OMP_NUM_THREADS=2 totalview a.out 127 OpenMP-Kurs Dieter an Mey Parallele Programmierung für Shared-Memory Memory-Rechner mit OpenMP Automatische Parallelisierung Explizite Parallelisierung mit OpenMP Debugging mit Assure und TotalView Performance Tools GuideView, WorkShop Hybride Parallelisierung 128 OpenMP-Kurs Dieter an Mey
65 Jacobi-Algorithm - Guide Runtime Statistics Barrier 1 Barrier 2 Barrier 3 Barrier 4!$omp parallel private(resid,k_local) k_local = 1 do while (k_local.le.maxit.and. error.gt.tol)!$omp do do j=1,m; do i=1,n; uold(i,j) = u(i,j); enddo; enddo!$omp single error = 0.0!$omp end single!$omp do reduction(+:error) do j..;do i..;resid=..;u(i,j)=..;error=..;enddo;enddo!$omp single error = sqrt(error)/dble(n*m)!$omp end single k_local = k_local + 1 enddo!$omp master k = k_local!$omp end master!$omp end parallel 129 OpenMP-Kurs Dieter an Mey Jacobi-Algorithm - Guide Runtime Statistics Barrier 1 Barrier 2 Barrier 3 Barrier 4!$omp parallel private(re k_local = 1 do while (k_local.l!$omp do do j=1,m; do i=1!$omp single error = 0.0!$omp end single!$omp do reduction(+:erro do j..;do i..;resi!$omp single error = sqrt(err!$omp end single k_local = k_loca enddo!$omp master k = k_local!$omp end master!$omp end parallel 130 OpenMP-Kurs Dieter an Mey
66 Parallele Programmierung für Shared-Memory Memory-Rechner mit OpenMP Automatische Parallelisierung Explizite Parallelisierung mit OpenMP Debugging mit Assure und TotalView Performance Tools GuideView, PerView, CXperf,, Puma Hybride Parallelisierung 131 OpenMP-Kurs Dieter an Mey Übersetzen, Binden und Starten von hybriden Programmen auf Sun mpf90 -c -openmp driver_mpi.f90 mpf90 -c openmp jacobi_mpi_omp.f90 mpf90 -o openmp jacobi.exe \ driver_mpi.o jacobi_mpi_omp.o lmpi_mt export OMP_NUM_THREADS=2 echo "200,200\n0.8\n1.0\n1e-7\n1000" mprun -np 2 jacobi.exe # Oder mit Guide : guidef90 WGcompiler=mpf90 -c driver_mpi.f90 guidef90 WGcompiler=mpf90 -c jacobi_mpi_omp.f90 guidef90 WGcompiler=mpf90 -o jacobi.exe \ driver_mpi.o jacobi_mpi_omp.o lmpi_mt export OMP_NUM_THREADS=2 echo "200,200\n0.8\n1.0\n1e-7\n1000" mprun -np 2 jacobi.exe 132 OpenMP-Kurs Dieter an Mey
67 Übersetzen, Binden und Starten von hybriden Programmen auf HP guidef90 -c -I/opt/mpi/include +O3 +Odataprefetch +DS2.0 \ +DA2.0 driver_mpi.f90 guidef90 -c -I/opt/mpi/include +O3 +Odataprefetch +DS2.0 \ +DA2.0 jacobi_mpi_omp.f90 guidef90 -o jacobi.exe driver_mpi.o jacobi_mpi_omp.o \ +DA2.0 -L/opt/mpi/lib/pa1.1 lmtmpi export OMP_NUM_THREADS=2 echo "200,200\n0.8\n1.0\n1e-7\n1000" \ mpirun -np 2 jacobi.exe 133 OpenMP-Kurs Dieter an Mey Pi: Hybrid-Programm in Fortran90 (Auszug) call MPI_INIT( ierr ) call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr ) call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr ) do if ( myid.eq. 0 ) read (5,10001) n call MPI_BCAST(n,1,MPI_INTEGER,0,MPI_COMM_WORLD,ierr) if (n <= 0) exit h = 1.0d0 / n sum = 0.0d0!$omp parallel do reduction(+:sum) private(i,x) do i = myid+1, n, numprocs x = h * (DBLE(i)-0.5d0) sum = sum + f(x) mypi = h * sum call MPI_REDUCE(mypi,pi,1,MPI_DOUBLE_PRECISION,MPI_SUM,0, ) if (myid.eq. 0) write (6,10002) pi, ABS(pi-pi25dt) 134 call MPI_FINALIZE(ierr) OpenMP-Kurs Dieter an Mey
68 Jacobi-Verfahren: MPI-Version (1) #include "mpif.h" integer reqcnt,reqary(4),reqstat(mpi_status_size,4),status(mpi_status_size) double precision u(n,mlo:mhi),f(n,mlo:mhi) do while (k.le.maxit.and. error.gt. tol) * Copy new solution into old reqcnt = 0 if ( me.ne. 0 ) then * receive stripe mlo from left neighbour blocking reqcnt = reqcnt + 1 call MPI_IRECV( uold(1,mlo), n,, me-1,,reqary(reqcnt),ierr) end if if ( me.ne. np-1 ) then * receive stripe mhi from right neighbour blocking reqcnt = reqcnt + 1 call MPI_IRECV( uold(1,mhi), n,, me+1,.,reqary(reqcnt),ierr) end if if ( me.ne. np-1 ) then * send stripe mhi-1 to right neighbour async reqcnt = reqcnt + 1 call MPI_ISEND ( u(1,mhi-1), n,, me+1,,reqary(reqcnt),ierr) end if if ( me.ne. 0 ) then * send stripe mlo+1 to left neighbour async reqcnt = reqcnt + 1 call MPI_ISEND ( u(1,mlo+1), n,., reqary(reqcnt),ierr) end if do j=mlo+1,mhi-1; do i=1,n; uold(i,j) = u(i,j); enddo; enddo 135 OpenMP-Kurs Dieter an Mey call MPI_WAITALL ( reqcnt, reqary, reqstat, ierr) Jacobi-Verfahren: MPI-Version (2) * Compute stencil, residual, & update do j = mlo+1,mhi-1 do i = 2,n-1 * Evaluate residual resid = (ax*(uold(i-1,j) + uold(i+1,j)) & + ay*(uold(i,j-1) + uold(i,j+1)) & + b * uold(i,j) - f(i,j))/b * Update solution u(i,j) = uold(i,j) - omega * resid * Accumulate residual error error = error + resid*resid enddo error_local = error call MPI_ALLREDUCE ( error_local, error,1,,mpi_sum,) * Error check k = k + 1 error = sqrt(error)/dble(n*m) * enddo! End iteration loop 136 OpenMP-Kurs Dieter an Mey
69 Jacobi-Verfahren: hybride OpenMP+MPI-Version do while (k.le.maxit.and. error.gt. tol) error = 0.0 * Copy new solution into old call MPI_IRECV call MPI_IRECV call MPI_ISEND call MPI_ISEND!$omp do parallel do j=mlo+1,mhi-1; do i=1,n; uold(i,j) = u(i,j); enddo; enddo call MPI_WAITALL * Compute stencil, residual, & update!$omp parallel!$omp do private(resid) reduction(+:error) do j = mlo+1,mhi-1; do i = 2,n-1 resid = u(i,j) = uold(i,j) - omega * resid error = error + resid*resid ; enddo!$omp nowait!$omp end parallel error_local = error call MPI_ALLREDUCE ( error_local, error,1,,mpi_sum,) * k = k + 1 error = sqrt(error)/dble(n*m) enddo! End iteration loop 137 OpenMP-Kurs Dieter an Mey Vielteilchenproblem AIXCCAD auf hpcline (16 Rechenknoten mit je 2 Prozessoren) 138 OpenMP-Kurs Dieter an Mey
70 TFS auf HP V-Class V (16 Shared-Memory Memory-Prozessoren) 139 OpenMP-Kurs Dieter an Mey OpenMP - Informationen Das OpenMP-Standardisierungsgremium Fortran und C Application Program Interfaces (APIs( APIs) openmp.orgorg The Community of OpenMP Users, Researchers,, Tool Developers and Providers compunity.orgorg OpenMP-Kurse im Netz Tutorial by the OPENMP ARB at SC University of Minnesota Boston University OpenMP hier: rz.rwth-aachen.de/.de/sw/prog/openmp/ Vortragsfolien: Literatur: Rohit Chandra,, et.al. Parallel Programming in OpenMP Morgan Kaufmann, ISBN OpenMP-Kurs Dieter an Mey
Beispiel: Schleifenparallelisierung
Beispiel: Schleifenparallelisierung for (i = 0; i high) { printf ( Exiting during iteration %d\n,i); break; for (j=low;j
Master-Thread führt Programm aus, bis durch die Direktive
OpenMP seit 1998 Standard (www.openmp.org) für die Shared-Memory Programmierung; (Prä-)Compiler für viele Systeme kommerziell oder frei (z.b. Omni von phase.hpcc.jp/omni) verfügbar Idee: automatische Generierung
Threads und OpenMP. Frank Mietke <[email protected]> Cluster- & Gridcomputing Frank Mietke 7/4/04
Threads und OpenMP Frank Mietke 1 Ziel der Vorlesungen Einführung in Threads Programmierung mit Threads Einführung in OpenMP Programmierung mit OpenMP 2 Was ist
6. Der OpenMP Standard. Direktiven-basiertes API zur Programmierung von Parallelrechnern mit gemeinsamem Speicher für FORTRAN, C und C++
6. Der OpenMP Standard Direktiven-basiertes API zur Programmierung von Parallelrechnern mit gemeinsamem Speicher für FORTRAN, C und C++ OpenMP Programmiermodell OpenMP Direktiven basieren in C and C++
1. Einführung in OpenMP
1. Einführung in OpenMP Übersicht Einführung Homogene und inhomogene Arbeitsverteilung Rekursive Parallelität Beispiele Parallele Programmierung 1 Nicolas Maillard, Marcus Ritt 1 Überblick OpenMP: Vereinfachte
OpenMP - Threading- Spracherweiterung für C/C++ Matthias Klein, Michael Pötz Systemprogrammierung 15. Juni 2009
- Threading- Spracherweiterung für C/C++ Matthias Klein, Michael Pötz Systemprogrammierung 15. Juni 2009 Grundlagen der Parallelen Programmierung Hardware Threads vs. Prozesse Kritische Abschnitte Lange
Vorlesung Parallelrechner und Parallelprogrammierung, SoSe 2016
Paralleles Programmieren mit und MPI Vorlesung Parallelrechner und Parallelprogrammierung, SoSe 2016 Steinbuch Centre for Computing Hartmut Häfner, Steinbuch Centre for Computing (SCC) STEINBUCH CENTRE
Parallele Programmierung mit OpenMP
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
OpenMP. Viktor Styrbul
OpenMP Viktor Styrbul Inhaltsverzeichnis Was ist OpenMP Warum Parallelisierung Geschichte Merkmale von OpenMP OpenMP-fähige Compiler OpenMP Ausführungsmodell Kernelemente von OpenMP Zusammenfassung Was
Praktikum: Paralleles Programmieren für Geowissenschaftler
Praktikum: Paralleles Programmieren für Geowissenschaftler Prof. Thomas Ludwig, Hermann Lenhart, Ulrich Körner, Nathanael Hübbe [email protected] OpenMP Einführung I: Allgemeine Einführung Prozesse
Parallele Programmierung mit OpenMP
Parallele Programmierung mit OpenMP Wolfgang Dautermann FH Joanneum Chemnitzer Linuxtage 2008 1 Motivation 2 OpenMP Übersicht 3 Hello World - der erste Code 4 OpenMP-Compilerdirektiven Threaderzeugung
Einige Grundlagen zu OpenMP
Einige Grundlagen zu OpenMP Stephanie Friedhoff, Martin Lanser Mathematisches Institut Universität zu Köln 22. Juni 2016 Überblick Was ist OpenMP? Basics Das OpenMP fork-join-modell Kompilieren und Ausführen
Konzepte der parallelen Programmierung
Fakultät Informatik, Institut für Technische Informatik, Professur Rechnerarchitektur Konzepte der parallelen Programmierung Parallele Programmiermodelle Nöthnitzer Straße 46 Raum 1029 Tel. +49 351-463
Programmieren mit OpenMP
Programmieren mit OpenMP Dr. Victor Pankratius David J. Meder IPD Tichy Lehrstuhl für Programmiersysteme KIT die Kooperation von Forschungszentrum Karlsruhe GmbH und Universität Karlsruhe (TH) Inhalt Was
Parallele Programmierung mit OpenMP
Parallele Programmierung mit OpenMP Wolfgang Dautermann FH Joanneum Chemnitzer Linuxtage 2009 1 Motivation 2 OpenMP Übersicht 3 Hello World - der erste Code 4 OpenMP-Compilerdirektiven Threaderzeugung
Automatische Parallelisierung
MPI und OpenMP in HPC Anwendungen findet man immer häufiger auch den gemeinsamen Einsatz von MPI und OpenMP: OpenMP wird zur thread-parallelen Implementierung des Codes auf einem einzelnen Rechenknoten
Anleitung für zwei Fortran-Openmp-Beispiele auf der NWZSuperdome
Anleitung für zwei Fortran-Openmp-Beispiele auf der NWZSuperdome (Timo Heinrich, [email protected]) Inhaltsverzeichnis: 0.Einleitung 1.Teil: Helloworldprogramm 1.1 Quellcode: Helloworld.f90 1.2
4. Parallelprogrammierung
4. Parallelprogrammierung AlDaBi Prak4kum David Weese 2010/11 Enrico Siragusa WS 2011/12 Inhalt Einführung in Parallelität OpenMP Bemerkungen zur P- Aufgabe EINFÜHRUNG IN PARALLELITÄT Folien z.t. aus VL
der RWTH Aachen Konfiguration und parallele Programmierung Dieter an Mey
Der Sun Fire SMP-Cluster der RWTH Aachen Konfiguration und parallele Programmierung Dieter an Mey http://www.rz.rwth-aachen.de/hpc e-mail: [email protected] Inhalt Das Sun Fire SMP-Cluster der RWTH
Parallelisierung der Vektoraddition 149
OpenMP 148 OpenMP ist ein seit 1997 bestehender Standard mit Pragma-basierten Spracherweiterungen zu Fortran, C und C++, die eine Parallelisierung auf MP-Systemen unterstützt. Pragmas sind Hinweise an
Lehrstuhl für Datenverarbeitung. Technische Universität München. Leistungskurs C++ Multithreading
Leistungskurs C++ Multithreading Threading mit Qt Plattformübergreifende Thread-Klasse Sehr einfach zu benutzen Leider etwas schlecht dokumentiert Leistungskurs C++ 2 QThread Plattformübergreifende Thread-Klasse
ÜBUNGS-BLOCK 7 LÖSUNGEN
ÜBUNGS-BLOCK 7 LÖSUNGEN Aufgabe 1: Gegeben ist folgender Code: Auto[] array = new Auto[3]; // Alle Autos im Array tunen: for (int i = 1; i
Syntax und Kontrollstrukturen
Syntax und Kontrollstrukturen Praktikum C-Programmierung Eugen Betke, Nathanael Hübbe, Michael Kuhn, Jakob Lüttgau, Jannek Squar Wissenschaftliches Rechnen Fachbereich Informatik Universität Hamburg 2018-10-29
4. Parallelprogrammierung. AlDaBi Praktikum
4. Parallelprogrammierung AlDaBi Praktikum Inhalt Einführung in Parallelität OpenMP Bemerkungen zur P-Aufgabe Einführung in Parallelität Folien z.t. aus VL Programmierung von Hardwarebeschleunigern von
4. Parallelprogrammierung
4. Parallelprogrammierung AlDaBi Prak4kum David Weese 2010/11 René Rahn WS 2014/15 Inhalt Einführung in Parallelität OpenMP Bemerkungen zur P- Aufgabe Einführung in Parallelität Folien z.t. aus VL Programmierung
Repetitorium Programmieren I + II
Repetitorium Programmieren I + II Stephan Gimbel Johanna Mensik Michael Roth 6. März 2012 Agenda 1 Operatoren 2 Datentypen Gleitpunkt Zahl Typkonvertierung 3 Strommanipulatoren 4 Bedingungen if-else switch-case
http://www.uniregensburg.de/edv/kurs_info/brf09510/hpc/openmp/openmp.dvi
Open Multi Processing Dipl. Math. F. Braun Universität Regensburg Rechenzentrum http://www.uniregensburg.de/edv/kurs_info/brf09510/hpc/openmp/openmp.html http://www.uniregensburg.de/edv/kurs_info/brf09510/hpc/openmp/openmp.pdf
Algorithmen und Datenstrukturen
Algorithmen und Datenstrukturen Dynamische Datenobjekte Pointer/Zeiger, Verkettete Liste Eigene Typdefinitionen 1 Zeigeroperatoren & und * Ein Zeiger ist die Speicheradresse irgendeines Objektes. Eine
Parallele Programmierung in C++ mit OpenMP
Parallele Programmierung in C++ mit OpenMP Lukas Wendt Hochschule für Angewandte Wissenschaften Hamburg [email protected] 31. Januar 2017 Zusammenfassung In den letzten Jahren haben sich Mehrkernsystem
Shared-Memory Parallelisierung von C++ Programmen
Shared-Memory Parallelisierung von C++ Programmen 9. Februar 2006 1 Übersicht Ergebnisse Zusammenfassung 2 3 Übersicht Ergebnisse Zusammenfassung Übersicht Verbreitete Parallelisierungstechniken für Shared-Memory:
Paralleles Programmieren mit OpenMP und MPI OpenMP-Übungsaufgaben Steinbuch Centre for Computing
Paralleles Programmieren mit OpenMP und MPI OpenMP-Übungsaufgaben Steinbuch Centre for Computing und Universität Karlsruhe (TH) www.scc.kit.edu Parallele Berechnung von PI program compute_pi integer integer,
2 Teil 2: Nassi-Schneiderman
2 Teil 2: Nassi-Schneiderman Wie kann man Nassi-Schneiderman in einer objektorientierten Sprache verwenden? Jedes Objekt besitzt Methoden, welche die Attribute des Objektes verändern. Das Verhalten der
2 Dieter an Mey, SunHPC 2002, Einleitung 10000,000 1000,000 100,000 10,000 1,000 0,100 0,010. 0,001 Cyber 175 Cyber 205
Inhalt Das Sun Fire SMP-Cluster: Dieter an Mey Rechen- und Kommunikationszentrum der RWTH Aachen 12. März 2002 anmey@rz rz.rwth-aachen.de http://www www.rz.rwth-aachen.de [/hpc hpc[/ [/sun]] -Optimierung
Betriebssysteme Teil 3: Laufzeitsystem für Programme
Betriebssysteme Teil 3: Laufzeitsystem für Programme 23.10.15 1 Literatur [3-1] Stack: http://fbim.fh-regensburg.de/~hab39652/pg1/skriptum/ ausdruecke/maschinenmodell.html [3-2] https://de.wikipedia.org/wiki/dynamischer_speicher
Multicore Parallelismus! in modernen CPUs
Multicore Parallelismus! in modernen CPUs Johannes Hofmann, 21.5.2014 Seminar Architekturen von Multi- und Vielkern-Prozessoren Universität Erlangen-Nürnberg Lehrstuhl für Rechnerarchitektur Informatik
Evaluation. Einleitung. Implementierung Integration. Zusammenfassung Ausblick
Christopher Schleiden Bachelor Kolloquium 15.09.2009 Einleitung Evaluation Implementierung Integration Zusammenfassung Ausblick Einleitung laperf Lineare Algebra Bibliothek für C++ Möglichkeit zur Integration
1.4. Funktionen. Objektorientierte Programmierung mit C++
mehrfache Deklarationen sind erlaubt für jede Funktion muss es (GENAU) eine Definition geben, ansonsten linker error [the one definition rule ODR] Deklarationen in *.h - Files, Definitionen in *.cpp -
Kurzeinführung in C99
Kurzeinführung in C99 Institut für Numerische Simulation Rheinische Friedrich-Wilhelms-Universität Bonn Oktober 2013 Überblick 1 Compiler und Editoren - Was wird benötigt um ein Programm zu erstellen 2
Einleitung Entwicklung in C Hello-World! Konstrukte in C Zusammenfassung Literatur. Grundlagen von C. Jonas Gresens
Grundlagen von C Jonas Gresens Proseminar C Grundlagen und Konzepte Arbeitsbereich Wissenschaftliches Rechnen Fachbereich Informatik Fakultät für Mathematik, Informatik und Naturwissenschaften Universität
2Binden 3. und Bibliotheken
3 Vom C-Programm zum laufenden Prozess 3.1 Übersetzen - Objektmodule 1Übersetzen 3. - Objektmodule (2) Teil III 3Vom C-Programm zum laufenden Prozess 2. Schritt: Compilieren übersetzt C-Code in Assembler
Einführung Programmierpraktikum C Michael Zwick
Einführung Programmierpraktikum C Michael Zwick Vorlesung, Übung & Fragestunde Dr.-Ing. Michael Zwick Raum Z945 [email protected] (089) 289 23609 Tutorium Ab Dienstag: Auswahl Tutoriumsplatz auf www.ldv.ei.tum.de/lehre/computertechnik
Einstieg in die Informatik mit Java
1 / 41 Einstieg in die Informatik mit Java Weitere Anweisungen Gerd Bohlender Institut für Angewandte und Numerische Mathematik Gliederung 2 / 41 1 Überblick 2 Verbundanweisung 3 Bedingte Anweisung 4 Auswahlanweisung
Zum Aufwärmen nocheinmal grundlegende Tatsachen zum Rechnen mit reelen Zahlen auf dem Computer. Das Rechnen mit Gleitkommazahlen wird durch den IEEE
Zum Aufwärmen nocheinmal grundlegende Tatsachen zum Rechnen mit reelen Zahlen auf dem Computer. Das Rechnen mit Gleitkommazahlen wird durch den IEEE 754 Standard festgelegt. Es stehen sogenannte einfach
Threads. Netzwerk - Programmierung. Alexander Sczyrba Jan Krüger
Netzwerk - Programmierung Threads Alexander Sczyrba [email protected] Jan Krüger [email protected] Übersicht Probleme mit fork Threads Perl threads API Shared Data Mutexes
Gedächtnis. Während der Abarbeitung eines Algorithmus müssen sich Dinge gemerkt werden bzw. auf Dingen wird gerechnet. Zugriff.
Gedächtnis Während der Abarbeitung eines Algorithmus müssen sich Dinge gemerkt werden bzw. auf Dingen wird gerechnet Hauptspeicher 38265 Telefon CPU Gedächtnis Vorlesender Zugriff Verarbeitungseinheit
Systemprogrammierung
Systemprogrammierung 3Vom C-Programm zum laufenden Prozess 6. November 2008 Jürgen Kleinöder Universität Erlangen-Nürnberg Informatik 4, 2008 SS 2006 SOS 1 (03-Pro.fm 2008-11-06 08.52) 3 Vom C-Programm
Einstieg in die Informatik mit Java
1 / 47 Einstieg in die Informatik mit Java Anweisungen Gerd Bohlender Institut für Angewandte und Numerische Mathematik Gliederung 2 / 47 1 Ausdrucksanweisung 2 Einfache Ausgabeanweisung 3 Einfache Eingabeanweisung,
Multi- und Many-Core
Multi- und Many-Core Benjamin Warnke Arbeitsbereich Wissenschaftliches Rechnen Fachbereich Informatik Fakultät für Mathematik, Informatik und Naturwissenschaften Universität Hamburg 2016-12-15 Benjamin
Programmieren in C. Funktionen mit Zeigern und Adressen. Prof. Dr. Nikolaus Wulff
Programmieren in C Funktionen mit Zeigern und Adressen Prof. Dr. Nikolaus Wulff ByValue versus byreferenz C übergibt immer Kopien der Variablen an Funktionen. Es ist nur dann möglich die Werte von Variablen
Angewandte Mathematik und Programmierung
Angewandte Mathematik und Programmierung Einführung in das Konzept der objektorientierten Anwendungen zu mathematischen Rechnens WS 2013/14 Operatoren Operatoren führen Aktionen mit Operanden aus. Der
Propädeutikum. Dipl.-Inf. Frank Güttler
Propädeutikum 2015 Vorbereitungskurs Informatikstudium Erfolgreich Studieren Programmieren (C-Kurs) [email protected] Universität Leipzig Institut für Informatik Technische Informatik
Einführung in den Einsatz von Objekt-Orientierung mit C++ I
Einführung in den Einsatz von Objekt-Orientierung mit C++ I ADV-Seminar Leiter: Mag. Michael Hahsler Syntax von C++ Grundlagen Übersetzung Formale Syntaxüberprüfung Ausgabe/Eingabe Funktion main() Variablen
Programmiersprachen Einführung in C
Programmiersprachen Einführung in C Teil 2: Prof. Dr. Unser erstes C-Programm int main (int argc, char *argv[]) int i; int sum = 0; for (i = 0; i
Wintersemester Maschinenbau und Kunststofftechnik. Informatik. Tobias Wolf Seite 1 von 29
Kapitel 2 Einführung in C++ Seite 1 von 29 C++ Zeichensatz - Buchstaben: a bis z und A bis Z. - Ziffern: 0 bis 9 - Sonderzeichen: ; :,. # + - * / % _ \! < > & ^ ~ ( ) { } [ ]? Seite 2 von 29 Höhere Elemente
RO-Tutorien 15 und 16
Tutorien zur Vorlesung Rechnerorganisation Tutorienwoche 2 am 04.05.2011 1 Christian A. Mandery: KIT Universität des Landes Baden-Württemberg und nationales Grossforschungszentrum in der Helmholtz-Gemeinschaft
Programmiertechnik. Teil 4. C++ Funktionen: Prototypen Overloading Parameter. C++ Funktionen: Eigenschaften
Programmiertechnik Teil 4 C++ Funktionen: Prototypen Overloading Parameter C++ Funktionen: Eigenschaften Funktionen (Unterprogramme, Prozeduren) fassen Folgen von Anweisungen zusammen, die immer wieder
C++ Teil 2. Sven Groß. 16. Apr IGPM, RWTH Aachen. Sven Groß (IGPM, RWTH Aachen) C++ Teil Apr / 22
C++ Teil 2 Sven Groß IGPM, RWTH Aachen 16. Apr 2015 Sven Groß (IGPM, RWTH Aachen) C++ Teil 2 16. Apr 2015 1 / 22 Themen der letzten Vorlesung Hallo Welt Elementare Datentypen Ein-/Ausgabe Operatoren Sven
Memory Models Frederik Zipp
Memory Models Frederik Zipp Seminar: Programmiersprachen für Parallele Programmierung (SS 2010) Fakultät für Informatik - IPD SNELTING LEHRSTUHL PROGRAMMIERPARADIGMEN 1
