В чем разница между использованием MPI_Type_contiguous и MPI_Type_create_struct для отправки / получения объявленной структуры данных с MPI - PullRequest
3 голосов
/ 10 октября 2019

В этом потоке было объяснено двумя способами, как передавать сообщения с использованием MPI с объявленными типами данных. У меня есть структура данных с помощью allocatables

  type t_example 
      real, allocatable :: x(:), y(:), z(:)
  end type 

. Для обеспечения работоспособности кода проще всего было бы не использовать MPI_TYPE_CONTIGUOUS следующим образом

  ! -- declare 
   type(t_example) :: p1 
   type(MPI_DATATYPE) :: mpi_dtexample

  (...) 

  call MPI_TYPE_CONTIGUOUS(sizeof(p1), MPI_BYTE, mpi_dtexample, ierr);
  call MPI_TYPE_COMMIT(mpi_dtexample, ierr) 

. После этого я могу просто использоватьотправить / recv с mpi_dtexample в качестве типа данных.

Я не могу прийти в голову, когда становится более разумным использовать mpi_type_create_struct, так как это потребует от вас явного указания последовательности объявленного типа с типом данных и их соответствующими размерами.

ДА, подход MPI_TYPE_CONTIGUOUS предполагает, что объявленный тип является смежным, и я не смог бы использовать этот подход, если бы я хотел пропустить определенные пошаговые элементы объявленного типа.

Есть ли еще что-то, что я должен поднять, когда буду звонить в тревогу, используя MPI_TYPE_CONTIGUOUS

ПОЛНЫЙ ПРИМЕР

Бег с двумя рядамитолько.

 module md_

   use mpi_f08

   integer numtasks, rank, tag, i,  ierr
   type(mpi_status) stat


   type T_PART
      real, allocatable :: x(:), y(:), z(:)
   end type

contains


end module

program struct
   use md_
   implicit none
   type(t_part)       :: test_
   type(mpi_datatype) :: mpidt
   integer            :: sz, szz

   call MPI_INIT(ierr)
   call MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr)
   call MPI_COMM_SIZE(MPI_COMM_WORLD, numtasks, ierr)

   tag = 1

   szz= 10
   allocate(test_% x(szz),test_% y(szz), test_% z(szz) )




   sz = sizeof(test_)
   call MPI_Type_contiguous(sz, MPI_BYTE ,mpidt, ierr)
   call MPI_TYPE_COMMIT(mpidt, ierr)



   if (rank .eq. 0) then
      do i=1,szz
         test_%x(i) = i*1+mod(i,3)
         test_%y(i) = i*2+mod(i,3)
         test_%z(i) = i*3+mod(i,3)
      end do

      call MPI_SEND(test_, 1, mpidt, 1, tag, &
                    MPI_COMM_WORLD, ierr)

   else
         call MPI_RECV(test_, 1, mpidt, 0, tag, &
                    MPI_COMM_WORLD, stat, ierr)
   endif

   print *, 'rank= ',rank,' test_% x= ', test_%z(1) ! seg faults for rank 2


   call mpi_barrier(MPI_COMM_WORLD, ierr)
   ! free datatype when done using it
   call MPI_TYPE_FREE(mpidt, ierr)
   call MPI_FINALIZE(ierr)


   end
...