Pourquoi des communications non bloquantes? Deadlock! (embrasse mortelle) communicator

Documents pareils
Introduction à la Programmation Parallèle: MPI

Systèmes parallèles et distribués

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

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

Introduction to Parallel Programming with MPI

Cours de Systèmes d Exploitation

1. Structure d un programme C. 2. Commentaire: /*..texte */ On utilise aussi le commentaire du C++ qui est valable pour C: 3.

Programmation parallèle et distribuée

Processus! programme. DIMA, Systèmes Centralisés (Ph. Mauran) " Processus = suite d'actions = suite d'états obtenus = trace

INTRODUCTION AUX SYSTEMES D EXPLOITATION. TD2 Exclusion mutuelle / Sémaphores

Centre CPGE TSI - Safi 2010/2011. Algorithmique et programmation :

Les processus légers : threads. Système L3, /31

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

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)

INITIATION AU LANGAGE C SUR PIC DE MICROSHIP

Programmation système de commandes en C

Les structures. Chapitre 3

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

Exceptions. 1 Entrées/sorties. Objectif. Manipuler les exceptions ;

OS Réseaux et Programmation Système - C5

Dans le chapitre 1, nous associions aux fichiers ouverts des descripteurs de fichiers par lesquels nous accédions aux fichiers.

Projet Active Object

Cahier des charges. driver WIFI pour chipset Ralink RT2571W. sur hardware ARM7

SNT4U16 - Initiation à la programmation TD - Dynamique de POP III - Fichiers sources

Cours d Algorithmique-Programmation 2 e partie (IAP2): programmation 24 octobre 2007impérative 1 / 44 et. structures de données simples

Programme Compte bancaire (code)


Introduction à la programmation concurrente

Architecture des ordinateurs

Les structures de données. Rajae El Ouazzani

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

IN Cours 1. 1 Informatique, calculateurs. 2 Un premier programme en C

as Architecture des Systèmes d Information

INFO-F-404 : Techniques avancées de systèmes d exploitation

Le prototype de la fonction main()

Les arbres binaires de recherche

Plan du cours Cours théoriques. 29 septembre 2014

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

MISE A NIVEAU INFORMATIQUE LANGAGE C - EXEMPLES DE PROGRAMMES. Université Paris Dauphine IUP Génie Mathématique et Informatique 2 ème année

Cours de Programmation Impérative: Zones de mémoires et pointeurs

STS SE. FreeRTOS. Programmation réseau WIFI. Programmation réseau. Socket Tcp. FlyPort smart Wi-Fi module

Introduction au langage C

Introduction à Java. Matthieu Herrb CNRS-LAAS. Mars

Langage C. Patrick Corde. 22 juin Patrick Corde ( Patrick.Corde@idris.fr ) Langage C 22 juin / 289

Chapitre 4 : Exclusion mutuelle

#include <stdio.h> #include <stdlib.h> struct cell { int clef; struct cell *suiv; };

Plan du Travail. 2014/2015 Cours TIC - 1ère année MI 30

DNS Server RPC Interface buffer overflow. Céline COLLUMEAU Nicolas BODIN

Threads. Threads. USTL routier 1

Chapitre 1 : La gestion dynamique de la mémoire

Problèmes liés à la concurrence

Brefs rappels sur la pile et le tas (Stack. / Heap) et les pointeurs

Cette application développée en C# va récupérer un certain nombre d informations en ligne fournies par la ville de Paris :

Plateforme «Inscription en ligne»

TP : Gestion d une image au format PGM

Introduction à la programmation orientée objet, illustrée par le langage C++ Patrick Cégielski

TP n 2 Concepts de la programmation Objets Master 1 mention IL, semestre 2 Le type Abstrait Pile

Plan du cours. Historique du langage Nouveautés de Java 7

Présentation du PL/SQL

Structure d un programme et Compilation Notions de classe et d objet Syntaxe

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

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

