我想在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,但后来意识到数组 x 和 y 的大小取决于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数据类型中使用连续的数据类型。
答案 0 :(得分:1)
从看起来你不能嵌套这些类型的数据类型,这是一个完全错误的解决方案。
感谢:http://static.msi.umn.edu/tutorial/scicomp/general/MPI/mpi_data.html和http://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)
这允许我以我原来想要的方式发送和接收对象!
答案 1 :(得分:0)
抱歉,我无法在任何地方发表评论,所以我必须在这里给你一个答案。在上面的答案中,有一个小问题:offsets(3) = offsets(2) + dpextent*blocklengths(2)
它应该是offsets(3) = offsets(2) + rextent*blocklengths(2)
,因为变量3是real
而不是double precision
。
答案 2 :(得分:0)
MPI结构类型非常令人头疼。如果此代码不在代码的性能关键部分,请查看MPI_PACKED
类型。包装调用相对较慢(基本上每个元素要发送一个函数调用!),因此不要将其用于很大的消息,但是它相当容易使用,并且发送内容非常灵活。