Datatype

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

Ce programme est un exemple simple de type dérivé pour MPI. La structure créée contient un entier et trois réels double précision. Au début du programme principal, le processeur 0 initialise chacune des structures à l'aide d'une fonction qui n'est pas donnée ici. Puis chaque processeur construit un type dérivé pour la communication de la structure. Dans cet exemple, on appelle la fonction MPI_Bcast pour le transfert des structures du processeur 0 aux autres processeurs.

En Fortran

Fichier : datatype.f
module typeDerivParticule
  implicit none
  include 'mpif.h'
  integer, parameter  :: dp = kind(1.d0)
 
!  Type dérivé dont l'on voudra communiquer des instanciations avec MPI.
!  Il est important que cette structure contienne un nombre fixe d'éléments,
!  donc qu'elle ne contienne aucun tableau allouable.
  type, public :: Particule
    private
    integer  :: species
    real(dp) :: x, y, z
  end type Particule
 
  contains
  subroutine BuildMPIParticuleType( ptc, MPIParticuleType )
    implicit none
    type(Particule), intent(in) :: ptc
    integer, intent(out)        :: MPIParticuleType
    integer, parameter          :: nblock = 2
    integer                     :: i
    integer                     :: ierr
    integer, dimension(nblock)  :: block_length = (/1, 3/)
    integer, dimension(nblock)  :: typelist = (/MPI_INTEGER, MPI_DOUBLE_PRECISION/)
    integer                     :: origin
    integer, dimension(nblock)  :: displacement, addresses
 
    call MPI_ADDRESS( ptc, origin, ierr )
    call MPI_ADDRESS( ptc%species, addresses(1), ierr )
    call MPI_ADDRESS( ptc%x, addresses(2), ierr )
 
!      Noter que l'on n'indique le déplacement que pour l'élément x et non pour
!      les éléments y et z. La raison est que nous utiliserons le fait que ces
!      éléments sont de même type et sont placés dans des espaces contigus
!      en mémoire.
 
    do i = 1, nblock
        displacement(i) = addresses(i) - origin
    end do
 
    call MPI_TYPE_STRUCT( nblock, block_length, displacement, typelist, &
   &                      MPIParticuleType, ierr )
 
!      Dans cet exemple, nous utilisons Type_struct, mais il existe d'autres
!      fonctions pour la création de types dérivés. Consulter le livre
!      « MPI - The Complete Reference ».
 
    call MPI_TYPE_COMMIT( MPIParticuleType, ierr )
!      Il est important, après avoir fait l'appel de la création du type dérivé,
!      d'appeler la fonction Commit pour que ce type puisse être utilisé.
  end subroutine BuildMPIParticuleType
 
  subroutine SetParticles( ptc, nombre_ptc )
    implicit none
    type(Particule),dimension(:),intent(out),target :: ptc
    integer,intent(in)                              :: nombre_ptc
    integer                                         :: iter
    type(Particule),pointer                         :: ptc_ptr
 
    do iter = 1, nombre_ptc
      ptc_ptr => ptc( iter )
      ptc_ptr%species = 1
      call random_number( ptc_ptr%x )
      call random_number( ptc_ptr%y )
      call random_number( ptc_ptr%z )
    end do
  end subroutine SetParticles
 
  subroutine PrintParticles( ptc, nombre_ptc )
    implicit none
    type(Particule),dimension(:),intent(in),target :: ptc
    integer,intent(in)                             :: nombre_ptc
    integer                                        :: iter
    type(Particule),pointer                        :: ptc_ptr
 
    do iter = 1, nombre_ptc
      ptc_ptr => ptc( iter )
      print*, 'species=',ptc_ptr%species,' pos=(',ptc_ptr%x,',',ptc_ptr%y &
     &      , ',', ptc_ptr%z, ')'
    end do
  end subroutine PrintParticles
 
end module typeDerivParticule
 
 
Program TypeDeriveMPI
  use typeDerivParticule
  implicit none
 
  integer, parameter                       :: nombre_ptc = 100
  integer                                  :: myrank
  integer                                  :: ierr
  type(Particule),dimension(:),allocatable :: molecules
  integer                                  :: MPIParticuleType
 
  call MPI_Init ( ierr )
  call MPI_Comm_rank ( MPI_COMM_WORLD, myrank, ierr )
  allocate( molecules( nombre_ptc ) )
 
