通過創建使用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 –