IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Programmation parallèle, calcul scientifique et de haute performance (HPC) Discussion :

Réduction sur plusieurs tableaux : plusieurs appels à MPI_Reduce ou opérateur de réduction ?


Sujet :

Programmation parallèle, calcul scientifique et de haute performance (HPC)

  1. #1
    Membre régulier
    Homme Profil pro
    Collégien
    Inscrit en
    Mars 2003
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Mars 2003
    Messages : 192
    Points : 87
    Points
    87
    Par défaut Réduction sur plusieurs tableaux : plusieurs appels à MPI_Reduce ou opérateur de réduction ?
    Salut,

    J'ai 4 tableaux de double sur lesquels je voudrais faire une réduction (MPI_SUM). Je me demande ce qui est le mieux dans le cas général. D'après ce que je comprends j'ai plusieurs options :

    1/ faire 4 réductions avec 4 appels successifs à MPI_Reduce()
    2/ Appeler MPI_Pack() pour mettre tout dans un tableau de 4x la taille de mes tableaux et faire 1 seul appel a MPI_Reduce() puis appeler MPI_Unpack()
    3/ Faire 2/ mais utiliser memcpy() au lieu de MPI_Pack()
    4/ Faire un type MPI avec un operateur de reduction perso et faire une réduction.


    Laquelle est la meilleure ? Aussi quelle différence y a-t-il exactement entre MPI_Pack/Unpack et utiliser memcpy() "à la main" ? J'ai l'impression que c'est pareil. A quoi sert le communicateur dans MPI_Pack/Unpack() je ne comprends pas vu qu'il s'agit d'une routine qui ne fait pas de communication.

    Voici un code qui test 1 VS 2. J'ai testé sur 1,2,3,4 processeurs et pour 2,3,4 la methode 2/ est meilleure, sans doute à cause du cout d'une communication dans le reduce() (?).


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
     
    #include <stdio.h>
    #include <stdlib.h>
    #include <mpi.h>
    #include <string.h>
     
     
    int main(int argc, char **argv)
    {
        double *buf1, *buf2, *buf3, *buf4;
        double *pack, *unpack;
        double size;
        double start, end;
        int pos;
        int i;
        int rank;
        int cnt;
        int ierr;
     
        MPI_Init(&argc, &argv);
        MPI_Comm_rank(MPI_COMM_WORLD, &rank);
     
        cnt = 100000;
     
        size = 10;
     
        buf1   = calloc(size, sizeof *buf1);
        buf2   = calloc(size, sizeof *buf2);
        buf3   = calloc(size, sizeof *buf3);
        buf4   = calloc(size, sizeof *buf4);
        pack   = calloc(3*size, sizeof *pack);
        unpack = calloc(3*size, sizeof *unpack);
     
        for (i=0; i<size; i++)
        {
            buf1[i] = 2;
            buf2[i] = 4;
        }
     
        MPI_Barrier(MPI_COMM_WORLD);
        start = MPI_Wtime();
     
        for (i=0; i< cnt; i++)
        {
     
            MPI_Reduce(buf1,               // send buffer
                       buf3,               // reduced data goes here
                       size,               // size of the buffers
                       MPI_DOUBLE,         // type of the data
                       MPI_SUM,            // operation
                       0,                  // proc 0 only will recieve data
                       MPI_COMM_WORLD);    // all procs do the reduction
     
     
            MPI_Reduce(buf2,               // send buffer
                       buf4,               // reduced data goes here
                       size,               // size of the buffers
                       MPI_DOUBLE,         // type of the data
                       MPI_SUM,            // operation
                       0,                  // proc 0 only will recieve data
                       MPI_COMM_WORLD);    // all procs do the reduction
     
        }
        end = MPI_Wtime();
     
        if(rank==0)
        {
            printf("%f seconds\n", end-start);
        }
     
        // empty buf3 and buf4
        memset(buf3, 0, size);
        memset(buf4, 0, size);
     
     
        MPI_Barrier(MPI_COMM_WORLD);
        start = MPI_Wtime();
        for(i=0; i < cnt; i++)
        {
            pos = 0;                           // start to pack at pack+0
     
            ierr = MPI_Pack(buf1,              // data to be packed
                     size,                     // size of buf1
                     MPI_DOUBLE,               // type of these elements
                     pack,                     // start adress of the pack
                     2*size*sizeof *pack,      // size of the pack buffer
                     &pos,                     // pack+pos is the start position
                     MPI_COMM_WORLD);          // every proc will use 'pack'
     
     
     
        // pack the second buffer
     
            MPI_Pack(buf2,                     // data to be packed
                     size,                     // size of buf1
                     MPI_DOUBLE,               // type of these elements
                     pack,                     // start adress of the pack
                     2*size*sizeof *pack,      // size of the pack buffer
                     &pos,                     // pack+pos is the start position
                     MPI_COMM_WORLD);          // every proc will use 'pack'
     
            // now reduce the pack
     
            MPI_Reduce(pack,               // send buffer
                       unpack,             // reduced data goes here
                       2*size,             // size of the buffers
                       MPI_DOUBLE,         // type of the data
                       MPI_SUM,            // operation
                       0,                  // proc 0 only will recieve data
                       MPI_COMM_WORLD);    // all procs do the reduction
     
        }
        end = MPI_Wtime();
        if(rank==0)
        {
            printf("%f seconds\n", end-start);
        }
     
     
     
        if (rank == 0)
        {
            for (i=0; i<2*size; i++)
            {
                printf("unpack[%d] = %f\n",i,unpack[i]);
            }
        }
     
     
        free(buf1);
        free(buf2);
        free(buf3);
        free(buf4);
        free(pack);
        free(unpack);
     
     
        MPI_Finalize();
     
        return 0;
    }
    Merci
    --
    Heimdall

  2. #2
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Points : 8
    Points
    8
    Par défaut
    Bonjour,

    Pack et Unpack servent uniquement pour les communications point a point.

    La meilleur methode depend un peu de ce que l'on cherche entre performance, lisibilite et consommation memoire.

    La troisieme est probablement la plus rapide, la quatrieme doit consommer moins de memoire.

  3. #3
    Membre régulier
    Homme Profil pro
    Collégien
    Inscrit en
    Mars 2003
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Mars 2003
    Messages : 192
    Points : 87
    Points
    87
    Par défaut
    Citation Envoyé par spica314 Voir le message
    Bonjour,
    Pack et Unpack servent uniquement pour les communications point a point.

    Je ne comprends pas cette phrase, pouvez-vous l'expliquer ?
    Merci
    --
    Heimdall

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Points : 8
    Points
    8
    Par défaut
    Dans l'idee le pack et le unpack s'ont fait pour les send/recv MPI.

    Pour eviter de faire plusieurs send, on fait 1 send en empaquetant les elements avant. Pareil on fait 1 recv et l'on recupere un a un les elements du message.

    Rq : Ces fonctions sont tres peu utilises et souvent pas tres performantes.

  5. #5
    Membre régulier
    Homme Profil pro
    Collégien
    Inscrit en
    Mars 2003
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Mars 2003
    Messages : 192
    Points : 87
    Points
    87
    Par défaut
    Salut,

    Je ne comprends pas pourquoi vous reservez pack/unpack au send/recv. Dans l'exemple que je donne j'utilise MPI_Reduce qui est une routine de communication globale et cela fonctionne parfaitement.
    --
    Heimdall

  6. #6
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Points : 8
    Points
    8
    Par défaut
    En fait cela marche parce que vous l'utilisez comme un memcpy, sauf que le pack/unpack fait plus que cela.

    En regardant dans la norme, je me rends compte que j'avait faux, on peut l'utiliser avec des communications collectives.

    En fait ce qui me trouble c'est que vous n'utilisez pas le type MPI_PACKED, qui sert justement a envoyer des paquets.

    Dans l'esprit du pack/unpack c'est d'envoyer en un seul bloc des donnees de types differents, non contigues. Mais les types MPI permettent deja de faire cela, et en plus sans faire de recopie. L'interet est plus dans le unpack, on peut lire le premier element, faire un calcul, puis lire l'element suivant, etc... Dans ce cas, il faut utiliser MPI_PACKED

  7. #7
    Membre régulier
    Homme Profil pro
    Collégien
    Inscrit en
    Mars 2003
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Mars 2003
    Messages : 192
    Points : 87
    Points
    87
    Par défaut
    en effet j'ai oublié le MPI_PACKED.
    Faire un type MPI ne fait pas de recopie des données dans le dos ?
    Pourquoi avez-vous dit que c'est plus lent que le pack/unpack alors ?
    --
    Heimdall

  8. #8
    Futur Membre du Club
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 7
    Points : 8
    Points
    8
    Par défaut
    En fait avec des types MPI, il n'y a pas obligatoirement de recopie dans un buffer, avec les systemes de RDMA (Remote Direct Memory Access = Acces directe a la memoire a distante). Dans ce cas les donnees sont envoyes directement a leur destination sans passer par un buffer.

    C'est les pack qui sont moins performant, a cause des recopies et aussi du fait que ce soit peu utilise.

  9. #9
    Membre régulier
    Homme Profil pro
    Collégien
    Inscrit en
    Mars 2003
    Messages
    192
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Afghanistan

    Informations professionnelles :
    Activité : Collégien

    Informations forums :
    Inscription : Mars 2003
    Messages : 192
    Points : 87
    Points
    87
    Par défaut
    Ok merci des infos !
    --
    Heimdall

Discussions similaires

  1. [XL-2010] Tri sur cellules de plusieurs tableaux différents
    Par Bou31 dans le forum Excel
    Réponses: 11
    Dernier message: 10/04/2014, 11h38
  2. [VxiR2] Problème déphasage alignement sur plusieurs tableaux
    Par scalpa63 dans le forum Deski
    Réponses: 5
    Dernier message: 27/03/2009, 11h17
  3. [Displaytag] trier plusieurs tableaux sur une page
    Par Kieda dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 03/06/2008, 12h07
  4. [Tableaux] plusieurs tableaux sur une même ligne
    Par zugolin dans le forum Langage
    Réponses: 6
    Dernier message: 12/01/2008, 23h29
  5. Afficher plusieurs tableaux sur une seule ligne
    Par kromartien dans le forum Mise en forme
    Réponses: 3
    Dernier message: 18/11/2007, 15h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo