Gather

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

Cet exemple illustre l'utilisation de la fonction MPI_Gather pour rassembler les données provenant de plusieurs processus vers un processus en particulier. Chaque processus prépare (initialise) un vecteur de réels sendbuff de dimension buffsize. Ensuite, la fonction MPI_Gather rassemble au processuse 0 le contenu de ces vecteurs et les place dans le tableau recvbuff.

Avant et après l'étape de communication, la somme de chacun des vecteurs est affichée à l'écran pour vérification.

En Fortran

Fichier : gather.f
!--------------------------------------------------------
!          sendbuff
!   
!          ########
!          #      #
!        0 #  AA  #
!          #      #
!          ########
!     T    #      #
!        1 #  BB  #
!     a    #      #
!          ########
!     c    #      #
!        2 #  CC  #                                    AVANT
!     h    #      #
!          ########
!     e    #      #
!        3 #  DD  #
!     s    #      #
!          ########
!          #      #
!        4 #  EE  #
!          #      #
!          ########
!          
!            <---------- recvbuff ---------->
!
!          ####################################
!          #      #      #      #      #      #
!        0 #  AA  #  BB  #  CC  #  DD  #  EE  #
!          #      #      #      #      #      #
!          ####################################
!     T    #      #      #      #      #      #
!        1 #      #      #      #      #      #
!     a    #      #      #      #      #      #
!          ####################################
!     c    #      #      #      #      #      #
!        2 #      #      #      #      #      #       APRÈS
!     h    #      #      #      #      #      #
!          ####################################
!     e    #      #      #      #      #      #
!        3 #      #      #      #      #      #
!     s    #      #      #      #      #      #
!          ####################################
!          #      #      #      #      #      #
!        4 #      #      #      #      #      #
!          #      #      #      #      #      #
!          ####################################
!
! Auteur : Carol Gauthier
!          Centre de Calcul scientifique
!          Universite de Sherbrooke
!
! Dernière révision : août 2004
!--------------------------------------------------------
Program Exemple_MPI
 
  include 'mpif.h'
  integer ierr,ntasks,taskid,itask,status(MPI_STATUS_SIZE)
  integer i,j,k,buffsize
  character argtmp*12
  real(8) inittime,recvtime,totaltime,rand,buffsum
 
  real(8),allocatable,dimension(:) :: sendbuff
  real(8),allocatable,dimension(:,:) :: recvbuff
 
  !---------------------------------------------------------------
  ! Initialisation de MPI. Il est important de placer cet appel   
  ! au début du programme, immédiatement après les déclarations.
  call MPI_INIT( ierr )
 
  !---------------------------------------------------------------
  ! Obtenir le nombre de processus MPI et le numéro d'identification
  ! du processus courant.
  call MPI_COMM_SIZE(MPI_COMM_WORLD,ntasks,ierr)
  call MPI_COMM_RANK(MPI_COMM_WORLD,taskid,ierr)
 
  !---------------------------------------------------------------
  ! Dimension  du vecteur à partir des arguments.
  call getarg(1,argtmp)
  read(argtmp,'(I12)')buffsize
 
  !---------------------------------------------------------------
  ! Affichage de la description de l'exemple.
  if ( taskid.eq.0 )then
    write(6,'(A)')
    write(6,'(A)')"##########################################################"
    write(6,'(A)')
    write(6,'(A)')" Exemple 9"
    write(6,'(A)')
    write(6,'(A)')" Communication collective : MPI_Gather"
    write(6,'(A)')
    write(6,'(A,I12)')" Dimension du vecteur :",buffsize
    write(6,'(A,I5)')" Nombre total de processus :",ntasks
    write(6,'(A)')
    write(6,'(A)')"##########################################################"
    write(6,'(A)')
    write(6,'(A)')"                --> AVANT COMMUNICATION <--"
    write(6,'(A)')
  endif
 
  !---------------------------------------------------------------
  ! Allocation de la mémoire 
  allocate( sendbuff(0:buffsize-1) )
  allocate( recvbuff(0:buffsize-1,0:ntasks-1) )
 
  !-----------------------------------------------------------------
  ! Initialisation des vecteurs ou tableaux.
  call srand(taskid*10)
  do i=0,buffsize-1
    sendbuff(i)=rand()
  end do
 
  !-----------------------------------------------------------------
  ! Affichage avant communication.
  call MPI_Barrier(MPI_COMM_WORLD,ierr)
 
  buffsum=0.0
  do i=0,buffsize-1
    buffsum=buffsum+sendbuff(i)
  end do
 
 
  write(6,'(A,I3,A,E14.8)')"Processus",taskid," : Somme du vecteur = ",buffsum
 
  call MPI_Barrier(MPI_COMM_WORLD,ierr);     
 
 
  !-----------------------------------------------------------------
  ! Communication
 
  inittime = MPI_Wtime()
 
  call MPI_Gather(sendbuff,buffsize,MPI_REAL8, &
  &               recvbuff,buffsize,MPI_REAL8, &
  &               0,MPI_COMM_WORLD,ierr)
 
  totaltime = MPI_Wtime()
 
  !-----------------------------------------------------------------
  ! Affichage après communication.
  if(taskid.eq.0)then
    write(6,*)
    write(6,'(A)')"##########################################################"
    write(6,*)
    write(6,'(A)')"                --> APRÈS COMMUNICATION <--"
    write(6,*)
    do itask=0,ntasks-1
      buffsum=0.0
      do i=0,buffsize-1
        buffsum=buffsum+recvbuff(i,itask)
      end do
      write(6,'(A,I3,A,I3,A,E14.8)')"Processus ",taskid," : Somme du vecteur reçu par ",itask, &
      &                             "= ",buffsum
    end do
    write(6,*)
    write(6,'(A)')"##########################################################"
    write(6,'(A,F5.2,A)')" Temps total communication : ",totaltime," secondes"
    write(6,'(A)')"##########################################################"
    write(6,*)
  end if
 
  !-----------------------------------------------------------------
  ! Libération de la mémoire
  deallocate(sendbuff)
  deallocate(recvbuff)
 
  !-----------------------------------------------------------------
  ! Finalisation de MPI
 
  call MPI_FINALIZE( ierr )
