在MPI中,通常有兩種方法發送和接收這種派生的數據類型。壹種方式是利用MPI提供的創建派生數據類型的命令,創建壹個與Fortran90程序中已經定義的派生數據類型相同的新數據結構,然後生成壹個MPI的派生數據類型,最後傳遞這個MPI的派生數據類型;另壹種方法是以數據包的形式發送數據,然後在接收端將其解包。最近在研究前壹種方法,這裏簡單介紹壹下我的經驗。
例如,在Fortran90程序中定義了以下派生數據類型:
type type_global!INT(5+5),character(2*10),real(3),real*8(2)
整數npoin、nelem、ngroup、nmat、nblks
真實的x,y,z
真實*8 x8,y8
整數icmatrix(5)
character*20 outplot,type_abc
結束類型type_global
這個派生數據類型有四種標準數據類型,分別是integer (10,包括5個標量和5個元素的1數組)、real類型(3)、雙精度real類型(3)和string類型(2,各20個字符)。為了傳遞這個派生類型的數據,首先要將其數據結構定義為壹個MPI派生類型,要使用兩個MPI命令,分別是MPI_TYPE_STRUCT和MPI_TYPE_COMMIT。前者用於定義派生的數據結構,後者用於提交確認。MPI_TYPE_STRUCT的調用格式如下:
調用MPI_TYPE_STRUCT(ndatatype,blocklens_global,offsets_global,oldtypes_global,& amp
type_global_MPI,ierr)
解釋如下:
Ndatatype為整型變量,其值為派生數據類型中包含的標準類型的個數(本例中合並了相同的標準類型數據),本例中的值為4,即整型、字符串型、實型和雙精度實型;
Blockens _ global (0: 3)是壹個有n個數據類型的整數數組,每個元素的值就是這個派生類型中對應的標準數據類型的個數。如果順序為整數、字符串、實數、雙精度實數,則該數組的值為;
Offsets_global(0:3)是壹個帶有ndatatype元素的整數數組,每個元素的值都是該派生類型中對應標準數據類型的位移偏移量。這需要知道派生類型數據結構的類型表。簡單來說,在這個派生類型中,第1個標準類型(整型)的位移偏移量是0,第二個標準類型(字符串型)的位移偏移量應該是前壹個標準類型(第1個標準類型)的個數乘以該標準類型在內存中占用的字節數(4字節*10 =40),第壹個標準類型應該是0。本例中,值為,在Fortran90中,默認整數點為4字節,實型為4字節,雙精度實型為8字節,字符串按其長度計算,壹個字符占壹個字節。
Oldtypes_global(0:3)是壹個有n個數據類型的整數數組,每個元素的值都是這個派生類型中對應標準數據類型的MPI類型。按照上面的順序,它的值應該是[MPI _ integer,MPI _ character,MPI _ real,MPI _ double _ precedent]。
Blocklines _ global、Offsets _ global和oldtypes _ global應該有相同的標準數據類型順序,哪個在前哪個在後並不重要,但是三個數據的順序必須相同。
Type_global_MPI是壹個整型變量,定義後成為MPI可以使用的派生數據類型名,可以像MPI_INTEGER、MPI_REAL等壹樣使用。
Ierr是壹個整型變量,妳應該對它了如指掌。
最後,可以使用Call MPI _ Type _ Commit(Type _ global _ MPI,IERR)提交確認,然後使用MPI_SEND和MPI_RECV作為派生數據類型進行傳遞。
下面給出壹個完整的用MPI傳輸Fortran90的派生數據類型的代碼,主要是用MPI傳輸壹個派生結構數據,然後在每個進程中修改數據,然後打印出每個進程修改的數據,看看是否成功。
!==============================================================
程序MPI_TypeData_SendRecv
使用mpi
character *(MPI _ MAX _ PROCESSOR _ NAME)PC NAME,text*20
整數,參數::ndatatype=4
整數myid,npc,namelen,re,ierr,ver,subver,m,n,status(MPI_STATUS_SIZE),ipc
整數type_block_MPI,type_global_MPI,& amp
block lens _ global(0:ndatatype-1),offsets _ global(0:ndatatype-1),& amp
old types _ global(0:ndatatype-1),& amp
blocklens_block(0:2),offsets_block(0:2),oldtypes_block(0:2)
整數(8)::範圍
type type_global!INT(5+5),character(2*10),real(3),real*8(2)
整數npoin、nelem、ngroup、nmat、nblks
真實的x,y,z
真實*8 x8,y8
整數icmatrix(5)
character*20 outplot,type_abc
結束類型type_global
類型類型_塊
integer,allocatable::appear_process(:,:),matno_process(:,:)
結束類型type_block
類型(類型_全球)GHM _全球,GHM _全球1
類型(類型塊)GHM塊
調用MPI_INIT(ierr)
調用MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)
調用MPI_COMM_SIZE(MPI_COMM_WORLD,npc,ierr)
btime=MPI_WTIME()
調用MPI_GET_PROCESSOR_NAME(pcname,namelen,ierr)
調用MPI_GET_VERSION(ver,subver,ieer)
寫(*,1000)myid,npc,trim(pcname),ver,subver
if(myid==0)then!處理器0中的初始類型數組
GHM _全球% npoin = 10;GHM _全球% n組=5
GHM _全球%nblks=2
do ipc=1,size(GHM _全球%icmatrix)
GHM _全球%icmatrix(ipc)=ipc-1
恩多
GHM _全球% y = 0.4GHM _全球%y8=0.8
GHM _全球%輸出計劃= ' GIDGHM _全球%type_ABC='VIE '
n group = GHM _全球%ngroup
nblks = GHM _全球%nblks
allocate(GHM塊百分比出現進程(n組,nblks),& amp
GHM _ Blocks % matno _ process(n group,nblks))
GHM _街區%出現_進程= 0;GHM_Blocks%matno_process=0
endif
blocklens_global(0)=10!10整數
offsets_global(0) =0
oldtypes_global(0) =MPI_INTEGER
調用MPI_TYPE_EXTENT(MPI_INTEGER,EXTENT,ierr)
blocklens_global(1)=40!40個字符
offsets _ global(www.cshangzj.com 1)= offsets _ global(0)+block lens _ global(0)*範圍
oldtypes _ global(1)= MPI _ CHARACTER
調用MPI_TYPE_EXTENT(MPI_CHARACTER,EXTENT,ierr)
blocklens_global(2)=3!3實數
offsets _ global(2)= offsets _ global(1)+block lens _ global(1)*範圍
oldtypes_global(2) =MPI_REAL
調用MPI_TYPE_EXTENT(MPI_REAL,EXTENT,ierr)
blocklens_global(3)=2!2實數*8
offsets _ global(3)= offsets _ global(2)+block lens _ global(2)*範圍
oldtypes _ global(3)= MPI _ DOUBLE _ PRECISION
調用MPI_TYPE_EXTENT(MPI_INTEGER,EXTENT,ierr)
write(*,'(a,10i4)')'myid_int = ',myid,extent
調用MPI_TYPE_EXTENT(MPI_REAL,EXTENT,ierr)
write(*,'(a,10i4)')'myid_real= ',myid,extent
調用MPI _ TYPE _ EXTENT(MPI _ DOUBLE _ PRECISION,EXTENT,ierr)
write(*,'(a,10i4)')'myid_doub= ',myid,extent
調用MPI_TYPE_EXTENT(MPI_CHARACTER,EXTENT,ierr)
write(*,'(a,10i4)')'myid_char= ',myid,extent,offsets_global
調用MPI_TYPE_STRUCT(ndatatype,blocklens_global,offsets_global,oldtypes_global,& amp
type_global_MPI,ierr)
調用MPI _ TYPE _ COMMIT(TYPE _ global _ MPI,ierr)
if(myid==0)then!將GHM _全局從0處理器發送到其他處理器
do ipc=1,npc-1
調用MPI _ SEND(GHM _全球,1,類型_全球_MPI,ipc,9,MPI _通訊_世界,ierr)
恩多
其他
調用MPI _ RECV(GHM _全球1,1,類型_全球_MP