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/04Vorlesung 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/04Vorlesung 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/04Vorlesung 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/04Vorlesung 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/04Vorlesung 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; iVorlesung 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/04Vorlesung 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/04Vorlesung 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/04Vorlesung 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/04Sie können auch lesen