Introduction à M.P.I. en Fortran

Documents pareils
Introduction à la Programmation Parallèle: MPI

Plan de la formation. Calcul parallèle avec MPI. Pourquoi paralléliser? Parallélisation. Présentation, environnement MPI. Communications point à point

MPI-1 2ème partie : Programmation «non bloquante» et communications de groupe

Plan du cours Cours théoriques. 29 septembre 2014

Grid Computing. Mihaela JUGANARU-MATHIEU École Nationale Supérieure des Mines de St Etienne

Les communications collectives. Caractéristiques. Communications dans un groupe de processus. Dans un communicateur donné.

Introduction to Parallel Programming with MPI

Cours Informatique Master STEP

Utilisation d objets : String et ArrayList

Cours 1 : Introduction. Langages objets. but du module. contrôle des connaissances. Pourquoi Java? présentation du module. Présentation de Java

Introduire un nouveau type de maille ou un nouvel élément de référence

Algorithmique et programmation : les bases (VBA) Corrigé

Cours d initiation à la programmation en C++ Johann Cuenin

Parallélisme et Répartition

LES TYPES DE DONNÉES DU LANGAGE PASCAL

Introduction à MATLAB R

Algorithmique et Programmation, IMA

Bases de programmation. Cours 5. Structurer les données

Runtime. Gestion de la réactivité des communications réseau. François Trahay Runtime, LaBRI sous la direction d'alexandre Denis Université Bordeaux I

Info0101 Intro. à l'algorithmique et à la programmation. Cours 3. Le langage Java

1 Description générale de VISFIELD

Chap III : Les tableaux

ALGORITHMIQUE ET PROGRAMMATION En C

Programmation parallèle et distribuée

Chapitre 5 : Les procédures stockées PL/SQL

1. Structure d'un programme FORTRAN 95

PVM 1 PVM. Parallel Virtual Machine

Architecture des Systèmes d Information Architecture des Systèmes d Information

Systèmes parallèles et distribués

1 Introduction - Qu est-ce que le logiciel R?

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

D2.2 Définition des mécanismes minimaux d un runtime tolérant aux pannes dans les infrastructures Petascale

Algorithme. Table des matières


Licence Sciences et Technologies Examen janvier 2010

Cours d introduction à l informatique. Partie 2 : Comment écrire un algorithme? Qu est-ce qu une variable? Expressions et instructions

TP1 : Initiation à Java et Eclipse

R, Bonnes pratiques. Christophe Genolini

Cours intensif Java. 1er cours: de C à Java. Enrica DUCHI LIAFA, Paris 7. Septembre Enrica.Duchi@liafa.jussieu.fr

Table des matières PRESENTATION DU LANGAGE DS2 ET DE SES APPLICATIONS. Introduction

Contexte. Pour cela, elles doivent être très compliquées, c est-à-dire elles doivent être très différentes des fonctions simples,

IRL : Simulation distribuée pour les systèmes embarqués

Plan. École Supérieure d Économie Électronique. Plan. Chap 9: Composants et systèmes de sécurité. Rhouma Rhouma. 21 Juillet 2014

L informatique en BCPST

Manuel d utilisation 26 juin Tâche à effectuer : écrire un algorithme 2

M06/5/COMSC/SP1/FRE/TZ0/XX INFORMATIQUE NIVEAU MOYEN ÉPREUVE 1. Mardi 2 mai 2006 (après-midi) 1 heure 30 minutes INSTRUCTIONS DESTINÉES AUX CANDIDATS

Ensimag 1ère année Algorithmique 1 Examen 2ième session 24 juin Algorithmique 1

Travaux pratiques. Compression en codage de Huffman Organisation d un projet de programmation

Initiation à la Programmation en Logique avec SISCtus Prolog

TP 2 Réseaux. Adresses IP, routage et sous-réseaux

Programmation C. Apprendre à développer des programmes simples dans le langage C

Débuter avec EXPRESS. Alain Plantec. 1 Schema 2

OCL - Object Constraint Language

BACCALAURÉAT PROFESSIONNEL ÉPREUVE DE MATHEMATIQUES. EXEMPLE DE SUJET n 2

Java Licence Professionnelle CISII,