Mesure de performances. [Architecture des ordinateurs, Hennessy & Patterson, 1996]

L exclusion mutuelle distribuée

DHCP et NAT. Cyril Rabat Master 2 ASR - Info Architecture des réseaux d entreprise

Java Licence Professionnelle CISII,

Arguments d un programme

Conventions d écriture et outils de mise au point

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Argument-fetching dataflow machine de G.R. Gao et J.B. Dennis (McGill, 1988) = machine dataflow sans flux de données

COMPARAISONDESLANGAGESC, C++, JAVA ET

ACTIVITÉ DE PROGRAMMATION

Parallélisme et Répartition

Corrigé des TD 1 à 5

SYSTEME DE GESTION DES ENERGIES EWTS EMBEDDED WIRELESS TELEMETRY SYSTEM

TP1 : Initiation à Java et Eclipse

Algorithmique et Programmation, IMA

1. Structure d'un programme FORTRAN 95

ARDUINO DOSSIER RESSOURCE POUR LA CLASSE

Les fichiers. Chapitre 4

J2SE Threads, 1ère partie Principe Cycle de vie Création Synchronisation

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

Réseau longue distance et application distribuée dans les grilles de calcul : étude et propositions pour une interaction efficace

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

CORBA haute performance

PROJET 1 : BASE DE DONNÉES REPARTIES

EPREUVE OPTIONNELLE d INFORMATIQUE CORRIGE

Prénom : Matricule : Sigle et titre du cours Groupe Trimestre INF1101 Algorithmes et structures de données Tous H2004. Loc Jeudi 29/4/2004

4. Outils pour la synchronisation F. Boyer, Laboratoire Lig

GESTION DES FICHIERS C/UNIX

Développement d un logiciel de messagerie instantanée avec Dotnet (version simplifiée)

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

INITIATION AU LANGAGE JAVA

Communications performantes par passage de message entre machines virtuelles co-hébergées

Programmation C++ (débutant)/instructions for, while et do...while

Chapitre 2. Classes et objets

INITIATION A LA PROGRAMMATION

Licence Sciences et Technologies Examen janvier 2010

Julien MATHEVET Alexandre BOISSY GSID 4. Rapport RE09. Load Balancing et migration

Transcription:

