mpi Tutoriel
Démarrer avec mpi
Recherche…
Remarques
MPI est une norme de communication entre un groupe de processus distribués (ou locaux). Il comprend des routines pour envoyer et recevoir des données, communiquer collectivement et d'autres tâches plus complexes.
La norme fournit une API pour C et Fortran, mais des liaisons vers divers autres langages existent également.
Versions
Version | la norme | Date de sortie |
---|---|---|
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 |
Rang et taille
Pour obtenir la taille d'un communicateur (par exemple, MPI_COMM_WORLD
) et le processus local, MPI_COMM_WORLD
-le à l'intérieur:
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);
}
Init / Finalize
Avant de pouvoir exécuter des commandes MPI, l'environnement doit être initialisé et finalisé à la fin:
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);
}
}
Bonjour le monde!
Trois choses sont généralement importantes lorsque vous commencez à apprendre à utiliser MPI. Tout d'abord, vous devez initialiser la bibliothèque lorsque vous êtes prêt à l'utiliser (vous devez également la finaliser). Deuxièmement, vous voudrez connaître la taille de votre communicateur (ce que vous utilisez pour envoyer des messages à d'autres processus). Troisièmement, vous voudrez connaître votre rang dans ce communicateur (quel numéro de processus êtes-vous dans ce communicateur).
#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);
}
}
Si vous exécutez ce programme comme ceci:
mpiexec -n 2 ./hello
Vous vous attendriez à obtenir une sortie comme ceci:
Hello World from rank 0 of 2!
Hello World from rank 1 of 2!
Vous pouvez également obtenir cette sortie en arrière (voir http://stackoverflow.com/a/17571699/491687 ) pour plus d'informations à ce sujet:
Hello World from rank 1 of 2!
Hello World from rank 0 of 2!
Renvoie les valeurs des appels MPI
Presque tous les appels MPI renvoient un code d'erreur entier, ce qui signifie le succès de l'opération. Si aucune erreur ne se produit, le code retour est MPI_SUCCESS
:
if (MPI_Some_op(...) != MPI_SUCCESS)
{
// Process error
}
Si une erreur survient, MPI appelle un gestionnaire d'erreur associé à l'objet communicateur, fenêtre ou fichier avant de retourner au code utilisateur. Il existe deux gestionnaires d’erreur prédéfinis (l’utilisateur peut définir des gestionnaires d’erreur supplémentaires):
-
MPI_ERRORS_ARE_FATAL
- des erreurs entraînent la fin du programme MPI -
MPI_ERRORS_RETURN
- des erreurs entraînent la transmission du code d'erreur à l'utilisateur
Le gestionnaire d'erreurs par défaut pour les communicateurs et les fenêtres est MPI_ERRORS_ARE_FATAL
; pour les objets de fichier, il s'agit de MPI_ERRORS_RETURN
. Le gestionnaire d'erreurs pour MPI_COMM_WORLD
s'applique également à toutes les opérations qui ne sont pas spécifiquement liées à un objet (par exemple, MPI_Get_count
). Ainsi, la vérification de la valeur de retour des opérations non-E / S sans définir le gestionnaire d'erreurs sur MPI_ERRORS_RETURN
est redondante car les appels MPI erronés ne seront pas MPI_ERRORS_RETURN
.
// 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);
}
Pour activer le traitement des erreurs utilisateur, il faut d'abord modifier le gestionnaire d'erreurs de 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);
}
La norme MPI ne nécessite pas que les implémentations MPI puissent récupérer des erreurs et continuer l'exécution du programme.