as Architecture des Systèmes d Information

THEME : CLES DE CONTROLE. Division euclidienne

Cours 1 : Introduction Ordinateurs - Langages de haut niveau - Application

C++ Programmer. en langage. 8 e édition. Avec une intro aux design patterns et une annexe sur la norme C++11. Claude Delannoy

DM 1 : Montre Autoquartz ETA

Chapitre I Notions de base et outils de travail

LES OUTILS D ALIMENTATION DU REFERENTIEL DE DB-MAIN

Cours de Programmation en Langage Synchrone SIGNAL. Bernard HOUSSAIS IRISA. Équipe ESPRESSO

Premiers Pas en Programmation Objet : les Classes et les Objets

1 Définition et Appel d une fonction. V. Phan Luong. Cours 4 : Fonctions

Python - introduction à la programmation et calcul scientifique

1/24. I passer d un problème exprimé en français à la réalisation d un. I expressions arithmétiques. I structures de contrôle (tests, boucles)

TD3: tableaux avancées, première classe et chaînes

Programmation parallèle et distribuée

RACCOURCIS CLAVIERS. DEFINITION : Une «combinaison de touches» est un appui simultané sur plusieurs touches.

Choisir le mode d envoi souhaité. Option 1 : Envoyer un SMS à un nombre réduit de numéros (0 10 )

Initiation à LabView : Les exemples d applications :

Université du Québec à Chicoutimi. Département d informatique et de mathématique. Plan de cours. Titre : Élément de programmation.

Informatique Générale

STAGE IREM 0- Premiers pas en Python

Vous revisiterez tous les nombres rencontrés au collège, en commençant par les nombres entiers pour finir par les nombres réels.

UEO11 COURS/TD 1. nombres entiers et réels codés en mémoire centrale. Caractères alphabétiques et caractères spéciaux.

Rappel. Analyse de Données Structurées - Cours 12. Un langage avec des déclaration locales. Exemple d'un programme

Présentation du langage et premières fonctions

Conventions d écriture et outils de mise au point

1 Introduction et installation

Skype (v2.5) Protocol Data Structures (French) Author : Ouanilo MEDEGAN

Représentation d un entier en base b

Rappels sur les suites - Algorithme

SIP. Plan. Introduction Architecture SIP Messages SIP Exemples d établissement de session Enregistrement

Mesurer les performances (CPU) sous Linux

Institut Supérieure Aux Etudes Technologiques De Nabeul. Département Informatique

IV- Comment fonctionne un ordinateur?

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Exclusion Mutuelle. Arnaud Labourel Courriel : arnaud.labourel@lif.univ-mrs.fr. Université de Provence. 9 février 2011

Gestion de clusters de calcul avec Rocks

Chapitre 2. Classes et objets

Programmation parallèle et distribuée

Langage et Concepts de ProgrammationOrientée-Objet 1 / 40

Aide - mémoire gnuplot 4.0

21 mars Simulations et Méthodes de Monte Carlo. DADI Charles-Abner. Objectifs et intérêt de ce T.E.R. Générer l'aléatoire.

Cours 1: Java et les objets

Langage propre à Oracle basé sur ADA. Offre une extension procédurale à SQL

Transcription:

