mpi并行程序设计-内容摘要:

意处理器来的数据 (任意消息来源 ). – Tag == MPI_ANY_TAG: 匹配任意 tag值的消息 (任意 tag消息 ). • 在阻塞式消息传送中不允许 Source==Dest,否则会导致deadlock. • 消息传送被限制在同一个 municator. • 在 send函数中必须指定唯一的接收者 (Push/pull通讯机制 ). 2020年 11月 MPI并行程序设计 42/217 status参数 • 当使用 MPI_ANY_SOURCE或 /和 MPI_ANY_TAG接收消息时如何确定消息的来源 source 和 tag值呢。 – 在 C中 , . – 在 Fortran中 , source=status(MPI_SOURCE), tag=status(MPI_TAG). • Status还可用于返回实际接收到消息的长度 – int MPI_Get_count(MPI_Status status, MPI_Datatype datatype,int* count) • IN status 接收操作的返回值 . • IN datatype 接收缓冲区中元素的数据类型 . • OUT count 接收消息中的元素个数 . 2020年 11月 MPI并行程序设计 43/217 分析 greetings include include “ main(int argc, char* argv[]) { int numprocs。 /*进程数 ,该变量为各处理器中的同名变量 , 存储是分布的 */ int myid。 /*我的进程 ID,存储也是分布的 */ MPI_Status status。 /*消息接收状态变量 ,存储也是分布的 */ char message[100]。 /*消息 buffer,存储也是分布的 */ /*初始化 MPI*/ MPI_Init(amp。 argc, amp。 argv)。 /*该函数被各进程各调用一次 ,得到自己的进程 rank值 */ MPI_Comm_rank(MPI_COMM_WORLD, amp。 myid)。 /*该函数被各进程各调用一次 ,得到进程数 */ MPI_Comm_size(MPI_COMM_WORLD, amp。 numprocs)。 2020年 11月 MPI并行程序设计 44/217 分析 greetings if (myid != 0) { /*建立消息 */ sprintf(message, Greetings from process %d!,myid)。 /* 发送长度取 strlen(message)+1,使 \0也一同发送出去 */ MPI_Send(message,strlen(message)+1, MPI_CHAR, 0,99,MPI_COMM_WORLD)。 } else { /* my_rank == 0 */ for (source = 1。 source numprocs。 source++) { MPI_Recv(message, 100, MPI_CHAR, source, 99, MPI_COMM_WORLD,amp。 status)。 printf(“%s\n, message)。 } } /*关闭 MPI,标志并行代码段的结束 */ MPI_Finalize()。 } /* End main */ 2020年 11月 MPI并行程序设计 45/217 Greetings执行过程 假设进程数为 3 (进程 0) (进程 1) (进程 2) (rank=0) (rank=1) (rank=2) . . Recv()。 . . Recv()。 . . . . . Send()。 . . . . . . Send() . . . 问题 :进程 1和 2谁先向根进程发送消息 ? ? % 2020年 11月 MPI并行程序设计 46/217 运行 greetings • [dair@node01 ~]$ mpicc –o greeting • [dair@node01 ~]$ mpirun np 4 greeting Greetings from process 1! Greetings from process 2! Greetings from process 3! • [dair@node01 ~]$ 计算机打印字符 我们输入的命令 2020年 11月 MPI并行程序设计 47/217 现在您已经能够用 MPI进行并行编程了 ! 2020年 11月 MPI并行程序设计 48/217 避免死锁 deadlock • 发送和接收是成对出现的,忽略这个原则 很可能会产生死锁 总会死锁的通信调用次序 2020年 11月 MPI并行程序设计 49/217 不安全的通信调用次序 2020年 11月 MPI并行程序设计 50/217 安全的通信调用次序 2020年 11月 MPI并行程序设计 51/217 MPI_Sendrecv函数原型 • int MPI_Sendrecv( void *sendbuf, int sendcount, MPI_Datatype sendtype, int dest, int sendtag, void *recvbuf, int recvcount, MPI_Datatype recvtype, int source, int recvtag, MPI_Comm m, MPI_Status *status) • 数据轮换 p0 p1 p2 P(n1) pi 2020年 11月 MPI并行程序设计 52/217 MPI_Sendrecv用法示意 … int a,b。 … MPI_Status status。 int dest = (rank+1)%p。 int source = (rank + p 1)%p。 /*p为进程个数 */ MPI_Sendrecv( amp。 a, 1, MPI_INT, dest, 99, amp。 b 1, MPI_INT, source, 99, MPI_COMM_WORLD, amp。 status)。 该函数被每一进程执行一次 . 2020年 11月 MPI并行程序设计 53/217 空进程 • rank = MPI_PROC_NULL的进程称为空进程 – 使用空进程的通信不做任何操作 . – 向 MPI_PROC_NULL发送的操作总是成功并立即返回 . – 从 MPI_PROC_NULL接收的操作总是成功并立即返回,且接收缓冲区内容为随机数 . – status • = MPI_PROC_NULL • = MPI_ANY_TAG • MPI_Get_count(amp。 status,MPI_Datatype datatype, amp。 count) =count = 0 p0 p1 p2 P(n1) pi 空进程 2020年 11月 MPI并行程序设计 54/217 空进程应用示意 … MPI_Status status。 int dest = (rank+1)%p。 int source = (rank + p 1)%p。 if(source == p1) source = MPI_PROC_NULL。 if(dest == 0) dest = MPI_PROC_NULL。 MPI_Sendrecv( amp。 a, 1, MPI_INT, dest, 99, amp。 b 1, MPI_INT, source, 99, MPI_COMM_WORLD, amp。 status)。 … 2020年 11月 MPI并行程序设计 55/217 阻塞与非阻塞的差别 • 用户发送缓冲区的重用 : – 非阻塞的发送:仅当调用了有关结束该发送的语句后才能重用发送缓冲区,否则将导致错误;对于接收方,与此相同,仅当确认该接收请求已完成后才能使用。 所以对于非阻塞操作,要先调用等待 MPI_Wait()或测试 MPI_Test()函数来结束或判断该请求,然后再向缓冲区中写入新内容或读取新内容。 • 阻塞发送将发生阻塞 ,直到通讯完成 . • 非阻塞可将通讯交由后台处理,通信与计算可重叠 . • 发送语句的前缀由 MPI_改为 MPI_I, I:immediate: – 标准模式 :MPI_Send(…) MPI_Isend(…) – Buffer模式 :MPI_Bsend(…) MPI_Ibsend(…) – … 2020年 11月 MPI并行程序设计 56/217 非阻塞发送与接收 • int MPI_Isend(void* buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm m, MPI_Request *request) – IN buf 发送缓冲区的起始地址 – IN count 发送缓冲区的大小 (发送元素个数 ) – IN datatype 发送缓冲区数据的数据类型 – IN dest 目的进程的秩 – IN tag 消息标签 – IN m 通信空间 /通信子 – OUT request 非阻塞通信完成对象 (句柄 ) • int MPI_Irecv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm m, MPI_Request* request) 2020年 11月 MPI并行程序设计 57/217 非阻塞标准发送和接收 2020年 11月 MPI并行程序设计 58/217 通信的完成 (常用于非阻塞通信 ) • 发送的完成 : 代表发送缓冲区中的数据已送出,发送缓冲区可以重用。 它并不代表数据已被接收方接收。 数据有可能被缓冲。 • 接收的完成 :代表数据已经写入接收缓冲区。 接收者可访问接收缓冲区。 • 通过 MPI_Wait()和 MPI_Test()来判断通信是否已经完成。 2020年 11月 MPI并行程序设计 59/217 MPI_Wait()及应用示例 • int MPI_Wait(MPI_Request* request, MPI_Status * status)。 当 request标识的通信结束后, MPI_Wait()才返回。 如果通信是非阻塞的,返回时 request = MPI_REQUEST_NULL。 函数调用是非本地的。 MPI_Request request。 MPI_Status status。 int x,y。 if(rank == 0){ MPI_Isend(amp。 x,1,MPI_INT,1,99,m,amp。 request) … MPI_Wait(amp。 request,amp。 status)。 }else{ MPI_Irecv(amp。 y,1,MPI_INT,0,99,m,amp。 request) … MPI_Wait(amp。 request,amp。 status)。 } 2020年 11月 MPI并行程序设计 60/217 MPI_Test()及应用示例 //int MPI_Test(MPI_Request *request,int *flag, MPI_Status *status)。 MPI_Request request。 MPI_Status status。 int x,y,flag。 if(rank == 0){ MPI_Isend(amp。 x,1,MPI_INT,1,99,m,amp。 request) while(!flag) MPI_Test(amp。 request,amp。 flag,amp。 status)。 }else{ MPI_Irecv(amp。 y,1,MPI_INT,0,99,m,amp。 request) while(!flag) MPI_Test(amp。 request,amp。 flag,amp。 status)。 } 2020年 11月 MPI并行程序设计 61/217 消息探测 Probe函数 (适用于阻塞与非阻塞 ) • MPI_Probe()和 MPI_Iprobe()函数 探测接收消息的。
阅读剩余 0%
本站所有文章资讯、展示的图片素材等内容均为注册用户上传(部分报媒/平媒内容转载自网络合作媒体),仅供学习参考。 用户通过本站上传、发布的任何内容的知识产权归属用户或原始著作权人所有。如有侵犯您的版权,请联系我们反馈本站将在三个工作日内改正。