Open MPI

De Wiki de Calcul Québec
Aller à : Navigation, rechercher
Autres langues :anglais 100% • ‎français 100%

Sommaire

Description générale

Open MPI est une bibliothèques implémentant la norme MPI et permet d'écrire des logiciels à calculs distribués.

Avantages et inconvénients

Open MPI est très modulaire, facile à utiliser et à installer. Son architecture modulaire permet de paramétrer le calcul de façon précise.

Compilateurs encapsulés

Comme la plupart des distributions MPI, Open MPI fourni ses propres compilateurs encapsulés. Il s'agit de scripts qui appellent les autres compilateurs (GCC par exemple) avec les bonnes options pour compiler le code MPI. Le nom du compilateur à appeler dépend du langage utilisé. On appellera mpicc pour du C, mpiCC, mpicxx ou mpic++ pour du C++, et mpif77 ou mpif90 pour du Fortran 77 ou 90.

L'option -showme affiche le compilateur utilisé pour compiler la bibliothèque ainsi que les options utilisées


[nom@serveur $] mpicxx -showme
 g++ -I/usr/include/openmpi-x86_64 -pthread -m64 -L/usr/lib64/openmpi/lib -lmpi_cxx -lmpi


Exécution

L'exécution d'un programme compilé avec Open MPI est lancée via la commande mpiexec. Par exemple :

[nom@serveur $] mpiexec ./mon_application parametres de mon application


mpiexec accepte un grand nombre d'arguments variés. Les arguments de base contrôlent entre autres le nombre de processus total, le nombre de processus par ressource, la distribution des processus et la fixation des processus. Ces réglages seront particulièrement important si vous voulez optimiser l'affinité de mémoire de vos processus.

Nombre de processus

Le nombre total de processus MPI est contrôlé par les options -c,-np,--np,-n,--n, qui sont tous des synonymes pour Open MPI. Par exemple, si vous voulez exécuter 16 processus, vous utiliseriez

[nom@serveur $] mpiexec -n 16 ./mon_application


Sur la plupart des superordinateurs de Calcul Québec (exception : Mp2), vous n'avez pas à spécifier ce paramètre si vous désirez exécuter autant de processus que le nombre de processeurs dont votre tâche dispose.

Vous pouvez ensuite indiquer combien de processus exécuter par ressource via les paramètres suivants

Paramètre Description
-npernode, --npernode Nombre de processus par nœud de calcul
-npersocket, --npersocket Nombre processus par socket

Il est rarement nécessaire de changer ces chiffres. Cela pourrait être le cas si vous exécutez une tâche hybride MPI/OpenMP. Dans ce cas, si le nœud a huit cœurs, vous pourriez vouloir fixer la variable d'environnement OMP_NUM_THREADS à 8, et indiquer --npernode 1, ainsi :

 
 [nom@serveur $] export OMP_NUM_THREADS=8
 [nom@serveur $] mpiexec --npernode 1 ./mon_application
 


Notez qu'il est très possible que votre application ait de meilleurs performances en utilisant davantage de rangs MPI et moins de fils d'exécution OpenMP. Vous pourriez ainsi vouloir utiliser plutôt

 
 [nom@serveur $] export OMP_NUM_THREADS=4
 [nom@serveur $] mpiexec --npernode 2 ./mon_application
 


ou encore

 
 [nom@serveur $] export OMP_NUM_THREADS=2
 [nom@serveur $] mpiexec --npernode 4 ./mon_application
 


Laquelle des options sera la plus performante dépendra beaucoup de l'application utilisée, de l'algorithme appliqué et de son implémentation. La seule solution pour en être certain est de tester votre application avec différents paramètres.

Distribution des processus

Vous pouvez aussi spécifier la manière dont les processus sont distribués. Ils peuvent être distribués par cœur, par socket, ou par nœud. Open MPI distribue les processus séquentiellement sur les cœurs disponibles. Ces paramètres modifient l'ordre dans lesquels les cœurs se retrouvent dans la liste. Prenons l'exemple d'une tâche exécutant 16 processus MPI sur deux nœuds possédant chacun deux processeurs de quatre cœurs chacun (total de 16 cœurs). Voici comment seront distribués les processus selon l'option choisie.