Introduction à M.P.I. en Fortran Nicolas Kielbasiewicz 17 novembre 2009 M.P.I. signifie Message Passing Interface. C est une bibliothèque disponible en C, C++ et Fortran qui permet dans un code parallèle ou réparti de gérer les échanges de messages entre les différents processeurs (ou nœuds). Toutes les informations concernant cette librairie sont disponibles sur le site : http ://www.mpi.org/ L objectif de ce petit document n est pas de donner une liste exhaustive des diverses fonctionnalités de la librairie M.P.I. la documentation disponible sur le lien précédent est faite pour ça, mais plutôt de donner un aperçu des fonctions les plus couramment utilisées, ainsi que les fonctionnalités que j ai personnellement eu du mal à trouver dans les docs disponibles sur le net, dans l esprit d un aide-mémoire. Il ne sera pas question ici non plus de présenter MPI-2. Par ailleurs, seules les syntaxes en Fortran seront données, avec le type de chacun des arguments. Sous cette forme, il y a un argument supplémentaire ierr qui désigne la variable d erreur. Elle n existe pas en C/C++. Table des matières 1 L environnement de base 2 1.1 Que faire pour pouvoir écrire des commandes M.P.I. dans un code?............ 2 1.2 Initialisation / Finalisation................................... 2 1.3 Prendre des mesures de temps.................................. 2 2 Communicateurs et topologies 3 2.1 Définir un communicateur.................................... 3 2.2 Rang et taille d un communicateur............................... 3 2.3 Subdiviser un communicateur.................................. 3 2.4 Créer une topologie cartésienne................................. 3 2.5 Coordonnées, rang et voisins dans une topologie cartésienne................. 4 3 Types de données 4 3.1 Types de base........................................... 4 3.2 Types dérivés........................................... 5 4 Communications point à point 5 4.1 Communications bloquantes................................... 5 4.2 Communications non bloquantes................................ 7 4.3 Communications persistantes.................................. 8 4.3.1 Définition......................................... 8 4.3.2 Équivalences entre communications persistantes et communications non bloquantes 8 Unité de Mathématiques Appliquées, École Nationale Supérieure de Techniques Avancées 1

5 Communications collectives 9 5.1 Envois et réceptions collectifs.................................. 9 5.2 Opérations de réduction..................................... 9 6 Et en C, comment ça marche? 10 1 L environnement de base 1.1 Que faire pour pouvoir écrire des commandes M.P.I. dans un code? Quel que soit le langage, il suffit de charger un fichier d en-tête qui s appelle mpif.h. Eventuellement, il faudra préciser à la compilation où se trouve ce fichier. Fortran90 et ses successeurs proposent une autre solution : utiliser le module mpi à l aide de la commande use mpi. La seule contrainte est que le module doit avoir été compilé avec le compilateur que vous utilisez pour votre propre code de calcul. Le cas échéant, il faudra le faire soi-même, ce qui n est pas très compliqué. Cette solution propose un avantage indéniable du fait que M.P.I. est considéré ici comme un module : la vérification de type et de syntaxe, évitant ainsi les conversions de type implicites, comme entre les entiers et les booléens. C est la raison pour laquelle non seulement la syntaxe Fortran qui donnée dans ce document sera celle de Fortran90, respectant ainsi le type véritable de chacun des arguments, mais aussi la solution que je vous conseille d utiliser, de par cette rigueur syntaxique imposée, les compilateurs Fortran actuels gérant tout aussi bien Fortran77 que Fortran90. 1.2 Initialisation / Finalisation Pour autoriser l utilisation des commandes M.P.I., il faut que celles-ci soient comprises entre l appel de deux routines particulières, dont la syntaxe est : MPI INIT ( i e r r ) MPI FINALIZE( i e r r ) Toute commande M.P.I. appelée en dehors des deux appels de ces deux routines ou l absence de l un de ces deux appels donnera une erreur de compilation. 1.3 Prendre des mesures de temps Pour mesurer les performances de vos algorithmes en terme de vitesse d exécution, M.P.I. propose une fonction permettant de récupérer le temps CPU, et ainsi de pouvoir évaluer le temps de calcul par différence. double p r e c i s i o n MPI WTIME( ) Il suffit donc d appeler cette commande au début de votre algorithme et à la fin, puis de faire la différence entre les deux valeurs. Une remarque cependant : pour que ces mesures de temps aient un sens, il fait que chaque processus l exécute en même temps. On précédera donc tout appel de MPI_WTIME par l appel de routine de synchronisation de tous les processeurs d un communicateur donné : MPI BARRIER(comm, i e r r ) i n t e g e r, i n t e n t ( in ) : : comm Cette notion de communicateur fait l objet de la section suivante. 2

