MPI-IO

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

Sommaire

Description

MPI-IO sont des routines MPI permettant de faire des opérations de lecture et écriture en parallèle sur des fichiers. MPI-IO fait partie du standard MPI-2. Le principal avantage de MPI-IO est qu'il permet, de manière simple et efficace, de lire et d'écrire des données réparties sur plusieurs processus, vers un seul fichier commun à tous les processus. Ceci s'avère particulièrement utile lorsque les données manipulées sont des vecteurs ou des matrices découpés de manière structurée entre les différents processus. Le présent document donne quelques indications à propos de l'utilisation de MPI-IO et des références vers des documents plus complets (principalement en anglais).

Utilisation de MPI-IO

Opérations par déplacements

La manière la plus simple de faire des opérations de lecture et écriture en parallèle est d'utiliser des déplacements (offsets). Chaque processus peut ainsi lire ou écrire dans le fichier avec un déplacement défini. Cela peut se faire en deux opérations (MPI_File_seek suivit de MPI_File_read ou de MPI_File_write), ou bien en une seule opération (MPI_File_read_at ou MPI_File_write_at). On calcule habituellement le déplacement en fonction du rang du processus.


Fichier : mpi_rw_at.c
#include <mpi.h>
 
#define TAILLEBLOC 80
#define NBRBLOCS   32
 
int main(int argc, char** argv) {
 
    MPI_File f;
    char*    nomfichier  = "testmpi.txt";
    char     buffer[TAILLEBLOC];
    int      rang, taille;
    int      i;
 
    /* Initialisation de MPI */ 
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rang);
    MPI_Comm_size(MPI_COMM_WORLD, &taille);
 
    /* Initialisation du buffer */
    memset(buffer, 'a'+rang, TAILLEBLOC);
    buffer[TAILLEBLOC - 1] = '\n';
 
    MPI_File_open(MPI_COMM_WORLD, nomfichier, (MPI_MODE_WRONLY | MPI_MODE_CREATE), MPI_INFO_NULL, &f);
 
    /* Écrit les données en alternance entre les processus : aabbccddaabbccdd... */
    MPI_File_seek(f, rang*TAILLEBLOC, MPI_SEEK_SET); /* Va à la position rang * TAILLEBLOC */
    for (i=0; i<NBRBLOCS; ++i) {
        MPI_File_write(f, buffer, TAILLEBLOC, MPI_CHAR, MPI_STATUS_IGNORE);
        /* Avance de (taille-1)*TAILLEBLOC octets */
        MPI_File_seek(f, (taille-1)*TAILLEBLOC, MPI_SEEK_CUR);
    }
 
    MPI_File_close(&f);
 
    MPI_File_open(MPI_COMM_WORLD, nomfichier, MPI_MODE_RDONLY, MPI_INFO_NULL, &f);
 
    /* Lit les données de manière séquentielle pour chaque processus. Chaque processus lit : aabbccdd */
    for (i=0; i<NBRBLOCS; ++i) {
        MPI_File_read_at(f, rang*i*NBRBLOCS*TAILLEBLOC, buffer, TAILLEBLOC, MPI_CHAR, MPI_STATUS_IGNORE);
    }
 
    MPI_File_close(&f);
    MPI_Finalize();
 
    return 0;
}


Utilisation des vues

En utilisant les vues, chaque processus peut voir une section du fichier, comme si c'était le fichier en entier. De cette manière, il n'est plus nécessaire de calculer les déplacements dans le fichier en fonction du rang du processus. Une fois la vue définie, il est donc beaucoup plus simple d'effectuer des opérations sur le fichier, sans craindre d'entrer en conflit avec les opérations réalisées par les autres processus. On définit une vue à l'aide de la fonction MPI_File_set_view. Voici un programme identique à celui de l'exemple précédent, mais en utilisant les vues.

Fichier : mpi_view.c
#include <stdio.h>
#include <mpi.h>
 
#define TAILLEBLOC 80
#define NBRBLOCS   32
 
int main(int argc, char** argv) {
 
    MPI_File f;
    MPI_Datatype type_intercal;
    MPI_Datatype type_contigu;
    char*    nomfichier  = "testmpi.txt";
    char     buffer[TAILLEBLOC];
    int      rang, taille;
    int      i;
 
    MPI_Init(&argc, &argv);
    MPI_Comm_rank(MPI_COMM_WORLD, &rang);
    MPI_Comm_size(MPI_COMM_WORLD, &taille);
 
    /* Initialise le buffer */
    memset(buffer, 'a'+rang, TAILLEBLOC);
    buffer[TAILLEBLOC - 1] = '\n';
 
    MPI_File_open(MPI_COMM_WORLD,
        nomfichier,
        (MPI_MODE_WRONLY | MPI_MODE_CREATE),
        MPI_INFO_NULL,
        &f);
 
    /* Écrit les données en alternance entre les processus
       aabbccddaabbccdd... */
    MPI_Type_contiguous(TAILLEBLOC, MPI_CHAR, &type_intercal);
    MPI_Type_commit(&type_intercal);
    for (i=0; i<NBRBLOCS; ++i) {
        MPI_File_set_view(f, rang*TAILLEBLOC+i*taille*TAILLEBLOC, MPI_CHAR, type_intercal, "native", MPI_INFO_NULL);
        MPI_File_write(f, buffer, TAILLEBLOC, MPI_CHAR, MPI_STATUS_IGNORE);
    }
 
    MPI_File_close(&f);
 
    MPI_File_open(MPI_COMM_WORLD,
        nomfichier,
        MPI_MODE_RDONLY,
        MPI_INFO_NULL,
        &f);
 
    /* Lit les données de manière séquentielle pour chaque processus
       chaque processus lit : aabbccdd */
    MPI_Type_contiguous(NBRBLOCS*TAILLEBLOC, MPI_CHAR, &type_contigu);
    MPI_Type_commit(&type_contigu);
    MPI_File_set_view(f, rang*NBRBLOCS*TAILLEBLOC, MPI_CHAR, type_contigu, "native", MPI_INFO_NULL);
    for (i=0; i<NBRBLOCS; ++i) {
        MPI_File_read(f,  buffer, TAILLEBLOC, MPI_CHAR, MPI_STATUS_IGNORE);
    }
 
    MPI_File_close(&f);
    MPI_Finalize();
 
    return 0;
}


Attention! Certains systèmes de fichiers ne supportent pas les verrous sur les fichiers (file locks). Par conséquent, certaines opérations ne sont pas possibles, notamment l'utilisation de vues sur des sections disjointes d'un fichier.

Références

Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Ressources de Calcul Québec
Outils
Partager