骞惰绠楁硶璁蹭箟 - 鐧惧害鏂囧簱 联系客服

发布时间 : 星期三 文章骞惰绠楁硶璁蹭箟 - 鐧惧害鏂囧簱更新完毕开始阅读d6ac36768e9951e79b8927da

Fortran 77

MPI_ADDRESS(BUFF, ADDRESS, IERR) BUFF(*)

INTEGER ADDRESS, IERR

C 语言中通过指针可以实现对地址的任何操作,而 Fortran 77 语言中则难以用通用的方式直接使用一个地址。为便于 Fortran 77 代码使用 MPI_ADDRESS函数返回的地址,MPI 定义了一个变量MPI_BOTTOM,它相当于绝对地址 0,因此,调用 CALL MPI_ADDRESS(BUFF, ADDRESS, IERR)

后,MPI_BOTTOM(ADDRESS)与 BUFF 代表着同一个内存地址。

例: 4.10

REAL A(N), B(N)

INTEGER TYPE, IA, IB ......

CALL MPI_ADDRESS(A, IA, IERR) CALL MPI_ADDRESS(B, IB, IERR)

CALL MPI_TYPE_HVECTOR(2, N, IB-IA, MPI_REAL, TYPE, IERR) ......

CALL MPI_SEND(A, 1, TYPE, ...) ... ...

同时发送两个同类型数组 A 和 B。

例 4.11

PARAMETER (N=1024, M=512, L=256)

REAL A(N) INTEGER B(M) COMPLEX C(L)

INTEGER LEN(3), DISP(3), TYPE(3), NEWTYPE, IA, IB, IC DATA TYPE /MPI_REAL, MPI_INTEGER, MPI_COMPLEX/, + LEN /N, M, L/

... ...

CALL MPI_ADDRESS(A, IA, IERR) CALL MPI_ADDRESS(B, IB, IERR) CALL MPI_ADDRESS(C, IC, IERR) DISPS(1)=0 DISPS(2)=IB-IA DISPS(3)=IC-IA

CALL MPI_TYPE_STRUCT(3, LEN, DISP, TYPE, NEWTYPE, IER) ... ...

CALL MPI_SEND(A, 1, NEWTYPE, ...) ... ...

同时发送三个不同类型数组 A, B 和 C。

例 4.12 例 4.ll 中最后几行可以改成: ... ...

DISPS(1)=IA DISPS(2)=IB DISPS(3)=IC

CALL MPI_TYPE_STRUCT(3, LEN, DISP, TYPE, NEWTYPE, IER) ... ...

CALL MPI_SEND(MPI_BOTTOM, 1, NEWTYPE, ...) ... ...

§4.3 数据类型的使用 除原始数据类型外,其它数据类型在首次用于消息传递之前必须通过 MPI_Type_commit函数进行提交。一个(非原始) 数据类型在不再需要时应该调用 MPI_Type_free 函数进行释放,以便释放它所占用的系统资源。 §4.3.1 数据类型的提交 C

int MPI_Type_commit(MPI_Datatype *datatype)

Fortran 77

MPI_TYPE_COMMIT(DATATYPE, IERR) INTEGER DATATYPE, IERR

一个数据类型在被提交后就可以和 MPI 原始数据类型完全一样地在消息传递中使用。

如果一个数据类型仅仅用于创建其它数据类型的中间步骤而并不直接在消息传递中使用,则不必将它提交,一旦基于它的其它数据类型创建完毕即可立即将它释放。

§4.3.2 数据类型的释放 C

int MPI_Type_free(MPI_Datatype *datatype)

Fortran 77

MPI_TYPE_FREE(DATATYPE, IERR) INTEGER DATATYPE, IERR

MPI_Type_free释放指定的数据类型。函数返回后,datatype 将被置成

MPI_DATATYPE_NULL。正在进行的使用该数据类型的通信将会正常完成。一个数据类型的释放对在它的基础上创建的其它数据类型不产生影响。

例 4.13

REAL U(N,M), V(N,M)

INTEGER IU, IV, CTYPE, LTYPE ... ...

CALL MPI_ADDRESS(U, IU, IERR) CALL MPI_ADDRESS(V, IV, IERR)

CALL MPI_TYPE_VECTOR(M, 1, N, MPI_REAL, CTYPE, IERR)

CALL MPI_TYPE_HVECTOR(2, 1, IV-IU, CTYPE, LTYPE, IERR) CALL MPI_TYPE_FREE(CTYPE, IERR)

CALL MPI_TYPE_HVECTOR(2, N, IV-IU, MPI_REAL, CTYPE,IERR) ... ...

!发送 ux U(1:N,1),V(1:N,1)