2 Communicateurs et topologies 2.1 Définir un communicateur Le communicateur est l environnement dans lequel les envois et réceptions de données entre différents nœuds ont lieu. C est donc un environnement dans lequel sera appelé les routines M.P.I.. Par défaut, il existe un communicateur utilisable avec la variable MPI_COMM_WORLD. Mais M.P.I. propose de définir de manière simple un communicateur, à l aide de la commande suivante : MPI COMM CREATE(comm, newgroup, newcomm, i e r r ) i n t e g e r, i n t e n t ( in ) : : comm, newgroup i n t e g e r, i n t e n t ( out ) : : newcomm, i e r r On lui donne dans l ordre le communicateur source existant, le numéro du groupe à créer et le nouveau communicateur à créer. Il existe d autres façons de définir des communicateurs. 2.2 Rang et taille d un communicateur Dans un communicateur, chaque nœud de calcul (ou chaque processus) est identifié par un entier, son rang. À partir du moment où l on peut définir plusieurs communicateurs, ce rang peut avoir une valeur différente dans des communicateurs différents. M.P.I. permet alors de récupérer le rang d un nœud dans un communicateur donné, ainsi que le nombre de nœuds d un communicateur donné : MPI COMM RANK(comm, rank, i e r r ) i n t e g e r, i n t e n t ( in ) : : comm i n t e g e r, i n t e n t ( out ) : : rank, i e r r MPI COMM SIZE(comm, nprocs, i e r r ) i n t e g e r, i n t e n t ( in ) : : comm i n t e g e r, i n t e n t ( out ) : : nprocs, i e r r 2.3 Subdiviser un communicateur M.P.I. permet de définir un nouveau communicateur par subdivision d un autre communicateur suivant un critère donné (appelé couleur) : MPI COMM SPLIT (comm, couleur, rank, nouveau comm, i e r r ) i n t e g e r, i n t e n t ( in ) : : comm, couleur, rank i n t e g e r, i n t e n t ( out ) : : nouveau comm, i e r r On crée ainsi un communicateur pour chaque valeur possible de la couleur. L exemple typique est la création des communicateurs contenant respectivement les nœuds de rang pair et les nœuds de rang impair. La couleur sera alors le rang modulo 2. 2.4 Créer une topologie cartésienne Dans un communicateur, on aimerait pouvoir maîtriser la numérotation des nœuds. Pour cela on peut définir un une topologie cartésienne à ndims-dimensions à l aide de la routine suivante : MPI CART CREATE(comm, ndims, dims, periods, reorder, comm cart, i e r r ) i n t e g e r, i n t e n t ( in ) : : comm, ndims i n t e g e r, dimension ( ndims ), i n t e n t ( in ) : : dims l o g i c a l, dimension ( ndims ), i n t e n t ( in ) : : p e r i o d s l o g i c a l, i n t e n t ( in ) : : r e o r d e r i n t e g e r, i n t e n t ( out ) : : comm cart, i e r r 3

Le tableau dims précise le nombre de nœuds dans chacune des dimensions, tandis que le tableau periods précise si la topologie est périodique dans une ou plusieurs dimensions données. Le booléen reorder sert à autoriser/interdire le réordonnancement des nœuds entre eux par M.P.I.. Dans la grande majorité des cas, vous souhaiterez l interdire en l initialisant à.false.. Remarque. La création d une topologie cartésienne dans un communicateur s accompagne de la création d un nouveau communicateur. 2.5 Coordonnées, rang et voisins dans une topologie cartésienne Puisque le communicateur que l on vient de créer est muni d une topologie cartésienne, la notion de coordonnées d un nœud a un sens dans ce communicateur. On récupèrera les coordonnées d un nœud donné (pas nécessairement le nœud courant) à l aide de la routine : MPI CART COORDS(comm, rank, ndims, coords, i e r r ) i n t e g e r, i n t e n t ( in ) : : comm, rank, ndims i n t e g e r, dimension ( ndims ), i n t e n t ( out ) : : coords À l inverse, il est possible à partir des coordonnées d un nœud de retrouver son rang à l aide de la routine : MPI CART RANK( comm cart, coords, rank, i e r r ) i n t e g e r, i n t e n t ( in ) : : comm cart i n t e g e r, dimension ( ndims ), i n t e n t ( in ) : : coords i n t e g e r, i n t e n t ( out ) : : rank, i e r r Si cela concerne le nœud courant, rien n empêche toutefois d utiliser MPI_COMM_RANK. De même, la topologie cartésienne permet d introduire la notion de voisins à une distance donnée dans un direction donnée et de les récupérer à l aide de la routine : MPI CART SHIFT( comm cart, d i r e c t i o n, distance, rank previous, rank next, i e r r ) i n t e g e r, i n t e n t ( in ) : : comm cart, d i r e c t i o n, d i s t a n c e i n t e g e r, i n t e n t ( out ) : : rank previous, rank next, i e r r Si le voisin n existe pas, alors le rang sera initialisé à -1, ou MPI_PROC_NULL, qui est la variable consacrée (et vaut -1). 3 Types de données Lors des communications, nous allons devoir préciser de quel type de données il s agit. Pour les types usuels, il existe des types de données M.P.I.. 3.1 Types de base Tous les types de base Fortran ont leur correspondance en terme de type de donnée M.P.I.. Type Fortran integer real double precision complex logical character Type M.P.I. mpi integer mpi real mpi double precision mpi complex mpi logical mpi character 4

