Broadcast

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

Ce programme est un exemple simple d'utilisation de la fonction MPI_Bcast. Le contenu du vecteur buff de dimension buffsize est transmis à tous les processus en effectuant une diffusion. Avant et après la diffusion, chaque processus calcule la somme des éléments du vecteur et l'affiche à l'écran. La dimension du vecteur est donnée en argument lors de l'exécution du programme.

En Fortran

Fichier : bcast.f90
!-----------------------------------------------------------------
!                buff                buff
!                                
!              ########            ########
!              #      #            #      #
!          0   # ABCD #            # ABCD #
!              #      #            #      #
!              ########            ########
!     T        #      #            #      #
!          1   # 0000 #            # ABCD #
!     a        #      #            #      #
!              ########            ########
!     c        #      #            #      #
!          2   # 0000 #            # ABCD #
!     h        #      #            #      #
!              ########            ########
!     e        #      #            #      #
!          3   # 0000 #            # ABCD #
!     s        #      #            #      #
!              ########            ########
!              #      #            #      #
!          4   # 0000 #            # ABCD #
!              #      #            #      #
!              ########            ########
!
!               AVANT                APRES
!               
! Auteur : Carol Gauthier
!          Centre de Calcul scientifique
!          Université de Sherbrooke
!
! Dernière révision : Michel Béland, Calcul Québec, octobre 2013
!-----------------------------------------------------------------
Program Exemple_MPI
 
  use mpi
  integer ierr,ntasks,taskid
  integer buffsize
  character argtmp*12
  integer l
  integer, parameter :: dp=kind(1.0d0)
  real(dp) inittime,totaltime
 
  real(dp),allocatable,dimension(:) :: buff
  real(dp) buffsum
 
  !---------------------------------------------------------------
  ! 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
  ! On utilise la méthode de Fortran 2003 pour récupérer les arguments
  if (command_argument_count() == 0) stop
  call get_command_argument(1,length=l)
  if (l > 12) stop
  call get_command_argument(1,value=argtmp)
  ! Si vous n'avez pas accès à un compilateur Fortran 2003, utilisez plutôt le
  ! sous-programme getarg, non standard mais relativement portable :
  ! call getarg(1,argtmp)
  read(argtmp,'(I12)')buffsize
 
  !---------------------------------------------------------------
  ! Allocation de la mémoire du vecteur buff sur chaque processus
  allocate( buff(buffsize) )  
 
   !---------------------------------------------------------------
   ! Affichage de la description de l'exemple.
   if ( taskid.eq.0 )then
     write(*,'(A)')
     write(*,'(A)')"##########################################################"
     write(*,'(A)')
     write(*,'(A)')" Exemple 3"
     write(*,'(A)')
     write(*,'(A)')" Communication collective : MPI_Bcast"
     write(*,'(A)')
     write(*,'(A,I12)')" Dimension du vecteur :",buffsize
     write(*,'(A,I5)')" Nombre total de processus :",ntasks
     write(*,'(A)')
     write(*,'(A)')"##########################################################"
     write(*,'(A)')
     write(*,'(A)')"                --> AVANT COMMUNICATION <--"
     write(*,'(A)')
   endif
 
   call MPI_Barrier(MPI_COMM_WORLD,ierr);
 
   !-----------------------------------------------------------------
   ! Initialisation des vecteurs ou tableaux.
   if( taskid.eq.0 )then
     call random_number(harvest=buff)
   else
     buff=0.0_dp
   end if
 
   !-----------------------------------------------------------------
   ! Affichage avant communication.
 
   buffsum = sum(buff)
 
   write(*,'(A,I3,A,ES16.8)')"Processus ",taskid," : somme du vecteur buff=",buffsum 
 
   !-----------------------------------------------------------------
   ! Communication
 
   inittime=MPI_Wtime()
   call MPI_Bcast(buff,buffsize,MPI_DOUBLE_PRECISION,0,MPI_COMM_WORLD,ierr)
   totaltime=MPI_Wtime()-inittime
 
   !-----------------------------------------------------------------
   ! Affichage après communication.
 
   buffsum = sum(buff)
 
   call MPI_Barrier(MPI_COMM_WORLD,ierr);
 
   if ( taskid.eq.0 )then
     write(*,*)
     write(*,'(A)')"##########################################################"
     write(*,'(A)')
     write(*,'(A)')"                --> APRÈS COMMUNICATION <-- "
     write(*,'(A)')
   end if
 
   call MPI_Barrier(MPI_COMM_WORLD,ierr)
 
   write(*,'(A,I3,A,ES16.8)')"Processus ",taskid," : somme du vecteur buff=",buffsum
 
   call MPI_Barrier(MPI_COMM_WORLD,ierr)
 
   if(taskid.eq.0)then
     write(*,*)
     write(*,'(A)')"##########################################################"
     write(*,'(A,ES10.2,A)')" Temps total de communication : ",totaltime," secondes" 
     write(*,'(A)')"##########################################################"
     write(*,*)
   end if
 
  !-----------------------------------------------------------------
  ! Libération de la mémoire
  deallocate(buff)
 
  !-----------------------------------------------------------------
  ! Finalisation de MPI
 
  call MPI_FINALIZE( ierr )
