Alltoall

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_Alltoall.

Chaque tâche initialise un ensemble de vecteurs réels de dimension buffsize et les place de façon contiguë en mémoire à l'intérieur du tableau sendbuff. Le vecteur à la position j du tableau sendbuff de la tâche i est transféré à la position i du tableau recvbuff de la tâche j. Ces transferts sont effectués collectivement en utilisant MPI_Alltoall.

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 : alltoall.f
!--------------------------------------------------------
!   
!             <--------- sendbuff ---------->
!          ####################################
!          #      #      #      #      #      #
!        0 #  A0  #  A1  #  A2  #  A3  #  A4  #
!          #      #      #      #      #      #
!          ####################################
!     T    #      #      #      #      #      #
!        1 #  B0  #  B1  #  B2  #  B3  #  B4  #
!     a    #      #      #      #      #      #
!          ####################################
!     c    #      #      #      #      #      #
!        2 #  C0  #  C1  #  C2  #  C3  #  C4  #       AVANT
!     h    #      #      #      #      #      #
!          ####################################
!     e    #      #      #      #      #      #
!        3 #  D0  #  D1  #  D2  #  D3  #  D4  #
!     s    #      #      #      #      #      #
!          ####################################
!          #      #      #      #      #      #
!        4 #  E0  #  E1  #  E2  #  E3  #  E4  #
!          #      #      #      #      #      #
!          ####################################
!   
!             <--------- recvbuff ---------->
!          ####################################
!          #      #      #      #      #      #
!        0 #  A0  #  B0  #  C0  #  D0  #  E0  #
!          #      #      #      #      #      #
!          ####################################
!     T    #      #      #      #      #      #
!        1 #  A1  #  B1  #  C1  #  D1  #  E1  #
!     a    #      #      #      #      #      #
!          ####################################
!     c    #      #      #      #      #      #
!        2 #  A2  #  B2  #  C2  #  D2  #  E2  #       APRES
!     h    #      #      #      #      #      #
!          ####################################
!     e    #      #      #      #      #      #
!        3 #  A3  #  B3  #  C3  #  D3  #  E3  #
!     s    #      #      #      #      #      #
!          ####################################
!          #      #      #      #      #      #
!        4 #  A4  #  B4  #  C4  #  D4  #  E4  #
!          #      #      #      #      #      #
!          ####################################
!
! Auteur: Carol Gauthier
!         Centre de Calcul scientifique
!         Universite de Sherbrooke
!
! Derniere revision: Aout 2004
!--------------------------------------------------------
Program Exemple_MPI
 
  include 'mpif.h'
  integer ierr,ntasks,taskid,itask,status(MPI_STATUS_SIZE)
  integer i,j,k,buffsize,jtask
  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 debut du programme, immediatement apres les declarations   
  ! Initialisation de MPI 
  call MPI_INIT( ierr )
 
  !---------------------------------------------------------------
  ! Obtenir le nombre de taches MPI et le numero d'identification
  ! de la tache courante
  call MPI_COMM_SIZE(MPI_COMM_WORLD,ntasks,ierr)
  call MPI_COMM_RANK(MPI_COMM_WORLD,taskid,ierr)
 
  !---------------------------------------------------------------
  ! Dimension  du vecteur a 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 11"
    write(6,'(A)')
    write(6,'(A)')" Communication collective : MPI_Alltoall"
    write(6,'(A)')
    write(6,'(A,I12)')" Dimension du vecteur:",buffsize
    write(6,'(A,I5)')" Nombre total de taches:",ntasks
    write(6,'(A)')
    write(6,'(A)')"##########################################################"
    write(6,'(A)')
    write(6,'(A)')"                --> AVANT COMMUNICATION <--"
    write(6,'(A)')
  endif
 
  !---------------------------------------------------------------
  ! Allocation de la memoire
  allocate( sendbuff(0:buffsize-1,0:ntasks-1) )
  allocate( recvbuff(0:buffsize-1,0:ntasks-1) )
 
  !-----------------------------------------------------------------
  ! Initialisation du/des vecteurs et/ou tableaux.
  call srand(taskid*10)
  do itask=0,ntasks-1
    do i=0,buffsize-1
      sendbuff(i,itask)=rand()
    end do
  end do
 
  !-----------------------------------------------------------------
  ! Affichage avant communication.
  do jtask=0,ntasks-1
    call MPI_Barrier(MPI_COMM_WORLD,ierr)
    if(taskid.eq.jtask)then
      write(6,*)
      do itask=0,ntasks-1
        buffsum=0.0
        do i=0,buffsize-1
          buffsum=buffsum+sendbuff(i,itask)
        end do
        write(6,'(A,I3,A,I3,A,E14.8)')"Tache ",taskid,": Somme du vecteur envoye a ",itask, &
        &                             "= ",buffsum
      end do
    end if
  end do
  call MPI_Barrier(MPI_COMM_WORLD,ierr)
 
  !-----------------------------------------------------------------
  ! Communication
 
  inittime = MPI_Wtime()
 
  call MPI_Alltoall(sendbuff,buffsize,MPI_REAL8, &
  &                  recvbuff,buffsize,MPI_REAL8, &
  &                  MPI_COMM_WORLD,ierr)
 
  totaltime = MPI_Wtime()
 
  !-----------------------------------------------------------------
  ! Affichage apres communication.
  if(taskid.eq.0)then
    write(6,*)
    write(6,'(A)')"##########################################################"
    write(6,*)
    write(6,'(A)')"                --> APRES COMMUNICATION <--"
    write(6,*)
  end if
  do jtask=0,ntasks-1
    call MPI_Barrier(MPI_COMM_WORLD,ierr)
    if(taskid.eq.jtask)then
      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)')"Tache ",taskid,": Somme du vecteur recu par ",itask, &
        &                             "= ",buffsum
      end do
    end if
  end do
  call MPI_Barrier(MPI_COMM_WORLD,ierr)
 
  if(taskid.eq.0)then
    write(6,*)
    write(6,'(A)')"##########################################################"
    write(6,'(A,F5.2,A)')" Temps total de communication : ",totaltime," seconds"
    write(6,'(A)')"##########################################################"
    write(6,*)
  end if
 
  !-----------------------------------------------------------------
  ! Liberation de la memoire
  deallocate(sendbuff)
  deallocate(recvbuff)
 
  !-----------------------------------------------------------------
  ! Finalisation de MPI
 
  call MPI_FINALIZE( ierr )
 
