Upload
others
View
1
Download
0
Embed Size (px)
Citation preview
MPI � Message Passing Interface
Dipl. Math. F. Braun
Universität Regensburg � Rechenzentrum
https://homepages.uni-
regensburg.de/~brf09510/EDV/kurs_info/brf09510/hpc/mpi.html
https://homepages.uni-
regensburg.de/~brf09510/EDV/kurs_info/brf09510/hpc/mpi.pdf
https://homepages.uni-
regensburg.de/~brf09510/EDV/kurs_info/brf09510/hpc/mpi.dvi
22. Oktober 2019
KAPITEL 1
High performance computing
1. Übungsaufgaben
3
4 1. HIGH PERFORMANCE COMPUTING
WS 2018/19
1. Schreiben Sie ein Hello-World-Programm mit MPI
2. Messen Sie Latenz und Bandbreite mit Nachrichten der Länge m.a) Nachricht zwischen 2 Prozessenb) Mehrfachnachricht zur Verhinderung von Starte�ektenc) Berechnung von Latenz b und Bandbreite 1
a aus dem Modell t = am+ b durch lineare Regressiond) Paarweise Werte mit vier Prozessen auf je 2 Cores und 2 Rechnern
3. Ringtausch
4. Ringtausch mit Strukturen
5. Reduktion in gaussp3.c (Pivotsuche)
siehe auch:
https://homepages.uni-regensburg.de/~brf09510/EDV/kurs_info/brf09510/hpc/ueb.pdf
https://homepages.uni-regensburg.de/~brf09510/EDV/kurs_info/brf09510/hpc/ueb2.pdf
3. GRÜNDE FÜR PARALLELES PROGRAMMIEREN 5
2. Literatur
MPI-Standard: http://www.mpi-forum.org/docs/http://www.mpi-forum.org/docs/mpi-3.1/mpi31-report.pdf
Ein hervorragendes Einzelwerk: Heiko Bauke, Stephan Mertens: Clustercomputing, ISBN-13: 978-3540422990
Weitere Literatur zum High performance computing: https://homepages.uni-regensburg.de/~brf09510/EDV/kurs_info/brf09510/hpc/Literatur.html
3. Gründe für paralleles Programmieren
3.1. Das Mooresche Gesetz. http://de.wikipedia.org/wiki/Mooresches_Gesetz
Nach dem Mooresche Gesetz (Moore's Law, 1965) verdoppelt sich die Komplexität integrierter Schaltkreise etwaalle zwei Jahre (18 Monate). Seit etwa 2005 ist dieses exponentielle Wachstum vorbei.
2003 wurde zwar noch argumentiert, dass das Mooresche Gesetz noch 10 Jahre gelten wird. Das hat sich nichterfüllt. http://news.cnet.com/2100-1001-984051.html
Diskussion der Graphik https://homepages.uni-regensburg.de/~brf09510/EDV/kurs_info/brf09510/png/
Auch die Leistungsdichte auf der Chip�äche begrenzt das weitere Wachstum:http://research.ac.upc.edu/pact01/keynotes/isaac.pdf, Seite 30
Absolute Rechenleistungsgrenze bei sequentiellen single-Core-Prozessoren: ca 109 FlOp/s.
Derzeit wird die Rechenleistung weitgehend mit dem Linpack-Benchmark gemessen. Aktuell ist der HPL; diebeiden älteren Benchmarks Linpack1000 und Linpack100 sind nicht mehr zeitgemäÿ.
http://www.netlib.org/benchmark/hpl/
http://www.netlib.org/benchmark/linpackd
http://www.netlib.org/benchmark/1000d
Der in die Jahre gekommene HPL verwendet die direkte Lösung eines linearen Gleichungssystems mit einerRechenzeit von O(n3). Das gewichtet die Rechenleistung sehr stark gegenüber der Speicherzugri�sleistung.Moderne iterative Solver benötigen jedoch nur O(n2) Rechenschritte. Hier begrenzt auch die Speicherzugri�s-leistung die Gesamtleistung der Anlage. Diese Entwicklung versuchen neuere Benchmarks wie der HPCG zuberücksichtigen. Ein zweiter Grund für einen neueren Benchmark ist der allen Benchmarks eigene E�ekt, dassdie Hard- und Software-Hersteller ihre Produkte an den Benchmark anpassen und die eigentlichen Anwendungenaus dem Blick verlieren. Je länger ein Benchmark verwendet wird, umso gröÿer wird dieser E�ekt.
https://software.sandia.gov/hpcg/
3.2. Stream Benchmark. Die Prozessorleistung entwickelt sich wesentlich schneller als die Speicherband-breite (und eigentlich als alle Bandbreiten).
http://www.cs.virginia.edu/stream/
Diskussion: der stream-Benchmark kann sequentiell und mit mehreren Threads durchgeführt werden; daher sindMulticore-Prozessoren bei der Speicherbandbreite berücksichtigt.
Typische Ergebnisse: pc58685 3 GB/s, rz412 12 GB/s, Athene 2017 10 GB/s, 15 GB/s (2 p), 28 GB/s (4 p), 48GB/s (8 p), 71 GB/s (16 p), 66 GB/s (32 p).
Ergebnis: CPUs müssen �ohne� Speicherzugri� rechnen, wenn sie nicht dauernd warten sollen!
3.3. Paralleles Programmieren. Der Bedarf an Rechenleistung wächst jedoch weiter. Ein Ausweg scheintderzeit nur in parallelem Programmieren zu liegen. Dabei werden mehrere Einzel-CPUs mit begrenzter Leistungzu einem leistungsfähigerem Gesamtsystem zusammengeschaltet.
Eventuell sehen wir die ersten Anzeichen einer Verlangsamung des Leistungszuwachses; Bedarf und Leistungkönnten in Zukunft auseinanderkla�en.
siehe Kommentare zur Top500/Juni2015
http://www.top500.org/blog/slides-highlights-of-the-45th-top500-list/
In jedem Fall werden die Beschleuniger immer wichtiger:
6 1. HIGH PERFORMANCE COMPUTING
siehe selbe Liste.
Green Computing ist auf dem Vormarsch, vor allem in Japan (8 erste Plätze von den ersten 20). Hier verweistder Xeon E5-2618Lv3 8C 2.3GHz und seine engen Verwandten (Haswell) die Konkurrenz auf Plätze unterhalbder Nummer 15. Beschleuniger phi taucht auf Platz 12 auf, Nvidia K20 auf Platz 13:
http://www.green500.org/lists/green201506&green500from=1&green500to=100
4. Übersicht über paralleles Programmieren
Lit.: Edinburg, Decomposing, MPI
4.1. Hardware Architekturmodelle. Nach Flynn können Rechnerarchitekturen mit dem folgendemSchema klassi�ziert werden:
Tabelle 1. Flynn:
SD (single data) MD (multiple data)SI (single instruction) SISD SIMDMI (multiple instruction) MISD MIMD
SISD: (Flynn); Single Instruction Single Data; der klassische sequentielle von-Neumann-Rechner.
SIMD: (Flynn); Single Instruction Multiple Data; Ein Befehlswerk holt und analysiert Befehle. Die eigentlicheAusführung wird von einem Array mehrerer Prozessoren übernommen, die dann mit mehreren Datenströmenunabhängig dieselbe Befehlssequenz durchführen können. Beispiele sind klassische Vektorrechner wie die CDCStar-100 oder moderne Graphikprozessoren wie GeForce von Nvidia.
MISD: (Flynn); Multiple Instruction Single Data; eigentlich über�üssige Einstufung, die nur zur Vervollstän-digung von SISD, SIMD, MISD, MIMD eingeführt wurde. Um dem Ausdruck nachträglich doch noch Sinn zuverleihen, wurden hier Pipeline-Architekturen, die ja hintereinander mit demselben Datum arbeiten, subsum-miert. Eigentlich jedoch liegt aber nach jedem Pipeline-Schritt ein anderes modi�ziertes Datum vor. Weiterwerden hier fehlerredundante Mehrfacharchitekturen genannt, wo mehrere Prozessoren mit demselben Datumrechnen, deren Ergebnis nur akzeptiert wird, wenn es überall gleich ist.
MIMD: (Flynn); Multiple Instruction Multiple Data; mehrere unabhängige Prozessoren bearbeiten mehrereBefehlsströme mit unabhängigen Daten.
Die Flynnsche Klassi�zierung di�erenziert zu wenig die eigentlichen Parallelrechner (MIMD). Deshalb wird dieseGruppe zusätzlich nach der Speicherarchitektur di�erenziert.
Tabelle 2. mimd:
SMP symmetric multiprocessor gemeinsamer Speicher für alle ProzessorenNUMA non uniform memory access jedem Rechner ist ein Teil des gemeinsamen
Speichers für schnellen Zugri� zugeordnetccNUMA cache coherent NUMADMP distributed memory processor jeder Rechner hat eigenen Speicher
alle Rechner kommunizieren über ein Datennetz
Ältere Bezeichnungen für SMP sind SM/SHMEM (shared memory). SMP kann man auch als Acronym fürshared memory processor lesen.
Heutige Parallelrechner sind meistens Hybridrechner, in denen mehrere Architekturmodelle vereinigt sind. EinLinuxcluster ist ein DMP-Rechner aus vielen Knoten mit einem schnellen Verbindungsnetz. Jeder Knoten enthältmehrere Chips mit gemeinsamem oder getrenntem Speicher. Jeder einzelne Chip ist heute eine Multicore-CPUmit gemeinsamem Speicher, also ein SMP-Rechner. Diese Chips können oft mehr als eine Gleitpunktoperationgleichzeitig mit den SSX-Registern durchgeführen und haben damit Eigenschaften eines klassischen Vektorrech-ners. Enthält der Cluster zusätzliche Graphikprozessoren, dann können auch diese als klassischer Vektorrechner(SIMD) interpretiert werden.
Schlieÿlich haben die Prozessoren Eigenschaften, die der Programmierer nicht direkt steuern kann, die aber diePerformance eines Programms stark beein�ussen. Pipelining und Caches müssen beim Programmieren beachtetwerden, um die verfügbare Leistung abrufen zu können. Man spricht von Single-node-Optimierung.
6. PARALLELPROGRAMMIERUNG IN DER NUSSSCHALE 7
4.2. Parallele Programmiermodelle. Die Programmiermodelle sind wesentlich einfacher. Man unter-scheidet hier nur
Tabelle 3. Software Programmiermodelle:
Modell Erklärung BeispieleThread-parallel pthreads oder openMPMessage passing PVM oder MPIPGAS partitioned global address space UPC, coarray-Fortran oder TitaniumVektorrechner CudaDarpa Chapel, X10 oder Fortress
Nicht jeder Algorithmus ist für jedes Programmiermodell geeignet.
Beispiele: Sortierverfahren.
5. Performancemaÿe
5.1. Grundbegri�e.
5.2. Amdahls Gesetz. https://homepages.uni-regensburg.de/~brf09510/EDV/kurs_info/brf09510/hpc/amdgus.pdf
BAU06, Seite 10
5.3. Gustafsons Gesetz. BAU06, Seite 16
5.4. Latenz. RAU07, Seite 65
5.5. Bandbreite. RAU07, Seite 65
6. Parallelprogrammierung in der Nussschale
6.1. Vom sequentiellen zum parallelen Programm. Sequentielle Programme:Datenbeschreibung (welchen Daten werden verarbeitet - Variable)Algorithmusbeschreibung (Sequenz, Alternative, Schleife - was wird wann gemacht)Programmorganisation (wie werden groÿe Probleme formuliert)
Parallele Programme:Individualisierung (wer bin ich)Organisation (wer macht was wann)Datenaustausch (wer sendet wann; wer empfängt wann)Synchronisierung (was muss auf verschiedenen Rechnern in de�nierter Reihenfolge geschehen)
6.2. Techniken jeder parallelen Programmierumgebung. Langläufer: regelmäÿig Stützpunkte schrei-ben, um Programme nach Abbruch ohne groÿen Rechenzeitverlust wieder aufnehmen zu können.
6.3. Kontrolle der Leistung: Zeitmessung. Programme werden parallel formuliert, um hohe Rechen-leistung zu erzielen. Ob ein konkretes Programm diese Leistung abruft, muss kontrolliert werden. Dazu benötigtman präzise Zeitmessungen.
MPI bietet genaue Zeitmessungen an, so dass weitere Messysteme (Posix, C/C++) unnötig sind.
KAPITEL 2
Einführung in das MPI (Message Passing Interface)
Das MPI ist ein standardisiertes Bibliotheks-Interface mit Funktionen, die von vielen Sprachen aufgerufen wer-den können: Fortran, C, C++. . . Die Erfahrung mit älteren Vorläufern wurden berücksichtigt und Veränderungenerfolgen vorsichtig und nach intensiven Diskussionen im MPI-Forum. Das MPI-Forum hat Firmen, Organisa-tionen, Wissenschaftler und andere Einzelpersonen, tri�t sich regelmäÿig und fällt Entscheidungen nach festenRegeln. Prinzipiell kann jeder Interessierte teilnahmen.
1. Geschichte
MPI: siehe 1 auf Seite 10
Open MPI (OMPI, nicht OpenMPI): siehe 2 auf Seite 11siehe http://www.open-mpi.org/papers/sc-2013/
MPICH: siehe 3 auf Seite 11 siehe http://trac.mpich.org/projects/mpich/roadmap
2. Eigenschaften
Charakterisierung von MPI:
1. MPI ist eine standardisierte Library-De�nition. Implementierer stellen die eigentlichen Libraries bereit.
2. MPI wurde für DMP entwickelt, arbeitet jedoch auch gut mit anderen Hardwaremodellen.
3. MPI greift (anders als die PGAS-Sprachen) nicht in die Sprachde�nition ein. MPI-Programme können mitjedem Compiler übersetzt werden.
4. MPI hat die Ziele: funktionell, portabel, hardwareunabhängig. MPI-Programme sollen e�zient sein. Hardware-Eigenschaften sollen mit MPI nutzbar sein.
9
10 2. EINFÜHRUNG IN DAS MPI (MESSAGE PASSING INTERFACE)
Tabelle 1. Zeittafel MPI:
N-cube (Caltech)P4 (Argonne)PICLLAMISIS (Cornell)
1989 PVM (Par. virt. machineOak Ridge)PThreadOpenMP
1992 Supercomputing 19921992 Beginn der MPI-Entwick.11'1992, 2'1993, 11'1993 Draft5.5.1994 MPI 1.0 (236 S) Static at runtime
Point-PointCollective communicationGroups, Contexts, CommunicatorsProcess topologiesEnvironmentPro�ling interfaceC/Fortran 77
12.6.1995 MPI 1.1 (239 S) Fehlerkorrekturen18.7.1997 MPI 1.2 (= MPI-1) Version identi�cation18.7.1997 MPI-2 Journal of development30.5.2008 MPI 1.3 (245 S) Fehlerkorrekturen1998, 15.11.2003 MPI 2.0 (370 S) Parallel IO
Dynamic process managementRemote memory operationsOne sided communicationFortran 90/ C++Creation of new MPI processesCommunication to other processesMPI_Comm_spawn, accept, connect, join
2002 Erste Impl. v. MPI 2.023.6.2008 MPI 2.1 (586 S)4.9.2009 MPI 2.2 (647 S) Korrekturen
C++ entsorgt (entgültig?)11'2010 MPI-3 Draft21.9.2012 MPI-3 (852 S)
Nonblocking collectivesSparse collectivesOne sided communicationPerformance tool supportFortran 2008C++ entgültig entsorgtWeitere deprecated features (MPI_UB) entsorgt
4.6.2015 MPI 3.1 (836 S)? MPI 4
2. EIGENSCHAFTEN 11
Tabelle 2. Zeittafel Open MPI:
Vorgänger: Ft-, LA-, LAM, PACX-MPI2004 Start2005 Open MPI 1.0 YAMPI (yet another. . . )20.3.2014 Open MPI 1.7 MPI-326.9.2014 Open MPI 1.8 MPI-312.7.2016 Open MPI 2.0 MPI-313.9.2016 Open MPI 2.1 MPI-312.9.2016 Open MPI 3.0 MPI-3
Tabelle 3. Zeittafel MPICH:
MPICH1 MPI-12001-2012 MPICH2 MPI-22008 MPICH2 1.12012 MPICH 3.0 MPI-32014 MPICH 3.1.315.2.2016 MPICH 3.2
Base of: IFM, Intel, Cray, MS, Myricom, MVAPICH. . .
KAPITEL 3
MPI-Installationen (Schwerpunkt: an der Uni. R. verfügbare Inst.)
1. MPI auf der Athene
1. Benutzeraccount (Antrag)
2. Athene nur im Netz der Uni zugänglich. Von auÿen zweistu�g, erst ssh [email protected],dann Athene-login
3. Von Windows putty.exe (interaktive session) und pscp.exe (Dateitransfer)
4. Fertige Dateien zur Athene: [p]scp filename bbbnnnnn@athene:/home/bbbnnnn/Rücktransfer: [p]scp bbbnnnnn@athene:/home/bbbnnnn/filename .
5. Athene: ssh bbbnnnnn@athene
6. AthOS:De�nition: class User-ID, Group-ID, Queue
athinv computing hardware available global or in a given queue, shows bookings (maintenance, courses, ...)cusage actual resource usage per classjobeff resource usage e�ciency of running jobsjps process snapshot of a running job [w/ threads + shm segments]liar instantly available ressources per queue w/ constraints. Aktuell verfügbare Ressourcenlqueues list enabled queues w/ access rightslpkgs packages (matching a given pattern) available at compute-nodes; Liste der auf den Knoten installiertenPaketepaqt plots your queue time characteristics curvepbstop utilization grid (use "h" to get the embedded help)qparams default/maximum resource attribute values for a given queue. Voreinstellungen und Maxima der ein-zelnen Queues.showstart [worst case] start time of your waiting job(s)slnfs-wtb slow nfs share? who's to blame [w/ probability]. Wodurch wird der NFS-Server bei Überlastblockiert?wip additional software installation work in progress news. Nicht in Debian-Paketen verfügbare, für die Atheneangepasste Software.
7. Jobverwaltung:man pbs_resources
qsub skriptfile empfohlener Jobstart (limits ins Skript�le)qsub -q express skriptfile
qsub -q express -l walltime=1:15:59 skriptfile
qsub -q express -l walltime=1:15:59,pmem=2gb skriptfile
qstat alle eigenen Jobsqstat jobid
qdel jobid
8. Batch-scripts:
#/bin/bash!#PBS -l nodes=2:ppn=8
#PBS -l walltime=0:10:0
#PBS -l pmem=100M
13
14 3. MPI-INSTALLATIONEN (SCHWERPUNKT: AN DER UNI. R. VERFÜGBARE INST.)
#PBS -q queuename
#cd ${PBS_O_WORKDIR}
mpiexec -n 16 /home/brf09510/svn/hpc/trunk/pgas/upc/nsphere/a.out
Die benötigten Ressourcen sollten immer im Skript�le angegeben werden. Wenn sie dort fehlen, werden dieAngaben aus dem qsub-Kommando verwendet. Steht auch hier nichts, gelten die Voreinstellungen.
Im Web �nden sich weitere Optionen wie -l cput (CPU time). Diese Option ist auf der Athene immer durch-l walltime zu ersetzen.
Thou shalt not use contradictory values in #PBS -l nodes=2:ppn=8 and mpiexec -n 16!
2. Debian Linux
Installation mit apt-get install
Package libopenmpi-dev
Package libmpich2-dev
Mehrere MPICH Versionen in den Paketen.
apt-get install libmpich2-dev apt-get install mpich-shmem-bin
mpd Daemon lokal starten
mpd cd $HOME touch .mpd.conf chmod 600 .mpd.conf vi .mpd.conf
3. openSuSE Linux
Installation mit yast2 oder zypper install
Package openmpi-devel
Package mpich-devel
4. Übersetzung und Start von MPI-Programmen (Athene)
Wrapper: mpicc mpicxx mpif90 mpif77
Der einzige launcher ist mpiexec.
Usage: mpiexec [OPTION...] <command> [cmd_options]
Common options: -np=num number of processes to start -n=num equal to np: number of processes to start -e,�exports=envlist environment to export to foreign nodes -x, �envall export all environment variables to all pro-cesses -E, �env=<name> <value> export this value of this env var -b, �bnr Enable ParaStation4 compatibilitymode -u, �usize=INT set the universe size
Job placement options: -N, �nodes=STRING list of nodes to use: nodelist <3-5,7,11-17> -H, �hosts=STRINGlist of hosts to use: hostlist <node-01 node-04> -f, �host�le=<�le> host�le to use -f, �machine�le=<�le>machine�le to use, equal to host�le -w, �wait wait for enough resources -o, �overbook allow overbooking -F,�loopnodes�rst place consecutive processes on di�erent nodes, if possible -X, �exclusive do not allow any otherprocesses on used node(s) -S, �sort=STRING sorting criterium to use:
proc|load|proc+load|none -d, �wdir=<directory> working directory for remote process(es) �umask=INT umaskfor remote process -p, �path=<directory> the path to search for executables
Communication options: -c, �discom=STRING disable an communication architecture: SHM,TCP,P4SOCK,GM,MVAPI,OPENIB,DAPL-t, �network=STRING set a space separeted list of networks enabled -y, �schedyield use sched yield system call-r, �retry=num number of connection retries -C, �collectives enable psmpi2 collectives -O, �ondemand usepsmpi2 "on demand/dynamic" connections �no_ondemand disable psmpi2 "on demand/dynamic" connections
I/O options: -i, �interactive set interactive mode (similar to ssh -t) -s, �inputdest=STRING direction to forwardinput: dest <1,2,5-10> or <all> -l, �sourceprintf print output-source info -R, �rusage print consumed sys/usertime -m, �merge merge similar output from di�erent ranks -T, �timestamp print detailed time-marks
Privileged options: -A, �admin start an admin-task which is not accounted -L, �login=login_name remote userused to execute command (with �admin only)
5. REX-LINUX (CIP-POOLS) 15
Other options: �gdb debug processes with gdb �noargs don't call gdb with �args -v, �verbose set verbose mode-V, �version output version information and exit
Help options: �extendedhelp display extended help �extendedusage print extended usage �debughelp displaydebug help �debugusage print debug usage �comphelp display compatibility help �compusage print compatibilityusage -h, �help show help message -?, �usage print usage
5. Rex-Linux (CIP-Pools)
Von mehreren Rechnern aus zugängliches Verzeichnis (wenn kein Samba-home, dann geht /temp immer)
Dort das mpi-Programm ablegen.
Übersetzen: mpicc hallo.c
Starten: mpiexec ./a.out
mpiexec -np 5 ./a.out
mpiexec -np 4 -host rex2,rex2,rz500,rz500 /temp/brf09510/svn/hpc/trunk/mssgpssg/mpi/hallo/a.out
mpiexec -np 4 -hostfile filewithhostnames /temp/brf09510/svn/hpc/trunk/mssgpssg/mpi/hallo/a.out
Es muss zum Einloggen das Passwort eingegeben werden.
Mit ssh kann das umgangen werden:
ssh-keygen
scp ~/.ssh/id_rsa.pub rz500:/home/brf09510/.ssh/authorized_keys
Jetzt muss nur noch einmal (!) das Hilfspasswort, das die ssh-Datei schützt, eingegeben werden.
Aus dem Partnerrechner kann die key-Datei wieder gelöscht werden, wenn die Verbindung nicht mehr benötigtwird.
rz500:~/.ssh> rm authorized_keys
rz500:~/.ssh> pwd
/home/brf09510/.ssh
KAPITEL 4
MPI-Implementationen
1. Übersicht
http://beige.ucs.indiana.edu/I590/node54.html
http://www.d.umn.edu/~psiders/vdil/MPIhistory.html
http://www.cs.kent.edu/~farrell/cc03/lectures/MPI-2.pdf
http://hpcl.cse.msstate.edu/projects/mpi/implementations.html
MPICHMVAPICHMPICH-PM/CLUMPMPICH-T3EBoost MPILAM/MPIOpen MPIIntel MPIHP MPIMicrosoft Message Passing InterfaceScore MPIChimpUnifyBDM/MPIMPICH/NTW32MPIWinMPIMPI-FM
2. Open-MPI
Open-MPI ist eine MPI-Implementierung. Sie darf nicht mit der Thread-De�nition OpenMP verwechselt werden.
1. Open-MPI ist open-source
2. Open-MPI ist thread-safe
3. MPICH
17
KAPITEL 5
Struktur
1. Allgemeines
Mit wenigen Ausnahmen (MPI_Init) wird hier nur der Prototyp in C angegeben. Die Deklarationen der anderenSprachen können problemlos hergeleitet werden.
In Fortran wird der Name komplett groÿ geschrieben; statt des Funktionsergebnisses wird die Fehlerinformationin einem zusätzlichen Argument IERROR gespeichert.
C++ wurde mit MPI-3 entsorgt. In C++ erfolgte der Aufruf mit dem Namespace MPI::. Weiter wurde eine mi-nimale (lightweight) Menge von Klassen de�niert. Vererbung kam vor, virtuelle Funktionen nicht. Als Ersatz kön-nen auch aus C++ die MPI-Funktionen direkt aufgerufen werden oder verfügbare Wrapper-Bibliotheken verwen-det werden. Eine dieser Bibliotheken ist die Boost-Library http://www.boost.org/doc/libs/1_46_1/doc/html/mpi.html
Die in C fehlenden Namespaces werden ersetzt durch das Prä�x MPI_. Das C-Funktionsergebnis ist immer einFehlercode und sollte mindestens mit MPI_SUCCESS verglichen werden. Di�erenzierte Fehlercodes stehen imStandard auf Seite 350 und 661.
Create erzeugt immer neues Objekt; Get liefert Informationen; Set setzt Informationen; Delete löscht Informa-tionen; Is fragt Eigenschaften und Einstellungen; all weist auf komplexere Aktionen mehrerer Prozesse einesKommunikators hin.
IN: Eingabeargument; OUT: Ausgabeargumente; INOUT: beides (weitgehend vermieden)
2. Begri�e
Blockierend, Nichtblockierend
lokal (nur ein Prozess betro�en)
nichtlokal (Das korrekte Ende einer Aktion hängt auch von anderen Prozessen ab)
kollektiv (Alle Prozesse einer Gruppe sind an einer Aktion beteiligt)
vorde�niert und abgeleitet (Datentypen)
portabel (Datentypen)
äquivalent (Datentypen)
opak (Datentypen)
3. MPI-Header
Zur Benutzung von MPI muss in C der Header mpi.h und in Fortran der Header mpif.h eingebunden werden.
#include "mpi.h"
include 'mpif.h'
Alle MPI-Tätigkeiten sind Funktionsaufrufe, die bei Nichterfolg den Fehler in Form einer ganzen Zahl signali-sieren. Es wird dringend empfohlen, ein Fehlersignal jeweils sofort auszuwerten und entsprechend zu reagieren.
int error;
error = MPI_Xxxxx (arguments);
CALL MPI_XXXXX (arguments, IERROR)
if (error != MPI_SUCCESS) { MPI_Abort (MPI_COMM_WORLD, 1); }
Die unterste Zeile ist nur ein Vorschlag und zwar der drastischst-mögliche!
19
20 5. STRUKTUR
4. Start und Ende des MPI-Programmteils
Alle MPI-Programme sollen in jeder Umgebung ohne Änderung des Programmtextes übersetzbar und lau�ähigsein. Das wird während des Programmlaufes durch die Funktion Init sichergestellt. Sie erledigt alle vor Beginneiner MPI-Kommunikation notwendigen Vorbereitungen. Das kann eine leere Tätigkeit sein, wenn der launcherschon alles erledigt hat. Im anderen Extremfall werden alle Threads gestartet, die Kommunikationshardwareinitialisiert und die gesamte Programmumgebung eingestellt.
Tabelle 1. Init:
int MPI_Init (int * argc, char *** argv) Cint MPI_Init (NULL, NULL) Cint MPI::Init () C++int MPI::Init (int & argc, char **& argv) C++MPI_INIT (IERROR) Fortran
In C und C++ können die Argumente von main oder NULL als Adressen übergeben werden. Sie werden dannals identische Kopien an alle gestarteten Threads weitergegeben. Die Adressangabe muss stehen, damit MPI beiBedarf den Inhalt der Variablen modi�zieren kann.
MPI-Programme müssen genau einen Aufruf von MPI_Init enthalten. Vorher dürfen lediglich die FunktionenMPI_Get_version (335), MPI_Initialized (362) und MPI_Finalized (363) aufgerufen werden.
int MPI_Finalize (void)
Die Funktion beendet den MPI-Teil eines Programms. Der Aufruf ist zwingend und darf nicht entfallen. Danachsind lediglich die Funktionen MPI_Get_version, MPI_Initialized und MPI_Finalized erlaubt. Beim Aufrufvon Finalize dürfen keine unabgeschlossenen Kommunikationen existieren.
int MPI_Abort (MPI_Comm comm, int errorcode)
Alle Threads der angegebenen Kommuniatorgruppe comm werden mit dem Fehlercode errorcode beendet. Fallsdie Beendigung der Threads einzeln nicht möglich ist, dürfen auch alle weiteren beteiligten Threads mitbeendetwerden. Die Umgebung kann den Fehlercode verarbeiten, ist aber dazu nicht verp�ichtet. Posix-Umgebungensollten das jedoch tun.
5. Abfragefunktionen
int MPI_Initialized (int * flag)
In der Variablen flag steht nach dem Aufruf der Wert true, wenn MPI_Initialize schon aufgerufen wurde.
int MPI_Finalized (int * flag)
In der Variablen flag steht nach dem Aufruf der Wert true, wenn MPI_Finalize schon aufgerufen wurde.
int MPI_Get_version (int * version, int * subversion)
Selbsterklärend. Seit 2015 sind die Werte 3 und 1 (MPI 3.1).
Die Version kann auch vom Compiler durch die Präprozessorvariablen MPI_VERSION und MPI_SUBVERSION er-mittelt werden.
Auch eine MPI-Implementierung hat eine Versionsnummer, die als String mit
int MPI_Get_library_version (char * version, int * resultlen)
ermittelt wird. Das Feld versionmuss mindestens Platz für MPI_MAX_LIBRARY_VERSION_STRING Zeichen haben.
6. Prozess-Identi�kation
int MPI_Comm_size(MPI_Comm comm, int *size)
In der Variablen size wird die Anzahl der zum Kommunikator comm gehörenden Prozesse gespeichert. JederProzess erhält eine Nummer rank, die mit
int MPI_Comm_rank(MPI_Comm comm, int *rank)
ermittelt wird.
9. START VON MPI-PROGRAMMEN 21
Nach Start des MPI-Programms ist der erste Kommunikator MPI_COMM_WORLD
int MPI_Get_processor_name(char *name, int *resultlen)
In der Variablen name wird mit resultlen Zeichen der Prozessorname gespeichert. Die Variable muss indestensPlatz für MPI_MAX_PROCESSOR_NAME Zeichen haben.
7. Rechenzeit
Gerade im Hochleistungsrechnen ist die genaue Messung von Rechenzeit von groÿer Bedeutung. Die normaleRechneruhr ist oft nicht genau genug. In Clustern sind spezielle Uhren eingebaut, die in MPI direkt angesprochenwerden können. In Programmen mit MPI sind andere Uhrenmechanismen weitgehend unnötig.
7.1. MPI-Funktionen zur Zeitbestimmung. MPI bietet eine eigene Schnittstelle zur Uhr an, obwohldas strenggenommen nicht zum "Message Passing" gehört, weil bereits existierende Schnittstellen entwederungeeignet (Posix 1003.1-1988/1003.4D 14.1, Fortran 90) oder nicht genau genug sind (<time.h> in C).
double MPI_Wtime (void)
Die Funktion liefert im lokalen Thread mit hoher Zeitau�ösung die verstrichene Zeit in Sekunden mit einemfesten Zeitnullpunkt, der nicht genauer festgelegt ist, sich im Lauf eines Programms aber nie ändert.
Der Wert MPI_WTIME_IS_GLOBAL ist true wenn die Uhren aller Threads synchronisiert sind, also denselbenWert bei gleichzeitigem Aufruf erhalten. Die Ungenauigkeit der Synchronisierung darf die halbe Zeitdauer einerMPI-Message der Länge 0 nicht übersteigen.
double MPI_Wtick (void)
Die Funktion liefert die Zeitau�ösung in Sekunden, also die Genauigkeit der Uhr.
7.2. Linux-Funktionen zur Zeitbestimmung. time Linux-Kommando
time mpirun executable Filename
7.3. Zeit in C. Die C-Schnittstelle zur Uhr (<time.h>) ist nicht geeignet, da sie keine ausreichendeGenauigkeit aufweist.
7.4. Posix-Zeit. Für rein lokale Zeitmessungen kann die Posix-Zeitschnittstelle verwendet werden. MitMPI istd das eher selten.
8. Übersetzung von MPI-Programmen
Die Übersetzung von MPI-Programmen kann direkt erfolgen, wird aber besser mit einem Compiler-Wrapperabgewickelt. Das genaue vom Wrapper erzeugte Kommando wird mit der Option -show (manchmal showme!)ausgegeben.
Die Wrapper sind mpicc, mpif77, mpicxx und mpif90
9. Start von MPI-Programmen
Der Start von MPI-Programmen wurde von den meisten Implementierungen mit Hilfe eines getrennten launchersdurchgeführt. Er muss dann nicht mehr auf derselben Maschine erfolgen, auf der das gestartete Programmabläuft. Dieser launcher ist nicht standardisiert, hat aber auf vielen Anlagen mittlerweile gleiche oder ähnlicheEigenschaften. Der Standard schlägt folgenden Aufruf vor:
mpirun mpirunArgs exec execArgs
Genauer, aber immer noch nicht verp�ichtend de�niert der Standard den launcher mpiexec. Dabei orientiertsich der Vorschlag an der MPI-Funktion MPI_Comm_spawn:
mpiexec -n maxprocnmb exec execArgs
Weitere Optionen sind -soft -host -arch -wdir -path -file.
Es können mehrere Programme in einem Kommando getrennt durch : gestartet werden.
22 5. STRUKTUR
mpiexec -n maxprocnmb exec execArgs : -n maxprocnmb exec execArgs : -n maxprocnmb exec execArgs
. . .
Die Argumente von mpiexec können auch aus einer bereitgestellten Datei geholt werden. Die durch : getrenntenAngaben stehen zeilenweise in dieser Datei:
mpiexec -configfile �lename
KAPITEL 6
Zwei-Punkte-Kommunikation
1. Übersicht
Die folgende Skizze enthält die wichtigsten Wege einer Nachricht zwischen zwei Knoten mit MPI. Die MPI-Funktionsnamen stehen immer an ihrem jeweiligen zeitlichen Endpunkt. Die Zahlen in der Skizze verweisenauf den MPI-3.0 Standard. Die senkrechten Pfeile deuten die Wartezeit in den jeweiligen Funktionen seit demzeitlichen Beginn des Aufrufs an. Waagrechte Pfeile und Kreise sind wartezeitfreie Aufrufe.
? ?Zeit - time
Sender area Receiver areaInterconnect area
nonblocking 47 nonblocking 47blocking 24,28 blocking 24,28
prepare data to transmit
process transmitted data
c
?MPI_Ssend 39(MPI_Send 24,37)
c?MPI_Bsend 38(MPI_Send 24,37)
MPI_Irsend 51MPI_Ibsend 49MPI_Issend 50MPI_Isend 49
cMPI_Rsend 39 XXXXXXXXXXXXXXXXz
XXXXXXXXXXXXXXXXz
c?
?MPI_Recv 28
cMPI_Irecv 51
c - c�MPI_Test 54 MPI_Test 54ready yes/no ready yes/no
c?MPI_Wait 53
c
?MPI_Wait 53
bu�ering 37,44
MPI_Bu�er_attach 44MPI_Bu�er_detach 45
handshake-�
envelope 27status 30
status.MPI_SOURCEstatus.MPI_TAGstatus.MPI_ERRORMPI_Get_count get length of message
MPI_Probe 65 check incoming messagesMPI_Iprobe 64 without receiving them
siehe 4 auf Seite 25
2. Datentypen
Fortran:
23
24 6. ZWEI-PUNKTE-KOMMUNIKATION
Tabelle 1. Zwei-Punkte-Kommunikation:
MPI_Send (buf, n, type, dest, tag, comm); 24,37 bu�ered or synchronousMPI_Rsend 39 don't! nearly never!MPI_Bsend 38 bu�eredMPI_Ssend 39 synchronousMPI_Recv (buf, n, type, source, tag, comm, &status); 28 receiveMPI_Buffer_attach (buf, n); 44 provide bu�erMPI_Buffer_detach (&bufadr, &n); 45 free provided bu�erstatus.MPI_SOURCE 27,30 contains senderstatus.MPI_TAG 27,30 contains tagstatus.MPI_ERROR 27,30 contains error code of received messageMPI_Get_count (&status, type, &n); 31 number of enrties of received messageMPI_Isend (buf, n, type, dest, tag, comm, &request); 49MPI_Irsend 51 don't! nearly never!MPI_Ibsend 49MPI_Issend 50MPI_Irecv 51MPI_Wait (&request, &status); 53 eine bestimmte NachrichtMPI_Waitany (m, requests[], &index, &status); 57 die nächste NachrichtMPI_Waitall (m, requests[], status[]); 59 alle NachrichtenMPI_Waitsome (m, requests[], &mbar, indices[], statuses[]); 60 mindestens eine, aber alle zu
diesem Zeitpunkt bekanntenMPI_Test (&request, &flag, &status); 54MPI_Testany (m, requests[], &index, &status); 58MPI_Testall (m, requests[], status[]); 60MPI_Testsome (m, requests[], &mbar, indices[], statuses[]); 61MPI_Iprobe 64 nur envelope ohne eigentliche
Nachricht empfangenMPI_Probe 65MPI_Sendrecv 74Daten, Konversionen 33Regeln, Fairness, Ressourcen 37,42
Tabelle 2. Fortrantypen in MPI:
MPI datatype Fortran datatypeMPI_INTEGER INTEGERMPI_REAL REALMPI_DOUBLE_PRECISION DOUBLE PRECISIONMPI_COMPLEX COMPLEXMPI_LOGICAL LOGICALMPI_CHARACTER CHARACTER(1)MPI_BYTEMPI_PACKED
C und C++:
MPI de�niert drei Typen für Fortran und C:
Die C++-Schnittstelle hat noch wenige C++-Namen hinterlassen, die Sie in 3.2.2 im Standard �nden.
1. Der Sender stellt n hintereinander im Speicher an der Adresse buf stehende Einträge des angegebenen Typstype bereit.
2. MPI_BYTE hat kein Fortran- oder C-Äquivalent. Es werden 8 Bit lange Bytes ohne Interpretation übertra-gen.
3. MPI_PACKED überträgt Daten, die im Speicher nichtzusammenhängend stehen und vorher mit MPI_Packverdichtet wurden. Nach dem Empfang können sie mit MPI_Unpack compilergerecht entzerrt werden.
4. MPI_AINT und MPI_OFFSET sind von MPI de�niert und in Fortran als auch in C verwendbar.
3. UMSCHLAG UND STATUS 25
Tabelle 3. C-Typen in MPI:
MPI datatype C datatypeMPI_CHAR char
(treated as printable character)MPI_SHORT signed short intMPI_INT signed intMPI_LONG signed long intMPI_LONG_LONG_INT signed long long intMPI_LONG_LONG (as a synonym) signed long long intMPI_SIGNED_CHAR signed char
(treated as integral value)MPI_UNSIGNED_CHAR unsigned char
(treated as integral value)MPI_UNSIGNED_SHORT unsigned short intMPI_UNSIGNED unsigned intMPI_UNSIGNED_LONG unsigned long intMPI_UNSIGNED_LONG_LONG unsigned long long intMPI_FLOAT �oatMPI_DOUBLE doubleMPI_LONG_DOUBLE long doubleMPI_WCHAR wchar_t
(de�ned in <stddef.h>)(treated as printable character)
MPI_C_BOOL _BoolMPI_INT8_T int8_tMPI_INT16_T int16_tMPI_INT32_T int32_tMPI_INT64_T int64_tMPI_UINT8_T uint8_tMPI_UINT16_T uint16_tMPI_UINT32_T uint32_tMPI_UINT64_T uint64_tMPI_C_COMPLEX �oat _ComplexMPI_C_FLOAT_COMPLEX (as a synonym) �oat _ComplexMPI_C_DOUBLE_COMPLEX double _ComplexMPI_C_LONG_DOUBLE_COMPLEX long double _ComplexMPI_BYTEMPI_PACKED
Tabelle 4. Fortran- und C-Typen in MPI:
MPI datatype C datatype Fortran datatypeMPI_AINT MPI_Aint INTEGER (KIND=MPI_ADDRESS_KIND)MPI_OFFSET MPI_O�set INTEGER (KIND=MPI_OFFSET_KIND)MPI_COUNT MPI_Count INTEGER (KIND=MPI_COUNT_KIND)
Tabelle 5. Umschlagdaten C:
Name Beschreibung Csource Sendernummer status.MPI_SOURCEdestination Empfängernummertag Etikett der Nachricht status.MPI_TAGcommunicator Kommunikatormenge der
NachrichtFehler status.MPI_ERRORAnzahl der Pu�erdaten MPI_Get_count (&status, type, &count)
26 6. ZWEI-PUNKTE-KOMMUNIKATION
Tabelle 6. Umschlagdaten Fortran:
Name Beschreibung Fortransource Sendernummer status(MPI_SOURCE)destination Empfängernummertag Etikett der Nachricht status(MPI_TAG)communicator Kommunikatormenge der
NachrichtFehler status(MPI_ERROR)Anzahl der Pu�erdaten MPI_GET_COUNT (STATUS, TYPE, COUNT, ERROR)
Tabelle 7. Umschlagdaten C++:
Name Beschreibung C++source Sendernummer MPI::status.Get_source()destination Empfängernummertag Etikett der Nachricht MPI::status.Get_tag()communicator Kommunikatormenge der
NachrichtFehler MPI::status.Get_error()Anzahl der Pu�erdaten MPI::status.Get_count(type)
3. Umschlag und Status
1. Der Umschlag einer Nachricht ist kurz, wird vor den eigentlichen Daten übertragen und dient zur Auswahlder nächsten zu empfangenden Nachricht.
2. Die Umschlagdaten werden vom Empfänger getrennt ausgewertet.
3. Die Umschlagdaten werden in der Statusvariablen bereitgestellt. Der Status enthält weitere Informationen.
4. In C ist status eine Struktur.
5. In Fortran ist status ein INTEGER-Feld.
6. In C++ werden Memberfunktionen im Namespaceobjekt status aufgerufen.
4. Kommunikationsregeln
1. Der Empfangspu�er muss groÿ genug sein, um die übertragene Nachricht speichern zu können. Ist er zu klein,erzeugt MPI einen Fehler.
2. Eine empfangene Nachricht verändert nur die benötigten Plätze im Empfangspu�er.
3. Vom selben Sender stammende Nachrichten überholen sich nicht. Wenn mehrere Nachrichten empfangenwerden können, wird zuerst die Nachricht empfangen, die auch zuerst gesendet wurde.
4. Von verschiedenen Sendern stammende Nachrichten werden nicht in garantierter Reihenfolge empfangen.Eine Nachricht kann dauerhaft von Nachrichten anderer Sender am Empfang gehindert werden (keine Fairness)
5. Fortschrittsgarantie: Wenn ein Sender und ein Empfänger eine Nachricht austauschen wollen, wird mindestenseiner der beiden seine MPI-Operation erfolgreich abschlieÿen. Es kann sein, dass am erfolgreichen Abschluÿ einDritter beteiligt ist.
5. Einzelbeschreibungen
5.1. Abschluÿ nichtblockierender Operationen. Nichtblockierende Operationen müssen abgeschlos-sen werden. Dazu liefern alle nichtblockierenden Operationen im letzten Argument einen request-Handle req
zurück. Dieser request-Handle wird später für den Abschluss benutzt. Mit wait geht ein Prozess in einen blockie-renden Abschluss über:
MPI_Wait (&req, &status);
5. EINZELBESCHREIBUNGEN 27
MPI_Wait blockiert und wartet, bis die durch den Handle req bezeichnete nichtblockierende Operation beendetist. Nach MPI_Wait steht in status der Status der Operation.
Mit test kann man nichtblockierend prüfen, ob eine nichtblockierende Operation abgeschlossen ist:
MPI_Test (&req, &result, &status);
MPI_Test prüft, ob die durch den Handle req bezeichnete nichtblockierende Operation beendet ist und hin-terläÿt dieses Ergebnis in result. Bei nichtbeendeten Operations ist result = false und status unde�niert.Andernfalls ist result = true und in status steht der Status der Operation.
Sind noch mehrere nichtblockierende Operationen o�en, kann mit MPI_Waitany und MPI_Testany das Ende vonmindestens einer dieser Operationen ermittelt werden. Analog kann man auch alle angegebenen Operationenabfragen. Schlieÿlich können mit einem Aufruf alle schon beendeten Operationen (mehr als eine) ermitteltwerden:
MPI_Waitany (n, req[], &status);
MPI_Testany (n, req[], &result, &status);
MPI_Waitall (n, req[], status[]);
MPI_Testall (n, req[], &result, status[]);
MPI_Waitsome (n, req[], &number, indices[], status[]);
MPI_Testsome (n, req[], &number, indices[], status[]);
5.2. Dynamische Nachrichten. In manchen Situationen werden Nachrichten bei Bedarf gesendet undnicht schon vom Programmierer fest geplant. Dann muss geprüft werden, ob überhaupt Nachrichten zum Emp-fang anstehen. Wenn das der Fall ist, wurde die Sendung natürlich schon eingeleitet. Der Empfänger kannprüfen, ob solche Sendungen anstehen:
MPI_Iprobe (source, tag, comm, &result, &status);
In source wird die vermutete Quelle der Nachricht oder der Wert MPI_ANY_SOURCE angegeben. In tag wird dergewünschte Nachrichten-tag oder der Wert MPI_ANY_TAG angegeben. Der Sender ist im Komunikator comm. Obeine solche Nachricht vorliegt, wird in der Variablen result hinterlassen.
Wenn Iprobe in result den Wert true hinterläÿt, kann ohne weitere Zeitverzögerung eine Nachricht empfangenwerden. Ihr envelope steht jetzt schon in status zur Verfügung.
Es gibt eine blockierende Variante Probe, die blockiert, bis mindestens eine Nachricht bereit steht. Man kannsie verwenden, wenn bis zur nächsten Nachricht nichts zu tun ist.
MPI_Probe (source, tag, comm, &status);
5.3. Beliebige Nachrichten. Auch in Recv können beliebige Nachrichten empfangen werden, wenn beisource statt der Quelle der Nachricht der Wert MPI_ANY_SOURCE angegeben wird. Genauso kann in tag stattdes gewünschten Nachrichten-tags der Wert MPI_ANY_TAG angegeben werden. Der envelope enthält dann dieInformationen über die tatsächlich empfangene Nachricht.
5.4. Irecv in Fortran. Die Folge Irecv(buff, request...; Wait(request..; buf(1) = buf(1)+1 inFortran hat ein Problem mit den hochoptimierenden Compilern: Der Compiler weiÿ nicht, dass Wait den Pu�erändert. Wenn er es für optimaler hält, zieht er die Erhöhung vor, was zu einer race-condition führt (wer istschneller: wait oder +). Eine Lösung ist die Verlegung von buf in einen Common-Block, der prinzipiell von jederSubroutine geändert werden kann. Alternativ kann man dem Compiler mit einem Aufruf von
MPI_GET_ADDRESS (buff, dummy, IERROR)
unmittelbar nach Wait die echte Realität klarmachen, dass Wait den Pu�er noch ändern kann. Der Parameterfür die Adresse dummy hat keine weitere Funktion; die wichtige Funktion ist die Übergabe des Pu�ers an eineSubroutine!
28 6. ZWEI-PUNKTE-KOMMUNIKATION
Race-conditions sind Wettrennen um Variable, bei denen alle so schnell wie möglich laufen und der ersteverliert1. Sie treten bei MPI selten auf, da MPI-Prozesse keine gemeinsamen Variablen kennen. Gefürchtet sindsie bei paralleler Thread-Programmierung (pthread, OpenMP) und PGAS-Sprachen (UPC, coarray-Fortran).Spezielle Analyse-Programme wie der Intel-Threadchecker helfen, race-conditions aufzuspüren.
5.5. Sendrecv. Wollen viele Prozesse Daten tauschen, entsteht leicht die Situation der Serialisierung derNachrichten. Das kann mit einem gekoppelten Sendrecv vermieden werden. Sendrecv sendet eine Nachricht aneinen Prozess und empgängt gleichzeitig eine andere Nachricht eines beliebigen Prozesses. Mit Sendrecv_replacekann für beide Nachrichten derselbe Pu�er verwendet werden.
MPI_Sendrecv (sbuf, sn, st, dest, stag, rbuf, rn, rt, source, rtag, comm, rstatus);
MPI_Sendrecv_replace (buf, n, t, dest, stag, source, rtag, comm, rstatus);
5.6. Nachrichtenpu�er. MPI verwendet interne Nachrichtenpu�er, die implementierungsabhängig beimSender, beim Empfänger oder bei beiden liegen können. Diese Pu�er sind opak (dem Programmierer nichttrans-parent), beschränkt (sie können überlaufen) und oft schlecht dokumentiert.
Auf Senderseite kann der Programmierer eigene Pu�er einrichten und wieder abmelden. Diese Pu�er unterliegender Kontrolle durch den Programmierer. Sie sind nicht rekursiv: Nur ein attach ist erlaubt.
In C ist der Pu�er eine Adresse. In Fortran können Felder und Memory Regions verwendet werden.
Detach gibt den Pu�er wieder frei, d.h. MPI verwendet wieder den System-dafault. Detach blockiert, bis derfreizugebende Pu�er wirklich unbenutzt ist.
5.7.
6. Hinweise und Probleme
1. In der Gruppe von s Prozessen mit Rank r = 0 . . . s − 1 soll jeder Prozess seinem Nachfolger r + 1 mod seine Nachricht senden und von seinem Vorgänger r − 1 mod s eine Nachricht empfangen. Überlegen Sie kurzdas folgende Programmfragment:
send (msg, (r+1)%s);
recv (msg, (r-1)%s);
2. In vielen Programmiersprachen funktioniert modulo (%) nicht konsistent für negative Zahlen. Entweder mussman Korrekturen für negative Zahlen einbauen (umständlich), reelle Zahlen und floor verwenden (rechenzeit-aufwändig) oder negative Zahlen unter allen Umständen vermeiden. Schreiben Sie also immer:
send (msg, (r+1)%s);
recv (msg, (r+s-1)%s);
3. Die Sperre des Todes (deadlock): Alle Prozesse warten auf ein Ereignis, aber niemand sorgt für dessenEintreten.Genauer: Alle Prozesse einer Gruppe warten auf ein Ereignis, aber niemand � auch niemand auÿerhalb derGruppe � sorgt für dessen Eintreten. In einem solchen Fall hängt das Programm ähnlich wie bei einer unendlichenSchleife in der sequentiellen Programmierung. Im Beispiel wollen alle senden, aber niemand empfängt! So kannein deadlock vermieden werden:
if (r == 0) {
recv (msg, (r+s-1)%s);
send (msg, (r+1)%s);
} else {
send (msg, (r+1)%s);
recv (msg, (r+s-1)%s);
}
1Denken Sie an das triwizard tournament im Band 4 der Harry-Potter-Serie: Wer am Ende den Pokal als erster berührt, landet
bei Lord Voldemort!
6. HINWEISE UND PROBLEME 29
4. Auch Nachrichten können lange dauern � zu lange! Alle sind mit Senden und Empfangen beschäftigt, bisdie Nachrichten schön hintereinander übertragen worden sind. Um diese Sequentialisierung zu vermeiden, kannman nichtblockierende Operationen verwenden:
Irecv (msg, (r+s-1)%s, &r1);
Isend (msg, (r+1)%s, &r2);
wait (r1);
wait (r2);
5. Genau für diesen Fall wurde in MPI ein gekoppeltes Sendrecv eingeführt:
sendrecv (msg, (r+1)%s, buf, (r+s-1)%s);
Dieser Befehl hat in MPI die Form:
MPI_Sendrecv (sbuf, sn, st, dest, stag, rbuf, rn, rt, source, rtag, comm, rstatus);
KAPITEL 7
Kollektive Kommunikation
Bei kollektiver Kommunikation sind immer mehrere, viele oder alle Prozesse beteiligt. Das wird durch denKommunikator gesteuert.
Ohne Datenaustausch spricht man von Synchronisierungen (Barrieren).
Ist vor oder nach der Kommunikation ein Datum beteiligt, liegt eine Broadcast- oder Reduce-Operation vor.Bei reduce-Operationen werden verschiedene Daten zusammengefasst.
broadcast-
A A
A
A
A
reduce�
A A1
A2
A3
A4
Werden p Daten auf einem Prozessor mit je einem Datum auf p Prozessoren ausgetauscht, heiÿen die Opera-tionen scatter oder gather.
scatter-gather�
A1 A2 A3 A4 A1
A2
A3
A4
Wird je ein Datum auf den p Prozessoren allen Prozessoren zur Verfügung gestellt, nennt man die Operationallgather.
allgather�
A1 A2 A3 A4
A1 A2 A3 A4
A1 A2 A3 A4
A1 A2 A3 A4
A1
A2
A3
A4
Schlieÿlich kann man p Daten auf p Prozessoren komplett transponieren, was einem kompletten Datenaustauschentspricht und alltoall heiÿt.
31
32 7. KOLLEKTIVE KOMMUNIKATION
alltoall�
A1 A2 A3 A4
B1 B2 B3 B4
C1 C2 C3 C4
D1 D2 D3 D4
A1
A2
A3
A4
B1
B2
B3
B4
C1
C2
C3
C4
D1
D2
D3
D4
In der genannten Reihenfolge werden die Operationen immer kommunikationsaufwändiger. (Die Kommunikationbraucht mehr Zeit!)
Die Skizzen stellen die ausgetauschten Daten als kleines Quadrat dar. Das bedeuted jedoch nicht, dass nureinzelne Variablen ausgetauscht werden können. Die ausgetauschten Daten können jede auch komplexe Struk-tur (Felder, struct, Bytefolgen. . . ) annehmen. MPI verlangt exakte Gleichheit der beteiligten Pu�er, um dieÜbertragung und Analyse der Datenlängen und anderer Envelope-Daten zu vermeiden.
Seit MPI-3 stehen auch nichtblockierende Versionen der kollektiven Kommunikation bereit. Eine nichtblockie-rende Barriere erscheint nur auf den ersten Blick sinnlos: sie gibt jedoch allen anderen Prozessen ein Signal,dass der sendende Prozess die Barriere durchschritten hat, ohne dass er gezwungen ist, wirklich zu warten.
1. Synchronisierung
Mit einer Barriere können alle Prozesse eines Kommunikators comm synchronisiert werden. Dabei werden alleProzesse, die den Aufruf schon getätigt haben, solange blockiert, bis der letzte Prozess ebenfalls an dieser Stelleangekommen ist.
int MPI_Barrier(MPI_Comm comm)
Barrieren sind in MPI eher selten, da durch gesendete und empfangene Nachrichten meist schon ausreichendeSynchronisation vorliegt. Schlieÿlich �ndet ein solches Senden und Empfangen immer gleichzeitig statt.
Barrieren haben drei Funktionen: Sie helfen oft in Programmen mit fehlerhafter Kommunikation, den Fehlereinzugrenzen. Sie ermöglichen die Analyse schlechter Lastverteilung bei einer Berechnung, wenn jeder Prozessdie Wartezeit von seinem Rechenende bis zur Barriere am Ende der Gesamtrechnung misst. Und sie werden oftbei der Synchronisierung von Ein- und Ausgaben benötigt.
MPI-3 hat eine nichtblockierende Barriere MPI_Ibarrier, die an die beteiligten Prozesse nur ein Signal sendet,dass der sendende Prozess die Barriere passiert hat.
2. Broadcast
Anders als bei Zwei-Punkt-Verbindungen sendet ein Prozess eine Nachricht an alle Empfänger im angegebenenKommunikator.
int MPI_Bcast(void* buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm )
root ist dabei der sendende Prozess. Allgemein stellt der Begri� root eine Datenquelle oder Datensenke dar.Meistens ist root der Prozess 0, das ist jedoch nicht zwingend.
3. Reduktionen
Das Gegenstück zu Broadcast sind Reduktionen. Hier werden Daten von allen Prozessoren zu einem Ergebnisverknüpft, das auf einem Zielrechner gespeichert wird.
int MPI_Reduce(void* sendbuf, void* recvbuf, int count, MPI_Datatype datatype,
MPI_Op op, int root, MPI_Comm comm)
Alle Prozessoren des Kommunikators comm haben count Daten des Typs dadatype im sendbuf, die elementweisemit der Operation op verknüpft werden. Die count Ergebnisse werden in recvbuf auf Prozessor root gespeichert.
Darüberhinaus sind programmde�nierte Operationen erlaubt. Sie müssen als assoziative Funktionen mit demPrototyp
typedef void MPI_User_function(void *invec, void *inoutvec, int *len, MPI_Datatype *datatype);
5. SAMMELN KOMPLEXER DATEN - GATHER 33
Tabelle 1. Reduce-Operationen
MPI_MAX maximumMPI_MIN minimumMPI_SUM sumMPI_PROD productMPI_LAND logical andMPI_BAND bit-wise andMPI_LOR logical orMPI_BOR bit-wise orMPI_LXOR logical exclusive or (xor)MPI_BXOR bit-wise exclusive or (xor)MPI_MAXLOC max value and locationMPI_MINLOC min value and location
de�niert werden. Im wesentlichen muss die bereitgestellte Funktion
inoutvec [i] = inoutvec [i] ◦ invec [i]
für alle i = 0, . . . ,len−1 verknüpfen. Diese Funktion muss der MPI-Bibliothek als Operation gemeldet werden.
int MPI_Op_create(MPI_User_function *function, int commute, MPI_Op*op)
Als Zusatzinformation wird vermerkt, ob die Operation nicht nur assoziative, sondern auch kommutativ ist. Derzurückgegebene MPI_Op-Handle op kann in der Reduktion als Operation verwendet werden.
Reduktionen sind für den Programmierer die wichtigsten Operationen, die in der sequentiellen Programmierungnicht au�allen, weil sie so schnell hingeschrieben sind. In der parallelen Programmierung sind sie erstaunlichschwierig und erst hier fällt ihre innere Komplexität auf. MPI stellt viele Reduktionen bereit � Luxus für denProgrammierer � die ho�entlich vom MPI-Implementierer sehr optimiert für das vorhandene Datennetz gestaltetsind.
In der Praxis werden Reduktionen meistens zweistu�g programmiert: In einem ersten Schritt reduzieren alleProzesse ihre lokalen Daten auf eine prozesseigene Reduktionsgröÿe. Diese Gröÿe wird mit derselben MPI-Reduktion im zweiten Schritt über alle Prozesse reduziert.
Wie wichtig Reduktionen sind, zeigt das Skalarprodukt bei DMP-Rechnern, die im wesentlichen eine Summen-reduktion ist.
Mit Reduktionen verwandt sind die Prä�x-Scans, Prä�x-Operationen oder einfach nur Scans. Hier wird nichtnur reduziert, sondern auch alle Zwischenergebnisse gespeichert. Scans bei DMP-Rechnern sind dreistu�g: derlokale Scan, der MPI-Scan und die notwendigen lokalen Korrekturen.
MPI_Scan Prozess i erhält Reduktion von 0 bis iMPI_Exscan Prozess i erhält Reduktion von 0 bis i− 1
Aufwändig sind Reduktionen, bei denen alle Prozesse das Reduktionsergebnis brauchen:
MPI_Allreduce
4. Verteilen komplexer Daten - Scatter
Scatter verteilt gleich groÿe Datenstücke aus dem Senderpu�er auf die beteiligten Prozesse.
Die v-Variante erlaubt variable Datenmengen bei den verschiedenen Prozessen.
5. Sammeln komplexer Daten - Gather
Gather sammelt gleich groÿ[ Datenstücke von den Sendern beim Empfänger unter Beibehaltung der Rankord-nung und ist damit das genaue Gegenstück zu scatter.
Die v-Variante erlaubt variable Datenmengen bei den verschiedenen Prozessen.
34 7. KOLLEKTIVE KOMMUNIKATION
6. Gleicher Datenstand auf allen Prozessen
Allgather ist eine optimierte Kombination von Gather und Bcast. Erst werden Datenstücke in der root einge-sammelt und dann der entstandene Datenbestand an alle Prozesse wieder verteilt. Anschlieÿend verfügen alleProzesse über alle Daten in identischer Form. Die gespeicherte Datenmenge wird durch Duplizieren vergröÿert.
7. Komplexer Datentausch
Alltoall transponiert Datenstücke auf allen Prozessen. Daten von einem Prozess werden aus alle anderen Prozesseverteilt. Der Datenbestand bleibt gleich, er wird nur anderen Prozessen zugeordnet.
KAPITEL 8
Datentypen
Programmiersprachen kennen komplexe Datentypbeschreibungen durch Felder, Strukturen und Kombinationendaraus, die man auch mit MPI übertragen will. Als Library hat MPI jedoch keinen Zugri� auf die internenInformationen eines Compilers. Deshalb müssen Datentypen für MPI getrennt beschrieben werden.
Datentypen in MPI beschreiben also das Pu�erlayout der Kommunikationspu�er. Elementare Datentypen wer-den mit ihren MPI-Namen beschrieben und sind sprachabhängig. Sie wurden bei zweiseitiger Kommunikationerläutert. Alle weiteren Datentypen werden dynamisch während des Programmlaufs abgeleitet. Der Compilerkann eine solche Beschreibung nicht liefern, da er von MPI nichts weiÿ. Daraus folgt, dass alle Kommunika-tionsdatentypen zweimal vom Programmierer beschrieben werden müssen: in üblicher Form für den Compilerund ein zweitesmal speziell für MPI. Diese zweite Beschreibung heiÿt abgeleiteter Datentyp (derived data type)und gilt für Felder, Strukturen und anderes.
Die Informationen über abgeleitete Datentypen werden vom Programmierer zusammengestellt. Für den Daten-typ wird dann ein Handle erzeugt, mit dem der Datentyp benutzt wird (Type_Create). Schlieÿlich muss derDatentyp im MPI-System bekannt gemacht werden (Type_Commit).
Mit abgeleiteten Datentypen können auch Pu�erstrukturen beschrieben werden, die nur Teile eines Speicher-bereichs übertragen. Das ist sowohl bei explizit vom Programmierer erwünschten Übertragungslöchern wie beicom Compiler erzeugten Optimierungsausrichtungen (alignments) wichtig.
struct. . .→ Compiler → SpeicherMPI-Beschreibung → MPI-Type → MPI-Commit
Da Datentypen rekursiv beschrieben werden, ist natürlich auch die MPI-Beschreibung "rekursiv".
Abbildung 1. abgeleitete Datentypen
35
36 8. DATENTYPEN
1. Zusammenhängende Felder
2. Strukturen
KAPITEL 9
Topologien
Virtuelle Topologien erlauben eine problemorientierte Neuanordnung der Prozesse, eine Neuverteilung der Pro-zessnummern und sogar eine mehrdimensionale Anordnung, wenn die Problemstellung es verlangt. So könnenNachbarprozesse leichter bestimmt werden � eine wesentliche Erleichterung für den Programmierer. Weiterkann die Nummerierung für den Cluster so optimiert werden, dass kommunizierende Prozesse (Nachbarn) ihreKommunikation auf kurzem Weg abwickeln können � eine anspruchsvolle Aufgabe für den Implementierer.
MPI erlaubt beliebige Prozesstopologien in allgemeinen Graphen; die häu�gste Topologie ist jedoch die Karte-sische in d-dimensionalen Rechteckgittern, die in PDEs sehr häu�g ist.
37
KAPITEL 10
Parallele Ein- und Ausgabe
Orientiert an Posix, aber Posix zu klein.
Gegenüber Posix stark verbessertes high-level interface.
Partitionierung von Dateien
Kollektives Interface
Asynchroner Zugri�
Strided Zugri�
Unabhängig von physikalischer Realisierung (Festplattensystem)
1. Begri�e
�le: Geordnete Menge von typisierten Datenelementen
displacement: Absolute Byteposition gerechnet von �lebeginn
etype: elementarer Datentyp: Elementare Positions- und Zugri�seinheit
�letype: Partitionierungsmuster
view: Sicht- und zugreifbare Datenmenge
o�set: etype-position relativ zu aktuellem view
�le size: in Byte; Position in Byte des ersten Byte nach dem �le
end of �le: o�set of �rst etype, das nach dem letzten Byte im �le beginnt, und im aktuellen view sichtbar ist.
�le pointer: impliziter o�set, der von MPI verwaltet wird. individual und shared
�le handle: opaker Typ zur Benutzung eines �le
2. Typische Dateizugri�
MPI_File_open (493)MPI_File_delete (496)File modes (494)File Info (365/500/)MPI_File_set_size (497) truncate/expandMPI_File_get_size (498)MPI_File_preallocate assure number of bytes allocated
z.B. MPI_Type_create_subarray (87) MPI_Type_submit (99)MPI_File_set_view (401/428)
native (429) homogen/interninternal (429) heterogen/internexternal32 (431) IEEE754 4/8/16 IEC60559user-de�ned (432)
Tabelle (404):x
39
40 10. PARALLELE EIN- UND AUSGABE
Abbildung 1. parallele Datei-Ein- und Ausgabe
Abbildung 2. parallele Datei-Ein- und Ausgabe
positioning (405): explicit o�sets (AT)/individual �lepointer/shared �lepointer (SHARED/ORDERED)
synchronizing (405): blocking/nonblocking (I/BEGIN/END) + MPI_Test/MPI_Wait
coordination (405): noncollective(collective (ALL/ORDERED/ALL_BEGIN/ALL_END)
8. BEGRIFFE 41
direction (404-407): READ/WRITE
MPI_File_seek (415/420)MPI_File_get_position (415/420)
Random access (440)
IO-Errors (447)
MPI_File_close (495)
3. File modes
MPI_MODE_RDONLY read onlyMPI_MODE_RDWR read and writeMPI_MODE_WRONLY write onlyMPI_MODE_CREATE create nonexisting �leMPI_MODE_EXCL error when creating existing �leMPI_MODE_DELETE_ON_CLOSE delete temporary �le when closingMPI_MODE_UNIQUE_OPEN �le is not concurrently opened elsewhereMPI_MODE_SEQUENTIAL �le is accessed sequentiallyMPI_MODE_APPEND initial �le position at EOF
Die Modi sind Zweierpotenzen und können durch + und | (bitweises oder) kombiniert werden. Bei Verwendungvon + ist es ein Fehler, denselben Modus zweimal zu verwenden.
RDONLY, RDWR und WRONLY schlieÿen sich gegenseitig aus.
RDONLY schlieÿt CREATE und EXCL aus.
SEQUENTIAL und RDWR schlieÿen sich aus.
4. Begri�e
5. Begri�e
6. Begri�e
7. Begri�e
8. Begri�e
KAPITEL 11
Kommunikatormanagement
43
KAPITEL 12
Einseitige Kommunikation
45
KAPITEL 13
Prozesstopologien
47
KAPITEL 14
Prozessmanagement
49
KAPITEL 15
Wichtige Grundmuster der parallelen Programmierung
1. Arbeitsverteilung
Eine Arbeitslast der Gröÿe n kann numeriert werden von 0 bis n − 1 und soll gleichmäÿig auf S Prozessoren,numeriert von R = 0 bis S − 1, verteilt werden (rank, size). Das ist immer gegeben, wenn in MPI ein C-Feldelementweise mit jeweils derselben Tätigkeit bearbeitet werden muss.
Alle angegebenen Formeln sind oft verwendete Standardformeln.
1.1. Nichtzusammenhängende Arbeitsbereiche. Vorteil: Einfache und übersichtliche Schleife.
for (i = rank; i < n; i += size)
1.2. Jeder Prozessor bearbeitet einen zusammenhängenden Bereich. q = n/S; r = n%S; e = (R+1)*q; if (R == S-1) e = n;
for (i = R*q; i < e; i ++)
Nachteil: Der letzte Prozessor bekommt zusätzlich den Rest und hat eine gröÿere Last, schlimmstenfalls bistfast zur doppelten.
1.3. Jeder Prozessor bearbeitet einen zusammenhängenden Bereich. q = (n+S-1)/S; r = n - q*S; e = (R+1)*q; if (e > n) e = n;
for (i = R*q; i < e; i ++)
Nachteil: Zwar bearbeitet jeder Prozessor mindestens ein Element, aber abhängig vom Rest der Division hatder letzte Rechner weniger Last.
1.4. Jeder Prozessor bearbeitet einen zusammenhängenden Bereich bei gleichmäÿiger Vertei-lung. q = n/S; r = n%S; if (R < r) { a = R*(q+1); e = (R+1)*(q+1); } else { a = R*q+r; e = (R+1)*q+r; }
for (i = a; i < e; i ++)
Vorteil: Der Lastunterschied beträgt maximal ein Element, weil der Divisionsrest auf die ersten Prozessorenverteilt wird.
2
3
51
KAPITEL 16
Kosten
Kompliziert, Hardware und Library-abhängig
Allgemein nur Schätzungen
https://www8.cs.umu.se/kurser/5DV050/VT10/handouts/F2b.pdf
https://computing.llnl.gov/tutorials/mpi_performance/
53
Inhalt
55
Inhaltsverzeichnis
Kapitel 1. High performance computing 31. Übungsaufgaben 32. Literatur 53. Gründe für paralleles Programmieren 54. Übersicht über paralleles Programmieren 65. Performancemaÿe 76. Parallelprogrammierung in der Nussschale 7
Kapitel 2. Einführung in das MPI (Message Passing Interface) 91. Geschichte 92. Eigenschaften 9
Kapitel 3. MPI-Installationen (Schwerpunkt: an der Uni. R. verfügbare Inst.) 131. MPI auf der Athene 132. Debian Linux 143. openSuSE Linux 144. Übersetzung und Start von MPI-Programmen (Athene) 145. Rex-Linux (CIP-Pools) 15
Kapitel 4. MPI-Implementationen 171. Übersicht 172. Open-MPI 173. MPICH 17
Kapitel 5. Struktur 191. Allgemeines 192. Begri�e 193. MPI-Header 194. Start und Ende des MPI-Programmteils 205. Abfragefunktionen 206. Prozess-Identi�kation 207. Rechenzeit 218. Übersetzung von MPI-Programmen 219. Start von MPI-Programmen 21
Kapitel 6. Zwei-Punkte-Kommunikation 231. Übersicht 232. Datentypen 233. Umschlag und Status 264. Kommunikationsregeln 265. Einzelbeschreibungen 266. Hinweise und Probleme 28
Kapitel 7. Kollektive Kommunikation 311. Synchronisierung 322. Broadcast 323. Reduktionen 324. Verteilen komplexer Daten - Scatter 335. Sammeln komplexer Daten - Gather 336. Gleicher Datenstand auf allen Prozessen 347. Komplexer Datentausch 34
57
58 INHALTSVERZEICHNIS
Kapitel 8. Datentypen 351. Zusammenhängende Felder 362. Strukturen 36
Kapitel 9. Topologien 37
Kapitel 10. Parallele Ein- und Ausgabe 391. Begri�e 392. Typische Dateizugri� 393. File modes 414. Begri�e 415. Begri�e 416. Begri�e 417. Begri�e 418. Begri�e 41
Kapitel 11. Kommunikatormanagement 43
Kapitel 12. Einseitige Kommunikation 45
Kapitel 13. Prozesstopologien 47
Kapitel 14. Prozessmanagement 49
Kapitel 15. Wichtige Grundmuster der parallelen Programmierung 511. Arbeitsverteilung 512. 513. 51
Kapitel 16. Kosten 53
Inhalt 55
INHALTSVERZEICHNIS 59
Erstellt mit LATEX und TTH:
TTH-Seite:http://hutchinson.belmont.ma.us/tth/
https://www.ctan.org/texarchive/support/tth/dist