end


En C

Fichier : gather.c
/*--------------------------------------------------------
          sendbuff
 
          ########
          #      #
        0 #  AA  #
          #      #
          ########
     T    #      #
        1 #  BB  #
     a    #      #
          ########
     c    #      #
        2 #  CC  #                                    AVANT
     h    #      #
          ########
     e    #      #
        3 #  DD  #
     s    #      #
          ########
          #      #
        4 #  EE  #
          #      #
          ########
 
            <---------- recvbuff ---------->
 
          ####################################
          #      #      #      #      #      #
        0 #  AA  #  BB  #  CC  #  DD  #  EE  #
          #      #      #      #      #      #
          ####################################
     T    #      #      #      #      #      #
        1 #      #      #      #      #      #
     a    #      #      #      #      #      #
          ####################################
     c    #      #      #      #      #      #
        2 #      #      #      #      #      #       APRÈS
     h    #      #      #      #      #      #
          ####################################
     e    #      #      #      #      #      #
        3 #      #      #      #      #      #
     s    #      #      #      #      #      #
          ####################################
          #      #      #      #      #      #
        4 #      #      #      #      #      #
          #      #      #      #      #      #
          ####################################
 
 Auteur : Carol Gauthier
          Centre de Calcul scientifique
          Université de Sherbrooke
 
 Dernière révision : septembre 2005
--------------------------------------------------------*/
 
#include <malloc.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "math.h"
#include "mpi.h"
 
