Datatype

De Wiki de Calcul Québec
Aller à : Navigation, rechercher
Cette page est une traduction de la page Datatype et la traduction est complétée à 100 % et à jour.

Autres langues :anglais 100% • ‎français 100%

This program is a simple derived type example for MPI. The structure that is created contains one integer and three double precision floating point variables. At the main program's start, processor 0 initializes each of structure using a function that is not given here. Then each processor constructs an derived type to communicate the structure. In this example, the MPI_Bcast function is called to transfer the structures from processor 0 to the other processors.

In Fortran

File : datatype.f
module typeDerivParticule
  implicit none
  include 'mpif.h'
  integer, parameter  :: dp = kind(1.d0)
 
!  In this program we will communicate with MPI objects that are described
!  by the following structure. It is important that the size memory of the
!  elements of the strucure is fixed.
  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 )
 
!      Note that we compute displacement fo the element x but not for the
!      y and z elements. We can do so because y and z are of the same type
!      as x and are contiguous in memory. We give a block length of 3
 
    do i = 1, nblock
        displacement(i) = addresses(i) - origin
    end do
 
    call MPI_TYPE_STRUCT( nblock, block_length, displacement, typelist, &
   &                      MPIParticuleType, ierr )
 
!      In this example we use Type_struct. But there is other functions that
!       can be used to create a derived datatype.
!       See book MPI - The Complete Reference
 
    call MPI_TYPE_COMMIT( MPIParticuleType, ierr )
!      It is important after creating a datatype to call the Commit function
!      so you can use this datatype
  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 ) )
 
!      Process rank 0 establishes the list of particles
  if ( myrank == 0 ) then
    call SetParticles ( molecules, nombre_ptc )
  endif
 
!      List of particles is transmitted to each processor
  call BuildMPIParticuleType ( molecules(1), MPIParticuleType )
  call MPI_Bcast ( molecules, nombre_ptc, MPIParticuleType, 0, &
 &                 MPI_COMM_WORLD, ierr )
 
!      Check the result
  if ( myrank == 1 ) then
    call PrintParticles ( molecules(1:1), 1 )
  endif
 
!      Clean memory
  deallocate ( molecules )
  call MPI_Finalize ( ierr )
end


In C

File : datatype.c
#include "mpi.h"
#include <stdlib.h>
 
/* In this program we will communicate with MPI objects that are described
   by the following structure. It is important that the size memory of the
   elements of the strucure is fixed */
 
enum ParticuleSpecies { H2, O2 };
 
typedef struct particule
{
    int species;
    double x;
    double y;
    double z;
} Particule;
 
/* Main program */
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 );
 
    /* Process rank 0 establishes the list of particles */
    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++;
        }
    }
 
    /* List of particles is transmitted to each processor */
    BuildMPIParticuleType ( molecules[0], &MPIParticuleType );
    MPI_Bcast ( molecules, nombre_ptc, MPIParticuleType, 0, MPI_COMM_WORLD );
 
    /* Check the result */
    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 );
    }
 
    /* Clean memory */
    free ( molecules );
    MPI_Finalize( );
}
 
// Definition of the function used to build the appropriate derived datatype
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] ) );
 
    /* Note that we compute displacement fo the element x but not for the
       y and z elements. We can do so because y and z are of the same type
       as x and are contiguous in memory. We give a block length of 3 */
 
    for ( i = 0; i < nblock; i++ )
    {
        displacement[i] = addresses[i] - origin;
    }
 
    MPI_Type_struct ( nblock, block_length, displacement, typelist,
                      MPIParticuleType );
    /* In this example we use Type_struct. But there is other functions that
       can be used to create a derived datatype.
       See book MPI - The Complete Reference */
 
    MPI_Type_commit ( MPIParticuleType );
    /* It is important after creating a datatype to call the Commit function
       so you can use this datatype */
}


Outils personnels
Espaces de noms

Variantes
Actions
Navigation
Ressources de Calcul Québec
Outils
Partager