通过创建使用MPI_TYPE_CREATE_STRUCT
的结构化数据类型发送结构的一个元件,简单地proceed as usual。根据程序堆和程序堆相互之间的位置关系,B(1)
相对于N
的偏移量最终可能是一个巨大的正数或负数,但这在大多数Unix平台上都没有问题,数字应该在INTEGER(KIND=MPI_ADDRESS_KIND)
的范围内。
重要:结构的不同实例将最有可能有B
相对的不同偏移N
,因此只能用于发送这是用于在施工过程中获得的偏移量的特定记录的MPI数据类型数据类型。
当我尝试使用MPI_TYPE_CREATE_STRUCT为这样的Struct创建派生数据类型时,碰巧不同的CPU会创建不一致的派生数据类型。这是因为在不同的CPU上,Struct%B(:)可能位于与第一个元素Struct%N不同的内存位置。
这是一个非问题。通信操作两边的MPI数据类型只能是一致的,这意味着它们应该由相同序列中相同的基本数据类型组成。 每个元素的偏移量是无关紧要的。换句话说,只要发送方和接收方在调用MPI_TYPE_CREATE_STRUCT
时指定了相同类型和数量的数据元素,程序就会正常工作。
要发送多个元素,事情会变得有点复杂。有两种解决方案:
使用MPI_PACK
来串行化发送端数据和MPI_UNPACK
以在接收端对其进行反序列化。由于打包和解包需要额外的缓冲空间,这使得程序的内存需求增加了一倍。
或
创建为每个记录单独的MPI结构数据类型,然后创建一个结合了所有记录的数据类型结构。下面是如何发送两个这样的结构的阵列,一个在B
10元和一个20一个例子:
TYPE(Struct) :: Structs(2)
ALLOCATE(Structs(1)%B(10))
ALLOCATE(Structs(2)%B(20))
! (1) Create a separate structure datatype for each record
DO i=1,2
CALL MPI_GET_ADDRESS(Structs(i)%N, POS_(1), IError)
CALL MPI_GET_ADDRESS(Structs(i)%A, POS_(2), IError)
CALL MPI_GET_ADDRESS(Structs(i)%B(1), POS_(3), IError)
Offsets = POS_ - POS_(1)
Types(1) = MPI_INTEGER
Types(2) = MPI_REAL8
Types(3) = MPI_REAL8
Blocks(1) = 1
Blocks(2) = 1
Blocks(3) = i * 10
CALL MPI_TYPE_CREATE_STRUCT(3, Blocks, Offsets, Types, Elem_Type(i), IError)
END DO
! (2) Create a structure of structures that describes the whole array
CALL MPI_GET_ADDRESS(Structs(1)%N, POS_(1), IError)
CALL MPI_GET_ADDRESS(Structs(2)%N, POS_(2), IError)
Offsets = POS_ - POS_(1)
Types(1) = Elem_Type(1)
Types(2) = Elem_Type(2)
Blocks(1) = 1
Blocks(2) = 1
CALL MPI_TYPE_CREATE_STRUCT(2, Blocks, Offsets, Types, TwoElem_Type, IError)
CALL MPI_TYPE_COMMIT(TwoElem_Type, IError)
! (2.1) Free the intermediate datatypes
DO i=1,2
CALL MPI_TYPE_FREE(Elem_Type(i), IError)
END DO
! (3) Send the array
CALL MPI_SEND(Structs(1)%N, 1, TwoElem_Type, ...)
需要注意的是,虽然构建MPI数据类型是一种相对廉价的操作,你不应该使用上述程序发送,例如1000000个结构化类型的实例。此外,MPI数据类型描述符位于库管理的内存中,并且不再需要的数据类型的及时释放非常重要。
你写这整个问题的方式很奇怪,你没有提到你使用的语言Fortran。好吧,我为你加了标签。 –
你见过http://stackoverflow.com/questions/2258759/passing-variable-length-structures-between-mpi-processes和http://stackoverflow.com/questions/4273253/variable-sized-message-in- mpi? –
对不起国旗...我刚才看到这些链接,他们没有解决我遇到的问题,我的意思是: 使用REAL * 8 :: B(2)而不是allocatable一个是好的,没有问题! 问题显示当我使用REAL * 8,ALLOCATABLE :: B(:) @JohnZwinck –