mpiErste Schritte mit MPI


Bemerkungen

MPI ist ein Standard für die Kommunikation zwischen einer Gruppe von verteilten (oder lokalen) Prozessen. Es enthält Routinen zum Senden und Empfangen von Daten, zum gemeinsamen Kommunizieren und für andere komplexere Aufgaben.

Der Standard bietet eine API für C und Fortran, es gibt jedoch auch Bindungen zu verschiedenen anderen Sprachen.

Versionen

Ausführung Standard Veröffentlichungsdatum
1 mpi-report-1.3-2008-05-30.pdf 1994-05-05
2,0 mpi2-report.pdf 2003-09-15
2.2 mpi22-report.pdf 2009-09-04
3,0 mpi30-report.pdf 2012-09-21
3.1 mpi31-report.pdf 2015-06-04

Hallo Welt!

Drei Dinge sind normalerweise wichtig, wenn Sie mit der Verwendung von MPI beginnen möchten. Zuerst müssen Sie die Bibliothek initialisieren, wenn Sie bereit sind, sie zu verwenden (Sie müssen sie auch abschließen, wenn Sie fertig sind). Zweitens möchten Sie wissen, wie groß Ihr Communicator ist (das, was Sie zum Senden von Nachrichten an andere Prozesse verwenden). Drittens möchten Sie wissen, welchen Rang Sie innerhalb dieses Kommunikators haben (welche Prozessnummer sind Sie innerhalb dieses Kommunikators).

#include <mpi.h>
#include <stdio.h>

int main(int argc, char **argv) {
    int size, rank;
    int res;

    res = MPI_Init(&argc, &argv);
    if (res != MPI_SUCCESS)
    {
        fprintf (stderr, "MPI_Init failed\n");
        exit (0);
    }

    res = MPI_Comm_size(MPI_COMM_WORLD, &size);
    if (res != MPI_SUCCESS)
    {
        fprintf (stderr, "MPI_Comm_size failed\n");
        exit (0);
    }
    res = MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    if (res != MPI_SUCCESS)
    {
        fprintf (stderr, "MPI_Comm_rank failed\n");
        exit (0);
    }

    fprintf(stdout, "Hello World from rank %d of %d~\n", rank, size);

    res = MPI_Finalize();
    if (res != MPI_SUCCESS)
    {
        fprintf (stderr, "MPI_Finalize failed\n");
        exit (0);
    }
}
 

Wenn Sie dieses Programm wie folgt ausführen:

mpiexec -n 2 ./hello
 

Sie würden erwarten, eine Ausgabe wie diese zu erhalten:

Hello World from rank 0 of 2!
Hello World from rank 1 of 2!
 

Sie können diese Ausgabe auch rückwärts erhalten (siehe http://stackoverflow.com/a/17571699/491687 ), um weitere Informationen dazu zu erhalten:

Hello World from rank 1 of 2!
Hello World from rank 0 of 2!
 

Init / Finalisieren

Bevor irgendwelche MPI-Befehle ausgeführt werden können, muss die Umgebung initialisiert und am Ende abgeschlossen werden:

int main(int argc, char** argv)
{
    int res;
    res = MPI_Init(&argc,&argv);
    if (res != MPI_SUCCESS)
    {
      fprintf (stderr, "MPI_Init failed\n");
      exit (0);
    }
    ...
    res = MPI_Finalize();
    if (res != MPI_SUCCESS)
    {
      fprintf (stderr, "MPI_Finalize failed\n");
      exit (0);
    }
}
 

Rang und Größe

So ermitteln Sie die Größe eines Kommunikators (z. B. MPI_COMM_WORLD ) und den Rang des lokalen Prozesses darin:

int rank, size;
int res;
MPI_Comm communicator = MPI_COMM_WORLD;

res = MPI_Comm_rank (communicator, &rank);
if (res != MPI_SUCCESS)
{
  fprintf (stderr, "MPI_Comm_rank failed\n");
  exit (0);
}
res = MPI_Comm_size (communicator, &size);
if (res != MPI_SUCCESS)
{
  fprintf (stderr, "MPI_Comm_size failed\n");
  exit (0);
}
 

Rückgabewerte von MPI-Aufrufen

Fast jeder MPI-Aufruf gibt einen ganzzahligen Fehlercode zurück, der den Erfolg der Operation anzeigt. Wenn kein Fehler auftritt, lautet der Rückkehrcode MPI_SUCCESS :

if (MPI_Some_op(...) != MPI_SUCCESS)
{
   // Process error
}
 

Wenn ein Fehler auftritt, ruft MPI eine mit dem Communicator-, Fenster- oder Dateiobjekt verknüpfte Fehlerbehandlungsroutine auf, bevor er zum Benutzercode zurückkehrt. Es gibt zwei vordefinierte Fehlerhandler (der Benutzer kann zusätzliche Fehlerhandler definieren):

  • MPI_ERRORS_ARE_FATAL - Fehler führen zum Abbruch des MPI-Programms
  • MPI_ERRORS_RETURN - Fehler führen dazu, dass der Fehlercode an den Benutzer zurückgegeben wird

Der Standardfehlerhandler für Kommunikatoren und Fenster ist MPI_ERRORS_ARE_FATAL . für MPI_ERRORS_RETURN ist es MPI_ERRORS_RETURN . Der Fehlerhandler für MPI_COMM_WORLD gilt auch für alle Operationen, die sich nicht speziell auf ein Objekt beziehen (z. B. MPI_Get_count ). Das Überprüfen des Rückgabewerts von Nicht-E / A-Vorgängen ohne Setzen des Fehlerbehandlungsprogramms auf MPI_ERRORS_RETURN ist daher redundant, da fehlerhafte MPI-Aufrufe nicht zurückgegeben werden.

// The execution will not reach past the following line in case of error
int res = MPI_Comm_size(MPI_COMM_WORLD, &size);
if (res != MPI_SUCCESS)
{
    // The following code will never get executed
    fprintf(stderr, "MPI_Comm_size failed: %d\n", res);
    exit(EXIT_FAILURE);
}
 

Um die Fehlerbehandlung durch Benutzer zu ermöglichen, muss zuerst der Fehlerbehandler von MPI_COMM_WORLD :

MPI_Comm_set_errhandler(MPI_COMM_WORLD, MPI_ERRORS_RETURN);

int res = MPI_Comm_size(MPI_COMM_WORLD, &size);
if (res != MPI_SUCCESS)
{
    fprintf(stderr, "MPI_Comm_size failed: %d\n", res);
    exit(EXIT_FAILURE);
}
 

Der MPI-Standard setzt nicht voraus, dass sich MPI-Implementierungen nach Fehlern beheben und die Programmausführung fortsetzen können.