!      Le processeur 0 établit la liste des particules.
  if ( myrank == 0 ) then
    call SetParticles ( molecules, nombre_ptc )
  endif
 
!      On communique la liste des particules à tous les processeurs.
  call BuildMPIParticuleType ( molecules(1), MPIParticuleType )
  call MPI_Bcast ( molecules, nombre_ptc, MPIParticuleType, 0, &
 &                 MPI_COMM_WORLD, ierr )
 
!      On affiche les résultats.
  if ( myrank == 1 ) then
    call PrintParticles ( molecules(1:1), 1 )
  endif
 
!      On libère la mémoire.
  deallocate ( molecules )
  call MPI_Finalize ( ierr )
end


En C

Fichier : datatype.c
#include "mpi.h"
#include <stdlib.h>
 
/* Structure dont l'on voudra communiquer des instanciations avec MPI.
   Il est important que cette structure contienne un nombre fixe d'éléments,
   donc qu'elle ne contienne ni de vector ni de string.
*/
 
enum ParticuleSpecies { H2, O2 };
 
typedef struct particule
{
    int species;
    double x;
    double y;
    double z;
} Particule;
 
/* Programme principal */
int main( int argc, char **argv )
{
#define nombre_ptc 100
    int          myrank;
    int          iter;
    Particule   *molecules, *ptc_ptr;
    MPI_Datatype MPIParticuleType;
    void BuildMPIParticuleType( Particule ptc, MPI_Datatype *MPIParticuleType );
 
    MPI_Init (&argc, &argv);
    MPI_Comm_rank ( MPI_COMM_WORLD, &myrank );
    molecules = ( Particule * ) malloc ( sizeof( Particule ) * nombre_ptc );
 
    /* Le processeur 0 établit la liste des particules. */
    if ( myrank == 0 )
    {
        ptc_ptr = molecules;
        for ( iter = 0; iter < nombre_ptc; iter++ )
        {
            ptc_ptr -> species = ( int ) H2;
            ptc_ptr -> x = ( (double) rand( ) ) / RAND_MAX;
            ptc_ptr -> y = ( (double) rand( ) ) / RAND_MAX;
            ptc_ptr -> z = ( (double) rand( ) ) / RAND_MAX;
            ptc_ptr++;
        }
    }
 
    /* On communique la liste des particules à tous les processeurs. */
    BuildMPIParticuleType ( molecules[0], &MPIParticuleType );
    MPI_Bcast ( molecules, nombre_ptc, MPIParticuleType, 0, MPI_COMM_WORLD );
 
    /* On affiche les résultats. */
    if ( myrank == 1 )
    {
        ptc_ptr = molecules;
        printf( "type=%d, pos=(%f,%f,%f)\n", ptc_ptr -> species, ptc_ptr -> x,
                 ptc_ptr -> y, ptc_ptr -> z );
    }
 
    /* On libère la mémoire. */
    free ( molecules );
    MPI_Finalize( );
}
 
/* Définition de la fonction pour construire le type dérivé */
void BuildMPIParticuleType ( Particule ptc, MPI_Datatype *MPIParticuleType )
{
#define nblock 2
    int          i;
    int          block_length[nblock] = {1, 3};
    MPI_Datatype typelist[nblock] = {MPI_INT, MPI_DOUBLE};
    MPI_Aint     displacement[nblock];
    MPI_Aint     origin, addresses[nblock];
 
    MPI_Address ( &ptc, &origin );
    MPI_Address ( &( ptc.species ), &( addresses[0] ) );
    MPI_Address ( &( ptc.x ), &( addresses[1] ) );
 
    /* Noter que l'on n'indique le déplacement que pour l'élément x et non pour
       les éléments y et z. La raison est que nous utiliserons le fait que ces
       éléments sont de même type et sont placés dans des espaces contigus
       en mémoire. */
 
    for ( i = 0; i < nblock; i++ )
    {
        displacement[i] = addresses[i] - origin;
    }
 
    MPI_Type_struct ( nblock, block_length, displacement, typelist,
                      MPIParticuleType );
    /* Dans cet exemple, nous utilisons Type_struct, mais il existe d'autres
       fonctions pour la création de types dérivés. Consulter le livre
       « MPI - The Complete Reference ». */
 
    MPI_Type_commit ( MPIParticuleType );
    /* Il est important, après avoir fait l'appel de la création du type derivé,
       d'appeler la fonction Commit pour que ce type puisse être utilisé. */
}


Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Ressources de Calcul Québec
Outils
Partager