3.2 Types dérivés Tout comme en Fortran, il est possible en M.P.I. de définir ses propres types de données. Par exemple, on souhaiterait définir un type de donnée permettant d extraire des blocs d éléments non continus en mémoire mais régulièrement espacés. Imaginez par exemple que vous voulez envoyer une ligne ou un bloc de lignes d un tableau 2D, en se rappelant qu en Fortran, les éléments d un tableau 2D sont rangés dans l ordre des colonnes. En M.P.I., vous pouvez réaliser cette opération en définissant un type dérivé à l aide des routines : MPI TYPE VECTOR( Nelem, t a i l l e B l o c, decalage, typeelem, nouveautype, i e r r ) i n t e g e r, i n t e n t ( in ) : : Nelem, t a i l l e B l o c, decalage, typeelem i n t e g e r, i n t e n t ( out ) : : nouveautype, i e r r MPI TYPE COMMIT( nouveautype, i e r r ) i n t e g e r, i n t e n t ( in ) : : nouveautype MPI_TYPE_VECTOR permet de définir son type de données tandis que MPI_TYPE_COMMIT permet de publier un type que vous avez défini dans l environnement M.P.I., vous permettant ainsi de l utiliser à loisirs comme un type de base dans vos communications. Reprenons notre exemple de lignes d un tableau 2D. Considérons une matrice rectangulaire entière contenant 5 lignes et 6 colonnes, et que vous souhaitez par exemple pouvoir échanger 3 lignes complètes. Puisque les éléments d une colonne sont continus en mémoire, vous allez donc définir un type de donnée que vous appelerez par exemple LIGNE de la manière suivante : call MPI TYPE VECTOR(6,3,5,MPI INTEGER, LIGNE, ierr) Il s agit en effet de blocs de 3 éléments (3 lignes), qu il y a 6 blocs à assembler (parce que 6 colonnes) et que ces blocs sont espacés en mémoire de 5 (nombre de lignes). Remarque. En Fortran, il est inutile de définir un type colonne parce que les éléments sont continus en mémoire. Si vous le souhaitez toutefois, vous avez 2 possibilités. Dans notre exemple, vous pouvez définir une colonne comme un bloc de 5 éléments, ou comme 5 blocs de 1 élément et espacés de 1. Nous allons donc maintenant aborder le cœur de la librairie M.P.I., à savoir la façon de communiquer des données entre nœuds. 4 Communications point à point On appelle communication «point à point» toute communication entre exactement 2 nœuds. On l appelle aussi «communication de un à un». Ces communications permettent d envoyer une ou plusieurs données d un type M.P.I. donné à condition qu elles soient continues en mémoire, un tableau de doubles, un paquet de lignes,... Il en existe plusieurs types. 4.1 Communications bloquantes Une communication est dite bloquante lorsqu elle empêche la poursuite de l exécution d un programme tant que la communication n est pas entièrement réalisée. C est le comportement assez classique de toute instruction en Fortran, exécutée de manière séquentielle. Les routines permettant d effectuer des communications bloquantes sont : MPI RECV( buf, count, datatype, source, tag, comm, status, i e r r ) i n t e g e r, i n t e n t ( in ) : : source, count, datatype, tag, comm 5