end


En C

Fichier : bcast.c
/* -----------------------------------------------------------------   
                buff                buff
 
              ########            ########
              #      #            #      #
          0   # ABCD #            # ABCD #
              #      #            #      #
              ########            ########
     T        #      #            #      #
          1   # 0000 #            # ABCD #
     a        #      #            #      #
              ########            ########
     c        #      #            #      #
          2   # 0000 #            # ABCD #
     h        #      #            #      #
              ########            ########
     e        #      #            #      #
          3   # 0000 #            # ABCD #
     s        #      #            #      #
              ########            ########
              #      #            #      #
          4   # 0000 #            # ABCD #
              #      #            #      #
              ########            ########
AVANT                APRÈS        
 
 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){
 
   int          taskid, ntasks;
   int          ierr,i,j,itask;
   int	        buffsize;
   double       *buff,buffsum;
   double       inittime,totaltime;
 
   /*---------------------------------------------------------------*/
   /* Initialisation de MPI. Il est important de placer cet appel   */
   /* au début du programme, immédiatement apres 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]);
 
   /*---------------------------------------------------------------*/
   /* Allocation de la mémoire.                                     */ 
   buff=(double *)malloc(sizeof(double)*buffsize);
 
   /*---------------------------------------------------------------*/
   /* Affichage de la description de l'exemple.                     */
   if ( taskid == 0 ){
     printf("\n\n\n");
     printf("##########################################################\n\n");
     printf(" Exemple 3 \n\n");
     printf(" Communication collective : MPI_Bcast \n\n");
     printf(" Le processus 0 envoie une copie du vecteur buff\n");
     printf(" à tous les autres processus. \n\n");
     printf(" Dimension du vecteur : %d\n",buffsize);
     printf(" Nombre total de processus : %d\n\n",ntasks);
     printf("##########################################################\n\n");
     printf("                --> AVANT COMMUNICATION <--\n\n");
   }
 
   ierr=MPI_Barrier(MPI_COMM_WORLD);
 
   /*---------------------------------------------------------------*/
   /* Initialisation des vecteurs ou tableaux                 */
   if( taskid == 0 ){
     srand((unsigned)time( NULL ) + taskid);
     for(i=0;i<buffsize;i++)buff[i]=(double)rand()/RAND_MAX;
   }
   else{
     for(i=0;i<buffsize;i++)buff[i]=0.0;
   }
 
   /*---------------------------------------------------------------*/
   /* Affichage avant communication.                                */
 
   buffsum=0.0;
   for(i=0;i<buffsize;i++){
     buffsum += buff[i];
   }
 
   printf("Processus %d : Somme du vecteur buff= %e\n",taskid,buffsum);  
 
   /*---------------------------------------------------------------*/
   /* Communication.                                                */
 
   inittime = MPI_Wtime();
 
   ierr=MPI_Bcast(buff,buffsize,MPI_DOUBLE,0,MPI_COMM_WORLD);
 
   totaltime = MPI_Wtime() - inittime;
 
   /*---------------------------------------------------------------*/
   /* Affichage après communication.                                */
 
   buffsum=0.0;
   for(i=0;i<buffsize;i++){
     buffsum += buff[i];
   } 
 
 
   if ( taskid == 0 ){
     printf("##########################################################\n\n");
printf("                --> APRÈS COMMUNICATION <-- \n\n");
   }
   ierr=MPI_Barrier(MPI_COMM_WORLD);
 
   printf("Processus %d : Somme du vecteur buff= %e\n",taskid,buffsum);
 
   ierr=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");
   }
 
   /*---------------------------------------------------------------*/
   /* Libération de la mémoire                                      */
   free(buff);
 
   /*---------------------------------------------------------------*/
   /* Finalisation de MPI                                           */
   MPI_Finalize();
}


Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Ressources de Calcul Québec
Outils
Partager