Pourquoi des communications non bloquantes? Illustration : mettez la main gauche dans le dos et passez une enveloppe avec la main droite à votre voisin de droite...deadlock! comment pourrait-on résoudre ce pb? C est le cas du ping pong vu précédemment... En cas de non tamponnage MPI_Send est un rendez vous. Donc si je programme comme suit: if (je suis le processus 0) {MPI_Send (.., 1,..) ; MPI_Recv(..., 1,..); else { MPI_Send(..., 0,...); MPI_Recv(..., 0,...): je me retrouve avec 2 processus bloqués indéfiniment : ils ne peuvent réaliser le rendez-vous car aucun n a pu faire le Recv! Par contre s ill y a tamponnage, le code fonctionne... Hugues Leroy Cours de DEA CH 3.4 / 1 Hugues Leroy Cours de DEA CH 3.4 / 2 Deadlock! (embrasse mortelle) 1 5 2 3 4 communicator 0 Tentative de résolution : inscrire le numéro du destinataire sur l enveloppe, la poser au milieu, puis prendre celle qui nous est destinée. Hugues Leroy Cours de DEA CH 3.4 / 3 Hugues Leroy Cours de DEA CH 3.4 / 4

Communications non bloquantes La communication se fait maintenant comme suit : Initialiser la communication non bloquante (on poste une demande) Aller faire autre un autre travail ( peut-être ce travail fera-t-il aussi d autres communications?) Attendre la fin de la communication non bloquante. En fait si je sais qu à un certain moment dans le futur proche que j aurais besoin d une donnée transmise par un autre processus, je peux anticiper en disant au système de communication de noter l information que je lui fournis dans ma demande (dans ce cas une réception non bloquante). Si un message du type spécifié (tag) et de l émetteur spécifié arrive, alors le système pourra le ranger directement dans le tampon que je lui ai indiqué. Lorsque j aurais besoin de la donnée, alors je ferais un Wait(). Si elle est arrivée, alors je serais bien parvenu à faire un recouvrement calcul/communication. Hugues Leroy Cours de DEA CH 3.4 / 5 Hugues Leroy Cours de DEA CH 3.4 / 6 Envoi non bloquant 1 5 2 in 3 4 communicator out 0 L émetteur poste une demande d envoi. Il devra tester l état de la requête avant de ré-utiliser le tampon. Hugues Leroy Cours de DEA CH 3.4 / 7 Hugues Leroy Cours de DEA CH 3.4 / 8

Réception non bloquante 1 5 2 in 3 4 communicator out 0 Le récepteur poste une demande de réception. Il ira tester ensuite si quelque chose est arrivé Hugues Leroy Cours de DEA CH 3.4 / 9 Hugues Leroy Cours de DEA CH 3.4 / 10 Handles datatype : idem comm. bloquantes ( MPI_Datatype ou INTEGER ) communicateur :... ( MPI_Comm ou INTEGER ) valeur permettant de tester l état de la communication ( request handle ) : MPI_Request ou INTEGER Le runtime de la bibliothèque MPI me fournira un handle (un descripteur) pour chaque communication non bloquante. Et ce handle me permettra de tester l état de la communication associée. Hugues Leroy Cours de DEA CH 3.4 / 11 Hugues Leroy Cours de DEA CH 3.4 / 12

Envois non bloquants synchrones C: int MPI_Issend (void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request)... int MPI_Wait (MPI_Request *request, MPI_Status *status) Fortran: MPI_ISSEND (buf, count, datatype, dest, tag,comm, handle, ierror)... MPI_WAIT (handle, status, ierror) Hugues Leroy Cours de DEA CH 3.4 / 13 Hugues Leroy Cours de DEA CH 3.4 / 14 Réception non bloquante C : int MPI_Irecv (void *buf, int count, MPI_Datatype datatype, int src, int tag,mpi_comm comm, MPI_Request *handle) int MPI_Wait (MPI_Request *handle, MPI_Status *status) Fortran : MPI_IRECV (buf, count, datatype, src, tag,comm, handle, ierror) MPI_WAIT (handle, status, ierror) Hugues Leroy Cours de DEA CH 3.4 / 15 Hugues Leroy Cours de DEA CH 3.4 / 16

bloquant ou non bloquant? Les envois et les réceptions peuvent être bloquants ou non bloquants. On peut combiner envoi bloquant et réception non bloquante (et vice-versa) Les envois non bloquants peuvent utiliser n importe quel mode : synchrone, tamponné, standard ou ready Le mode synchrone affecte uniquement la terminaison de l opération. Attention, les communications non bloquantes consomment des ressources mémoire : l émetteur doit conserver un descripteur pour la requête, le récepteur doit aussi pouvoir tester l enveloppe. Les envois Bsend bloquants demandent aussi plus de mémoire et impliquent des tamponnages intermédiaires, alors que les comm. non bloquantes demandent au programmeur d utiliser plus de fonctions MPI... Attention aux hot spots (ex: un seul processus devant recevoir une floppée de messages ) Hugues Leroy Cours de DEA CH 3.4 / 17 Hugues Leroy Cours de DEA CH 3.4 / 18 Communications non bloquantes mode Envoi standard Envoi synchrone Envoi tamponné (Buffered) Ready send Réception MPI MPI_Isend MPI_Issend MPI_Ibsend MPI_Irsend MPI_Irecv Ce sont les mêmes modes que pour les comm. bloquantes : on a juste un grand I avant le nom de la fonction. Send devient Isend, Recv -> Irecv,... et un paramètre de plus (le handle de type MPI_Request) Hugues Leroy Cours de DEA CH 3.4 / 19 Hugues Leroy Cours de DEA CH 3.4 / 20

Terminaison on peut attendre la fin de l opération ou tester son état : C: int MPI_Wait (MPI_Request *handle, MPI_Status *status) int MPI_Test (MPI_Request *handle, int *flag, MPI_Status *status) flag vaudra vrai si la communication testée est terminée Fortran: MPI_WAIT (handle, status, ierror) MPI_TEST (handle, flag, status, ierror) Hugues Leroy Cours de DEA CH 3.4 / 21 Hugues Leroy Cours de DEA CH 3.4 / 22 Exercice 3 : communications sur un anneau Un ensemble de processus est sur un anneau virtuel : Chaque processus conserve (dans un entier) son rang dans MPI_COMM_WORLD. Chaque processus passe cet entier à son voisin de droite. Puis reçoit un entier de son voisin de gauche. Il continue à passer cette information jusqu à ce qu il reçoive de nouveau son rang. Chaque processus calcule la somme des rangs (somme de tout ce qui passe) On utilisera des communications bloquantes. Modifier le programme pour utiliser des communications non bloquantes. 0 1 3 2 Cet exercice doit être développé comme il est dit dans l énoncé! Vous pourrez simplement vérifier que votre résultat est correct en le comparant avec la formule adhoc : n*(n+1)/2 Dans la suite de ce cours, nous ferons le même exercice en utilisant une topologie virtuelle, ou une opération de réduction. Hugues Leroy Cours de DEA CH 3.4 / 23 Hugues Leroy Cours de DEA CH 3.4 / 24

Communications multiples Avec un seul appel de fonction MPI, on peut tester l état ou attendre la fin d une ou de plusieurs communications. int MPI_Testall(int count, MPI_Request array_of_requests[], int *flag, MPI_Status *array_of_statuses ) int MPI_Testsome (...) int MPI_Testany (...) int MPI_Waitall(...) int MPI_Waitany(...) int MPI_Waitsome(...) Pour le manuel d utilisation des diverses fonctions, on peut aussi commander sous Unix (ou Linux) : man -M /home/mpi/man MPI_Waitany... consultez le manuel! par ex: commande mpiman -netscape pour mpich Hugues Leroy Cours de DEA CH 3.4 / 25 Hugues Leroy Cours de DEA CH 3.4 / 26 Communications multiples Wait Test au moins un Waitany Testany retourne un seul tous Waitall Testall au moins un retourne tous ceux qui ont fini Waitsome Testsome Hugues Leroy Cours de DEA CH 3.4 / 27 Hugues Leroy Cours de DEA CH 3.4 / 28

Exemple : multiples producteurs / un seul consommateur typedef struct{ char data[maxsize]; int datasize; MPI_Request req; Buffer; Buffer buffer[]; MPI_Status status; Pn-1... MPI_Comm_rank(comm, &rank); MPI_Comm_size(comm,&size); if (rank!= size-1) { /* producteur */ buffer=(buffer *) malloc (sizeof(buffer)); while ( 1 ) { /* boucle inficie */ produire (buffer->data,&buffer->datasize); MPI_Send ( buffer->data,buffer->datasize,mpi_char,size-1,tag,comm); else { /* rank == size-1 : le consommateur */ buffer=(buffer *) malloc (sizeof(buffer)*(size-1)); for (i=0;i<size-1;i++) MPI_Irecv ( buffer[i].data,maxsize, MPI_CHAR, i, tag, comm, &(buffer[i].req)); for (i=0; ; i=(i+1)%(size-1) ) { /* PREMIERE POSSIBILITE */ MPI_Wait ( &(buffer[i].req), &status); MPI_Get_count ( &status, MPI_CHAR, &(buffer[i].datasize)); consommer ( buffer[i].data, buffer[i]->datasize); MPI_Irecv (buffer[i].data, MAXSIZE, MPI_CHAR, i, tag, comm, &(buffer[i].req)); P0 P1 P2 Pn-2 Un consommateur : le processus de numéro n-1, et n-1 producteurs (de 0 à n-2). L exploration séquentielle de la boucle (marquée par la main) montre que tant que le processus i n a pas tranmis son message, alors on reste bloqué sur le Wait. Donc si un processus produit 2 fois plus que les autres, on ne pourra pas le traiter en priorité. Dès qu on a traité sa demande, alors on repart dans la boucle sur i, et on ne reviendra à lui que lorsqu on aura traité (attendu) toutes les autres demandes. Une alternative est de faire un MPI_Test sur la requête du processus courant (i). MPI_test rend vrai ou faux suivant que la communication en question est finie ou pas. Hugues Leroy Cours de DEA CH 3.4 / 29 Hugues Leroy Cours de DEA CH 3.4 / 30 /* DEUXIEME POSSIBILITE ( version plus élégante ), la 1ère version ne traitant pas de façon équitable tous les producteurs car il y a une séquentialisation dans le traitement */ i=0; while (1) { for (flag=0;! flag; i=(i+1)%(size-1) ) MPI_Test (&(buffer[i].req), &flag, &status); MPI_Get_count ( &status, MPI_CHAR, &(buffer[i].datasize)); consommer ( buffer[i].data, buffer[i]->datasize); MPI_Irecv (buffer[i].data, MAXSIZE, MPI_CHAR, i, tag, comm, &(buffer[i].req)); Ici on a un meilleur traitement des demandes, et on ne consomme plus comme précédemment au rythme du plus lent des producteurs. remarquez comment la boucle sur MPI_Test permet de sélectionner une requête! (on sort lorsque flag vaut vrai) Hugues Leroy Cours de DEA CH 3.4 / 31 Hugues Leroy Cours de DEA CH 3.4 / 32

Remarques Le processus inexistant est noté MPI_PROC_NULL une communication vers ce processus retourne tout de suite. Un message reçu de ce processus sera de longueur 0 et aura l étiquette MPI_ANY_TAG Intérêt : (cf Jacobi sur domaine 2D maillé) on pourra utiliser le même appel MPI pour les communications d échange des bords, les processus étant ou non sur les bords de la grille La requête inexistante est MPI_REQUEST_NULL On a la garantie que toutes les communications vers le processus MPI_PROC_NULL terminent. Idem pour les Recv. On verra que cette propriété va nous permettre de rendre le code source plus lisible lorsqu on utilisera les topologies virtuelles. On n aura plus les fastidieux tests du genre: si je suis un processus sur le bord gauche alors je reçois et envoie à droite, sinon si je suis un processus sur le bord droit alors je reçoit et envoie à gauche, sinon (je suis un processus au milieu) je reçoit/envoie à gauche et je reçoit/envoie à droite. Hugues Leroy Cours de DEA CH 3.4 / 33 Hugues Leroy Cours de DEA CH 3.4 / 34 Fonctions avancées int MPI_Probe ( int source, int tag, MPI_Comm comm, MPI_Status *status) permet de choisir une enveloppe avant d en lire le contenu l appel non bloquant est MPI_Iprobe (int source, int tag, int *flag, MPI_Comm comm, MPI_Status *status). flag prendra la valeur vrai ou faux suivant l état de la communication testée. Communications persistantes (non bloquantes, donc il faut tester ou attendre la fin avant de réutiliser les tampons) int MPI_Send_init ( void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request) int MPI_Start ( MPI_Request *request) ou int MPI_Startall ( int count, MPI_Request array_of_requests[] ) int MPI_Request_free ( MPI_Request *request) supprimer une requête ( attention! si le message est déjà parti ou a été reçu..?!??..) int MPI_Cancel ( MPI_Request *request ) int MPI_Test_cancelled ( MPI_Status *status, int *flag ) Hugues Leroy Cours de DEA CH 3.4 / 35 Hugues Leroy Cours de DEA CH 3.4 / 36

Intérêt des communications persistantes Dans un programme il arrive qu il y ait une boucle sur un envoi et une réception de message, où seules les données échangées varient, mais ni leurs adresses en mémoire, ni leur nombre, ni leurs types (regardez par exemple le programme ping pong). On va donc créer un schéma de communication une fois pour toutes, et dans la boucle on activera la requête. À la fin de la boucle, on pourra libérer la requête. Ce schéma va permettre de masquer la latence de communication et de réduire les surcoûts induits par les appels aux fonctions de communications dans la boucle. On n aura plus non plus la recopie des paramètres. boucle {... ; a=... ; MPI_Send ( &a, 1, MPI_INT,...); peut devenir : MPI_Send_init (&a, 1, MPI_INT,...,&req); boucle {...; a=...; MPI_Start( &req);... MPI_Request_free(&req); mode standard synchrone tamponné réception MPI MPI_Send_init MPI_Ssend_init MPI_Bsend_init MPI_Recv_init Hugues Leroy Cours de DEA CH 3.4 / 37 Hugues Leroy Cours de DEA CH 3.4 / 38 Remarquons les équivalences : MPI_Irecv(...,&req) avec MPI_Recv_init (...&req); MPI_Start(&req); MPI_Wait (&req) avec MPI_Wait(&req); MPI_Request_free(&req); Exercice 4 Bien mesurer les latences et débits obtenus. Après cet exercice vous pourrez savoir quelles sont les primitives de communications les plus efficaces : Send/Recv, Sendrecv, Sendrecv_replace, Send_init/Start, etc... Remarque: nous n aurons pas les mêmes indications suivant les architectures matérielles et les implémentations de MPI utilisées. Reprendre le ping pong et remplacer les envois/réceptions pour en faire des communications persistantes. Hugues Leroy Cours de DEA CH 3.4 / 39 Hugues Leroy Cours de DEA CH 3.4 / 40

Utilisation de MPI_Probe int MPI_Probe (int source, int tag, MPI_Comm comm, MPI_Status *status ) #define MCW MPI_COMM_WORLD double eleven[500]; double data[500]; MPI_Init(&argc,&argv); MPI_Comm_rank(MCW,&rank); if ( rank == 1 ) { for (i=0; i<50;i++) {eleven[i]=11.0; MPI_Send(eleven,50,MPI_DOUBLE,0,1001,MCW); else { MPI_Recv(data,500,MPI_DOUBLE,MPI_ANY_SOURCE,MPI_ANY_TAG,MCW, &status); MPI_Get_count(&status,MPI_DOUBLE,&count); printf( Process %d received %d doubles\n,rank,count); Qui y a-t-il de mal fait dans ce code? le récepteur ne sait pas combien d éléments il va recevoir => gaspillage de mémoire (500 au lieu de 50) ne connait pas le TAG (pourrait être utilisé comme un signal) ne connait pas l émetteur (pas important ici, mais on pourrait avoir un traitement différent suivant l émetteur du message) Solution : utiliser MPI_Probe et l allocation dynamique de mémoire Hugues Leroy Cours de DEA CH 3.4 / 41 Hugues Leroy Cours de DEA CH 3.4 / 42 double eleven[500]; double *data; MPI_Init(&argc,&argv); MPI_Comm_rank(MCW,&rank); if ( rank == 1 ) { for (i=0; i<50;i++) {eleven[i]=11.0; MPI_Send(eleven,50,MPI_DOUBLE,0,1001,MCW); else { MPI_Probe(1,MPI_ANY_TAG,MCW,&status); MPI_Get_count(&status,MPI_DOUBLE,&count); MPI_Type_size(MPI_DOUBLE,&n); data=(double *) calloc (count,n); MPI_Recv(data, count, MPI_DOUBLE, 1, MPI_ANY_TAG, MCW, &status); Hugues Leroy Cours de DEA CH 3.4 / 43