<type >, dimension ( : ), i n t e n t ( out ) : : buf i n t e g e r, dimension (MPI STATUS SIZE), i n t e n t ( out ) : : s t a t u s MPI SEND( buf, count, datatype, dest, tag, comm, i e r r ) <type >, dimension ( : ), i n t e n t ( in ) : : buf i n t e g e r, i n t e n t ( in ) : : dest, count, datatype, tag, comm MPI SENDRECV( sendbuf, sendcount, sendtype, dest, sendtag, recvbuf, recvcount, recvtype, source, recvtag, comm, status, i e r r ) <type >, i n t e n t ( in ) : : sendbuf ( ) i n t e g e r, i n t e n t ( in ) : : dest, source, sendcount, recvcount, sendtype, recvtype, sendtag, recvtag, comm i n t e g e r, dimension (MPI STATUS SIZE), i n t e n t ( out ) : : s t a t u s Leurs noms sont assez explicites et leurs syntaxe assez proche. Quelle est la signification de chacun des arguments? buf, count, datatype : Ces 3 arguments permettent de spécifier le nombre de données envoyées (count), leur type (datatype) au sens de M.P.I., et qui est le premier élément envoyé / reçu (<type> désigne le type Fortran de la variable buf). C est la raison pour laquelle on peut donner le tableau complet ou uniquement le premier élement d un tableau en guise de premier argument. source / dest : rang du nœud qui envoie / reçoit, celui qui effectue la communication étant le nœud appelant la routine. tag : permet de donner un numéro d identification à la communication. L intérêt est de pouvoir distinguer plusieurs envois ou réceptions d un nœud à un autre (voir l exemple ci-dessous). comm : le communicateur dans lequel la communication est faite. status : tableau donnant des informations sur le déroulement de l envoi / réception. La routine MPI_SENDRECV est en fait un MPI_SEND suivi d un MPI_RECV. C est une commande très utile car elle correspond à une bonne organisation des communications. Pour bien comprendre son rôle, traitons un cas simple : celui d un envoi d une donnée entière i du nœud 0 au nœud 1, et de la même donnée entière i du nœud 1 au nœud 2, schématisée ci-dessous. entier i entier i nœud 0 nœud 1 nœud 2 Ces deux communications sont de même nature et peuvent être traitée simultanément. Comment procéder? Si je regarde ces communications de leur point de départ, je vais considérer qu il s agit d un envoi d un entier à mon voisin de droite rank_next. SI maintenant je les regarde de leur point d arriver, je dirai qu il s agit d une réception d un entier de mon voisin de gauche rank_previous. Rappelons que es deux voisins peuvent être définis à l aide de MPI_CART_SHIFT que nous avons vu plus tôt. Cette même communication peut donc être vue comme un envoi ou une réception. Il s agit en fait des deux. C est la raison pour laquelle je vais traiter les deux en même temps, en écrivant : 6

