并行算法讲义 联系客服

发布时间 : 星期日 文章并行算法讲义更新完毕开始阅读d6ac36768e9951e79b8927da

PI_WTICK 则返回MPI_WTIME 函数的时钟精度,也是以秒为单位。 例如,假设

MPI_WTIME 使用的硬件时钟计数器每1/1000 秒增加1,则 MPI_WTICK 的返回值为 10-3,表示用函数 MPI_WTIME 得到的时间精度为干分之一秒。

在 C 中,这是唯一两个返回双精度值而非整型错误码的 MPI 接口函数。在 Fortran 77中,这是唯一两个FUNCTION形式的接口。其它 Fortran 77 MPI 的接口一律以SUBROUTINE的形式定义)。 §2.7 MPI程序的基本结构 § 2.7.1 Fortran 77程序 PROGRAM MPIPRG

INCLUDE ?mpif.h?

INTEGER MYRANK, NPROCS, IERR *

CALL MPI_INIT(IERR)

CALL MPI_COMM_RANK( MPI_COMM_WORLD, MYRANK, IERR) CALL MPI_COMM_SIZE( MPI_COMM_WORLD, NPROCS, IERR) ... ...

CALL MPI_FINALIZE(IERR) STOP END

程序实例 【 02-mpi.f】

15 § 2.7.2 C 程序 #include \... ...

int main(int argc, char *argv[]) {

int myrank, nprocs;

MPI_Init(&argc,&argv);

MPI_Comm_size(MPI_COMM_WORLD,&nprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myrank); ... ...

MPI_Finalize(); }

程序实例 【 02-mpi.c】

16

第三章 点对点通信

点对点通信指在一对进程之间进行的消息收发操作。一个进程发送消息,另一个进程接

收消息。 §3.1 标准阻塞型点对点通信函数 § 3.1.1 标准阻塞发送 C

int MPI_Send(void *buff, int count,

MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) Fortran 77

MPI_SEND(BUFF, COUNT, DATATYPE, DEST, TAG, COMM, IERR) BUFF(*)

INTEGER COUNT, DATATYPE, DEST, TAG, COMM, IERR tag 的取值范围为0 - MPI_TAG_UB.

dest 的取值范围为 0 - np-1 (np 为通信器 comm 中的进程数) 或 MPI_PROC_NULL. count 是指定数据类型的个数,而不是字节数。 §3.1.2 阻塞接收 C

int MPI_Recv(void *buff, int count,

MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status status) Fortran 77

MPI_RECV(BUFF, COUNT, DATATYPE, SOURCE, TAG, COMM, + STATUS, IERR) BUFF(*)

INTEGER COUNT, DATATYPE, SOURCE, TAG, COMM, IERR INTEGER STATUS(MPI_STATUS_SIZE)

tag 的取值范围为0 - MPI_TAG_UB ,或 MPI_ANY_TAG.

source 的取值范围为 0 - np-1(np 为通信器 comm 中的进程数),或 MPI_ANY_SOURCE,,或MPI_PROC_NULL。

count 给出接收缓冲区的大小 ( 定数据类型的个数),它是接收数据长度的上界。具体接收到的数据长度可通过调用 MPI_Get_count 函数得到。

17 §3.1.2.1 status 中的内客

status 返回有关接收到的消息的信息,它的结构如下: · 在 C 中 status 是一个结构,它包含下面三个用户可以使用的域: typedef struct{ ... ...

int MPI_SOURCE; 消息源地址 int MPI_TAG; 消息标签 int MPI_ERROR; 错误码 } M PI_Status;

· 在 Fortran 77 中 status 各个元素的含义如下 STATUS(MPI_SOURCE) 消息源地址 STATUS(MPI_TAG) 消息标签 STATUS(MPI_ERROR) 错误码 §31.4.2.2 查询接收到的消息长度 C

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

Fortran 77

MPI_GET_COUNT(STATUS, DATATYPE, COUNT, IERR) INTEGER DATATYPE, COUNT, IERR INTEGER STATUS(MPI_STATUS_SIZE)

该函数在 count 中返回消息的长度 (数据类型个数)。 §31.4.3 阻塞型消息传递实例

例 3.1 阻塞型消息传递: 【 03_exl.f 】

18

例 3.2 消息收发顺序导致的程序死锁: 【 03_ex2.f 】 例 3.3 长消息导致的程序死锁: 【 03_ex3.f 】

例 3.4 0 号进程先发, 其它进程先收: 【 03_ex4.f 】 通信过程是串行的。

例 3.5 偶数号的进程先发,奇数号的进程先收:【03_ex5.f 】 通信过程是并发的, 当 NPROCS=1时仍有可能发生死锁。如果将接收及求和中的数组 B 改成 A,会得到什么结果?

§3.1.4 其它一些阻塞型消息传递函数 §3.1.4.1 发送与接收组合进行

MPI_SENDRECV 函数将一次发送调用和一次接收调用合并进行。它使得 MPI 程序更为简洁,更重要的是,MPI 的实现通常能够保证使用MPI_SENDRECV 函数的程序不会出现上节例子中出现的由于消息收发配对不好而引起的程序死锁。 C

int MPI_Sendrecv(void *sendbuff, int sendcount, MPI_Datatype sendtype, int dest, int sendtag, void *recvbuff, int recvcount,

MPI_Datatype recvtype, int source, int recvtag, MPI_Comm comm, MPI_Status status)

Fortran 77

MPI_SENDRECV(SENDBUFF, SENDCOUNT, SENDTYPE, + DEST, SENDTAG,

+ RECVBUFF, RECVCOUNT, RECVTYPE, SOURCE, RECVTAG, + COMM, STATUS, IERR)

SENDBUFF(*), RECVBUFF(*)

INTEGER SENDCOUNT, SENDTYPE, DEST, SENDTAG, + RECVCOUNT, RECVTYPE, SOURCE, RECVTAG, + COMM, IERR

INTEGER STATUS(MPI_STATUS_SIZE)

例 3.6 用 MPI_SENDRECV 替换 MPI_SEND和 MPI_RECV: 【 03_ex6.f 】 §3.1.4.2 发送与接收组合进行,收发使用同一缓冲区 C

int MPI_Sendrecv_replace(void *buff, int count,

MPI_Datatype datatype,

19 int dest, int sendtag,

int source, int recvtag,

MPI_Comm comm, MPI_Status status)

Fortran 77

MPI_SENDRECV_REPLACE(BUFF, COUNT, DATATYPE, + DEST, SENDTAG, SOURCE, RECVTAG, + COMM, STATUS, IERR) BUFF(*)

INTEGER COUNT, DATATYPE, DEST, SENDTAG,