end


En C

Fichier : alltoall.c
/*--------------------------------------------------------
 
             <--------- sendbuff ---------->
          ####################################
          #      #      #      #      #      #
        0 #  A0  #  A1  #  A2  #  A3  #  A4  #
          #      #      #      #      #      #
          ####################################
     T    #      #      #      #      #      #
        1 #  B0  #  B1  #  B2  #  B3  #  B4  #
     a    #      #      #      #      #      #
          ####################################
     c    #      #      #      #      #      #
        2 #  C0  #  C1  #  C2  #  C3  #  C4  #       AVANT
     h    #      #      #      #      #      #
          ####################################
     e    #      #      #      #      #      #
        3 #  D0  #  D1  #  D2  #  D3  #  D4  #
     s    #      #      #      #      #      #
          ####################################
          #      #      #      #      #      #
        4 #  E0  #  E1  #  E2  #  E3  #  E4  #
          #      #      #      #      #      #
          ####################################
 
             <--------- recvbuff ---------->
          ####################################
          #      #      #      #      #      #
        0 #  A0  #  B0  #  C0  #  D0  #  E0  #
          #      #      #      #      #      #
          ####################################
     T    #      #      #      #      #      #
        1 #  A1  #  B1  #  C1  #  D1  #  E1  #
     a    #      #      #      #      #      #
          ####################################
     c    #      #      #      #      #      #
        2 #  A2  #  B2  #  C2  #  D2  #  E2  #       APRES
     h    #      #      #      #      #      #
          ####################################
     e    #      #      #      #      #      #
        3 #  A3  #  B3  #  C3  #  D3  #  E3  #
     s    #      #      #      #      #      #
          ####################################
          #      #      #      #      #      #
        4 #  A4  #  B4  #  C4  #  D4  #  E4  #
          #      #      #      #      #      #
          ####################################
 
 Auteur: Carol Gauthier
         Centre de Calcul scientifique
         Universite de Sherbrooke
 
 Derniere revision: 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)
{
   /*===============================================================*/
   /* Declaration des variables                                     */
   int          taskid, ntasks;
   MPI_Status   status;
   int          ierr,i,j,itask,jtask;
   int	        buffsize;
   double       **sendbuff,**recvbuff,buffsum;
   double       inittime,totaltime,recvtime;
 
   /*===============================================================*/
   /* Initialisation de MPI. Il est important de placer cet appel   */
   /* au debut du programme, immediatement apres les declarations   */
   MPI_Init(&argc, &argv);
 
   /*===============================================================*/
   /* Obtenir le nombre de taches MPI et le numero d'identification */
   /* de la tache courante taskid                                   */
   MPI_Comm_rank(MPI_COMM_WORLD,&taskid);
   MPI_Comm_size(MPI_COMM_WORLD,&ntasks);
 
   /*===============================================================*/
   /* Obtenir buffsize a 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 11 \n\n");
     printf(" Communication collective : MPI_Alltoall \n\n");
     printf(" Le vecteur a la position j du tableau sendbuff de la\n");
     printf(" tache i est transfere a la position i du tableau recvbuff\n");
     printf(" de la tache j, en meme temps pour toutes les taches. \n\n");
     printf(" Dimension des vecteurs: %d\n",buffsize);
     printf(" Nombre total de taches: %d\n\n",ntasks);
     printf("##########################################################\n\n");
     printf("               --> AVANT COMMUNICATION <--\n");
   }
 
   /*=============================================================*/
   /* Allocation de la memoire.                                   */ 
   sendbuff=(double **)malloc(sizeof(double *)*ntasks);
   sendbuff[0]=(double *)malloc(sizeof(double)*ntasks*buffsize);
   for(i=1;i<ntasks;i++)sendbuff[i]=sendbuff[i-1]+buffsize;
   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;
 
   /*=============================================================*/
   /* Initialisation du/des vecteurs et/ou tableaux               */
   srand((unsigned)time( NULL ) + taskid);
   for(itask=0;itask<ntasks;itask++){
     for(i=0;i<buffsize;i++){
       sendbuff[itask][i]=(double)rand()/RAND_MAX;
     }
   }
 
   /*==============================================================*/
   /* Affichage avant communication.                               */
 
   for(jtask=0;jtask<ntasks;jtask++){
     MPI_Barrier(MPI_COMM_WORLD);
     if ( taskid == jtask ){
       printf("\n");
       for(itask=0;itask<ntasks;itask++){
         buffsum=0.0;
         for(i=0;i<buffsize;i++){
           buffsum=buffsum+sendbuff[itask][i];
         }
         printf("Tache %d : Somme du vecteur envoye a %d -> %e \n",
                 taskid,itask,buffsum);
 
       }
     }
   }
 
 
   /*===============================================================*/
   /* Communication.                                                */
 
   inittime = MPI_Wtime();
 
   ierr=MPI_Alltoall(sendbuff[0],buffsize,MPI_DOUBLE,
                     recvbuff[0],buffsize,MPI_DOUBLE,
                     MPI_COMM_WORLD);
 
   totaltime = MPI_Wtime() - inittime;
 
   /*===============================================================*/
   /* Affichage apres communication.                                */
 
   MPI_Barrier(MPI_COMM_WORLD);
   if(taskid==0){
     printf("\n");
     printf("##########################################################\n\n");
     printf("               --> APRES COMMUNICATION <-- \n");
   }
   for(jtask=0;jtask<ntasks;jtask++){
     MPI_Barrier(MPI_COMM_WORLD);
     if ( taskid == jtask ){
       printf("\n");
       for(itask=0;itask<ntasks;itask++){
         buffsum=0.0;
         for(i=0;i<buffsize;i++){
           buffsum=buffsum+recvbuff[itask][i];
         }
         printf("Tache %d : Somme du vecteur recu par %d -> %e \n",
                 taskid,itask,buffsum);
 
       }
     }
   }
 
   MPI_Barrier(MPI_COMM_WORLD);
   if(taskid==0){
     printf("\n");
     printf("##########################################################\n\n");
     printf(" Temps total de communication : %f secondes\n\n",totaltime);  
     printf("##########################################################\n\n");
   }
 
   /*===============================================================*/
   /* Liberation de la memoire                                      */
   free(sendbuff[0]);
   free(sendbuff);
   free(recvbuff[0]);
   free(recvbuff);
 
   /*===============================================================*/
   /* Finalisation de MPI                                           */
   MPI_Finalize();
}


Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Ressources de Calcul Québec
Outils
Partager