LecNote_12

上传人:紫** 文档编号:243140645 上传时间:2024-09-16 格式:PPT 页数:78 大小:444.50KB
返回 下载 相关 举报
LecNote_12_第1页
第1页 / 共78页
LecNote_12_第2页
第2页 / 共78页
LecNote_12_第3页
第3页 / 共78页
点击查看更多>>
资源描述
单击此处编辑母版标题样式,单击此处编辑母版文本样式,第二级,第三级,第十二讲,MPI,群通信、并行函数调用、并行程序性能分析,Collective communication,通信子与并行函数调用,MPI,并行程序性能分析,我们已经熟悉两种并行计算的方式,Client-server,:求素数,Server,负责:输入、输出、产生和派发子任务,Client,负责:计算子任务,不需要知道整个计算任务的描述:,素数的搜索范围,N,子任务是,server,计算出来的,Peer-to-Peer collaborating: N-Body,每个处理器都需要知道输入数据:,粒子数,N(,决定存储开销,),、模拟的时间步数,T (,决定计算任务量,),每个处理器都需要知道一部分输入数据:粒子的初始状态,(,在练习中,由,0#,处理器统一产生;实际中,是由某个处理器负责从输入文件中读入,),在,client-server,方式下,,MPI_Send/MPI_Recv,似乎已经足够,MPI_Send/MPI_Recv,与需要的数据交换机制很吻合,你还能想出一种更简洁的表达方式吗?,在,Peer-to-Peer collaborating,方式下, 对上面的两个通信情况,分别使用了一个循环,MPI_Send/MPI_Recv,让程序显得比较臃肿,不简洁,仔细分析,效率似乎也有影响,对,T,和,N(,假设,8,个处理器,),:在,0#,处理器上可减少,4,次通信启动开销,,如何实现,?,原方式:,7,次通信,一种更高效率的方式,:,每个处理器上最多执行,3,次通信,但如何实现?,(0),(1),(0, 1),(2, 3),(0, 1, 2, 3),(4, 5, 6, 7),群通信(,collective communication),虽然能够用,MPI_Send/MPI_Recv,满足任何的消息交换要求,但如果能有更简洁的手段,将可以大大简化并行程序开发的工作量(,事实上,把“,复杂,”的工作交给系统去完成,也给了系统优化运行效率的机会,),Collective communication:,涉及通信子中全部进程的一种通信模式,一个组中的所有成员都要参加,但所扮演的角色可能不一样。,Processes call the,same function,at certain point of execution, with,different argument values,.,注: 在点对点通信中,通信参与双方调用不同的函数,目的,程序代码简洁,便于,MPI runtime,根据数据交换的模式提高效率,MPI_Send/MPI_Recv,交换,N-Body,问题中,N,和,T,的代码,if(myRank,=0) ,n=,BodyNum,; t=,TimeSteps,;,for(i,=1;iproc; i+),MPI_Send(&n, 1, MPI_INT, i, 10, MPI_COMM_WORLD);,MPI_Send(&t, 1, MPI_INT, i, 20, MPI_COMM_WORLD);,else ,MPI_Recv(&n, 1, MPI_INT, 0, 10, MPI_COMM_WORLD, ,MPI_Recv(&t, 1, MPI_INT, 0, 20, MPI_COMM_WORLD, ,群通信交换,N-Body,问题中,N,和,T,的代码,if(myRank,=0) ,n=,BodyNum,; t=,TimeSteps,;,MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD);,MPI_Bcast(&t, 1, MPI_INT, 0, MPI_COMM_WORLD);,三类群通信,数据交换,Broadcast from one member to all other members,Gather data from an array spread across processors into one array,Scatter data from one member to all members,全局计算,REDUCTION,进程强制进度同步,Barrier synchronization,broadcast,把一个进程中的某个数据广播给,同一通信子,中的其余进程,A,0,A,0,A,0,A,0,A,0,A,0,A,0,data,processes,MPI_Bcast(void,* buffer,int,count,MPI_Datatype,datatype,int,root,MPI_Comm,comm,),root:,属于通信子,comm,的一个进程,在,root,进程上:把(,buffer, count,datatype,),指定的数据(标量或向量,),,作为一条,message,,分别向,comm,中的每个进程(包括,root,自己)发送,在,comm,中的每个进程(包括,root,自己)上:把从,root,所接收,message,中的数据存储在(,buffer, count),指定的缓冲区中,datatype,是缓冲区元素的类型,可以是,MPI,基本类型,也可以是派生数据类型,comm,中的每个进程都需要执行,MPI_Bcast,,,而且它们的参数,root,和,comm,必须完全一致,群通信,MPI_Bcast(void,* buffer,int,count,MPI_Datatype,datatype,int,root,MPI_Comm,comm,),等价,MPI_Send/MPI_Recv,If(myRank,=root),for(i,=0; i,procs,; i+) ,if(i,=root) continue;,MPI_Send(buffer, count,datatype, i, tag,comm,),else,MPI_Send(buffer, count,datatype, root, tag,comm, &status),gather,把分布存储在一组进程中的某个数组收集起来,重新组成一个数组,存储在其中一个进程中,这一组进程用一个通信子表示,A,0,A,1,A,2,A,3,A,4,A,5,data,processes,A,0,A,1,A,2,A,3,A,4,A,5,MPI_Gather(void*,sbuf,int,scount,MPI_Datatype,stype, void *,rbuf,int,rcount,MPI_Datatype,rtype,int,root,MPI_Comm,comm,),root:,属于通信子,comm,的一个进程,在,comm,中的每个进程(包括,root,自己)上:把(,sbuf,rcount,stype,),描述的数据发送给,root,进程,在,root,进程上:把从,comm,中的各进程(包括,root,自己)所接收的数据组织成一个数组,存储在,rbuf,指向的存储空间,存储空间的数据元素类型为,rtype,按照发送者的进程号安排存储空间中的数据存储顺序:第,i,号进程发送来的数据存储在第,i-1,号进程发送来的数据之后,所以数据连续存储,scount:sbuf,所指缓冲区中数据元素(类型为,stype,),的数量,而不是需要发送的数据元素的数量,comm,中的每个进程都需要执行,MPI_Gather,,而且它们的参数,root,和,comm,必须完全一致,参数,rbuf、rtype、rcount,只对,root,进程有意义,其它进程中可以没有定义,stype,和,rtype,可以是,MPI,基本类型,也可以是派生数据类型,问题:把分布在各个处理器上的数组片段按照处理器编号顺序合成一个完整的数组,存放在其中一个处理器上,数组元素类型为,INT,每个处理器上数组片段的长度的100,实现1,MPI_Comm,comm,;,int,gsize, sendarray100;,int,root, *,rbuf,;,MPI_Comm_size,(,comm, &,gsize,);,rbuf,= (,int,*),malloc(gsize,*100*,sizeof(int,);,MPI_Gather(,sendarray, 100, MPI_INT,rbuf, 100*,gsize, MPI_INT, root,comm,);,实现2,MPI_Comm,comm,;,int,gsize, sendarray100;,int,root,myrank, *,rbuf,;,MPI_Comm_rank,(,comm, &,myrank,);,MPI_Comm_size,(,comm, &,gsize,);,if (,myrank,= root ) ,rbuf,= (,int,*),malloc(gsize,*100*,sizeof(int,);,MPI_Gather(,sendarray, 100, MPI_INT,rbuf, 100*,gsize, MPI_INT, root,comm,);,实现3,MPI_Comm,comm,;,int,gsize, sendarray100;,int,root, *,rbuf,;,MPI_Datatype,rtype,;,MPI_Comm_size,(,comm, &,gsize,);,MPI_Type_contiguous( 100, MPI_INT, &,rtype,);,MPI_Type_commit (,rtype,);,MPI_Gather(,sendarray, 100, MPI_INT,rbuf,gsize,rtype, root,comm,);,scatter,从一个通信子的某个进程上,把一个数组均匀分发到通信子的各个进程上,这一组进程用一个通信子表示,A,0,A,1,A,2,A,3,A,4,A,5,data,processes,A,0,A,1,A,2,A,3,A,4,A,5,MPI_Scatter(void*,sbuf,int,scount,MPI_Datatype,stype, void *,rbuf,int,rcount,MPI_Datatype,rtype,int,root,MPI_Comm,comm,),root:,属于通信子,comm,的一个进程,在,root,进程上:把,sbuf,所指存储空间中的第(,i-1),scont,到,第,i,scont,-1,号元素发送给,comm,中的第,i,号进程,sbuf,所指存储空间的数据元素类型为,stype,0i0),连接了,indexi- indexi-1,条边,,,这些进程(在,old,中)的序号存储在,edgesj,中(,indexi-1,j,indexi),例如:有四个进程,邻接关系为,则输入参数为,nnodes,=4,index=2,3,4,6,edges=1,3,0,3,0,2,process,neighbors,0,1,3,1,0,2,3,3,0,2,MPI_Topo_test(MPI_Comm,comm,int,*status),查询通信子,comm,的拓扑结构类型,结果放在,status,中返回,有三种取值:,MPI_GRAPH(,无向图结构)、,MPI_CART(,笛卡尔结构)、,MPI_UNDEFINED(,无拓扑结构定义),注意:,MPI_COMM_WORLD,没有拓扑结构定义,MPI_Cartdim_get(MPI_Comm,comm,int,*,ndims,),查询通信子,comm,的笛卡尔结构的维度,ndims,通信子,comm,已经通过,MPI_Cart_create,附加了,cartesian,拓扑信息,MPI_Cart_get(MPI_Comm,comm,int,maxdims,int,*dims,int,*periods,int,*,coords,),查询通信子,comm,的,cartesian,拓扑信息,通信子,comm,已经通过,MPI_Cart_create,附加了,cartesian,拓扑信息,maxdims,是笛卡尔结构的最大维度,可以通过,MPI_Cartdim_get,获得,返回结果,网格第,i,个维度的大小是,dimsi,periodsi,是一个布尔量,表示网格的第,i,个维度是否是循环的(即它的最后一个处理器是否与它的第一个处理器“相邻”,),当前进程在,comm,中的笛卡尔坐标是,coord,MPI_Graphdims_get(MPI_Comm,comm,int,*,nnodes,int,*,nedges,),查询通信子,comm,的,Graph,拓扑信息:有,graph,中有多少个进程、多少条边,通信子,comm,已经通过,MPI_Graph_create,附加了,Graph,拓扑信息,返回结果:进程数,nnodes,、,边数,nedges,MPI_Graph_get(MPI_Comm,comm,int,maxindex,int,maxedges,int,*index,int,*edges),查询通信子,comm,的,Graph,拓扑信息:,graph,中每个进程分别有多少条边相连、与哪个进程相连,通信子,comm,已经通过,MPI_Graph_create,附加了,Graph,拓扑信息,maxindex,和,maxedges,分别是,graph,中的进程数和边数,可以通过,MPI_Graphdims_get,得到的,返回结果,comm,中的第0号进程与,index0,个进程之间有边连接,,,这些进程(在,old,中)的序号存储在,edgesj,中(0,j,index0),进程,i(comm,中的,rank,i0),连接了,indexi- indexi-1,条边,,,这些进程(在,comm,中)的序号存储在,edgesj,中(,indexi-1,j,indexi),笛卡尔坐标与进程组序号的互换,MPI_Cart_rank(MPI_Comm,comm,int,*,coords,int,*rank),把当前进程在通信子,comm,中的笛卡尔坐标,coord,转换成进程序号,rank,MPI_Cart_coords(MPI_Comm,comm,int,rank,int,maxdims,int,*,coords,),把当前进程在通信子,comm,中的序号,rank,转换成笛卡尔坐标,coord,maxdims,是,coord,的最大长度(即笛卡尔坐标的最大维度),Graph,上“邻居”的查询,MPI_Graph_neighbors_count(MPI_Comm,comm,int,rank,int,*,nneighbors,),查询,comm,中第,rank,号进程在,graph,中所连接的边数,nneighbors,MPI_,Graph_neighbors(MPI_Comm,comm,int,rank,int,maxneighbors,int,*neighbors),查询,comm,中第,rank,号进程在,graph,中各条边所连接的进程分别是谁,maxneighbors,是,rank,号进程所连接边的最大数量,可通过,MPI_Graph_neighbors_count,获得,neighborsi,返回第,i,条边所连接进程的,rank,Cartesian,结构的特别支持,MPI_Dims_create(int,nnodes,int,ndims,int,*dims),根据进程组中的进程数量,nnodes,、,cartesian,结构的维度,ndims,,,计算每一维的大小(,dimsi,是第,i,维的大小),MPI_Dims_create,尽可能平衡,cartesian,结构各维的大小,MPI_Cart_shift(MPI_Comm,comm,int,direction,int,disp,int,*rank_source,int,*,rank_dest,),这是常用的“移位”函数,但它并不真正使得数据发生移动。只是,返回在这个结构中的“相邻”进程的,rank,,,为后续,send/,recv,做准备。,假定,comm,的,cartesian,结构有,d,维,调用,Cart_shift,的进程的,cartesian,坐标为:(,i,0, i,1, ., i,d-1,)。,那么调用,Cart_shift,的进程得到两个返回值,source:,cartesian,坐标为,(i,0, ,i,direction,- displacement, , i,d-1,),的进程在,comm,中的,rank,dest,:,cartesian,坐标为,(i,0, ,i,direction,+ displacement, , i,d-1,),的进程在,comm,中的,rank,如果,(i,0, ,i,direction,- displacement, , i,d-1,),超出了,cartesian,坐标范围,则,source,返回,MPI_PORC_NULL,如果,(i,0, ,i,direction,+ displacement, , i,d-1,),超出了,cartesian,坐标范围,则,dest,返回,MPI_PORC_NULL,int,dims2, periods2,cartRank, coords2,rowID,colID, size;,MPI_Comm,cart,cartRow,cartCol,;,MPI_Init(&argc,&argv,);,MPI_Comm_size(MPI_COMM_WORLD, ,MPI_Dims_create(size, 2, dims);,dims0=dims1 =0;,periods0=periods1=0;,MPI_Cart_create(MPI_COMM_WORLD, 2, dims, periods, 0, ,MPI_Comm_rank(cart, &,cartRank,);,MPI_Cart_coords(cart,cartRank, 2,coords,);/,获得在,cart,中的坐标,创建了一个新的通信子,cart,拥有,MPI_COMM_WORLD,的全部处理器、在这些处理器上运行的进程,与,MPI_COMM_WORLD,不同的,CONTEXT,与,MPI_COMM_WORLD,不同的,TOPOLOGY,创建新的通信子,MPI,中提供了两类通信子的管理函数,访问通信子,创建通信子,访问通信子:查寻一个通信子的信息,直接访问本进程中的,MPI_COMM,对象,不需要与其他进程通信,MPI_Comm_rank,MPI_Comm_size,MPI_Comm_compare,创建通信子:用一个已有的通信子,创建一个或多个新的通信子。创建一个新通信子涉及原通信子中的全部进程,,MPI,在实现通信子的创建函数时,用到了对原通信子的群通信。因此,并行程序用创建一个新通信子时,对于原通信子中的每个进程,无论是否属于新通信子,都需要执行创建该新通信子的函数,MPI_Comm_dup,MPI_Comm_split,MPI_Comm_create,所有新通信子的创建都是从,MPI,预定义的通信字,MPI_COMM_WORLD,开始的,MPI_Comm_rank,(,MPI_Comm,comm,int,*ranks),查询当前进程在通信子,comm,中的序号,返回结果放在,rank,中,与,MPI_Group_rank,的功能相同,都是查询当前进程在一个进程组中的序号,MPI_Comm_size,(,MPI_Comm,comm,int,*size),查询通信子,comm,中的进程总数,返回结果放在,rank,中,与,MPI_Group_size,的功能相同,都是查询一个进程组中的进程总数,MPI_Comm_compare,(,MPI_Comm,comm1,MPI_Comm,comm2,int,*result),比较两个通信子,comm1,和,comm2,的关系,返回结果有四种情况,放在,result,中,MPI_IDENT,:,comm1,和,comm2,是指向同一个,MPI_COMM,对象的句柄,MPI_CONGRUENT:comm1,和,comm2,的,context,不同,但它们的进程组所包括的进程相同,而且同一个进程在两个进程组中的序号(,rank),一相同,MPI_SIMILAR: comm1,和,comm2,的进程组所包括的进程相同,但其中至少有一个进程,在两个进程组中的序号(,rank),不一样,MPI_UNEQUAL: comm1,和,comm2,的进程组所包括的进程不相同,MPI_Comm_dup,(,MPI_Comm,old,MPI_Comm,*new),使用时,在参数,old,所包含的每个进程上,都要执行相同的,MPI_Comm_dup,语句,用一个已有的通信子,old,创建一个新的通信子,new,old,与,new,除通信域(,context),不同外,其他的属性都相同,有相同的进程组,同一个进程在,old,与,new,中的序号也相同,有相同的进程组拓扑结构信息,old,与,new,分别代表了两个不同的通信范围,在并行函数调用时非常有用:在函数内部用,new,调用者和被调用者有两个不同的消息交换空间,MPI_Comm_split,(,MPI_Comm,old,int,color,int,key,MPI_Comm,*new),把,old,的进程组拆分成一组不相交的子集,为每个子集创建一个新的通信子,在,old,的各个进程上,,color,和,key,可以不同,color,相同的进程被划分到相同的进程子组,color,不能为负数,color,可以为,MPI_UNDEFINED,每个进程子组中的进程按,key,进行排序,对其中任意的两个进程,a,和,b,如果进程,a,的,key,小于进程,b,的,key,,那么在这个进程子组中,,a,的序号(,rank),小于进程,b,的序号(,rank),如果进程,a,的,key,等于进程,b,的,key,,那么在,old,中的序号大的那个进程在进程子组中的序号也大,当一个进程上的,color,取,MPI_UNDEFINED,时,则该进程将不属于任何子组,返回值,new,为,MPI_COMM_NULL,在,old,的各个进程上,如果,color,不为,MPI_UNDEFINED,new,返回一个新创建的通信子,其中包括了,old,中与本地进程有相同,color,值的全部进程,MPI_Comm_free,(,MPI_Comm,comm,),删除一个由应用程序所创建的通信子,comm,,,释放,comm,占用的资源,通信子(,communicator),的管理示例,假设,MPI_COMM_WORLD,中有10个进程,a,b,c,d,e,f,j,h,i,j,,,它们执行,MPI_Comm_split,的参数如下表所示,产生三个新的通信子,color=0:f,g,a,d,color=3:e,i,c,color=5:h,在进程,b,和,j,上,返回,MPI_COMM_NULL,在进程,a, d, f,和,g,上,返回一个通信子,其中包括进程,a, d, f,和,g,在进程,c, e,和,i,上,返回一个通信子,其中包括进程,c, e,和,i,在进程,h,上,返回一个通信子,其中只包括进程,h,rank,0,1,2,3,4,5,6,7,8,9,process,a,b,c,d,e,f,g,h,i,j,color,0,*,3,0,3,0,0,5,3,*,key,3,1,2,5,1,1,1,2,1,0,MPI_Cart_coords(cart,cartRank, 2,coords,);/,获得在,cart,中的坐标,/,将,Cart,中的每一行中的处理器分别组成一个通信子,color = coords0;,key = coords1;,MPI_Comm_split(cart, color, key, &,cartRow,);,将,cart,中的每一行分别作为一个新的通信子,新的通信子是一维的,每个新通信子分别有一个唯一的,CONTEXT,Cart,的进程组也被拆分:各个进程在新的进程组中分别有自己的编号,通信子与并行函数调用、任务并行,在开发并行函数时,在函数的接口,有一个额外的参数,说明并行函数需要的运行环境:通信子及其拓扑结构,对每个数据参数,要说明参数在通信子上的分布要求,在函数的内部:,使用参数中的通信子,创建一个新的通信子,用于函数内部的通信,使得函数内部的消息不于外部的消息混淆,在调用并行函数时,每个参与函数运算的进程都要调用并行函数,要根据并行函数接口的要求,准备通信子、数据分布,通过通信子管理函数,可以把,MPI_COMM_WORLD,划分成若干个互不相交的新通信子,在每个新通信子上,分别执行相同、或不同的函数,实现,任务并行,更灵活的通信子创建方式,MPI_Comm_create,(,MPI_Comm,old,MPI_Group,group,MPI_Comm,*new),用一个已有的通信子,old,创建一个新的通信子,new,group,是,old,的进程组子集,指定,new,所包括的进程,使用时,在参数,old,所包含的每个进程上,都要执行,MPI_Comm,_ create,语句,且各自的参数,group,必须相同,如果当前进程属于,group,new,中返回新创建的通信子,如果当前进程不属于,group,new,中返回,MPI_COMM_NULL:,一个没有任何进程的,MPI,预定义通信子,进程组(,group),的管理,MPI,提供了一个预定义的进程组,MPI_GROUP_EMPTY:,表示一个没有任何成员的进程组,MPI,提供了一个预定义的常量,MPI_GROUP_NULL:,表示一个无效的,MPI_Group,对象(,MPI_GROUP_EMPTY,是一个有效的,MPI_Group,对象),MPI,对进程组的管理,创建,MPI_Group,对象:,MPI_Comm_group,用已有的,MPI_Group,对象,构造,新的,MPI_Group,对象:,MPI_Group_union、MPI_Group_intersection,、,MPI_Group_difference、MPI_Group_incl、MPI_Group_excl,查询,MPI_Group,对象的属性:,MPI_Group_rank、MPI_Group_size,比较,两个,MPI_Group,对象:,MPI_Group_compare,删除,一个,MPI_Group,对象:,MPI_Group_free,创建,MPI_Group,对象,MPI_Comm_group,(,MPI_Comm,comm,MPI_Group,*group),
展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 图纸专区 > 小学资料


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!