Paramètre Nœud 0 Nœud 1
Processeur 0 Processeur 1 Processeur 0 Processeur 1
-bycore,--bycore 0, 1, 2, 3 4, 5, 6, 7 8, 9, 10, 11 12, 13, 14, 15
-bysocket,--bysocket 0, 2, 4, 6 1, 3, 5, 7 8, 10, 12, 14 9, 11, 13, 15
-bynode,--bynode 0, 2, 4, 6 8, 10, 12, 14 1, 3, 5, 7 9, 11, 13, 15

Fixer ce paramètre peut être important si la charge ou l'utilisation de mémoire n'est pas uniforme sur tous les rangs MPI. Si vous avez par exemple que les huit premiers rangs de votre application utilisent davantage de mémoire que les huit derniers, vous pourriez vouloir répartir la charge en spécifiant l'option bynode. Si votre application fait beaucoup de communications entre les rangs voisins, vous voudrez probablement choisir bycore afin de minimiser la communication entre les nœuds ou les sockets.

Un autre exemple est une application hybride MPI/OpenMP. Si par exemple votre application utilise quatre rangs MPI de quatre fils d'exécution chacun, soit

 
 [nom@serveur $] export OMP_NUM_THREADS=4
 [nom@serveur $] mpiexec --np 4 ./mon_application
 


voici la répartition que vous obtiendrez selon le cas :

Paramètre Nœud 0 Nœud 1
Processeur 0 Processeur 1 Processeur 0 Processeur 1
-bycore,--bycore 0, 1, 2, 3 - - -
-bysocket,--bysocket 0, 2 1, 3 - -
-bynode,--bynode 0, 2 - 1, 3 -
--npernode 2 --bysocket 0 1 2 3

On voit ici que pour avoir une charge distribuée sur les quatre sockets disponibles, il faut ajouter --npernode 2 et spécifier une répartition par socket, c'est à dire exécuter

 
 [nom@serveur $] export OMP_NUM_THREADS=4
 [nom@serveur $] mpiexec --np 4 --npernode 2 --bysocket ./mon_application
 


Fixation des processus

En général, sur une machine dédiée, les processus sauteront rarement d'un cœur à l'autre. Néanmoins, c'est une situation qui peut se produire. Le système d'exploitation doit exécuter certaines tâches de fond et doit utiliser les cœurs de temps à autre. Lorsque ceci se produit, le processus MPI est mis en veille, puis restauré automatiquement par le système. Il n'y a en principe rien qui garantit que le processus est restauré sur le même cœur de calcul où il était initialement. Cela peut mener à des situations où la mémoire utilisée par un cœur est allouée sur de la mémoire physique mal affinée avec celui-ci. Afin d'assurer la fixation des processus sur les cœurs ou sockets initiaux, Open MPI offre les paramètres suivants :

Paramètre Description
-bind-to-core,--bind-to-core Fixe les processus au cœur de calcul initial
-bind-to-socket,--bind-to-socket Fixe les processus au socket initial
-bind-to-none,--bind-to-none Ne fixe par les processus

Si la performance de votre application est fortement dépendante de la bande passante mémoire, il est recommandé de fixer les processus aux sockets initiaux ou au cœurs initiaux.

Note : Dans tous les cas, les processus MPI sont fixés aux nœuds de calcul initiaux.

Paramètres par défaut

Les paramètres par défaut d'Open MPI sont --bind-to-none --bycore, c'est à dire que les processus sont distribués séquentiellement sur les cœurs de calcul d'un même socket, puis d'un même nœud, avant de changer de nœud. De même, les processus peuvent être changés de cœur à volonté par le système d'exploitation (toujours à l'intérieur d'un même nœud).

Afficher les fixations

