带有数组的MPI结构数据类型

问题描述 投票:0回答:2

我想在mpi的一个MPI_SEND / RECV调用中轻松发送someObject

   type someObject
     integer :: foo
     real :: bar,baz
     double precision :: a,b,c
     double precision, dimension(someParam) :: x, y
   end type someObject

我开始使用MPI_TYPE_STRUCT,但是后来意识到数组xy的大小取决于someParam。我最初想到的是在结构中嵌套MPI_TYPE_CONTIGUOUS来表示数组,但似乎无法使其正常工作。如果可能的话?

  ! Setup description of the 1 MPI_INTEGER field
  offsets(0) = 0
  oldtypes(0) = MPI_INTEGER
  blockcounts(0) = 1
  ! Setup description of the 2 MPI_REAL fields
  call MPI_TYPE_EXTENT(MPI_INTEGER, extent, ierr)
  offsets(1) = blockcounts(0) * extent
  oldtypes(1) = MPI_REAL
  blockcounts(1) = 2
  ! Setup descripton of the 3 MPI_DOUBLE_PRECISION fields
  call MPI_TYPE_EXTENT(MPI_DOUBLE_PRECISION, extent, ierr)
  offsets(2) = offsets(1) + blockcounts(1) * extent
  oldtypes(2) = MPI_DOUBLE_PRECISION
  blockcounts(2) = 3
  ! Setup x and y MPI_DOUBLE_PRECISION array fields
  call MPI_TYPE_CONTIGUOUS(someParam, MPI_DOUBLE_PRECISION, sOarraytype, ierr)
  call MPI_TYPE_COMMIT(sOarraytype, ierr)
  call MPI_TYPE_EXTENT(sOarraytype, extent, ierr)
  offsets(3) = offsets(2) + blockcounts(2) * extent
  oldtypes(3) = sOarraytype
  blockcounts(3) = 2 ! x and y

  ! Now Define structured type and commit it
  call MPI_TYPE_STRUCT(4, blockcounts, offsets, oldtypes, sOtype, ierr)
  call MPI_TYPE_COMMIT(sOtype, ierr)

我想做什么:

...
type(someObject) :: newObject, rcvObject
double precision, dimension(someParam) :: x, y
do i=1,someParam
  x(i) = i
  y(i) = i
end do
newObject = someObject(1,0.0,1.0,2.0,3.0,4.0,x,y)
MPI_SEND(newObject, 1, sOtype, 1, 1, MPI_COMM_WORLD, ierr) ! master
...
! slave would:
MPI_RECV(rcvObject, 1, sOtype, master, MPI_ANY_TAG, MPI_COMM_WORLD, status, ierr)
WRITE(*,*) rcvObject%foo
do i=1,someParam
  WRITE(*,*) rcvObject%x(i), rcvObject%y(i)
end do
...

到目前为止,我只是遇到分段错误,没有太多迹象表明我在做什么错,或者甚至有可能这样做。该文档从未说过我无法在struct数据类型内使用连续的数据类型。

fortran mpi fortran90
2个回答
1
投票

从表面上看,您无法嵌套这些数据类型,这是完全错误的解决方案。

由于:http://static.msi.umn.edu/tutorial/scicomp/general/MPI/mpi_data.htmlhttp://www.osc.edu/supercomputing/training/mpi/Feb_05_2008/mpi_0802_mod_datatypes.pdf为指导。

定义MPI_TYPE_STRUCT的正确方法如下:

type(someObject) :: newObject, rcvObject
double precision, dimension(someParam) :: x, y
data x/someParam * 0/, w/someParam * 0/
integer sOtype, oldtypes(0:7), blocklengths(0:7), offsets(0:7), iextent, rextent, dpextent
! Define MPI datatype for someObject object
! set up extents
call MPI_TYPE_EXTENT(MPI_INTEGER, iextent, ierr)
call MPI_TYPE_EXTENT(MPI_REAL, rextent, ierr)
call MPI_TYPE_EXTENT(MPI_DOUBLE_PRECISION, dpextent, ierr)
! setup blocklengths /foo,bar,baz,a,b,c,x,y/
data blocklengths/1,1,1,1,1,1,someParam,someParam/
! setup oldtypes
oldtypes(0) = MPI_INTEGER
oldtypes(1) = MPI_REAL
oldtypes(2) = MPI_REAL
oldtypes(3) = MPI_DOUBLE_PRECISION
oldtypes(4) = MPI_DOUBLE_PRECISION
oldtypes(5) = MPI_DOUBLE_PRECISION
oldtypes(6) = MPI_DOUBLE_PRECISION
oldtypes(7) = MPI_DOUBLE_PRECISION
! setup offsets
offsets(0) = 0
offsets(1) = iextent * blocklengths(0)
offsets(2) = offsets(1) + rextent*blocklengths(1)
offsets(3) = offsets(2) + rextent*blocklengths(2)
offsets(4) = offsets(3) + dpextent*blocklengths(3)
offsets(5) = offsets(4) + dpextent*blocklengths(4)
offsets(6) = offsets(5) + dpextent*blocklengths(5)
offsets(7) = offsets(6) + dpextent*blocklengths(6)
! Now Define structured type and commit it
call MPI_TYPE_STRUCT(8, blocklengths, offsets, oldtypes, sOtype, ierr)
call MPI_TYPE_COMMIT(sOtype, ierr)

这使我可以用我最初想要的方式发送和接收对象!


0
投票

MPI结构类型非常令人头疼。如果此代码不在代码的性能关键部分,请查看MPI_PACKED类型。包装调用相对较慢(基本上是您要发送的每个元素一个函数调用!),因此不要将其用于很大的消息,但它相当容易使用,并且可以灵活发送。

© www.soinside.com 2019 - 2024. All rights reserved.