CALL MPI_SEND(U(1,1), 1, CTYPE, ...) ! 发送 ux U(1,1:M),V(1,1:M)

CALL MPI_SEND(U(1,1), 1, LTYPE, ...) ! 发送 ux U(1:N,M),V(1:N,M)

CALL MPI_SEND(U(1,M), 1, CTYPE, ...) ! 发送 ux U(N,1:M),V(N,1:M)

CALL MPI_SEND(U(N,1), 1, LTYPE, ...) ... ...

例 4.14

REAL U(N,M), V(N,M)

INTEGER IU, IV, EX, CTYPE, LTYPE INTEGER LENS(3), DISPS(3), TYPES(3)

DATA LENS/1, 1, 1/, TYPES/MPI_REAL, MPI_REAL, MPI_UB/ ... ...

CALL MPI_ADDRESS(U, IU, IERR) CALL MPI_ADDRESS(V, IV, IERR)

CALL MPI_TYPE_EXTENT(MPI_REAL, EX, IERR) DISPS(1) = 0

DISPS(2) = IV - IU DISPS(3) = EX

CALL MPI_TYPE_STRUCT(3, LENS, DISPS, TYPES, CTYPE, IERR) DISPS(3) = EX*N

CALL MPI_TYPE_STRUCT(3, LENS, DISPS, TYPES, LTYPE, IERR) ... ...

! 发送 ux U(1:N,1),V(1:N,1)

CALL MPI_SEND(U(1,1), N, CTYPE, ...) ! 发送 ux U(1,1:M),V(1,1:M)

CALL MPI_SEND(U(1,1), M, LTYPE, ...) ! 发送 ux U(1:N,M),V(1:N,M)

CALL MPI_SEND(U(1,M), N, CTYPE, ...) ! 发送 ux U(N,1:M),V(N,1:M)

CALL MPI_SEND(U(N,1), M, LTYPE, ...) ... ...

§4.3.3 MPI_Get_elements

函数 MPI_Get_elements与MPI_Get_count类似,但它返回的是消息中所包含的 MPI 原始数据类型的个数。MPI_Get_elements返回的 count 值如果不等于 MPI_UNDEFINED的话,则必然是MPI_Get_count返回的count值的倍数。

C

int MPI_Get_elements(MPI_Status *status, MPI_Datatype datatype, int *count)

Fortran 77

MPI_GET_ELEMENTS(STATUS, DATATYPE, COUNT, IERR)

INTEGER STATUS(MPI_STATUS_SIZE), DATATYPE, COUNT, IERR

~ 4.15 MPI Get elements:=04-ex4.f>

例 4.15 MPI Get elements: 【 04-ex4.f 】 §4.4 数据的打包与拆包

在MPI中,通过使用特殊数据类型 MPI_PACKED,用户可以以类似于 PVM 中的方式将不同的数据进行打包后再一次发送出去,接收方在收到消息后再进行拆包。 §4.4.1 数据打包 C

int MPI_Pack(void *inbuf, int incount, MPI_Datatype datatype, void *outbuf,

int outsize, int *position, MPI_Comm comm)

Fortran 77

MPI_PACK(INBUF, INCOUNT, DATATYPE, OUTBUF, OUTSIZE, + POSITION, COMM, IERR) INBUF(*), OUTBUF(*)

INTEGER INCOUNT, DATATYPE, OUTSIZE, POSITION, COMM, + IERR

该函数将缓冲区 inbuf 中的 incount 个类型为 datatype 的数据进行打包 打包后的数据放在缓冲区 outbuf 中 outsize 给出的是 outbuf 的总长度 (字节数,供函数检查打包缓冲区是否越界用)。comm 是发送打包数据将使用的通信器。position是打包缓冲区中的位移,每次打包笫一次调用 MPI-Pack前用户程序应将position设为 0,随后 MPI_Pack 将自动修改它,使得它总是指向打包缓冲区中尚未使用部分的起始位置。每次调用 MPI-Pack后的 position实际上就是已打包的数据的总长度。 §4.4.2 数据拆包 C

int MPI_Unpack(void *inbuf, int insize, int *position, void *outbuf, int outcount,

MPI_Datatype datatype, MPI_Comm comm)

Fortran 77

MPI_UNPACK(INBUF, INSIZE, POSITION, OUTBUF, OUTCOUNT, + DATATYPE, COMM, IERR)

INBUF(*), OUTBUF(*)

INTEGER INSIZE, POSITION, OUTCOUNT, DATATYPE, COMM, + IERR

MPI_UNPACK进行数据拆包操作,它正好是 MPI_Pack 的逆操作。它从inbuf中拆包