VT2019 MPI

MPI (Message Passing Interface) est une norme de transmission de message qui permet de dialoguer entre des machine sur un reseau. Dans notre cas c'est une API qui permet de paralléliser du code avec un système d'envoie de message en langage C et C++.

=Introduction=

MPI est une spécification pour les développeurs et les utilisateurs de bibliothèques de transmission de messages. Ce n'est pas une bibliothèque, mais plutôt la spécification de ce qu'une telle bibliothèque devrait être.

MPI s'adresse principalement au modèle de programmation parallèle à transmission de messages: les données sont déplacées de l'espace d'adressage d'un processus vers celui d'un autre processus via des opérations coopératives sur chaque processus (On appellera cela routine par la suite).

En termes simples, l'objectif de l'interface de transmission de messages est de fournir une norme largement utilisée pour l'écriture de programmes de transmission de messages. L'interface tente d'être:
 * Pratique
 * Portable
 * Efficace
 * Flexible

=Principe de fonctionnement=

MPI_DATATYPE
De nombreuses fonctions MPI exigent que vous spécifiiez le type de données qui est envoyé entre les processus. En effet, MPI vise à supporter des environnements hétérogènes où les types peuvent être représentés différemment sur les différents réseau (par exemple, ils peuvent exécuter différentes architectures de CPU), auquel cas les implémentations MPI peuvent effectuer une conversion de données. Puisque le langage C ne permet pas de passer un type lui-même en paramètre, MPI prédéfinit les constantes MPI_INT, MPI_CHAR, MPI_DOUBLE pour correspondre avec int, car, double, etc.

Architecture
Grâce a des routines nous pouvons envoyer des message dans le réseau avec des données. Les objets communicateurs connectent des groupes de processus dans un réseau MPI. Chaque communicateur donne à chaque processus confiné un identificateur indépendant (nous allons utilser 'rank' par la suite) et organise ses processus confinés dans une topologie ordonnée.

MPI gère les opérations intracommunicateurs d'un seul groupe et les communications bilatérales intercommunicateurs.

Les communicateurs peuvent être partitionnés à l'aide de plusieurs commandes MPI. Ces commandes incluent MPI_COMM_SPLIT, où chaque processus rejoint l'un de plusieurs sous-communicateurs dis colorés en se déclarant d'avoir cette couleur.



Par exemple dans ce cas d'architecture chaque core CPU de chaque machine aura un 'rank' différent et seront tous dans le même communicateur. Par exemple les rank [0..3] seront sur la machine 1, rank[4..7] sur la machine 2, rank[8..11] sur la machine 3 et, rank [12..15] sur la machine 4. Toute ces machines seront donc connecter sur un même réseau.

Communication
Nous pouvons utiliser plusieurs sorte de communication :

la communication point à point
Cette communication permet a deux processus (machine ou core de CPU) de pouvoir s'envoyer des donné souvent des vecteur de nombre. Les routines qui permette de faire cela sont : sont MPI_Send, MPI_Recv et MPI_Sendrecv. Routine :
 * MPI_Send : int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) ou *buf est le pointeur sur le buffeur de donnée a envoyer, count le nombre d'élément envoyé, datatype est le type de donnée envoyé dans le buffer, dest est le rank de destination. Cette fonction permet d'envoyer 'count' donnée de taille 'datatype' suivant l'adresse '*buf' vers le processus numéro 'rank'


 * MPI_Revc : int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status) qui permet de recevoir des donnée de la source, elle est l'inverse de la fonction MPI_Send.


 *  MPI_Sendrecv : int MPI_Sendrecv(const void *sendbuf, int sendcount, MPI_Datatype sendtype, int dest, int sendtag, void *recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status *status). Cette fonction permet d'envoyer et de recevoir des donnée vers/depuis un processus.

la communication collective
La communication collective permet a tous les processus d'un réseau de recevoir un message d'un autre processus. Pour ce faire nous avons accès a 2 routines : MPI_Bcast et MPI_Scatter.
 *  MPI_Bcast : int MPI_Bcast( void *buffer, int count, MPI_Datatype datatype, int root, MPI_Comm comm ). Cette fonction permet d'envoyer un message depuis le numéro 'rank' vers tout les processus d'un réseau.


 *  MPI_Scatter : int MPI_Scatter(const void *sendbuf, int sendcount, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm). Cette fonction permet à un processus du reseau d'envoyer un message vers tout les autre processus du réseau.

=Cas d'utilisation= Ci dessous un code 'HelloWorld' qui permet d'afficher le message helloworld depuis tout les processus :

Dans le cas de notre démonstration nous allons faire de l'accélération de code sur des multiplications de matrice simple en utilisant un cluster de plusieurs Raspberry Pi. Le but de cette démonstration permet de voir qu'un cluster peut être plus rapide qu'un ordinateur normal.

Ce genre de bibliothèque est utile lors de l’accélération de code pour du HPC (High Performance Computing). MPI est peut être plus intéressant que du OpenMP car nous pouvons,grâce a MPI, dialoguer avec des processus extérieur à une seule machine.

=Source=
 * https://computing.llnl.gov/tutorials/mpi/
 * https://fr.wikipedia.org/wiki/Message_Passing_Interface
 * https://www.mpich.org/static/docs/v3.2/www3/index.htm
 * https://mpitutorial.com/tutorials/mpi-hello-world/

=Veille Technologique 2019=
 * Année : VT2019
 * Sujet : MPI
 * Slides : [[Media:|MPIpdf]]
 * Démonstration : []
 * Auteurs : Guillaume DENIS, Bastien DE ARAUJO