
Déblocage d'une communication point à point standard dans un programme MPI
L'exécution d'un programme faisant appel à la fonction MPI_Send
suivie de MPI_Recv
peut rester bloquée sur MPI_Send
quant au moins deux processus s'échangent des messages de tailles importantes (variable selon le nombre de processus sur Ada, >2048 octets sur Turing).
Ce problème est dû à l'utilisation du mode d'envoi MPI dit standard (MPI_Send
). Ce mode autorise l'implémentation MPI à choisir la façon d'envoyer les messages. En général (et sur toutes les machines de l'IDRIS), les petits messages sont recopiés dans un espace mémoire temporaire avant d'être expédiés. Tandis que les gros messages sont envoyés en mode synchrone. Ce mode synchrone implique que pour que le message parte (càd pour que l'appel MPI_Send
puisse se terminer), il faut que la réception de ce message ait été postée (càd que l'appel à MPI_Recv
ait été effectué).
Des situations de blocage peuvent alors apparaître. Cela peut arriver, par exemple, pour le schéma de communication suivant :
processus 0 1 send(vers 1) send(vers 0) recv( de 1) recv( de 0)
Ce schéma de communication n'est pas du tout conseillé et est d'ailleurs considéré comme erroné par la norme MPI. Heureusement, les solutions ne manquent pas mais elles nécessitent toutes une légère modification de votre source :
- Remplacer
MPI_SEND
/MPI_RECV
parMPI_SENDRECV
:processus 0 1 sendrecv(vers 1, de 1) sendrecv(vers 0, de 0)
- Remplacer
MPI_SEND
parMPI_BSEND
(attention : il faut allouer un buffer spécifique) :processus 0 1 bsend(vers 1) bsend(vers 0) recv( de 1) recv( de 0)
- Pour un des processus, inverser
MPI_SEND
etMPI_RECV
:processus 0 1 send(vers 1) recv( de 0) recv( de 1) send(vers 0)
- Utiliser les fonctions non-bloquantes
MPI_ISEND
etMPI_IRECV
suivies d'un appel àMPI_WAITALL
:processus 0 1 isend(vers 1) isend(vers 0) irecv( de 1) irecv( de 0) waitall() waitall()
Selon la machine, il est possible de modifier la valeur à partir de laquelle les messages sont envoyés en mode synchrone :
- sur Turing : la variable d'environnement
PAMID_EAGER
permet de fixer la taille de message à en octets partir de laquelle les envois seront synchrones (2049 par défaut), - sur Ada : la variable d'environnement
MP_EAGER_LIMIT
permet de fixer la taille de message à partir de laquelle les envois seront synchrones.
Si vous voulez vous assurer que votre application ne risque pas de souffrir de ce problème, il est conseillé de la tester en mettant ces variables d'environnement à 0 afin de forcer le mode synchrone pour tous les envois standards. Si tout se passe bien (pas de blocage), votre application ne devrait pas avoir ce soucis (sauf si vous variez vos schémas de communication).