C02高级MPI编程技术.ppt_第1页
C02高级MPI编程技术.ppt_第2页
C02高级MPI编程技术.ppt_第3页
C02高级MPI编程技术.ppt_第4页
C02高级MPI编程技术.ppt_第5页
已阅读5页,还剩183页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

高级mpi编程技术,谭光明副研究员tgm中国科学院计算技术研究所国家智能计算机研究开发中心计算机体系结构国家重点实验室(筹),阻塞通信模式,由发送方体现(send语句).阻塞通信中接收语句相同按发送方式的不同,消息或直接被copy到接收者的buffer中或被拷贝到系统buffer中。标准模式standard最常用的发送方式b:缓冲模式buffer发到系统缓冲区s:同步模式synchronous任意发出,不需系统缓冲区r:就绪模式ready就绪发出,不需系统缓冲区,阻塞,需要等待操作的实际完成,或至少等待mpi系统安全地备份后才返回;mpi_send与mpi_recv都是阻塞的;mpi_send调用返回时表明数据已经发出或被mpi系统复制,随后对发送缓冲区的修改不会改变所发送的数据;而mpi_recv返回,则表明已完成数据接收。函数调用是非局部的,测量点到点通信带宽(p2p),#include#include#include“mpi.h”intmain(intargc,char*argv)intmy_rank,tag=0,send_m,recv_m;charmessage100,send_c100,recv_c100;floatsend_n,recv_n;doublestart_time,end_time;mpi_statusstatus;mpi_commcomm;mpi_init(,测量点到点通信带宽(p2p),start_time=mpi_wtime();mpi_send(,测量点到点通信带宽(p2p),else/*my_rank=1*/mpi_recv(,测量点到点通信带宽(hot_potato),#include“mpi.h”main(intargc,char*argv)intp,my_rank,tag,source,dest,tag=0;mpi_statusstatus;charsend_m100,recv_m100;doublestart_time,end_time;mpi_commcomm;mpi_init(/*消息接收的源*/,测量点到点通信带宽,if(my_rank=0)sprintf(send_m,greetingsfromprocess%d!,my_rank);/*建立消息*/start_time=mpi_wtime()mpi_send(send_m,strlen(send_m)+1,mpi_char,dest,tag,comm);mpi_recv(recv_m,100,mpi_char,source,tag,comm,/*关闭mpi,标志并行代码段的结束*/*main*/,接收的有序性,在阻塞通信中对于接收进程在接收消息时除了要求接收到的消息的消息信封和接收操作自身的消息信封相一致还要求它接收到的消息是最早发送给自己的消息若两个消息的消息信封都和自己的消息信封吻合则必须先接收首先发送的消息哪怕后发送的消息首先到达该接收操作也必须等待第一个消息,mpi内容,基本概念点到点通信自定义数据类型集合通信mpi环境管理函数实例,点到点通信详解,mpi通信模式标准模式:standard同步模式:buffer缓冲模式:synchronous预备模式:ready实现方式阻塞通信(blocking)非阻塞通信(nonblocking),非阻塞,函数的调用总是立即返回,而实际的操作则由mpi系统在后台进行;用户必须随后调用其他函数来等待或查询完成情况;在操作完成之前对相关数据区的操作是不安全的;函数调用是局部的,阻塞与非阻塞的差别,用户发送缓冲区的重用:阻塞的发送:仅当调用了有关结束该发送的语句后才能重用发送缓冲区,否则将导致错误;对于接收方,与此相同,仅当确认该接收请求已完成后才能使用。非阻塞操作,要先调用等待mpi_wait()或测试mpi_test()函数来结束或判断该请求,然后再向缓冲区中写入新内容或读取新内容。阻塞发送将发生阻塞,直到通讯完成.非阻塞可将通讯交由后台处理,通信与计算可重叠.,非阻塞发送,一个非阻塞sendstart调用发起一个发送,但并不完成,而且sendstart调用会在消息拷贝出发送缓冲区以前返回;另一个sendcomplete调用来完成发送操作,即证实数据已被拷贝出发送缓冲区,缓冲区可重用。通过合适的硬件,在sendstart完成之后,sendcomplete完成之前,数据向外传送的过程可以和计算同时进行。,非阻塞接收,一个非阻塞的receivestart调用发起一个接收操作,这个调用会在消息存入接收缓冲区之前返回,但其返回并不表示接收已完成;另一个receivecomplete调用来完成接收操作,并证实数据已写入接收缓冲区。通过合适的硬件,在receivestart完成后,receivecomplete完成之前,数据的写入过程可以和计算同时进行。非阻塞通信可以避免系统缓冲以及内存到内存的复制,计算和通信可以重叠,从而使性能得到改善。,非阻塞发送mpi_isend(),intmpi_isend(void*message/*in*/,intcount/*in*/,mpi_datatypedatatype/*in*/,intdest/*in*/,inttag/*in*/,mpi_commcomm/*in*/,mpi_request*request/*out*/)the“i”standsfor“immediate”,非阻塞发送mpi_isend(),提交一个消息发送请求,要求mpi系统在后台完成。mpi_isend为该发送创建一个请求,并将请求的句柄通过request变量返回给mpi进程。随后mpi_test/mpi_wait(查询/等待)等函数可以使用request来判断发送是否完成。,非阻塞发送的四种模式,标准-mpi_isend()缓冲-mpi_ibsend()同步-mpi_issend()就绪-mpi_irsend(),非阻塞接收mpi_irecv(),intmpi_irecv(void*message/*out*/,intcount/*in*/,mpi_datatypedatatype/*in*/,intsource/*in*/,inttag/*in*/,mpi_commcomm/*in*/,mpi_request*request/*out*/),非阻塞通信的完成,发送的完成:代表发送缓冲区中的数据已送出,发送缓冲区可以重用。它并不代表数据已被接收方接收。数据有可能被缓冲;同步模式:发送完成=接收方已初始化接收,数据将被接收方接收;接收的完成:代表数据已经写入接收缓冲区。接收者可访问接收缓冲区,status对象已被释放。它并不代表相应的发送操作已结束。通过mpi_wait和mpi_test来判断通信是否已经完成;,mpi_wait()函数,intmpi_wait(mpi_request*request/*in/out*/,mpi_status*status/*out*/)当request标识的通信结束后,mpi_wait才返回。如果通信是非阻塞的,返回时request=mpi_request_null,函数调用是非本地的.mpi_wait一直等到非阻塞操作真正完成之后才返回,可以认为阻塞通信等于非阻塞通信加上mpi_wait.,mpi_wait()应用示例1,mpi_requestrequest;mpi_statusstatus;intx,y;if(rank=0)mpi_isend(,mpi_wait()应用示例2,intx;mpi_comm_rank(mpi_comm_world,.,mpi_test()函数,intmpi_test(mpi_request*request/*in/out*/,int*flag/*out*/,mpi_status*status/*out*/)mpi_test用来检测非阻塞操作是否真正结束mpi_test不论通信是否完成,立即返回。如果通信已经完成,flag=true;否则flag=false,mpi_test()应用示例,mpi_requestrequest;mpi_statusstatus;intx,y,flag;if(rank=0)mpi_isend(,request对象的释放,request参数用来描述非阻塞通信状况的对象,通过对其查询,可以知道与之相应的非阻塞发送和接收是否完成。request对象只有在通信完成后才会被释放。mpi中提供了函数mpi_request_free,可不必等待通信完成便可释放request对象。intmpi_request_free(mpi_request*request/*in/out*/),消息探测probe,mpi_probe()和mpi_iprobe()函数探测接收消息的内容,但并不实际接收消息。用户根据探测到的消息内容决定如何接收这些消息,如根据消息大小分配缓冲区等。在接收未知长度的消息时,可先用mpi_probe和mpi_get_count得到消息的长度.前者为阻塞方式,即只有探测到匹配的消息才返回;后者为非阻塞,即无论探测到与否均立即返回.,mpi_probe()函数,intmpi_probe(intsource/*in*/,inttag/*in*/,mpi_commcomm/*in*/,mpi_status*status/*out*/)阻塞型探测,直到有一个符合条件的消息到达,返回mpi_any_sourcempi_any_tag,mpi_iprobe()函数,intmpi_iprobe(intsource/*in*/,inttag/*in*/,mpi_commcomm/*in*/,int*flag/*out*/,mpi_status*status/*out*/)非阻塞型探测,无论是否有一个符合条件的消息到达,返回。有flag=true;否则flag=false,mpi_probe()应用示例1,intx;floaty;mpi_comm_rank(comm,mpi_probe()应用示例2,intx;floaty;mpi_comm_rank(comm,mpi_cancel()函数,mpi_cancel用于取消一个尚未完成的通信请求,它在mpi系统中设置一个通信请求取消的标志后立即返回,具体的取消工作由mpi在后台完成。调用mpi_cancel后,仍然需要调用mpi_wait/mpi_test/mpi_request_free等函数来释放该通信请求cancel函数用于取消一个被挂起的通信函数,并释放这些资源。一般,其代价是昂贵的,对性能影响较大,尽量少用。mpi_test_cancelled用来测试一个通信请求是否已经取消,flag=true表明已经取消。,mpi_cancel()函数,intmpi_cancel(mpi_request*request/*in*/)intmpi_test_cancelled(mpi_status*status/*in*/,int*flag/*out*/),发送与接收组合,mpi_sendrecv()函数将一次发送调用和一次接收调用合并进行.它使得mpi程序更为简洁.更重要的是,mpi的实现通常能够保证使用mpi_sendrecv函数的程序不会出现由于消息收发配对不好而引起的程序死锁.,mpi_sendrecv(),intmpi_sendrecv(void*send_buf/*in*/,intsend_count/*in*/,mpi_datatypesend_type/*in*/,intdest/*in*/,intsend_tag/*in*/,void*recv_buf/*out*/,intrecv_count/*in*/,mpi_datatyperecv_type/*in*/,intsource/*in*/,intrecv_tag/*in*/,mpi_commcomm/*in*/,mpi_status*status/*out*/),send,recv,mpi_sendrecv(),send-recv操作把发送一个消息到一个目的地和从另一个进程接收一个消息合并到一个调用中。源和目的可以是同一个地方。一个由send-receive发出的消息可以被一个普通接收操作接收,或被一个检查操作检查;一个send-receive操作可以接收一个普通发送操作发送的消息。,mpi_sendrecv(),一个send-receive操作对穿过一个进程链的切换操作非常有用。如果阻塞的发送和接收被用于这种切换,则需要正确排列发送和接收的顺序(例如偶数进程发送,然后接收,奇数进程先接收,然后发送)以避免循环以赖导致死锁。,mpi_sendrecv例1,mpi_comm_dup(mpi_comm_world,mpi_sendrecv例2,mpi_comm_dup(mpi_comm_world,mpi_sendrecv例3,mpi_comm_dup(mpi_comm_world,mpi_sendrecv_replace(),intmpi_sendrecv(void*buffer/*in/out*/,intcount/*in*/,mpi_datatypedatatype/*in*/,intdest/*in*/,intsend_tag/*in*/,intrecv_tag/*in*/,mpi_commcomm/*in*/,mpi_status*status/*out*/),空进程,rank=mpi_proc_null的进程称为空进程使用空进程的通信不做任何操作.在很多情况下为通信指定一个“假”的源或目标是非常方便的。这可以简化处理边界的代码,例如,用调用mpi_sendrecv实现非循环切换的时候。mpi_proc_null这个特殊的值可以用来替换一个调用所要求的源或目标。一个使用mpi_proc_null进程的通信没有动作。一个给mpi_prc_null的发送会立即成功返回。一个从mpi_proc_null的接收会立即成功返回,对接收缓冲区没有任何改变.,空进程,mpi_get_count(doubleb;intc;t;,main()tm;printf(sizeof(t)=%d,sizeof(m)=%dn,sizeof(t),sizeof(m);printf(“m.a=%d,m.b=%d,m.c=%dn,(char*),c语言中的对界,struct(char,double,int),char,double,int,mpi_lb和mpi_ub,mpi提供了两个特殊数据类型mpi_lb和mpi_ub,称为伪数据类型(pseudodatatype).它们的大小是0,作用是让用户人工指定一个数据类型的上下界.mpi规定:如果一个数据类型的基本类型中含有mpi_lb,则它的下界定义为:如果一个数据类型的基本类型中含有mpi_ub,则它的上界定义为:,例3,类型图(mpi_lb,-4),(mpi_ub,20),(mpi_double,0),(mpi_integer,8),(mpi_byte,12)问题:下界为,上界为,域为.,-4,20,24,数据类型查询函数,查询指定数据类型的大小:intmpi_type_size(mpi_datatypedatatype/*in*/,int*size/*out*/)查询指定数据类型的域:intmpi_type_extent(mpi_datatypedatatype/*in*/,mpi_aint*extent/*out*/),数据类型查询函数,查询指定数据类型的上界:intmpi_type_ub(mpi_datatypedatatype/*in*/,mpi_aint*displacement/*out*/)查询指定数据类型的下界:intmpi_type_lb(mpi_datatypedatatype/*in*/,mpi_aint*displacement/*out*/),mpi自定义数据类型,连续数据类型向量数据类型索引数据类型结构数据类型,连续数据类型的创建,intmpi_type_contiguous(intcount/*in*/,mpi_datatypeoldtype/*in*/,mpi_datatype*newtype/*out*/),同一类型的多次重复,作用:将连续的基类型重复作为一个整体看待,新类型的递交和释放,提交:intmpi_type_commit(mpidatatype*datatype)将数据类型映射进行转换或“编译”一种数据类型变量可反复定义,连续提交释放:intmpi_type_free(mpi_datatype*datatype)将数据类型设为mpi_datatype_null,定义矩阵的一行(例4),在c中定义矩阵的一行floata44;mpi_datatypec_r;mpi_comm_dup(mpi_comm_world,mpi_recv(mpi_datatypec_c;mpi_type_vector(4,1,4,mpi_float,mpi_send(mpi_datatypen_t;mpi_type_vector(n-1,m-1,m+1,mpi_int,mpi自定义数据类型,连续数据类型向量数据类型索引数据类型结构数据类型,索引数据类型,intmpi_type_indexed(intcount/*in*/,intblocklens/*in*/,intindices/*in*/,mpi_datatypeoldtype/*in*/,mpi_datatype*newtype/*out*/)countnumberofblocks-alsonumberofentriesinindicesandblocklensblocklensnumberofelementsineachblockindicesdisplacementofeachblockinmultiplesofold_type,索引数据类型,mpi_type_indexed(count,array_of_blocklengths,array_of_displacemets,oldtype,newtype)重复形成块,不同的块放到不同的位置,位置的指定可以是以旧数据类型为单位,索引数据类型,intmpi_type_hindexed(intcount/*in*/,intblocklens/*in*/,intindices/*in*/,mpi_datatypeoldtype/*in*/,mpi_datatype*newtype/*out*/)countnumberofblocks-alsonumberofentriesinindicesandblocklensblocklensnumberofelementsineachblockindicesdisplacementofeachblockinbytes,例6,问题,mpi_type_vector()与mpi_type_indexed()的区别?mpi_type_indexed与mpi_type_vector的区别在于每个数据块的长度可以不同,数据块间也可以不等距.,mpi自定义数据类型,连续数据类型向量数据类型索引数据类型结构数据类型,结构数据类型,intmpi_type_struct(intcount/*in*/,intblocklens/*in*/,mpi_aintindices/*in*/,mpi_datatypetypes/*in*/,mpi_datatype*newtype/*out*/)countnumberofblocks(integer)blocklensnumberofelementsineachblockindicesbytedisplacementofeachblock(array)typesofelementsineachblock,结构数据类型,mpi_type_struct(count,array_of_blocklens,array_of_displacemets,array_of_types,newtype)将多个不同的旧数据类型进行组合,而前面的数据类型生成方法都是对一个旧数据类型进行重复。,例7,数据的打包与拆包,在mpi中,通过使用特殊数据类型mpi_packed,用户可以将不同的数据进行打包后再一次发送出去,接收方在收到消息后再进行拆包.为了与早期其它并行库兼容mpi不建议用户进行显式的数据打包,数据的打包,intmpi_pack(void*inbuf/*in*/,intincount/*in*/,mpi_datatypedatatype/*in*/,void*outbuf/*in*/,intoutsize/*in*/,int*position/*in/out*/,mpi_commcomm/*in*/)该函数将缓冲区inbuf中的incount个类型为datatype的数据进行打包.打包后的数据放在缓冲区outbuf中.outsize给出的是outbuf的总长度(字节数,供函数检查打包缓冲区是否越界用).,数据的打包,position是打包缓冲区中的位移,第一次调用mpi_pack前用户程序将position设为0随后mpi_pack将自动修改它,使得它总是指向打包缓冲区中尚未使用部分的起始位置每次调用mpi_pack后的position实际上就是已打包的数据的总长度,例8,mpi_comm_dup(mpi_comm_world,数据的拆包,intmpi_unpack(void*packbuf/*in*/,intinsize/*in*/,int*position/*in/out*/,void*outbuf/*out*/,intoutcount/*in*/,mpi_datatypedatatype/*in*/,mpi_commcomm/*in*/)从packbuf中拆包outcount个类型为datatype的数据到outbuf中.函数中各参数的含义与mpi_pack类似,只不过这里的packbuf和insize对应于mpi_pack中的outbuf和outsize,而outbuf和outcount则对应于mpi_pack中的inbuf和incount.,例9,mpi_comm_dup(mpi_comm_world,数据类型函数汇总,上机试验1,实现点到点通信,并计算通信带宽实现结点间的循环消息传递,并计算通信带宽012345-n-10,尝试非阻塞通信方式,上机实验2,将矩阵a的转置拷贝到矩阵b中a(0,0)a(0,1)a(0,n)a(1,0)a(1,1)a(1,n)a(m,0)a(m,1)a(m,n),type1,矩阵转置,多种实现方法,矩阵转置,#include#include“mpi.h”#definen10intmain(intargc,char*argv)intmy_rank,tag=0,ann,bnn,i,j;mpi_statusstatus;mpi_commcomm;mpi_datatypecolumn_type;mpi_datatyperaw_type;mpi_init(,矩阵转置,mpi_type_vector(n,1,n,mpi_int,矩阵转置,mpi_type_vector(n,1,n,mpi_int,mpi内容,基本概念点到点通信自定义数据类型集合通信mpi环境管理函数实例,组通信概述,通信域限定哪些进程参加以及组通信的上下文组通信调用可以和点对点通信共用一个通信域mpi保证由组通信调用产生的消息不会和点对点调用产生的消息相混淆在组通信中不需要通信消息标志参数组通信一般实现三个功能通信、同步和计算通信功能主要完成组内数据的传输同步功能实现组内所有进程在特定地点在执行进度上取得一致计算功能要对给定的数据完成一定的操作,三种通信方式,一对多、多对一、多对多(按通信方向),组通信中的同步,点到点通信的完成,重新使用缓冲区一个进程组通信的完成,并不表示其他所有进程的组通信都已经完成。同步操作,完成各个进程之间的同步,协调各个进程的进度和步伐。,同步函数mpi_barrier,intmpi_barrier(mpi_commcomm/*in*/)mpi唯一的一个同步函数,当comm中的所有进程都执行这个函数后才返回。如果有一个进程没有执行此函数,其余进程将处于等待状态。在执行完这个函数之后,所有进程将同时执行其后的任务。,组通信中的同步,mpi_barrier(comm),实例:mpi_barrier,mpi_init(,组通信中的计算,组通信除了通信和同步之外,还可进行计算。mpi组通信的计算功能是分三步实现的首先是通信的功能,即消息根据要求发送到目的进程,目的进程也已经接收到了各自所需要的消息然后是对消息的处理即计算部分。mpi组通信有计算功能的调用都指定了计算操作,用给定的计算操作对接收到的数据进行处理最后一步是将处理结果放入指定的接收缓冲区,组通信中的计算图示,全局数据运算reduce,mpi_reduce将组内每个进程输入缓冲区中的数据按给定的操作op进行运算,并将结果返回到根进程的输出缓冲区中。输入缓冲区由参数sendbuf、count和datatype定义。输出缓冲区由参数recvbuf、count和datatype定义要求两者的元素数目和类型都必须相同。所有组成员都用同样的count、datatype、op、root和comm来调用此例程,故所有进程都提供长度相同、元素类型相同的输入和输出缓冲区每个进程可能提供一个元素或一系列元素,组合操作依次针对每个元素进行,全局归约mpi_reduce,intmpi_reduce(void*openand/*in*/,void*result/*in*/,intcount/*in*/,mpi_datatypedatatype/*in*/,mpi_opoperator/*out*/,introot/*in*/,mpi_commcomm/*in*/),openand操作数(发送缓冲区)起始地址result接收缓冲区(结果)的地址count发送缓冲区数据个数operator归约操作符,mpi_reduce图示,归约求和图示,p0,p1,p2,a0+b0+c0,mpi_reduce,a1+b1+c1,a2+b2+c2,mpi预定义操作,数据广播mpi_bcast,mpi_bcast完成从root进程将一条消息广播发送到组内的所有进程,包括它本身在内其执行结果是将根进程通信消息缓冲区中的消息拷贝到其他所有进程中去组内所有进程不管是root进程本身还是其它的进程都使用同一个通信域comm和根标识root数据类型datatype可以是预定义或派生数据类型其它进程指定的通信元素个数count,、数据类型datatype必须和根进程指定的count和datatype保持一致,mpi_bcast,intmpi_bcast(void*buffer/*in/out*/intcount/*in*/mpi_datatypedatatype/*in*/introot/*in*/mpi_commcomm/*in*/),buffer通信消息缓冲区的起始地址count将广播出去/或接收的数据个数datatype广播/接收数据的数据类型root广播数据的根进程的标识号comm通信域,mpi_bcast图示,databuf.mpi_bcast();.,data.mpi_bcast();.,data.mpi_bcast();.,process0myrank=0,process1myrank=1,processp-1myrank=p-1,a,a,a,a,mpi_bcast,p0,p1,p2,p3,p0,p1,p2,p3,实例:mpi_bcast,mpi_init(,实例:求向量点积,p0,p0,p1,p2,p3,p4,求向量点积计算流程,向量点积代码1,#definen20000main(intargc,char*argv)intxn,yn,gsize,size,myrank,i;floatlocal_sum=0.0,sum;mpi_statusstatus;mpi_commcomm;mpi_init(,向量点积代码2,if(myrank=0)/*给两个向量x,y赋值*/for(i=0;in;i+)xi=i+1;yi=i+1;/*进程0广播向量x和y到各个进程*/mpi_bcast(x,n,mpi_int,0,comm);mpi_bcast(y,n,mpi_int,0,comm);size=n/gsize;for(i=0;isize;i+)/*各进程并行计算局部向量点积*/local_sum=local_sum+xmyrank*size+i*ymyrank*size+i;mpi_reduce(,数据收集mpi_gather,把所有进程(包括root)的数据聚集到root进程中,并且按顺序存放在接收缓冲区中.其结果就象一个进程组中的n个进程(包括root)都执行了一个发送调用,同时根进程执行了n次接收调用.,mpi_gather函数,intmpi_gather(void*sendbuf/*in*/intsendcount/*in*/mpi_datatypesendtype/*in*/void*recvbuf/*out*/intrecvcount/*in*/mpi_datatyperecvtype/*in*/introot/*in*/mpi_commcomm/*in*/),sendbuf发送缓冲区起始地址sendcount发送缓冲区数据个数sendtype发送缓冲区数据类型,recvbuf接收缓冲区起始地址recvcount接收缓冲区数据个数recvtype接收缓冲区数据类型,rootonly,mpi_gather函数详解,从各个进程收集到的数据一般是互不相同的收集调用每个进程的发送数据个数sendcount和发送数据类型sendtype都是相同的,都和根进程中接收数据个数recvcount和接收数据类型recvtype相同。root和comm在所有进程中都必须是一致的根进程中指定的接收数据个数是指从每一个进程接收到的数据的个数而不是总的接收个数对于所有非根进程接收消息缓冲区被忽略但是各个进程必须提供这一参数所有参数对根进程都是有意义的,而对于其它进程只有sendbuf、sendcount、sendtype、root和comm有意义,其它的参数虽没有意义但却不能省略,mpi_gather图示,data.mpi_gather();.,data.mpi_gather();.,data.mpi_gather();.,process0myrank=0,process1myrank=1,processp-1myrank=p-1,buf,mpi_gather图示,a,b,c,d,k,在接收缓冲区有序存放,mpi_gather,p0,p1,p2,p3,p0,p1,p2,p3,a0,a1,a2,a3,实例:mpi_gather,mpi_commcomm;intsize,root,s_data100,*rbuf;mpi_comm_size(comm,mpi_scatter函数详解,根进程中的发送数据元素个数sendcount和发送数据类型sendtype必须和所有进程的接收数据元素个数recvcount和接收数据类型recvtype相同对于所有非根进程,发送消息缓冲区被忽略根进程发送元素个数指的是发送给每一个进程的数据元素的个数而不是总的数据个数此调用中的所有参数对根进程来说都是有意义的而对于其他进程来说只有recvbuf、recvcount、recvtype、root和comm是有意义的参数root和comm在所有进程中都必须是一致,实例:mpi_scatter,mpi_commcomm;intsize,*sendbuf;introot,rbuf100;.mpi_comm_size(comm,mpi_gatherv函数,intmpi_gatherv(void*sendbuf/*in*/intsendcount/*in*/mpi_datatypesendtype/*in*/void*recvbuf/*out*/intrecvcounts/*in*/intdispls/*in*/mpi_datatyperecvtype/*in*/introot/*in*/mpi_commcomm/*in*/),mpi_gatherv函数详解,收集不同长度数据块。从不同进程接收不同数量的数据,为此接收数据元素的个数recvcounts是一个数组,用于指明从不同的进程接收的数据元素的个数根从每一个进程接收的数据元素的个数可以不同,但是发送和接收的个数必须一致除此之外它还为每一个接收消息在接收缓冲区的位置提供了一个位置偏移displs数组用户可以将接收的数据存放到根进程消息缓冲区的任意位置mpi_gatherv明确指出了从不同的进程接收数据元素的个数以及这些数据在root接收缓冲区存放的起始位置,mpi_gathervsmpi_gatherv,gather,gatherv,应用vector派生数据类型,实例:mpi_gatherv,intsize,root,s_data100,*rbuf,*displs,*rcount;intstride=120;mpi_comm_size(comm,/*申请缓冲区*/,mpi_scatterv函数,intmpi_scatterv(void*sendbuf/*in*/intsendcounts/*in*/intdispls/*in*/mpi_datatypesendtype/*in*/void*recvbuf/*out*/intrecvcount/*in*/mpi_datatyperecvtype/*in*/introot/*in*/mpi_commcomm/*in*/),mpi_scatterv函数详解,mpi_scatterv允许root向各个进程发送个数不等的数据。因此要求sendcounts是一个数组同时还提供一个新的参数displs指明根进程发往其它不同进程数据在根发送缓冲区中的偏移位置根进程中sendcounti和sendtype的类型必须和进程i的recvcount和recvtype的类型相同这就意谓着在每个进程和根进程之间发送的数据量必须和接收的数据量相等对于所有非根进程,发送消息缓冲区被忽略。此调用中的所有参数对根进程来说都是很重要的而对于其他进程来说只有recvbuf、recvcount、recvtype、root和comm是有意义的参数root和comm在所有进程中都必须是一致的,实例:mpi_scatterv,inti,size,root,*sendbuf,rbuf100,*displs,*scounts;intstride=120;.mpi_comm_size(comm,/*申请缓冲区*/,mpi_allgather函数,intmpi_allgather(void*sendbuf/*in*/intsendcount/*in*/mpi_datatypesendtype/*in*/void*recvbuf/*out*/intrecvcount/*in*/mpi_datatyperecvtype/*in*/mpi_commcomm/*in*/),mpi_allgather函数详解,mpi_gather将数据收集到根进程,mpi_allgather相当于每一个进程都作为root执行了一次mpi_gather调用,即每一个进程都收集到了其它所有进程的数据从参数上看mpi_allgather和mpi_gather完全相同,只不过在执行效果上对于mpi_gather执行结束后,只有root进程的接收缓冲区有意义;mpi_allgather调用结束后所有进程的接收缓冲区都有意义。它们接收缓冲区的内容是相同的。,mpi_allgather函数图示,各进程接收缓冲区,mpi_allgather,p0,p1,p2,p3,p0,p1,p2,p3,mpi_allgatherv函数,intmpi_allgatherv(void*sendbuf/*in*/,intsendcount/*in*/,mpi_datatypesendtype/*in*/,void*recvbuf/*out*/,intrecvcounts/*in*/,intdispls/*in*/,mpi_datatyperecvtype/*in*/,mpi_commcomm/*in*/),rootonly,mpi_allgatherv函数详解,mpi_allgatherv也是所有的进程都将接收结果,而不是只有根进程接收结果;从每个进程发送的第j块数据将被每个进程接收,然后存放在各个进程接收消息缓冲区recvbuf的第j块,进程j的sendcount和sendtype的类型必须和其他所有进程的recvcountsj和recvtype相同,mpi_allgathervsmpi_allgatherv,实例:mpi_allgather,mpi_commcomm;intsize,sendarray100,*rbuf;.mpi_comm_size(comm,实例:mpi_allgatherv,intsize,sendarray100,*rbuf,*displs,i,*rcounts;intstride=120;.mpi_comm_size(comm,/*申请缓冲区*/,mpi全发散收集函数,每个进程散发自己的一个数据块,并且收集拼装所有进程散发过来的数据块。称该操作为数据的“全散发收集”。它既可以被认为是数据全收集的扩展,也可以被认为是数据散发的扩展,mpi_alltoall函数详解,mpi_alltoall是组内进程之间完全的消息交换,每一个进程都向其它所有的进程发送消息,同时每一个进程都从其它所有的进程接收消息。mpi_allgather每个进程散发一个相同的消息给所有的进程mpi_alltoall散发给不同进程的消息是不同的。因此它的发送缓冲区也是一个数组调用mpi_alltoall相当于每个进程依次将它的发送缓冲区的第i块数据发送给第i个进程,同时每个进程又都依次从第j个进程接收数据放到各自接收缓冲区的第j块数据区的位置。,mpi_alltoall函数详解,mpi_alltoall的每个进程可以向每个接收者发送数目不同的数据,第i个进程发送的第j块数据将被第j个进程接收,并存放在其接收消息缓冲区recvbuf的第i块。每个进程的sendcount和sendtype的类型必须和所有其他进程的recvcount和recvtype相同这就意谓着在每个进程和根进程之间发送的数据量必须和接收的数据量相等。,p0,p1,p2,p3,p0,p1,p2,p3,mpi_alltoall,mpi_alltoall函数,intmpi_alltoall(void*sendbuf/*in*/,intsendcount/*in*/,mpi_datatypesendtype/*in*/,void*recvbuf/*out*/,intrecvcount/*in*/,mpi_datatyperecvtype/*in*/,mpi_commcomm/*in*/),mpi_alltoallv函数,intmpi_alltoallv(void*sendbuf/*in*/,intsendcounts/*in*/,intsdispls/*in*/,mpi_datatypesendtype/*in*/,void*recvbuf/*out*/,intrecvcounts/*in*/,intrdispls/*in*/,mpi_datatyperecvtype/*in*/,mpi_commcomm/*in*/),mpi_alltoallv函数详解,正如mpi_allgatherv和mpi_allgather的关系一样mpi_alltoallv在mpi_alltoall的基础上进一步增加了灵活性。它可以由sdispls指定待发送数据的位置,在接收方则由rdispls指定接收的数据存放在缓冲区的偏移量所有参数对每个进程都是有意义的,并且所有进程中的comm值必须一致mpi_alltoall和mpi_alltoallv可以实现n次独立的点对点通信但也有限制:1)所有数据必须是同一类型;2)所有的消息必须按顺序进行散发和收集,mpi_alltoallvsmpi_alltoallv,全局归约mpi_reduce,intmpi_reduce(void*openand/*in*/,void*result/*in*/,intcount/*in*/,mpi_datatypedatatype/*in*/,mpi_opoperator/*out*/,introot/*in*/,mpi_commcomm/*in*/),openand操作数(发送缓冲区)起始地址result接收缓冲区(结果)的地址count发送缓冲区数据个数operator归约操作符,组归约函数mpi_allreduce,intmpi_reduce(void*openand/*in*/,void*result/*in*/,intcount/*in*/,mpi_datatypedatatype/*in*/,mpi_opoperator/*out*/,mpi_commcomm/*in*/)mpi_allreduce比mpi_reduce少一个root参数,其它参数及含义与后者一样,mpi_allreduce函数详解,mpi_allreduce相当于组中每一个进程都作为root分别进行了一次归约操作。mpi_allreduce相当于在mpi_reduce后马上再将结果进行一次广播mpi_bcast归约的结果不只是某一个进程所有而是所有的进程都所有。它在某种程度上和组收集与收集的关系很相似,mpi_allreduce函数图示,sendbuf,recvbuf,mpi_allreduce:np=3;count=3;op=mpi_sum,a0+b0+c0,mpi_allreduce,a1+b1+c1,a2+b2+c2,p0,p1,p2,a0+b0+c0,a1+b1+c1,a2+b2+c2,a0+b0+c0,a1+b1+c1,a2+b2+c2,归约发散函数mpi_reduce_scatter,intmpi_reduce_scatter(void*sendbuf/*in*/,void*recvb

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论