Parallel Programming: Message-Passing-Interface
←
→
Transkription von Seiteninhalten
Wenn Ihr Browser die Seite nicht korrekt rendert, bitte, lesen Sie den Inhalt der Seite unten
Vorlesung Rechnerarchitektur 2 Seite 9 Parallel Programming: Message-Passing-Interface MPI - das Message Passing Interface • Das MPI Forum trat offiziell im Jahre 1992 zusammen (SuperComputing ’92) • parmacs Gruppe (wesentliche Teile Kommunikatoren, Kartesische Topologien,...) • PVM Gruppe • Ziel: ein Standard für ein striktes Message-Passing Model, • kooperativer Datentransfer zwischen teilnehmenden Prozessen • keine I/O Spezifikation • nur C und Fortran 77 Unterstützung • der MPI Standard wurde 1994 freigegeben • eine portable Message Passing Umgebung mit klassischen und auch einigen (damals) neuen Features (abgeleitete Datentypen, Kommunikatoren...) • offene und vendor-spezifische Implementierungen waren schnell verfügbar • dieser Standard ist heute als MPI-1 bekannt MPI wurde sehr schnell der de-facto Standard für Message Passing auf Parallel Rech- nern MPI-2 • Im Jahr 1995 trat das MPI Forum wieder zusammen, Ziel: Spezifizierung von MPI-2 • Zunächst: Fehlerkorrekturen für MPI-1, Ergebnis: MPI-1.2 • Neu: • Parallel I/O, genannt MPI-IO. Analogie: Nachrichten an Prozesse senden - Nachrichten an das Dateisystem senden • Remote Memory Operations (auch RDMA, one-sided communication). Hauptoperationen: put und get, direkter Zugriff auf Speicher in einem entfernten Knoten durch explizite Kommuni- kation • Dynamisches Prozess Management (MPI_Comm_Spawn), Standardisiertes Interface zum Starten von MPI jobs (mpiexec) • Erweiterung der Kollektiven Operationen • Unterstützung der Sprachen C++ und Fortran 90 • Externes Interface für Debuggers, Profilers etc. • bessere Thread-Safety • MPI-2 Standardardisierung beendet im Jahr 1997, inzwischen auch viele Implementierun- gen • Hier: im wesentlichen MPI-1 Kommunikation, Implementierung (MPICH2) ist aber MPI-2 Lehrstuhl für Rechnerarchitektur - Universität Mannheim WS03/04
Vorlesung Rechnerarchitektur 2 Seite 10 Message-Passing-Interface MPI-Einführung Voraussetzungen im Source-Code für ein MPI Programm: • mpi.h includen • Die Kommandozeilenparameter des Programms müssen an MPI_Init übergeben werden (die Parameter werden automatisch von dem Run-Script mpirun zugewiesen). MPI_Init muß vor allen anderen MPI-Funktionen aufgerufen werden: MPI_Init(&argc,&argv); • Nach der letzten MPI-Funktion muß der Befehl MPI_Finalize aufgerufen werden, um der MPI-Umgebung das Programmende mitzuteilen. Nach dem Befehl MPI_Finalize darf keine andere MPI-Funktion mehr aufgerufen werden: MPI_Finalize(); • Jeder Prozess kann mittels MPI-Funktionen feststellen, wieviele Prozesse es insgesamt gibt (MPI_Comm_size) und seine eindeutige Nummer ermitteln (MPI_Comm_rank): MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); • Der Standard-Kommunikator ist MPI_COMM_WORLD. Es ist jederzeit möglich, neue Kommunikatoren zu erstellen und verschiedene Topologien auf diese Kommunikatoren zu mappen. ////////////////////////////////////////////////////////////////////// // A very short MPI test routine to show the involved hosts ////////////////////////////////////////////////////////////////////// #include #include #include int main(int argc, char **argv) { int size,rank; char hostname[50]; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); //How many processes? MPI_Comm_size(MPI_COMM_WORLD, &size); //Who am I? gethostname (hostname, 50); printf ("Hello World! I'm number %2d of %2d running on host %s\n", rank, size, hostname); MPI_Finalize(); return 0; } Lehrstuhl für Rechnerarchitektur - Universität Mannheim WS03/04
Vorlesung Rechnerarchitektur 2 Seite 11 Message-Passing-Interface Kompilieren/Starten eines MPI-Programmes Einlesen des Source-Scriptes für MPI: pcatoll03 # source /opt0/Administration/common/mpich_path Setting up MPI-environment for Linux Anlegen der MPD Konfigurations Datei: • .mpd.conf im Homeverzeichnis, Dateizugriffsrechte 0600. • Inhalt min. die Zeile password= Starten der MPI Process Daemons (MPD): pcatoll03 # mpdboot --totalnum=3 --file=machinefile 1 out of 3 mpds started; waiting for more ... 3 out of 3 mpds started Kompilieren des Programmes (anstatt von gcc): pcatoll03 # mpicc -Wall mpitest.c -o mpitest Starten des Programmes: pcatoll03 # mpiexec -np 4 ./mpitest Hello World! I’m number 0 of 4 running on host pcatoll03 Hello World! I’m number 2 of 4 running on host pcatoll02 Hello World! I’m number 1 of 4 running on host pcatoll01 Hello World! I’m number 3 of 4 running on host pcatoll01 Beachte: • Angabe der Anzahl Prozesse mit dem Parameter ’-np ’ • Reihenfolge der Ausgabe! Beispiel für ein Machinefile: pcatoll04 pcatoll06 • MPICH2 basiert auf ssh, einloggen ohne Angabe des Passworts muss konfiguriert sein (sie- he http://mufasa.ra.informatik.uni-mannheim.de/page.php?name=lsra/persons/hol- ger/HowTosPublic/ssh.html) • Der Node auf dem das Programm gestartet wird, ist immer mit beteiligt (hier: pcatoll03) und gleichzeitig der Root-Prozess (id=0). • Die restlichen benötigten Nodes (hier 3) werden aus dem machinefile gelesen, gegebenfalls werden auf einem Rechner mehrere Prozesse gestartet. In jedem Fall muss der totalnum Pa- rameter angegeben werden Weitere Kommandos für den Umgang mit dem MPD: • mpdtrace - Zeigt alle Knoten an auf denen ein eigener MPD läuft • mpdallexit - Beendet alle eigenen MPDs. Wichtig: Vor dem ausloggen ausführen! • mpdringtest - Testet die Verbindung zwischen den einzelnen MPDs • mpdhelp - Zeigt alle verfügbaren MPD Kommandos Lehrstuhl für Rechnerarchitektur - Universität Mannheim WS03/04
Vorlesung Rechnerarchitektur 2 Seite 12 Message-Passing-Interface Kommunikationsverfahren (communication modes) Prinzipiell wird zwischen blockierendem und nicht-blockierendem Senden/Empfangen unter- schieden (blocking und non-blocking). Blocking Send/Receive: Ein blocking Send wird sofort ausgeführt, ohne auf den zugehörigen Receive zu warten. Beim Rück- sprung wurde die Nachricht garantiert versandt, der Buffer kann wieder verwendet werden. Ein blocking Send sagt nichts über den Empfang der Nachricht aus. Non-blocking Send/Receive: Ein non-blocking Send wird ebenfalls sofort ausgeführt, allerdings kann der Rücksprung sofort nach der Benachrichtigung des Systems über den Versand der Nachricht erfolgen. Daher ist der Buffer unter Um- ständen noch mit der Nachricht belegt. Man darf den Buffer erst wieder verwenden, wenn man über ent- sprechende Funktionen überprüft hat, daß die Nachricht versandt worden ist. Überprüfung des Status von non-blocking Send/Receive: Mittels der Funktionen MPI_Wait und MPI_Test kann man den Status einer non-blocking Kommunika- tion überprüfen. Jede non-blocking Kommunikation muss/sollte mit diesem Completion-Check abge- schlossen werden, um eventuell belegte Systemresourcen wieder freizugeben (implementationsabhängig) und sicherzustellen, dass der Sendepuffer wieder verwendet werden kann (senden) bzw. die Nachricht komplett empfangen wurde. Send-Varianten (jeweils kombinierbar mit blockierenend/nicht-blockierenend): Synchronous Send/Receive(MPI_SSend, MPI_Issend): Bevor von A an B gesendet wird, muß B einen entsprechenden synchronous Receive gestartet haben. Erst dann wird die Nachricht versendet. Nach dem Aufruf der Send-/Receive-Funktion ist die Kommunikation garantiert abgeschossen und der Buffer kann wieder verwendet werden. Buffered-Send (MPI_BSend, MPI_Ibsend): Beim buffered-Send muss der User explizit Speicherplatz im System reservieren (MPI_Buffer_attach, MPI_Buffer_detach). Die Funktion ist nicht abhängig von einem passenden Receive. Standard-Send (MPI_Send, MPI_Isend): MPI kann die Nachricht puffern, muss aber nicht. Der Aufruf kann direkt nach Pufferung zurückkehren oder auch erst wenn die Nachricht empfangen wurde (d.h. ähnlich synchronem Senden). Ready-Send (MPI_RSend, MPI_Irsend): Hier muss der Anwender dafür sorgen, daß der entsprende Receive schon gestartet ist. So kann man Overhead durch Warten vermeiden und sofort mit dem Versenden beginnen. Sollte ein Ready-Send ohne Receive gestartet werden, ist das Verhalten undefiniert. Lehrstuhl für Rechnerarchitektur - Universität Mannheim WS03/04
Vorlesung Rechnerarchitektur 2 Seite 13 Message-Passing-Interface Verschiedene Buffer-Typen in MPI A M B Process P Process Q User buffer only A M T B S Process P Process Q A Usage of a user-level buffer T M B Process P Process Q Usage of a system buffer S User buffer only: Einfach für synchronem- und ready-Send, bei anderem Send ohne Zwischenspeicher u.U. nicht möglich. Usage of a system buffer S: Alternative für nicht synchrones- oder ready-Send. Hier wird die Nachricht zuerst in einen Zwischenspei- cher kopiert. Probleme: Zusätzlicher Overhead, Nachricht kann zu groß sein für Zwischenspeicherung (Maximal ver- fügbarer Systemspeicher nicht zugänglich für den User). Usage of a user-level buffer T: In diesem Falle sorgt der User für einen entsprechend großen Zwischenspeicher. Da jetzt der User weiß wieviel Speicher verfügbar ist, kann er die Nachricht gegebenenfalls in kleinere Stücke aufteilen (buffe- red send). Ganz anderer Ansatz: Verwendung von One-sided-Commmunication: Remote-Direct-Memory-Access (RDMA). Zu verglei- chen mit DMA innerhalb eines Systems, nur auf einen entfernten Rechner. Der entfernte Rechner muss vor der Kommunikation ein Memory-Window freigeben, in dem bestimmte Rechner lesen/schreiben dürfen. Andere Kommunikationspartner können dann mit Put/Get-Operationen auf diesen Speicherbe- reich zugreifen. Lehrstuhl für Rechnerarchitektur - Universität Mannheim WS03/04
Vorlesung Rechnerarchitektur 2 Seite 14 Message-Passing-Interface Beispiel für eine Kommunikation mit MPI ////////////////////////////////////////////////////////////////////// //// A very short MPI test routine to test message passing ////////////////////////////////////////////////////////////////////// #include #include int main(int argc, char **argv) { int i, size, rank, signal; MPI_Status status; double starttime, endtime; //Initialisation of MPI MPI_Init (&argc, &argv); MPI_Comm_rank (MPI_COMM_WORLD, &rank); MPI_Comm_size (MPI_COMM_WORLD, &size); //Master: send to every proc and wait for answer if (rank == 0) { signal = 666; starttime=MPI_Wtime(); for (i=1; i
Vorlesung Rechnerarchitektur 2 Seite 15 Message Passing Interface Communicators Ein Kommunikator spezifiziert eine Kommunikations-Domäne. Ein Kommunikator besizt zwei feste Attribute: eine Prozessgruppe und eine Topologie, die die logische Anordnung der Prozesse in der Gruppe beschreibt. MPI_COMM_WORLD ist der vordefinierte Kommunika- tor. Funktionen für Kommunikatoren: • MPI_Comm_size - liefert die Anzahl der Prozesse in einem Kommunikator • MPI_Comm_rank - liefert den Rang des aufrufenden Prozesses in einem Kom- munikator • MPI_Comm_compare - vergleicht zwei Kommunikatoren • MPI_Comm_dup - dupliziert einen Kommunikator • MPI_Comm_create - erzeugt einen neuen Kommunikator für eine gegebene Pro- zessgruppe • ver. Funktionen um Prozessgruppen zu manipulieren Beispiel siehe oben. (für mehr Information insbesondere zu Parametern, man !) Kommunikatoren können mit einer (virtuellen) Topologie versehen werden: • Kartesische Topologie, d.h. Gitter oder Torus • MPI_Cart_create - Erzeugt einen Kommunikator mit kartesischer Topologie, Dimension und Periodizität können angegeben werden • MPI_Dims_create/MPI_Cartdim_get/MPI_Cart_get/MPI_Cart_rank/MPI_Car t_coords - Hilfsfunktionen zum Umgang mit kartesischen Topologien • MPI_Cart_shift ( für MPI_Sendrecv) - Hilfsfunktion um source und destination ranks für einen shift zu erhalten • Allgemeine Topologie • MPI_Graph_Create - Erzeugt eine allgemeine Topologie auf Basis einer ange- gebenen Graphenbeschreibung • Die Implementierung kann eine optimierte Anordnung der Prozesse z.B. für ein 2-D Gitter vornehmen. MPI_Dims_create(size, 2,dims); MPI_Cart_create(MPI_COMM_WORLD,2,dims,period,reorder,&cart); Lehrstuhl für Rechnerarchitektur - Universität Mannheim WS03/04
Vorlesung Rechnerarchitektur 2 Seite 16 Message Passing Interface Send/Receive Funktionen - Übersicht • Standard-Send (normalerweise ausreichend) • MPI_Send - Standard Send • MPI_Isend - non-blocking Standard Send • MPI_Wait / MPI_Test / MPI_Test_some / MPI_Wait_all /... - Funktionen, um zu testen das eine oder mehrere Operationen abgeschlossen wurden • Blocking Send-Varianten: • MPI_Bsend - Bufferend Send • MPI_Ssend - Synchronous Sned • MPI_Rsend - Ready Send • Non-blocking Send-Varianten: • MPI_Ibsend - non-blocking, buffered Send • MPI_Issend - non-blocking, synchronous Send • MPI_Irsend - non-blocking, ready Send Beispiel s.o. Receive Funktionen: • MPI_Recv - Blocking Receive • MPI_Irecv - Non-blocking Receive • MPI_Iprobe - Prüft, ob eine Nachricht jetzt empfangen werden könnte Senden und Receive in einem: • MPI_Sendrecv - Funktion, die eine Nachricht sendet und gleichzeitig eine Nach- richt empfängt. Kann zum Beispiel in einer Gitter-orientierten Applikation ge- nutzt werden, um mit einem Nachbarn Daten auszutauschen oder um einen Daten-Shift durchzuführen. MPI_Status status; MPI_Sendrecv(send_buf, count, MPI_BYTE, neighbor_rank, tag, recv_buf, count, MPI_BYTE, neighbor_rank, tag, cart, &status); Lehrstuhl für Rechnerarchitektur - Universität Mannheim WS03/04
Vorlesung Rechnerarchitektur 2 Seite 17 Message Passing Interface Kollektive Operationen • MPI_Barrier - Barriere für alle Prozesse eines Kommunikators • MPI_Bcast - Broadcaste eine Nachricht an alle Prozesse eines Kommunikators • MPI_Gather - "Sammle" ein Datum von allen Prozessen in einem Prozess ein • MPI_Gatherv - wie MPI_Gather, aber flexibler, da unterschiedlich viele Daten von den einzelnen Prozessein eingesammelt werden kann • MPI_Scatter - "Verteile" Daten an alle andere Prozesse • MPI_Scatterv - entsprechend MPI_Gatherv • MPI_Allgather - Verschicke ein Datum von jedem Prozess an jeden anderen Prozess, so- dass alle Prozesse am Ende jeweils ein Datum von jedem Prozess besitzten (wie MPI_Gather, aber alle Prozesse empfangen das Ergebnis, nicht nur ein Empfänger). • MPI_Alltoall - Erweiterung von MPI_Allgather. Jeder Prozess sendet unterschiedliche Da- ten zu jedem empfangenden Prozess. Der j. Block gesendet von Prozess i wird von Prozess j empfangen und in den i. Empfangspuffer empfangen. • MPI_Reduce und MPI_Allreduce - Führt eine globale Reduktionsoperation aus, zum Bei- piel eine globale Summe. Bei Allreduce wird das Ergebnis an alle Prozesse geliefert. • ... Kollektive Operationen für eine Gruppe von 6 Prozessen a0 a0 a0 a1 a2 a3 a4 a5 a0 broad- a0 scatter a1 Prozesse cast a0 a2 a0 a3 a0 a4 gather a0 a5 Daten a0 a0 b0 c0 d0 e0 f0 a0 a1 a2 a3 a4 a5 a0 b0 c0 d0 e0 f0 all- b0 a0 b0 c0 d0 e0 f0 b0 b1 b2 b3 b4 b5 a1 b1 c1 d1 e1 f1 gather alltoall c0 a0 b0 c0 d0 e0 f0 c0 c1 c2 c3 c4 c5 a2 b2 c2 d2 e2 f2 d0 a0 b0 c0 d0 e0 f0 d0 d1 d2 d3 d4 d5 a3 b3 c3 d3 e3 f3 e0 a0 b0 c0 d0 e0 f0 e0 e1 e2 e3 e4 e5 a4 b4 c4 d4 e4 f4 f0 a0 b0 c0 d0 e0 f0 f0 f1 f2 f3 f4 f5 a5 b5 c5 d5 e5 f5 Quelle:MPI - The Complete Reference, M.Snir et al., MIT Press, 1996 Lehrstuhl für Rechnerarchitektur - Universität Mannheim WS03/04
Vorlesung Rechnerarchitektur 2 Seite 18 Message Passing Interface Utility Funktionen / Diverses • MPI_Wtime - Liefert die vergangene Zeit seit einem Zeitpunkt in der Vergangenheit als eine double Nummer (in Sekunden) • MPI_Get_Processor_Name - liefert den Namen der Maschine auf der der Prozess läuft • MPI_Init / MPI_Finalize / MPI_Abort - Initialisiere, beende, breche ab MPI Zusammenfassung - MPI 1.2 enthält sehr viele Funktionen, auch manchmal etwas "exotischere". Die meisten Applikationen verwenden nur ein kleines Subset dieser Funktionen. - Inzwischen ist der MPI Standard 2 verabschiedet und auch implementiert. MPI-2 erweitert MPI noch weiter, zum Beispiel um one-sided Communications (Remote Memory Operati- ons), Parallel IO, Dynamic Process Management, ausserdem mehrere kleinere Änderun- gen. - wir verwenden MPICH2 Version 1.0 Lehrstuhl für Rechnerarchitektur - Universität Mannheim WS03/04
Sie können auch lesen