Open MPI offre un paramètre --report-bindings qui affiche la façon dont les rangs MPI ont été distribués. Le résultat ressemblera à celui-ci, dans le fichier d'erreur de votre tâche :

Fichier : report-bindings.txt
[r103-n2:05877] MCW rank 8 bound to socket 1[core 0]: [. . . .][B . . .]
[r103-n2:05877] MCW rank 10 bound to socket 1[core 1]: [. . . .][. B . .]
[r103-n2:05877] MCW rank 12 bound to socket 1[core 2]: [. . . .][. . B .]
[r103-n2:05877] MCW rank 14 bound to socket 1[core 3]: [. . . .][. . . B]
[r103-n2:05877] MCW rank 0 bound to socket 0[core 0]: [B . . .][. . . .]
[r103-n2:05877] MCW rank 2 bound to socket 0[core 1]: [. B . .][. . . .]
[r103-n2:05877] MCW rank 4 bound to socket 0[core 2]: [. . B .][. . . .]
[r103-n2:05877] MCW rank 6 bound to socket 0[core 3]: [. . . B][. . . .]
[r109-n77:05754] MCW rank 9 bound to socket 1[core 0]: [. . . .][B . . .]
[r109-n77:05754] MCW rank 11 bound to socket 1[core 1]: [. . . .][. B . .]
[r109-n77:05754] MCW rank 13 bound to socket 1[core 2]: [. . . .][. . B .]
[r109-n77:05754] MCW rank 15 bound to socket 1[core 3]: [. . . .][. . . B]
[r109-n77:05754] MCW rank 1 bound to socket 0[core 0]: [B . . .][. . . .]
[r109-n77:05754] MCW rank 3 bound to socket 0[core 1]: [. B . .][. . . .]
[r109-n77:05754] MCW rank 5 bound to socket 0[core 2]: [. . B .][. . . .]
[r109-n77:05754] MCW rank 7 bound to socket 0[core 3]: [. . . B][. . . .]


Architecture modulaire de composantes

La bibliothèque Open MPI est très modulaire. Elle est construit avec le Modular Component Architecture (MCA). Il est possible d'énumérer tous les paramètres MCA disponibles avec la commande

[nom@serveur $] ompi_info -a | less


Les composantes logicielles pour le transport de messages

La première couche est appelée Point-to-point Messaging Layer (PML). Deux composantes implémentent cette interface, nommées ob1 (pour Obi-Wan Kenobi) et cm (pour Connor MacLeod, du film Highlander)[1].

La composante PML ob1

Les couches de transport d'octets, appelées Byte Transfer Layer (BTL) sont utilisées pour transporter des octets par le PML ob1. Puisque la force est forte avec Obi-Wan Kenobi, il peut utiliser plusieurs types de BTL. Les BTL disponibles sont les suivants.

Composantes BTL du PML ob1
Nom Signification Description
self self copie en mémoire virtuelle
sm shared memory Les octets sont passés en mémoire.
tcp Transmission Control Protocol Les octets sont transmis avec le protocole TCP.
openib OpenFabrics Tout ce qui est compatible avec OpenFabrics. InfiniBand fait partie de cette catégorie.

Il est possible de désactiver des composantes BTL à l'exécution via le MCA btl :


[nom@serveur $] mpiexec --mca btl ^sm -n 64 Programme   # ceci désactive le BTL sm


Le PML ob1 est utilisé par Open MPI sur Colosse et sur Mammouth Parallèle II.

La composante PML cm

Le nom cm vient du nom Connor MacLeod. Connor MacLeod est un personnage fictif immortel du film Highlander qui est en compétition avec d'autres immortels. À la fin, il ne peut ne rester qu'un seul immortel. Pour cette raison, la composante PML cm peut utiliser seulement une seule composante MTL (Media Transfer Layer). Par exemple, Guillimin utilise la composante MTL qui s'appelle PSM (pour Performance Scaled Messaging).

Références

  1. http://www.open-mpi.org/community/lists/devel/2008/05/3925.php
Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Ressources de Calcul Québec
Outils
Partager