... c a l l MPI SEND( i, 1 MPI INTEGER, rank next, 1 0 0,MPI COMM WORLD, i e r r ) c a l l MPI RECV( i, 1 MPI INTEGER, rank previous, 1 0 0,MPI COMM WORLD, i e r r )... Remarque. La valeur du tag dans les deux appels est la même, puisqu il s agit de la même communication. C est là la signification de cet argument, à savoir coupler un envoi à la réception qui lui correspond, permettant ainsi d identifier de manière unique tout échange de données. Le nœud 2 va lui aussi envoyer l entier i à son voisin de droite. Hors, celui-ci n existe pas (son rang sera -1), l envoi n aura donc pas lieu. De même, 0 n ayant pas de voisin de gauche, il n en recevra pas de données. Ces deux éléments nous permettent de comprendre qu en dépit du bon sens, nous aurions très bien pu écrire la réception avant l envoi. Je dis «en dépit du bon sens», car tout nœud n a besoin d attendre quoi que ce soit pour envoyer des données à son voisin de droite, alors qu il doit attendre que son voisin de gauche ait envoyé des données pour qu il les reçoive. En pratique, vous écrirez donc toujours un appel de MPI_SEND suivi d un appel de MPI_RECV. La commande MPI_SENDRECV permet de regrouper ces deux appels. Remarque. Il n existe pas de routine MPI_RECVSEND, la logique voulant que l envoi ait lieu avant la réception, comme nous venons de le voir. 4.2 Communications non bloquantes Les communications non bloquantes laissent le programme poursuivre son exécution, que la communication soit réellement faite ou non. Elle présentent donc un avantage indéniable en terme de temps d exécution puisqu un nœud peut travailler tout en envoyant des données. Les routines liées à des communications non bloquantes sont : MPI IRECV( buf, count, datatype, dest, tag, comm, request, i e r r ) i n t e g e r, i n t e n t ( in ) : : count, datatype, dest, tag, comm <type >, dimension ( : ), i n t e n t ( out ) : : buf MPI ISEND( buf, count, datatype, dest, tag,comm, i e r r ) <type >, dimension ( : ), i n t e n t ( in ) : : buf i n t e g e r, i n t e n t ( in ) : : dest, count, datatype, tag, comm MPI WAIT( request, status, i e r r ) i n t e g e r, i n t e n t ( in ) : : r e q u e s t i n t e g e r, dimension (MPI STATUS SIZE ), i n t e n t ( out ) : s t a t u s MPI WAITALL( count, request tab, s t a t u s t a b, i e r r ) i n t e g e r, dimension ( : ), i n t e n t ( in ) : : r e q u e s t t a b i n t e g e r, i n t e n t ( in ) : : count i n t e g e r, dimension (MPI STATUS SIZE, : ), i n t e n t ( out ) : : s t a t u s t a b Les deux dernières commandes permettent d attendre que les communications non bloquantes aient été effectuées avant de poursuivre l exécution. A utiliser par exemple lorsque les données échangées doivent être utilisées. 7

Les arguments ont la même signification que pour les communications bloquantes. Seul l entier request est inédit, il contient des informations sur la communication elle-même. C est cet argument qui est utilisé pour les routines MPI_WAIT et MPI_WAITALL. Remarque. Puisque request contient des informations liées à une commande de communication non bloquante, et qu il est possible de passer un tableau en argument de MPI_WAITALL, je vous conseille de définir request comme un tableau d entiers de rang 1 et de taille le nombre de réceptions non bloquantes effectuées par votre code. 4.3 Communications persistantes 4.3.1 Définition Les communications persistantes sont une autre façon d écrire des communications non bloquantes. En effet, on définit les communications à effectuer, mais sans les exécuter. On dispose alors de commandes spécifiques pour lancer l exécution de ces communications. MPI RECV INIT( buf, count, datatype, source, tag, comm, request, i e r r ) i n t e g e r, i n t e n t ( in ) : : count, datatype, source, tag, comm <type >, dimension ( : ), i n t e n t ( out ) : : buf i n t e g e r, i n t e n t ( out ) : : request, i e r r MPI SEND INIT( buf, count, datatype, dest, tag, comm, request, i e r r ) <type >, dimension ( : ), i n t e n t ( in ) : : buf i n t e g e r, i n t e n t ( in ) : : count, datatype, dest, tag, comm i n t e g e r, i n t e n t ( out ) : : request, i e r r MPI START( request, i e r r ) i n t e g e r, i n t e n t ( in ) : : r e q u e s t MPI STARTALL( count, request tab, i e r r ) i n t e g e r, i n t e n t ( in ) : : count i n t e g e r, dimension ( : ), i n t e n t ( in ) : : r e q u e s t t a b MPI REQUEST FREE( request, i e r ) i n t e g e r, i n t e n t ( in ) : : r e q u e s t Cette dernière commande permet de libérer les communications persistantes, d empêcher leur utilisation dans ce qui suit, un peu comme de la libération mémoire ou de la désallocation. Remarque. Il est à noter que l argument request apparaît aussi dans les envois. Fort de la remarque précédente, on fixera sa taille à l ensemble des communications persistantes. 4.3.2 Équivalences entre communications persistantes et communications non bloquantes Les communications persistantes étant non bloquantes, il existe des équivalences entre les deux syntaxes, que ce soit la commuication en elle-même, où l attente de son exécution : c a l l MPI IRECV (..., request, i e r )... c a l l MPI WAIT( request, status, i e r ) c a l l MPI RECV INIT (..., request, i e r ) c a l l MPI START( request, i e r )... c a l l MPI WAIT( request, status, i e r ) c a l l MPI REQUEST FREE( request, i e r ) 8