int main(int argc,char** argv)
{
   /*===============================================================*/
   /* Déclaration des variables                                     */
   int          taskid, ntasks;
   MPI_Status   status;
   int          ierr,i,j,itask;
   int	        buffsize;
   double       *sendbuff,**recvbuff,buffsum;
   double       inittime,totaltime;
 
   /*===============================================================*/
   /* Initialisation de MPI. Il est important de placer cet appel   */
   /* au début du programme, immédiatement après les déclarations.  */
   MPI_Init(&argc, &argv);
 
   /*===============================================================*/
   /* Obtenir le nombre de processus MPI et le numéro d'identification */
   /* du processus courant taskid.                                     */
   MPI_Comm_rank(MPI_COMM_WORLD,&taskid);
   MPI_Comm_size(MPI_COMM_WORLD,&ntasks);
 
   /*===============================================================*/
   /* Obtenir buffsize à partir des arguments.                      */
   buffsize=atoi(argv[1]);
 
   /*===============================================================*/
   /* Affichage de la description de l'exemple.                     */
   if ( taskid == 0 ){
     printf("\n\n\n");
     printf("##########################################################\n\n");
     printf(" Exemple 9 \n\n");
     printf(" Communication collective : MPI_Gather \n\n");
     printf(" Le processus 0 rassemble les données du vecteur sendbuff de\n");
     printf(" chaque processus et les place dans recvbuff. \n\n");
     printf(" Dimension de chaque vecteur à transferer : %d\n",buffsize);
     printf(" Nombre total de processus : %d\n\n",ntasks);
     printf("##########################################################\n\n");
     printf("                --> AVANT COMMUNICATION <--\n\n");
   }
 
   /*=============================================================*/
   /* Allocation de la mémoire.                                   */ 
   sendbuff=(double *)malloc(sizeof(double)*buffsize);
   if( taskid == 0 ){
     recvbuff=(double **)malloc(sizeof(double *)*ntasks);
     recvbuff[0]=(double *)malloc(sizeof(double)*ntasks*buffsize);
     for(i=1;i<ntasks;i++)recvbuff[i]=recvbuff[i-1]+buffsize;
   }
   else{
     recvbuff=(double **)malloc(sizeof(double *)*1);
     recvbuff[0]=(double *)malloc(sizeof(double)*1);
   }
 
   /*=============================================================*/
   /* Initialisation des vecteurs ou tableaux               */
   srand((unsigned)time( NULL ) + taskid);
   for(i=0;i<buffsize;i++){
       sendbuff[i]=(double)rand()/RAND_MAX;
   }
 
   /*==============================================================*/
   /* Affichage avant communication.                               */
 
   MPI_Barrier(MPI_COMM_WORLD);
 
   buffsum=0.0;
   for(i=0;i<buffsize;i++){
     buffsum=buffsum+sendbuff[i];
   }
   printf("Processus %d : somme du vecteur = %e \n",taskid,buffsum);
 
   MPI_Barrier(MPI_COMM_WORLD);     
 
   /*===============================================================*/
   /* Communication.                                                */
 
   inittime = MPI_Wtime();
 
   ierr=MPI_Gather(sendbuff,buffsize,MPI_DOUBLE,
                   recvbuff[0],buffsize,MPI_DOUBLE,
                   0,MPI_COMM_WORLD);
 
   totaltime = MPI_Wtime() - inittime;
 
   /*===============================================================*/
   /* Affichage après communication.                                */
   if ( taskid == 0 ){
     printf("\n");
     printf("##########################################################\n\n");
     printf("                --> APRÈS COMMUNICATION <-- \n\n");
     for(itask=0;itask<ntasks;itask++){
       buffsum=0.0;
       for(i=0;i<buffsize;i++){
         buffsum=buffsum+recvbuff[itask][i];
       }
       printf("Processus %d : Somme du vecteur reçu par %d -> %e \n",
               taskid,itask,buffsum);
 
     }       
   }       
 
   if(taskid==0){
     printf("\n");
     printf("##########################################################\n\n");
     printf(" Temps total de communication : %f secondes\n\n",totaltime);  
     printf("##########################################################\n\n");
   }
 
   /*===============================================================*/
   /* Libération de la mémoire                                      */
   if ( taskid == 0 ){
     free(recvbuff[0]);
     free(recvbuff);
   }
   else{
     free(recvbuff[0]);
     free(recvbuff);
     free(sendbuff);
   }
 
   /*===============================================================*/
   /* Finalisation de MPI                                           */
   MPI_Finalize();
}


Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Ressources de Calcul Québec
Outils
Partager