5 Communications collectives Jusque là, nous avons vu les communications entre un nœud et un autre nœud. M.P.I. permet également des communications dites collectives, mettant en jeu d une façon ou d une autre tous les processeurs. 5.1 Envois et réceptions collectifs MPI BCAST( b u f f e r, count, datatype, root, comm, i e r r ) i n t e g e r, i n t e n t ( in ) : : count, datatype, root, comm <type >, dimension ( : ), i n t e n t ( inout ) : : buf i n t e g e r, i n t e n t ( inout ) : : i e r r MPI SCATTER( sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm, i e r r ) <type >, dimension ( : ), i n t e n t ( in ) : : sendbuf i n t e g e r, i n t e n t ( in ) : : sendcount, sendtype, recvcount, recvtype, root, comm MPI GATHER( sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, root, comm, i e r r ) <type >, dimension ( : ), i n t e n t ( in ) : : sendbuf i n t e g e r, i n t e n t ( in ) : : sendcount, sendtype, recvcount, recvtype, root, comm MPI_BCAST permet au nœud root de communiquer des données à tous les nœuds du communicateur. MPI_SCATTER permet de décomposer en part égales de données et de distribuer ces parts à chacun des nœuds. MPI_GATHER permet d effectuer l opération inverse, c est à dire concaténer des données de même nature envoyées à un même nœud. Ces 3 routines permettent de mettre en œuvre des «communications de un à tous». Il existe également des communications dites de «tous à tous». Par exemple, la généralisation de MPI_GATHER où le résultat concaténé sera récupéré par l ensemble des nœuds : MPI ALLGATHER( sendbuf, sendcount, sendtype, recvbuf, recvcount, recvtype, comm, i e r r ) <type >, dimension ( : ), i n t e n t ( in ) : : sendbuf i n t e g e r, i n t e n t ( in ) : : sendcount, sendtype, recvcount, recvtype, comm 5.2 Opérations de réduction Il est également possible de faire ce que l on appelle une opération de réduction en appelant : MPI REDUCE( sendbuf, recvbuf, count, datatype, operation, root, comm, i e r r ) <type >, dimension ( : ), i n t e n t ( in ) : : sendbuf i n t e g e r, i n t e n t ( in ) : : count, datatype, root, operation, comm innteger, i n t e n t ( out ) : : i e r r 9

La variable désignée par operation est parmi la liste suivante : MPI MAX, MPI MIN, MPI SUM, MPI PROD, MPI BAND, MPI BOR, MPI BXOR, MPI LAND, MPI LOR, MPI LXOR. C est la commande que l on appellera lorsque l on a parallélisé le calcul d une somme et que l on veut calculer la somme totale comme étant la somme des valeurs des sommes partielles calculées sur chaque nœud. Là encore, il existe une version «tous à tous» appelée MPI_ALLREDUCE : MPI ALLREDUCE( sendbuf, recvbuf, count, datatype, operation,comm, i e r r ) <type >, dimension ( : ), i n t e n t ( in ) : : sendbuf i n t e g e r, i n t e n t ( in ) : : count, datatype, operation, comm innteger, i n t e n t ( out ) : : i e r r Cette fois-ci, tous les nœuds disposeront du résultat de l opération de réduction. Très utile par exemple pour calculer l erreur quadratique d une méthode itérative comme Jacobi, Gauss-Seidel,... 6 Et en C, comment ça marche? La syntaxe de chacune des commandes M.P.I. est assez proche de celle en Fortran. Il y a essentiellement 3 différences : 1. l argument ierr n existe pas en C, il est remplacé par une valeur de retour à chacune des fonctions appelée. 2. les types de données M.P.I.sont beaucoup plus nombreux. Prenons l argument status de MPI_Recv. En Fortran, c est un entier, alors qu en C, il est de type MPI_Status. De même, un nouveau type défini avec MPI_TYPE_VECTOR est de type MPI_Datatype en C alors qu il est entier en Fortran. 3. le nom des routines est sensible à la casse en C. Hormis MPI, chaque mot utilisé dans le nom d une routine commence par une majuscule. 10