MPI并行程序设计

上传人:新** 文档编号:585165433 上传时间:2024-09-01 格式:PPT 页数:219 大小:3.44MB
返回 下载 相关 举报
MPI并行程序设计_第1页
第1页 / 共219页
MPI并行程序设计_第2页
第2页 / 共219页
MPI并行程序设计_第3页
第3页 / 共219页
MPI并行程序设计_第4页
第4页 / 共219页
MPI并行程序设计_第5页
第5页 / 共219页
点击查看更多>>
资源描述

《MPI并行程序设计》由会员分享,可在线阅读,更多相关《MPI并行程序设计(219页珍藏版)》请在金锄头文库上搜索。

1、九月 24MPI并行程序设计1/217机群应用开发并行编程原理及并行编程原理及程序设计程序设计Parallel Programming: Parallel Programming: Fundamentals and ImplementationFundamentals and Implementation曙光信息产业有限公司曙光信息产业有限公司曙光信息产业有限公司曙光信息产业有限公司九月九月24九月 24MPI并行程序设计2/217参考文献黄铠,徐志伟著,陆鑫达等译. 可扩展并行计算技术可扩展并行计算技术,结构与编程结构与编程. 北京:机械工业出版社, P.3356,P.227237, 200

2、0.陈国良著.并行计算并行计算结构、算法、编程结构、算法、编程. 北京:高等教育出版社,1999.Barry Wilkinson and Michael Allen. Parallel Programming(Techniques and Applications using Networked Workstations and Parallel Computers). Prentice Hall, 1999.李晓梅,莫则尧等著. 可扩展并行算法的设计与分析可扩展并行算法的设计与分析. 北京:国防工业出版社,2000.张宝琳,谷同祥等著. 数值并行计算原理与方法数值并行计算原理与方法. 北京:

3、国防工业出版社,1999.都志辉著. 高性能计算并行编程技术高性能计算并行编程技术MPI并行程序设计并行程序设计. 北京:清华大学出版社, 2001. 九月 24MPI并行程序设计3/217相关网址MPI: http:/ww.mpi-forum.org, http:/www.mcs.anl.gov/mpiPthreads: http:/PVM: http:/www.epm.ornl.gov/pvm/ OpemMP: http:/www.openmp.org网上搜索:九月 24MPI并行程序设计4/217MPI并行程序设计并行程序设计Parallel Programming with theMa

4、ssage Passing Interface (MPI)九月 24MPI并行程序设计5/217多线程库标准多线程库标准Win32 API.POSIXthreads.编译制导标准编译制导标准OpenMP 可移植共享存储并行编程标准.消息传递库标准消息传递库标准MPI PVM并行编程标准并行编程标准本讨论的重点本讨论的重点九月 24MPI并行程序设计6/217消息传递并行程序设计消息传递并行程序设计消息传递并行程序设计消息传递并行程序设计指用户必须通过显式地发送和接收消息来实现处理机间的数据交换。在这种并行编程中,每个并行进程均有自己独立的地址空间,相互之间访问不能直接进行,必须通过显式的消息传

5、递来实现。这种编程方式是大规模并行处理机(MPP)和机群(Cluster)采用的主要编程方式。并行计算粒度大,特别适合于大规模可扩展并行算法并行计算粒度大,特别适合于大规模可扩展并行算法由于消息传递程序设计要求用户很好地分解问题,组织不同进程间的数据交换,并行计算粒度大,特别适合于大规模可扩展并行算法.消息传递是当前并行计算领域的一个非常重要的并行程序消息传递是当前并行计算领域的一个非常重要的并行程序设计方式设计方式九月 24MPI并行程序设计7/217什么是什么是MPI?Massage Passing Interface:是消息传递函数库的标准规范,由MPI论坛开发,支持Fortran和C一

6、种新的库描述,不是一种语言。共有上百个函数调用接口,在Fortran和C语言中可以直接对这些函数进行调用MPI是一种标准或规范的代表,而不是特指某一个对它的具体实现MPI是一种消息传递编程模型,并成为这种编程模型的代表和事实上的标准九月 24MPI并行程序设计8/217MPI的发展过程的发展过程发展的两个阶段MPI 1.1: 1995MPICH:是MPI最流行的非专利实现,由Argonne国家实验室和密西西比州立大学联合开发,具有更好的可移植性.MPI 1.22.0:动态进程, 并行 I/O, 支持F90和C+(1997).九月 24MPI并行程序设计9/217为什么要用MPI?高可移植性高可

7、移植性MPI已在IBM PC机上、MS Windows上、所有主要的Unix工作站上和所有主流的并行机上得到实现。使用MPI作消息传递的C或Fortran并行程序可不加改变地运行在IBM PC、MS Windows、Unix工作站、以及各种并行机上。九月 24MPI并行程序设计10/217讲座内容提示基本的基本的MPI基本概念基本概念点到点通信点到点通信(Pointtopoint)MPI中中API的主要内容,为的主要内容,为MPI最基本,最重要的内容最基本,最重要的内容MPI程序的编译和运行程序的编译和运行深入深入MPI用户自定义用户自定义(/派生派生)数据类型数据类型(User-define

8、d(Derived)datatype)事实上事实上MPI的所有数据类型均为的所有数据类型均为MPI自定义类型自定义类型支持异构系统支持异构系统允许消息来自不连续的或类型不一致的存储区允许消息来自不连续的或类型不一致的存储区(结构结构,数组散元数组散元)集合通信集合通信(Collective)数据移动数据移动,数据聚集,同步数据聚集,同步基于基于pointtopoint构建构建MPI环境管理函数环境管理函数组组,上下文和通信空间上下文和通信空间/通信子的管理通信子的管理实例实例九月 24MPI并行程序设计11/217从简单入手!下面我们首先分别以C语言和Fortran语言的形式给出一个最简单的M

9、PI并行程序Hello (下页).该程序在终端打印出Hello World!字样.“Hello World”:一声来自新生儿的问候. 九月 24MPI并行程序设计12/217Hello world(C)#include #include mpi.h“main( int argc, char *argv ) MPI_Init( &argc, &argv ); printf( Hello, world!n ); MPI_Finalize();九月 24MPI并行程序设计13/217Hello world(Fortran)program maininclude mpif.hinteger ierrc

10、all MPI_INIT( ierr )print *, Hello, world!call MPI_FINALIZE( ierr )end九月 24MPI并行程序设计14/217C和和Fortran中中MPI函数约定函数约定C必须包含mpi.h.MPI 函数返回出错代码或 MPI_SUCCESS成功标志成功标志.MPI-前缀,且只有MPI以及MPI_标志后的第一个字母大写,其余小写.Fortran必须包含mpif.h.通过子函数形式调用MPI,函数最后一个参数为返回值.MPI-前缀,且函数名全部为大写.MPI函数的参数被标志为以下三种类型:IN:参数在例程的调用中不会被修正.OUT:参数在例

11、程的调用中可能会被修正.INOUT:参数在一些例程中为IN,而在另一些例程中为OUT.九月 24MPI并行程序设计15/217MPI初始化-MPI_INITint MPI_Init(int *argc, char *argv)MPI_INIT(IERROR)MPI_INIT是MPI程序的第一个调用,它完成MPI程序的所有初始化工作。所有的MPI程序的第一条可执行语句都是这条语句。启动MPI环境,标志并行代码的开始.并行代码之前,第一个mpi函数(除MPI_Initialize()外).要求main必须带参数运行,否则出错.九月 24MPI并行程序设计16/217MPI结束-MPI_FINALI

12、ZEint MPI_Finalize(void)MPI_FINALIZE(IERROR)MPI_FINALIZE是MPI程序的最后一个调用,它结束MPI程序的运行,它是MPI程序的最后一条可执行语句,否则程序的运行结果是不可预知的。标志并行代码的结束,结束除主进程外其它进程.之后串行代码仍可在主进程(rank = 0)上运行(如果必须).九月 24MPI并行程序设计17/217MPI程序的的编译与运行mpif77 hello.f 或 mpicc hello.c 默认生成a.out的可执行代码.mpif77 o hello hello.f 或mpicc o hello hello.c生成hell

13、o的可执行代码.mpirun np 4 a.outmpirun np 4 hello4 指定np的实参,表示进程数,由用户指定.a.out / hello 要运行的MPI并行程序.%小写o%np:The number of process.九月 24MPI并行程序设计18/217:运行我们的MPI程序!dairnode01 $ mpicc -o hello hello.cdairnode01 $ ./hello ( ) 0 Aborting program ! Could not create p4 procgroup. Possible missing fileor program star

14、ted without mpirun.dairnode01 $ mpirun -np 4 hello ( ) Hello World! Hello World! Hello World! Hello World!dairnode01 $ 计算机打印字符我们输入的命令九月 24MPI并行程序设计19/217:Hello是如何被执行的?SPMD: Single Program Multiple Data(SPMD) :#include mpi.h#include main( int argc, char *argv ) MPI_Init( &argc, &argv ); printf( Hello

15、, world!n ); MPI_Finalize();#include mpi.h#include main( int argc, char *argv ) MPI_Init( &argc, &argv ); printf( Hello, world!n ); MPI_Finalize();#include mpi.h#include main( int argc, char *argv ) MPI_Init( &argc, &argv ); printf( Hello, world!n ); MPI_Finalize();#include mpi.h#include main( int a

16、rgc, char *argv ) MPI_Init( &argc, &argv ); printf( Hello, world!n ); MPI_Finalize();Hello World!Hello World!Hello World!Hello World!#include mpi.h#include main( int argc, char *argv ) MPI_Init( &argc, &argv ); printf( Hello, world!n ); MPI_Finalize();九月 24MPI并行程序设计20/217:开始写MPI并行程序在写MPI程序时,我们常需要知道以

17、下两个问题的答案:任务由任务由多少多少个进程来进行并行计算?个进程来进行并行计算?我是我是哪一个哪一个进程进程? 九月 24MPI并行程序设计21/217:开始写MPI并行程序MPI 提供了下列函数来回答这些问题:用用MPI_Comm_size 获得进程个数 p int MPI_Comm_size(MPI_Comm comm, int *size);用用MPI_Comm_rank 获得进程的一个叫rank的值,该 rank值为0到p-1间的整数,相当于进程的IDint MPI_Comm_rank(MPI_Comm comm, int *rank);九月 24MPI并行程序设计22/217更新的

18、Hello World(c)#include #include mpi.hmain( int argc, char *argv ) int myid, numprocs; MPI_Init( &argc, &argv ); MPI_Comm_rank( MPI_COMM_WORLD, &myid ); MPI_Comm_size( MPI_COMM_WORLD, &numprocs ); printf(“I am %d of %dn, myid, numprocs ); MPI_Finalize();九月 24MPI并行程序设计23/217更新的Hello World(Fortran)prog

19、ram maininclude mpif.hinteger ierr, myid, numprocscall MPI_INIT( ierr )call MPI_COMM_RANK( MPI_COMM_WORLD, myid, ierr )call MPI_COMM_SIZE( MPI_COMM_WORLD, numprocs, ierr )print *, I am, myid, of, numprocscall MPI_FINALIZE( ierr )end九月 24MPI并行程序设计24/217:运行结果dairnode01 $ mpicc o hello1 hello1.cdairnod

20、e01 $ mpirun -np 4 hello1I am 0 of 4I am 1 of 4I am 2 of 4I am 3 of 4dairnode01 $计算机打印字符我们输入的命令九月 24MPI并行程序设计25/217有消息传递 Greeting九月 24MPI并行程序设计26/217greetings(c)#include #include mpi.hmain(int argc, char* argv) int numprocs, myid, source; MPI_Status status; char message100; MPI_Init(&argc, &argv); M

21、PI_Comm_rank(MPI_COMM_WORLD, &myid); MPI_Comm_size(MPI_COMM_WORLD, &numprocs);九月 24MPI并行程序设计27/217有消息传递greetings(c) if (myid != 0) strcpy(message, Hello World!); MPI_Send(message,strlen(message)+1, MPI_CHAR, 0,99, MPI_COMM_WORLD); else /* myid = 0 */ for (source = 1; source numprocs; source+) MPI_Re

22、cv(message, 100, MPI_CHAR, source, 99, MPI_COMM_WORLD, &status); printf(%sn, message); MPI_Finalize(); /* end main */九月 24MPI并行程序设计28/217解剖greetings程序头文件: mpi.h/mpif.h.int MPI_Init(int *argc, char *argv) 启动MPI环境,标志并行代码的开始.并行代码之前,第一个mpi函数(除MPI_Initialize()外).要求main必须带能运行,否则出错.通信子(通信空间): MPI_COMM_WORL

23、D:一个通信空间是一个进程组和一个上下文的组合.上下文可看作为组的超级标签,用于区分不同的通信子.在执行函数MPI_Init之后,一个MPI程序的所有进程形成一个缺省的组,这个组的通信子即被写作MPI_COMM_WORLD.该参数是MPI通信操作函数中必不可少的参数,用于限定参加通信的进程的范围.九月 24MPI并行程序设计29/217解剖greetings程序int MPI_Comm_size ( MPI_Comm comm, int *size )获得通信空间comm中规定的组包含的进程的数量.指定一个communicator,也指定了一组共享该空间的进程, 这些进程组成该communic

24、ator的group.int MPI_Comm_rank ( MPI_Comm comm, int *rank ) 得到本进程在通信空间中的rank值,即在组中的逻辑编号(从0开始).int MPI_Finalize() 标志并行代码的结束,结束除主进程外其它进程.之后串行代码仍可在主进程(rank = 0)上运行(如果必须).九月 24MPI并行程序设计30/217消息传送(先可不关心参数含义)MPI_Send(A,10,MPI_DOUBLE,1,99,MPI_COMM_WORLD);MPI_Recv(B,20,MPI_DOBULE,0,99,MPI_COMM_WORLD,&status);

25、数据传送数据传送 + 同步操作同步操作l需要发送方与接收方合作完成.DataProcess 0Process 1发送请求YesDataDataDataDataDataDataDataDataTime九月 24MPI并行程序设计31/217最基本的MPIMPI调用借口的总数虽然庞大,但根据实际编写MPI的经验,常用的MPI调用的个数确实有限。下面是6个最基本的MPI函数。1.MPI_Init();2.MPI_Comm_size();3.MPI_Comm_rank();4.MPI_Send();5.MPI_Recv();6.MPI_Finalize();MPI_Init();并行代码并行代码;MP

26、I_Fainalize();只能有串行代码只能有串行代码;九月 24MPI并行程序设计32/217讲座内容提示基本的MPI基本概念点到点通信(Point to point)MPI中API的主要内容,为MPI最基本,最重要的内容MPI程序的编译和运行深入MPI用户自定义(/派生)数据类型(User-defined(Derived) data type)事实上MPI的所有数据类型均为MPI自定义类型支持异构系统允许消息来自不连续的或类型不一致的存储区(结构,数组散元)集合通信(Collective)数据移动,数据聚集,同步基于point to point 构建MPI环境管理函数组,上下文和通信空间

27、/通信子的管理实例九月 24MPI并行程序设计33/217Point to Point单个进程对单个进程的通信,重要且复杂术语Blocking(阻塞) :一个例程须等待操作完成才返回,返回后用户可以重新使用调用中所占用的资源. Non-blocking(非阻塞):一个例程不必等待操作完成便可返回,但这并不意味着所占用的资源可被重用. Local(本地):不依赖于其它进程. Non-local(非本地):依赖于其它进程.九月 24MPI并行程序设计34/217Blocking Sendint MPI_Send(void* buf, int count, MPI_Datatype datatype

28、, intdest,inttag,MPI_Commcomm); IN buf 发送缓冲区的起始地址发送缓冲区的起始地址 IN count 要发送信息的要发送信息的元素元素个数个数 IN datatype 发送信息的数据类型发送信息的数据类型 IN dest 目标进程的目标进程的rank值值 IN tag 消息标签消息标签 IN comm 通信子通信子九月 24MPI并行程序设计35/217Blocking Receiveint MPI_Recv(void* buf, int count, MPI_Datatype datatype, intsource,inttag,MPI_Commcomm,

29、MPI_Status*status); OUT buf 接收接收缓冲区的起始地址缓冲区的起始地址 IN count 要接收信息的要接收信息的元素元素个数个数 IN datatype 接收信息的数据类型接收信息的数据类型 IN source 源进程的源进程的rank值值 IN tag 消息标签消息标签 IN comm 通信子通信子OUT statusstatus对象对象,包含实际接收到的消息的有关信息包含实际接收到的消息的有关信息九月 24MPI并行程序设计36/217MPI消息MPI消息包括信封和数据两个部分,信封指出了发送或接收消息的对象及相关信息,而数据是本消息将要传递的内容数据:信封:九

30、月 24MPI并行程序设计37/217消息数据由count个类型为datatype的连续数据空间组成, 起始地址为buf不是以字节数, 而是以元素的个数指定消息的长度count可以是零, 这种情况下消息的数据部分是空的MPI基本数据类型相应于宿主语言的基本数据类型 九月 24MPI并行程序设计38/217什么是缓冲区?1.应用程序中说明的变量,在消息传递语句中又用作缓冲区的起始位置.2.也可表示由系统(不同用户)创建和管理的某一存储区域,在消息传递过程中用于暂存放消息.也被称为系统缓冲区.3.用户可设置一定大小的存储区域,用作中间缓冲区以保留可能出现在其应用程序中的任意消息.进程PAM进程QB

31、进程PAMS进程QB进程PAMT进程QB系统缓冲区用户指定缓冲区用户缓冲区九月 24MPI并行程序设计39/217MPI标识一条消息的信息包含四个域标识一条消息的信息包含四个域:Source: 发送进程隐式确定,由进程的rank值唯一标识Destination: Send函数参数确定Tag: Send函数参数确定,用于识别不同的消息 (0,UB),UB:MPI_TAG_UB=32767.Communicator: 缺省MPI_COMM_WORLDGroup:有限/N,有序/Rank 0,1,2,N-1Contex:Super_tag,用于标识该通讯空间.消息信封九月 24MPI并行程序设计40

32、/217九月 24MPI并行程序设计41/217消息匹配接收buffer必须至少可以容纳count个由datatype参数指明类型的数据. 如果接收buf太小, 将导致溢出、出错.消息匹配参数匹配 dest,tag,comm/ source,tag,commSource = MPI_ANY_SOURCE:接收任意处理器来的数据(任意消息来源).Tag = MPI_ANY_TAG:匹配任意tag值的消息(任意tag消息).在阻塞式消息传送中不允许Source=Dest,否则会导致deadlock.消息传送被限制在同一个communicator.在send函数中必须指定唯一的接收者(Push/pu

33、ll通讯机制).九月 24MPI并行程序设计42/217status参数当使用当使用MPI_ANY_SOURCE或或/和和MPI_ANY_TAG接收消接收消息时如何确定消息的来源息时如何确定消息的来源source和和tag值呢值呢?在C中,status.MPI_SOURCE, status.MPI_TAG.在Fortran中, source=status(MPI_SOURCE), tag=status(MPI_TAG).Status还可用于返回实际接收到消息的长度还可用于返回实际接收到消息的长度int MPI_Get_count(MPI_Status status, MPI_Datatype

34、datatype,int* count)IN status 接收操作的返回值.IN datatype 接收缓冲区中元素的数据类型.OUT count 接收消息中的元素个数.九月 24MPI并行程序设计43/217分析greetings#include#includempi.h“main(intargc,char*argv)intnumprocs;/*进程数进程数,该变量为各处理器中的同名变量该变量为各处理器中的同名变量,存储是分布的存储是分布的*/intmyid;/*我的进程我的进程ID,存储也是分布的存储也是分布的*/MPI_Statusstatus;/*消息接收状态变量消息接收状态变量,存

35、储也是分布的存储也是分布的*/charmessage100;/*消息消息buffer,存储也是分布的存储也是分布的*/*初始化初始化MPI*/MPI_Init(&argc, &argv);/*该函数被各进程各调用一次该函数被各进程各调用一次,得到自己的进程得到自己的进程rank值值*/MPI_Comm_rank(MPI_COMM_WORLD, &myid);/*该函数被各进程各调用一次该函数被各进程各调用一次,得到进程数得到进程数*/MPI_Comm_size(MPI_COMM_WORLD, &numprocs);九月 24MPI并行程序设计44/217分析greetingsif (myid

36、!= 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 count = 0p0p1p2P(n-1)pi空进程空进程九月 24MPI并行程序设计54/217空进程应用示意MPI_Statu

37、s status;int dest = (rank+1)%p;int source = (rank + p -1)%p;if(source = p-1) source = MPI_PROC_NULL;if(dest = 0) dest = MPI_PROC_NULL;MPI_Sendrecv( &a, 1, MPI_INT, dest, 99, &b 1, MPI_INT, source, 99, MPI_COMM_WORLD, &status);九月 24MPI并行程序设计55/217阻塞与非阻塞的差别用户发送缓冲区的重用:非阻塞的发送:仅当调用了有关结束该发送的语句后才能重用发送缓冲区,否

38、则将导致错误;对于接收方,与此相同,仅当确认该接收请求已完成后才能使用。所以对于非阻塞操作,要先调用等待MPI_Wait()或测试MPI_Test()函数来结束或判断该请求,然后再向缓冲区中写入新内容或读取新内容。阻塞发送将发生阻塞,直到通讯完成.非阻塞可将通讯交由后台处理,通信与计算可重叠.发送语句的前缀由MPI_改为MPI_I, I:immediate:标准模式:MPI_Send()-MPI_Isend()Buffer模式:MPI_Bsend()-MPI_Ibsend()九月 24MPI并行程序设计56/217非阻塞发送与接收int MPI_Isend(void* buf, int cou

39、nt, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm, MPI_Request *request)IN buf 发送缓冲区的起始地址IN count 发送缓冲区的大小(发送元素个数)IN datatype 发送缓冲区数据的数据类型IN dest 目的进程的秩IN tag 消息标签IN comm 通信空间/通信子OUT request 非阻塞通信完成对象(句柄)int MPI_Irecv(void* buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Co

40、mm comm, MPI_Request* request)九月 24MPI并行程序设计57/217非阻塞标准发送和接收九月 24MPI并行程序设计58/217通信的完成(常用于非阻塞通信)发送的完成: 代表发送缓冲区中的数据已送出,发送缓冲区可以重用。它并不代表数据已被接收方接收。数据有可能被缓冲;接收的完成:代表数据已经写入接收缓冲区。接收者可访问接收缓冲区。通过MPI_Wait()和MPI_Test()来判断通信是否已经完成;九月 24MPI并行程序设计59/217MPI_Wait()及应用示例int MPI_Wait(MPI_Request* request, MPI_Status *

41、 status);当当request标识的通信结束后,标识的通信结束后,MPI_Wait()才返回才返回。如果通信是非阻塞的,返回时request = MPI_REQUEST_NULL;函数调用是非本地的;MPI_Request request;MPI_Status status;int x,y;if(rank = 0)MPI_Isend(&x,1,MPI_INT,1,99,comm,&request)MPI_Wait(&request,&status);elseMPI_Irecv(&y,1,MPI_INT,0,99,comm,&request)MPI_Wait(&request,&statu

42、s);九月 24MPI并行程序设计60/217MPI_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(&x,1,MPI_INT,1,99,comm,&request)while(!flag)MPI_Test(&request,&flag,&status);elseMPI_Irecv(&y,1,MPI_INT,0,99,comm,&request

43、)while(!flag)MPI_Test(&request,&flag,&status);九月 24MPI并行程序设计61/217消息探测-Probe函数(适用于阻塞与非阻塞)MPI_Probe()和MPI_Iprobe()函数探测接收消息的内容。用户根据探测到的消息内容决定如何接收这些消息,如根据消息大小分配缓冲区等。前者为阻塞方式,即只有探测到匹配的消息才返回;后者为非阻塞,即无论探测到与否均立即返回.int MPI_Probe(int source, int tag, MPI_Comm comm, MPI_Status* status)int MPI_Iprobe(int source

44、, int tag, MPI_Comm comm, int*flag, MPI_Status* status)IN source 数据源的rank,可以是MPI_ANY_SOURCEIN tag 数据标签,可以是MPI_ANY_TAGIN comm 通信空间/通信子OUT flag 布尔值,表示探测到与否(只用于非阻塞方式)OUT status status对象,包含探测到消息的内容 九月 24MPI并行程序设计62/217MPI_Probe应用示例intx;floaty;MPI_Comm_rank(comm,&rank);if(rank=0)/*0-2发送一发送一int型数型数*/MPI_S

45、end(100,1,MPI_INT,2,99,comm);elseif(rank=1)/*1-2发送一发送一float型数型数*/MPI_Send(100.0,1,MPI_FLOAT,2,99,comm);else/*根进程接收根进程接收*/for(inti=0;i2;i+)MPI_Probe(MPI_ANY_SOURCE,0,comm,&status);/*Blocking*/if(status.MPI_SOURCE=0)MPI_Recv(&x,1,MPI_INT,0,99,&status);elseif(status.MPI_SOURCE=1)MPI_Recv(&y,1,MPI_FLOAT

46、,0,99,&status);九月 24MPI并行程序设计63/217讲座内容提示基本的MPI基本概念点到点通信(Point to point)MPI中API的主要内容,为MPI最基本,最重要的内容MPI程序的编译和运行深入MPI用户自定义(/派生)数据类型(User-defined(Derived) data type)事实上MPI的所有数据类型均为MPI自定义类型支持异构系统允许消息来自不连续的或类型不一致的存储区(结构,数组散元)集合通信(Collective)数据移动,数据聚集,同步基于point to point 构建MPI环境管理函数组,上下文和通信空间/通信子的管理实例九月 24

47、MPI并行程序设计64/217MPI程序的编译mpicc编译并连接用C语言编写的MPI程序mpiCC编译并连接用C+编写的MPI程序mpif77编译并连接用FORTRAN 77编写的MPI程序mpif90编译并连接用Fortran 90编写的MPI程序这些命令可以自动提供MPI需要的库,并提供特定的开关选项(用-help查看)。九月 24MPI并行程序设计65/217MPI程序的编译用mpicc编译时,就像用一般的C编译器一样。还可以使用一般的C的编译选项,含义和原来的编译器相同例如:./mpicc-cfoo.c./mpicc-ofoofoo.o九月 24MPI并行程序设计66/217MPI程

48、序的运行MPI程序的执行步骤一般为:编译以得到MPI可执行程序(若在同构的系统上,只需编译一次;若系统异构,则要在每一个异构系统上都对MPI源程序进行编译)将可执行程序拷贝到各个节点机上通过mpirun命令并行执行MPI程序九月 24MPI并行程序设计67/217最简单的MPI运行命令mpirun np N 其中:N: 同时运行的进程数: 可执行MPI程序名例如:mpirun np 6 cpimpirun np 4 hello九月 24MPI并行程序设计68/217一种灵活的执行方式mpirunp4pg为配置文件,其格式为:为配置文件,其格式为:例如例如:(注:第一行的注:第一行的0并不表示在

49、并不表示在node0上没有上没有进程,这里的进程,这里的0特指在特指在node0上启动上启动MPI程序程序)node00/public0/dair/mpi/cpinode11/public0/dair/mpi/cpinode21/public0/dair/mpi/cpi这种方式允许可执行程序由不同的名字和不同的这种方式允许可执行程序由不同的名字和不同的路径路径九月 24MPI并行程序设计69/217另一种灵活的执行方式mpirunmachinefile-np为配置文件,其格式为:为配置文件,其格式为:例如例如:node0node1node2node3九月 24MPI并行程序设计70/217完整

50、的MPI运行方式MPI程序的一般启动方式:程序的一般启动方式:mpirun np 完整的完整的MPI运行方式:运行方式:mpirun mpirun_options options详细参数信息执行mpirun -help九月 24MPI并行程序设计71/217讲座内容提示基本的MPI基本概念点到点通信(Point to point)MPI中API的主要内容,为MPI最基本,最重要的内容MPI程序的编译和运行深入MPI用户自定义(/派生)数据类型(User-defined(Derived) data type)事实上MPI的所有数据类型均为MPI自定义类型支持异构系统允许消息来自不连续的或类型不一

51、致的存储区(结构,数组散元)集合通信(Collective)数据移动,数据聚集,同步基于point to point 构建MPI环境管理函数组,上下文和通信空间/通信子的管理实例九月 24MPI并行程序设计72/217MPI数据类型if (my_rank != 0) /*建立消息建立消息*/ sprintf(message, Greetings from process %d!,my_rank); /* 发送长度取发送长度取strlen(message)+1,使使0也一同发送出去也一同发送出去*/ MPI_Send(message,strlen(message)+1, MPI_CHAR, 0,

52、99,MPI_COMM_WORLD);else /* my_rank = 0 */ for (source = 1; source p; source+) MPI_Recv(message, 100, MPI_CHAR, source, 99, MPI_COMM_WORLD,&status); printf(“%sn, message); /*关闭关闭MPI,标志并行代码段的结束标志并行代码段的结束*/ MPI_Finalize(); /* main */九月 24MPI并行程序设计73/217用户自定义数据类型/派生数据类型目的目的异构计算: 不同系统有不同的数据表示格式。MPI预先定义一些

53、基本数据类型,在实现过程中在这些基本数据类型为桥梁进行转换。派生数据类型:允许消息来自不连续的和类型不一致的存储区域,如数组散元与结构类型等的传送。MPI中所有数据类型均为中所有数据类型均为MPI自定义类型自定义类型基本数据类型,如MPI_INT,MPI_DOUBLE用户定义数据类型或派生数据类型.九月 24MPI并行程序设计74/217MPI基本数据类型九月 24MPI并行程序设计75/217数据类型图九月 24MPI并行程序设计76/217Derived Datatype(派生)常用MPI_Type_contiguousMPI_Type_vectorMPI_Type_indexedMPI_

54、Type_struct九月 24MPI并行程序设计77/217MPI_Type_contiguous将原数据类型,按顺序进行多次复制九月 24MPI并行程序设计78/217在FORTRAN中定义矩阵的一列REAL A(1000,1000)INTEGER F_COLMPI_TYPE_CONTIGUOUS(1000,MPI_REAL,F_COL)MPI_SEND(A,1,F_COL,right,tag,MPI_COMM_WORLD)在C中定义矩阵的一行float a10001000; MPI_Datatype C_R;MPI_Type_contiguous(1000,MPI_FLOAT,&C_R)

55、;MPI_SEND(&(a00),1,C_R, right,tag ,MPI_COMM_WORLD)九月 24MPI并行程序设计79/217用MPI_Vector进行矩阵的行列置换以C语言的数组表示为例:将矩阵的一列送到另一数组的一行中九月 24MPI并行程序设计80/217MPI_Vector函数原型MPI_Vector()MPI_Vector()函函数数首首先先通通过过连连续续复复制制若若干干个个旧旧数数据据类类型型形形成成一一个个“块块”,然然后后通通过过等等间间隔隔地地复复制制该该块块儿儿形形成成新新的的数数据据类类型。型。块与块之间的空间时旧数据类型的倍数块与块之间的空间时旧数据类型

56、的倍数。#include mpi.hint MPI_Type_vector ( int count, /*数据块个数数据块个数 (非负整数非负整数)*/ int blocklen, /*块中元素个数块中元素个数 (非负整数非负整数)*/ int stride, /*块间块间起始地址间隔起始地址间隔 (非负整数非负整数)*/ MPI_Datatype old_type, /*原始数据类型原始数据类型(句柄句柄)*/ MPI_Datatype *newtype /*派生数据类型指针派生数据类型指针*/)九月 24MPI并行程序设计81/217MPI_Type_vector应用示意用用MPI_Vec

57、tor进行矩阵的行列置换进行矩阵的行列置换 float A1010; MPI_Datatype column_mpi_t; MPI_Type_vector(10, 1, 10, MPI_FLOAT, &column_mpi_t); MPI_Type_commit(&column_mpi_t); if (my_rank = 0) MPI_Send(&(A00), 1, column_mpi_t, 1, 0, MPI_COMM_WORLD); else /* my_rank = 1 */ MPI_Recv(&(A00), 10, MPI_FLOAT, 0, 0, MPI_COMM_WORLD, &

58、status);九月 24MPI并行程序设计82/217用MPI_Type_indexed发送矩阵的上三角部分以C语言表示的数组为例,数组按行连续存储九月 24MPI并行程序设计83/217MPI_Type_indexed函数原型#include mpi.hint MPI_Type_indexed ( int count, /*数据块的个数,数据块间不连续数据块的个数,数据块间不连续*/int blocklens, /*每一数据块中元素的个数,为一个非负整型数组每一数据块中元素的个数,为一个非负整型数组*/int indices, /*每一块数据在每一块数据在原始数据类型原始数据类型中的起始位

59、置中的起始位置,整型数组整型数组*/MPI_Datatype old_type, /*原始数据类型原始数据类型(名柄名柄)*/MPI_Datatype* newtype /*派生数据类型指针派生数据类型指针*/)九月 24MPI并行程序设计84/217MPI_Type_indexed应用示意应用示意(将将A矩阵的上三角矩阵的上三角部分送到另一个处理器中的部分送到另一个处理器中的T矩阵的对应位置矩阵的对应位置) floatAnn; /* Complete Matrix */float Tnn; /* Upper Triangle */int displacementsn;int block_le

60、ngthsn;MPI_Datatype index_mpi_t;for (i = 0; i n; i+) block_lengthsi = n-i; displacementsi = (n+1)*i;MPI_Type_indexed(n, block_lengths, displacements,MPI_FLOAT, &index_mpi_t);MPI_Type_commit(&index_mpi_t);if (my_rank = 0) MPI_Send(A, 1, index_mpi_t, 1, 0, MPI_COMM_WORLD);else /* my_rank = 1 */ MPI_Re

61、cv(T, 1, index_mpi_t, 0, 0, MPI_COMM_WORLD, &status);九月 24MPI并行程序设计85/217MPI_Type_struct允许每个块包含不同数据类型的拷贝九月 24MPI并行程序设计86/217MPI_Type_struct的例子struct partstruct char class; double d6; char b7;struct partstruct particle1000;int i,dest,rank;MPI_Datatype particletype,type3=MPI_CHAR, MPI_DOUBLE,MPI_CHARi

62、nt blocklen3=1,6,7;MPI_Aint disp3=0,sizeof(double),7*sizeof(double);MPI_Type_struct(3,blocklen,disp,type,&particletype);九月 24MPI并行程序设计87/217其它派生类型MPI_HvectorMPI_HindexedMPI_Pack/MPI_Unpack:数据打包/解包是其它数据派生数据类型的基础,MPI不建议用户进行显式的数据打包为了与早期其它并行库兼容九月 24MPI并行程序设计88/217MPI_Pack ()int MPI_Pack (void*inbuf, /*

63、输入缓冲区起始地址*/int incount, /* 输入数据项个数 */MPI_Datatypedatatype, /* 输入数据项的数据类型 */void*outbuf, /* 输出缓冲区起始地址 */intoutcount, /* 输出缓冲区大小 */int*position, /* 输出缓冲区当前位置 */MPI_Commcomm /* 通信域 */)例:packsize=0;MPI_Pack(&a,1,MPI_INT,packbuf,100,&packsize,MPI_COMM_WORLD);MPI_Pack(&b,1,MPI_DOUBLE, packbuf,100,&packsiz

64、e,MPI_COMM_WORLD);九月 24MPI并行程序设计89/217MPI_Unpack()int MPI_Unpack (void*inbuf, /* 输入缓冲区起始地址*/int incount, /* 输入数据项大小*/int*position, /* 缓冲区当前位置 */void*outbuf, /* 输出缓冲区起始地址 */intoutcount, /* 输出缓冲区大小 */MPI_Datatypedatatype, /* 输出数据项的数据类型 */MPI_Commcomm /* 通信域 */)例:pos=0;MPI_Unpack(packbuf,packsize,&pos,

65、&a,1,MPI_INT,MPI_COMM_WROLD);MPI_Unpack(packbuf,packsize,&pos,&b,1,MPI_FLOAT,MPI_COMM_WROLD);九月 24MPI并行程序设计90/217派生数据类型的应用提交:int MPI_Type_commit(MPI Datatype *datatype)将数据类型映射进行转换或“编译”一种数据类型变量可反复定义,连续提交释放:int MPI_Type free(MPI_Datatype *datatype)将数据类型设为MPI_DATATYPE_NULL九月 24MPI并行程序设计91/217讲座内容提示基本的M

66、PI基本概念点到点通信(Point to point)MPI中API的主要内容,为MPI最基本,最重要的内容MPI程序的编译和运行深入MPI用户自定义(/派生)数据类型(User-defined(Derived) data type)事实上MPI的所有数据类型均为MPI自定义类型支持异构系统允许消息来自不连续的或类型不一致的存储区(结构,数组散元)集合通信(Collective)数据移动,数据聚集,同步基于point to point 构建MPI环境管理函数组,上下文和通信空间/通信子的管理实例九月 24MPI并行程序设计92/217集合通信Collective Communication特点

67、通信空间中的所有进程都参与通信操作每一个进程都需要调用该操作函数一到多多到一同步九月 24MPI并行程序设计93/217类型函数功能数据移动MPI_Bcast一到多,数据广播MPI_Gather多到一,数据汇合MPI_GathervMPI_Gather的一般形式MPI_AllgatherMPI_Gather的一般形式MPI_AllgathervMPI_Allgather的一般形式MPI_Scatter一到多,数据分散MPI_ScattervMPI_Scatter的一般形式MPI_Alltoall多到多,置换数据(全互换)MPI_AlltoallvMPI_Alltoall的一般形式数据聚集MPI

68、_Reduce多到一,数据归约MPI_Allreduce上者的一般形式,结果在所有进程MPI_Reduce_scatter结果scatter到各个进程MPI_Scan前缀操作同步MPI_Barrier同步操作MPI集合通信函数All:表示结果到所有所有进程.V:Variety,被操作的数据对象和操作更为灵活.%九月 24MPI并行程序设计94/217数据移动BroadcastScatterGatherAllgatherAlltoall九月 24MPI并行程序设计95/217数据聚集ReduceAllreduceReduce-scatterScanMPI 预定义全局数据运算符:MPI_MAX /

69、 MPI_MIN; MPI_SUM 求和 MPI_PROD 求积MPI_LAND 逻辑与 MPI_LOR 逻辑或 MPI_MAXLOC/MPI_MINLOC 最大/小值求下相应位置 九月 24MPI并行程序设计96/217intp,myrank;floatbuf;MPI_Commcomm;MPI_Init(&argc,&argv);/*得进程编号得进程编号*/MPI_Comm_rank(comm,&my_rank);/*得进程总数得进程总数*/MPI_Comm_size(comm,&p);if(myrank=0)buf=1.0;MPI_Bcast(&buf,1,MPI_FLOAT,0,comm

70、);Broadcast - 数据广播databuf.MPI_Bcast();.data.MPI_Bcast();.data.MPI_Bcast();.Process 0myrank = 0Process 1myrank = 1Process p-1myrank = p-1int MPI_Bcast ( int MPI_Bcast ( void *buffer,/* void *buffer,/*发送发送/ /接收接收buf*/buf*/ int count, int count,/* /*元素个数元素个数* */ / MPI_Datatype datatype, MPI_Datatype da

71、tatype, int root,int root,/* /*指定根进程指定根进程* */ / MPI_Comm comm) MPI_Comm comm) 根进程既是发送缓冲区也是接收缓冲区根进程既是发送缓冲区也是接收缓冲区九月 24MPI并行程序设计97/217Gather - 数据收集intp,myrank;floatdata10;/*分布变量分布变量*/float*buf;MPI_Commcomm;MPI_Init(&argc,&argv);/*得进程编号得进程编号*/MPI_Comm_rank(comm,&my_rank);/*得进程总数得进程总数*/MPI_Comm_size(com

72、m,&p);if(myrank=0)buf=(float*)malloc(p*10*sizeof(float);/*开辟接收缓冲区开辟接收缓冲区*/MPI_Gather(data,10,MPI_FLOAT,buf,10,MPI_FlOAT,0,comm);data.MPI_Gather();.data.MPI_Gather();.data.MPI_Gather();.Process 0myrank = 0Process 1myrank = 1Process p-1myrank = p-1根进程接收其他进程来的消息根进程接收其他进程来的消息( (包括根进程包括根进程), ),按每在进程按每在进程

73、在通信组中的编号在通信组中的编号依次联接在一依次联接在一下下, ,存放在根进程的接收缓冲区中存放在根进程的接收缓冲区中. .int MPI_Gather ( void *sendbuf, int sendcnt, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm ) buf九月 24MPI并行程序设计98/217Scatter - 数据分散intp,myrank;floatdata10;float*buf;MPI_Commcomm;MPI_Ini

74、t(&argc,&argv);/*得进程编号得进程编号*/MPI_Comm_rank(comm,&my_rank);/*得进程总数得进程总数*/MPI_Comm_size(comm,&p);if(myrank=0)buf=(float*)malloc(p*10*sizeof(float);/*开辟开辟发送发送缓冲区缓冲区*/MPI_Scatter(buf,10,MPI_FLOAT,data,10,MPI_FlOAT,0,comm);data.MPI_Scatter();.data.MPI_ Scatter();.data.MPI_ Scatter();.Process 0myrank = 0P

75、rocess 1myrank = 1Process p-1myrank = p-1根进程中存储了根进程中存储了p p个消息个消息, ,第第i i个消息将传给第个消息将传给第i i个进程个进程. .int MPI_Scatter ( void *sendbuf, int sendcnt, MPI_Datatype sendtype, void *recvbuf, int recvcnt, MPI_Datatype recvtype, int root, MPI_Comm comm ) buf九月 24MPI并行程序设计99/217Reduce - 全局数据运算intp,myrank;floatd

76、ata=0.0;floatbuf;MPI_Commcomm;MPI_Init(&argc,&argv);/*得进程编号得进程编号*/MPI_Comm_rank(comm,&my_rank);/*各进程对各进程对data进行不同的操作进行不同的操作*/data=data+myrank*10;/*将各进程中的将各进程中的data数相加并存入根进数相加并存入根进程的程的buf中中*/MPI_Reduce(&data,&buf,1,MPI_FLOAT,MPI_SUM,0,comm);data.MPI_Scatter();.data.MPI_ Scatter();.data.MPI_ Scatter()

77、;.Process 0myrank = 0Process 1myrank = 1Process p-1myrank = p-1对组中所有进程的发送缓冲区中的数据用OP参数指定的操作进行运算,并将结果送回到根进程的接收缓冲区中. int MPI_Reduce ( void *sendbuf, void *recvbuf, int count, MPI_Datatype datatype, MPI_Op op, int root, MPI_Comm comm )buf+九月 24MPI并行程序设计100/217集合通信的应用p0p1p2p3p0p1p2p3p0p1p2p3向量按行存储集合通信在向量

78、-矩阵乘中的应用k=m/p九月 24MPI并行程序设计101/217后缀V:更灵活的集合通信带后缀带后缀V的集合通信操作是一种更为灵活的集合的集合通信操作是一种更为灵活的集合通信操作通信操作通信中元素块的大小可以变化发送与接收时的数据位置可以不连续九月 24MPI并行程序设计102/217MPI_Gatherint MPI_Gather ( void *sendbuf, int sendcnt, MPI_Datatype sendtype, void *recvbuf, int recvcount, MPI_Datatype recvtype, int root, MPI_Comm comm

79、) 参数:sendbuf发送缓冲区起始位置 sendcount发送元素个数sendtype发送数据类型recvcount接收元素个数接收元素个数(所有进程相同所有进程相同) (该参数仅对根进程有效)recvtype接收数据类型(仅在根进程中有效)root通过rank值指明接收进程comm通信空间通信空间九月 24MPI并行程序设计103/217MPI_Gathervint MPI_Gatherv ( void *sendbuf, int sendcnt, MPI_Datatype sendtype, void *recvbuf, int *recvcnts, int *displs, MPI_

80、Datatype recvtype, int root, MPI_Comm comm ) 参数:sendbuf 发送缓冲区的起始位置sendcount 发送元素个数sendtype 发送数据类型recvcounts 整型数组(大小等于组的大小),用于指明从各进程要接收的元素的个数(仅对根进程有效) displs 整型数组(大小等于组的大小). 其元素 i指明要接收元素存放位置相对于接收缓冲区起始位置的偏移量 (仅在根进程中有效)recvtype 接收数据类型root 通过rank值指明接收进程comm 通信空间九月 24MPI并行程序设计104/217Gather与GatherV应用Vecto

81、r派生数据类型GatherGatherVGatherV九月 24MPI并行程序设计105/217Scatter与ScatterVScatterScatterVScatterV应用Vector派生数据类型九月 24MPI并行程序设计106/217注意事项组内所有进程都参与才能完成各进程的调用形式都相同常见问题有的调用,有的不调用(主进程广播,从进程没有广播)广播语句和接收语句对应调用参数不对(若使用一对多或者多对一通信,则各个进程所使用的ROOT值必须都是相同的)九月 24MPI并行程序设计107/217讲座内容提示基本的MPI基本概念点到点通信(Point to point)MPI中API的主

82、要内容,为MPI最基本,最重要的内容MPI程序的编译和运行深入MPI用户自定义(/派生)数据类型(User-defined(Derived) data type)事实上MPI的所有数据类型均为MPI自定义类型支持异构系统允许消息来自不连续的或类型不一致的存储区(结构,数组散元)集合通信(Collective)数据移动,数据聚集,同步基于point to point 构建MPI环境管理函数组,上下文和通信空间/通信子的管理实例九月 24MPI并行程序设计108/217MPI环境管理MPI起动与结束:MPI_Init();MPI_Initialized();测试是否已执行MPI_Init();MP

83、I_Finalize();MPI计时函数double MPI_Wtime();返回自过去某一时刻调用时的时间间隔,以秒为单位.double MPI_Wtick();返回用作硬件计时的两次脉冲间的间隔时间,以秒为单位. 组,上下文和通信空间管理.九月 24MPI并行程序设计109/217通信域通信域:描述进程间的通信关系,包括通信上下文:区别不同的通信域,一个上下文所发送的消息不能被另一个上下文所接收进程组:多个进程的有序集合虚拟拓扑:多个进程在逻辑上的排列关系,反映了进程间的通信模型属性:用户可通过自定义的属性,将任意信息附加到通信域上九月 24MPI并行程序设计110/217预定义的进程组和

84、通信域MPI_GROUP_NULL无效进程组句柄MPI_COMM_NULL无效通信域句柄MPI_GROUP_EMPTY有效进程组句柄,包括元素个数为0MPI_COMM_SELF有效通信域句柄,包括元素仅为当前进程MPI_COMM_WORLD有效通信域句柄,包括元素为所有进程九月 24MPI并行程序设计111/217进程组不同的进程可以有不同的分工,可为之建立不同的通信域,这要借助进程组完成。得到通信域对应的进程组:MPI_COMM_GROUP(comm,group)根据组创建新的通信域:MPI_COMM_CREATE(comm,g,ncomm)九月 24MPI并行程序设计112/217进程组操

85、作比较:MPI_GROUP_COMPARE(g1,g2,result)并: MPI_GROUP_UNION(g1,g2,newg)交:MPI_GROUP_INTERSECTION(g1,g2,newg)差:MPI_GROUP_DIFFERENCE(g1,g2,newg)九月 24MPI并行程序设计113/217所包含的进程形成新组:MPI_GROUP_INCL(g,n,ranks,newg)去除掉进程后形成新组:MPI_GROUP_EXCL(g,n,ranks,newg)得到组的大小 MPI_GROUP_SIZE(group,size)得到当前进程在组中的编号MPI_GROUP_RANK(gr

86、oup,rank)九月 24MPI并行程序设计114/217进程组的例子九月 24MPI并行程序设计115/217通信域比较MPI_COMM_COMPARE(comm1,comm2,result)复制MPI_COMM_DUP(comm,newcomm)释放MPI_COMM_FREE(comm)九月 24MPI并行程序设计116/217通信域的分裂MPI_COMM_SPLIT(comm,color,key,newcomm)根据color值的不同,形成不同的通信域根据key值的大小,决定新通信域中的编号顺序九月 24MPI并行程序设计117/217通信域分裂的例子九月 24MPI并行程序设计118

87、/217虚拟拓扑在许多并行应用程序中,进程的线性排列不能充分地反映进程间的通信模型进程经常被排列成二维或三维网格形式的拓扑模型,而且通常用一个图来描述逻辑进程排列不同的进程拓扑结构,可使程序设计更为自然,也为在相近的物理拓扑上的高效实现提供支持。九月 24MPI并行程序设计119/217图拓扑节点表示进程边表示进程之间的通信可以表示所有类型的通信九月 24MPI并行程序设计120/217笛卡尔拓扑使用环、网格等进程拓扑时,笛卡尔坐标更为方便查看topo类型九月 24MPI并行程序设计121/217Status:MPI_GRAPH、MPI_CART、MPI_UNDEFINED九月 24MPI并行

88、程序设计122/217创建笛卡儿拓扑2*7九月 24MPI并行程序设计123/217调用MPI_COMM_WORLD,2,4,5,false,false,false,newcomm九月 24MPI并行程序设计124/217得到每一维的大小MPI_DIMS_CREATE(nnodes, ndims,dims)根据用户指定的总进程数nnodes和总维数ndims,得到每一维上的进程个数,放在dims中(20,2,4,5) 九月 24MPI并行程序设计125/217得到卡氏坐标MPI_CART_COORDS(comm, rank, maxdims, coords) 得到rank值对应的笛卡尔坐标九月

89、 24MPI并行程序设计126/217平移操作MPI_CART_SHIFT(comm, direction, disp, rank_source, rank_dest)哪一维哪一维 偏移偏移rank_source偏移后得到当前进程当前进程偏移后得到rank_dest向右偏移向右偏移3 3当前进程当前进程九月 24MPI并行程序设计127/217例子九月 24MPI并行程序设计128/217例子(续)九月 24MPI并行程序设计129/217创建图拓扑九月 24MPI并行程序设计130/217九月 24MPI并行程序设计131/217得到相邻进程数得到与指定进程rank相邻的进程总数nneigh

90、bors九月 24MPI并行程序设计132/217得到相邻进程标识得到与指定进程rank相邻的进程标识neighbors九月 24MPI并行程序设计133/217讲座内容提示基本的MPI基本概念点到点通信(Point to point)MPI中API的主要内容,为MPI最基本,最重要的内容MPI程序的编译和运行深入MPI用户自定义(/派生)数据类型(User-defined(Derived) data type)事实上MPI的所有数据类型均为MPI自定义类型支持异构系统允许消息来自不连续的或类型不一致的存储区(结构,数组散元)集合通信(Collective)数据移动,数据聚集,同步基于poin

91、t to point 构建MPI环境管理函数组,上下文和通信空间/通信子的管理实例九月 24MPI并行程序设计134/217实例分析求PI向量点积矩阵向量相乘Jacobi迭代并行拉格朗日元算法九月 24MPI并行程序设计135/217实例分析:求PI九月 24MPI并行程序设计136/217串行代码h=1.0/(double)n;sum=0.0;for (i=1; i=n; i+) x=h*(double)i 0.5);sum += f(x);pi=h*sum;double f(double a)return (4.0/(1.0+a*a);九月 24MPI并行程序设计137/217并行代码h=

92、1.0/(double)n;sum=0.0;for(i=myid+1;i=n;i+=numprocs)x=h*(double)i0.5);sum+=f(x);mypi=h*sum;MPI_Reduce(&mypi,&pi,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);double f(double a)return (4.0/(1.0+a*a);九月 24MPI并行程序设计138/217cpi.c#include mpi.h#include #include double f( double );double f( double a ) return (4.0

93、/ (1.0 + a*a);九月 24MPI并行程序设计139/217cpi.cintmain(intargc,char*argv)intdone=0,n,myid,numprocs,i;doublePI25DT=3.141592653589793238462643;doublemypi,pi,h,sum,x;doublestartwtime=0.0,endwtime;intnamelen;charprocessor_nameMPI_MAX_PROCESSOR_NAME;MPI_Init(&argc,&argv);MPI_Comm_size(MPI_COMM_WORLD,&numprocs);

94、MPI_Comm_rank(MPI_COMM_WORLD,&myid);MPI_Get_processor_name(processor_name,&namelen);fprintf(stderr,Process%don%sn,myid,processor_name);九月 24MPI并行程序设计140/=100;while(!done)if(myid=0)startwtime=MPI_Wtime();MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD); 九月 24MPI并行程序设计141/217cpi.cif(n=0)done=1;elseh=1.0/(doub

95、le)n;sum=0.0;for(i=myid+1;i=n;i+=numprocs)x=h*(double)i-0.5);sum+=f(x);mypi=h*sum; 九月 24MPI并行程序设计142/217cpi.cMPI_Reduce(&mypi,&pi,1,MPI_DOUBLE,MPI_SUM,0,MPI_COMM_WORLD);if(myid=0)printf(piisapproximately%.16f,Erroris%.16fn,pi,fabs(pi-PI25DT);endwtime=MPI_Wtime();printf(wallclocktime=%fn,endwtime-sta

96、rtwtime);MPI_Finalize();return0;九月 24MPI并行程序设计143/217代码导读main()pi:圆周率的计算结果mypi:每个进程的积分结果n:积分区间数量h:积分区间大小九月 24MPI并行程序设计144/217实例分析:点积运算p0p0p1p2九月 24MPI并行程序设计145/217Parallel_dot.c/* parallel_dot.c - compute a dot product of a * vector distributed among the processes. * Uses a block distribution of the

97、 vectors.* Input: * n: global order of vectors* x, y: the vectors* Output:* the dot product of x and y.* Note: Arrays containing vectors are statically allocated. Assumes* n, the global order of the vectors, is divisible by p, the number* of processes.*/九月 24MPI并行程序设计146/217#include #include mpi.h#d

98、efine MAX_LOCAL_ORDER 100main(int argc, char* argv) float local_xMAX_LOCAL_ORDER; float local_yMAX_LOCAL_ORDER; int n; int n_bar; /* = n/p */ float dot; int p; int my_rank; void Read_vector(char* prompt, float local_v, int n_bar, int p, int my_rank); float Parallel_dot(float local_x, float local_y,

99、int n_bar);九月 24MPI并行程序设计147/217 MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &p); MPI_Comm_rank(MPI_COMM_WORLD, &my_rank); if (my_rank = 0) printf(Enter the order of the vectorsn); scanf(%d, &n); MPI_Bcast(&n, 1, MPI_INT, 0, MPI_COMM_WORLD); n_bar = n/p; Read_vector(the first vector, local

100、_x, n_bar, p, my_rank); Read_vector(the second vector, local_y, n_bar, p, my_rank); dot = Parallel_dot(local_x, local_y, n_bar); if (my_rank = 0) printf(The dot product is %fn, dot); MPI_Finalize(); /* main */ 九月 24MPI并行程序设计148/217void Read_vector(char* prompt/* in */,float local_v/* out */,int n_ba

101、r/* in */,int p/* in */, int my_rank/* in */) int i, q; float tempMAX_LOCAL_ORDER; MPI_Status status; if (my_rank = 0) printf(Enter %sn, prompt); for (i = 0; i n_bar; i+) scanf(%f, &local_vi); for (q = 1; q p; q+) for (i = 0; i n_bar; i+) scanf(%f, &tempi); MPI_Send(temp, n_bar, MPI_FLOAT, q, 0, MPI

102、_COMM_WORLD); else MPI_Recv(local_v, n_bar, MPI_FLOAT, 0, 0, MPI_COMM_WORLD, &status); /* Read_vector */九月 24MPI并行程序设计149/217float Serial_dot( float x /* in */, float y /* in */, int n /* in */) int i; float sum = 0.0; for (i = 0; i n; i+) sum = sum + xi*yi; return sum; /* Serial_dot */九月 24MPI并行程序设

103、计150/217float Parallel_dot( float local_x /* in */, float local_y /* in */, int n_bar /* in */) float local_dot; float dot = 0.0; float Serial_dot(float x, float y, int m); local_dot = Serial_dot(local_x, local_y, n_bar); MPI_Reduce(&local_dot, &dot, 1, MPI_FLOAT, MPI_SUM, 0, MPI_COMM_WORLD); return

104、 dot; /* Parallel_dot */九月 24MPI并行程序设计151/217代码导读main()local_x / local_y:本地计算的矢量分量n:矢量的全局阶数n_bar:本地计算的分量阶数dot:点积结果Read_vector()temp:每个进程计算的矢量分量Serial_dot()Parallel_dot()local_dot:本地的计算结果九月 24MPI并行程序设计152/217实例分析:矩阵向量相乘p0p1p2九月 24MPI并行程序设计153/217parallel_mat_vect.c#include#includempi.h#defineMAX_ORDE

105、R100typedeffloatLOCAL_MATRIX_TMAX_ORDERMAX_ORDER;main(intargc,char*argv)intmy_rank;intp;LOCAL_MATRIX_Tlocal_A;floatglobal_xMAX_ORDER;floatlocal_xMAX_ORDER;floatlocal_yMAX_ORDER;intm,n;intlocal_m,local_n;九月 24MPI并行程序设计154/217voidRead_matrix(char*prompt,LOCAL_MATRIX_Tlocal_A,intlocal_m,intn,intmy_rank

106、,intp);voidRead_vector(char*prompt,floatlocal_x,intlocal_n,intmy_rank,intp);voidParallel_matrix_vector_prod(LOCAL_MATRIX_Tlocal_A,intm,intn,floatlocal_x,floatglobal_x,floatlocal_y,intlocal_m,intlocal_n);voidPrint_matrix(char*title,LOCAL_MATRIX_Tlocal_A,intlocal_m,intn,intmy_rank,intp);voidPrint_vect

107、or(char*title,floatlocal_y,intlocal_m,intmy_rank,intp);MPI_Init(&argc,&argv);MPI_Comm_size(MPI_COMM_WORLD,&p);MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);if(my_rank=0)printf(Entertheorderofthematrix(mxn)n);scanf(%d%d,&m,&n);MPI_Bcast(&m,1,MPI_INT,0,MPI_COMM_WORLD);MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD)

108、;九月 24MPI并行程序设计155/217local_m=m/p;local_n=n/p;Read_matrix(Enterthematrix,local_A,local_m,n,my_rank,p);Print_matrix(Weread,local_A,local_m,n,my_rank,p);Read_vector(Enterthevector,local_x,local_n,my_rank,p);Print_vector(Weread,local_x,local_n,my_rank,p);Parallel_matrix_vector_prod(local_A,m,n,local_x,

109、global_x,local_y,local_m,local_n);Print_vector(Theproductis,local_y,local_m,my_rank,p);MPI_Finalize();/*main*/九月 24MPI并行程序设计156/217voidRead_matrix(char*prompt/*in*/,LOCAL_MATRIX_Tlocal_A/*out*/,intlocal_m/*in*/,intn/*in*/,intmy_rank/*in*/,intp/*in*/)inti,j;LOCAL_MATRIX_Ttemp;/*Filldummyentriesintemp

110、withzeroes*/for(i=0;ip*local_m;i+)for(j=n;jMAX_ORDER;j+)tempij=0.0;if(my_rank=0)printf(%sn,prompt);for(i=0;ip*local_m;i+)for(j=0;jn;j+)scanf(%f,&tempij);MPI_Scatter(temp,local_m*MAX_ORDER,MPI_FLOAT,local_A,local_m*MAX_ORDER,MPI_FLOAT,0,MPI_COMM_WORLD);/*Read_matrix*/九月 24MPI并行程序设计157/217voidRead_vec

111、tor(char*prompt/*in*/,floatlocal_x/*out*/,intlocal_n/*in*/,intmy_rank/*in*/,intp/*in*/)inti;floattempMAX_ORDER;if(my_rank=0)printf(%sn,prompt);for(i=0;ip*local_n;i+)scanf(%f,&tempi);MPI_Scatter(temp,local_n,MPI_FLOAT,local_x,local_n,MPI_FLOAT,0,MPI_COMM_WORLD);/*Read_vector*/九月 24MPI并行程序设计158/217/*A

112、llarraysareallocatedincallingprogram*/*Notethatargumentmisunused*/voidParallel_matrix_vector_prod(LOCAL_MATRIX_Tlocal_A/*in*/,intm/*in*/,intn/*in*/,floatlocal_x/*in*/,floatglobal_x/*in*/,floatlocal_y/*out*/,intlocal_m/*in*/,intlocal_n/*in*/)/*local_m=m/p,local_n=n/p*/inti,j;MPI_Allgather(local_x,loc

113、al_n,MPI_FLOAT,global_x,local_n,MPI_FLOAT,MPI_COMM_WORLD);for(i=0;ilocal_m;i+)local_yi=0.0;for(j=0;jn;j+)local_yi=local_yi+local_Aij*global_xj;/*Parallel_matrix_vector_prod*/九月 24MPI并行程序设计159/217voidPrint_matrix(char*title/*in*/,LOCAL_MATRIX_Tlocal_A/*in*/,intlocal_m/*in*/,intn/*in*/,intmy_rank/*in*

114、/,intp/*in*/)inti,j;floattempMAX_ORDERMAX_ORDER;MPI_Gather(local_A,local_m*MAX_ORDER,MPI_FLOAT,temp,local_m*MAX_ORDER,MPI_FLOAT,0,MPI_COMM_WORLD);if(my_rank=0)printf(%sn,title);for(i=0;ip*local_m;i+)for(j=0;jn;j+)printf(%4.1f,tempij);printf(n);/*Print_matrix*/九月 24MPI并行程序设计160/217voidPrint_vector(ch

115、ar*title/*in*/,floatlocal_y/*in*/,intlocal_m/*in*/,intmy_rank/*in*/,intp/*in*/)inti;floattempMAX_ORDER;MPI_Gather(local_y,local_m,MPI_FLOAT,temp,local_m,MPI_FLOAT,0,MPI_COMM_WORLD);if(my_rank=0)printf(%sn,title);for(i=0;ip*local_m;i+)printf(%4.1f,tempi);printf(n);/*Print_vector*/九月 24MPI并行程序设计161/21

116、7代码导读main()local_A:本地矩阵global_x:全局矢量local_x:本地输入矢量local_y:本地结果矢量Read_matrix()temp:全局矩阵Read_vector()temp:全局输入矢量Parallel_matrix_vector_prod()Print_matrix()Print_vector()九月 24MPI并行程序设计162/217实例分析:Jacobi迭代最基本的Jacobi迭代SENDRECV实现引入MPI_PROC_NULL定义数据类型定义进程拓扑拉普拉斯方程九月 24MPI并行程序设计163/217求解拉普拉斯方程是电磁学、天文学和流体力学等领

117、域经常遇到的一类重要的数学问题,因为这种方程以势函数的形式描写了电场、引力场和流场等物理对象(一般统称为“保守场”或“有势场”)的性质。Jacobi迭代九月 24MPI并行程序设计164/217九月 24MPI并行程序设计165/217基本含义上下左右相加取平均使用旧值九月 24MPI并行程序设计166/217数据划分按行划分处理器个数九月 24MPI并行程序设计167/217各个进程空间的声明 上下都多一行大小(N,N/NP),假设正好整除九月 24MPI并行程序设计168/217任取一个进程的执行轨迹1 得到边界数据2 循环计算新值3 更新旧值九月 24MPI并行程序设计169/217应该

118、采取的模式1 接收边界数据同时提供边界数据2 循环计算得到新值3 更新旧值九月 24MPI并行程序设计170/217具体的例子数组大小100100处理器个数4九月 24MPI并行程序设计171/217局部数组大小100/425,划分后的行25100,本地数组大小27100,加上边界后数组的大小九月 24MPI并行程序设计172/217通信得到或者发出边界数据向上平移,上面的进程接收,下面的进程发送九月 24MPI并行程序设计173/217平移前后的对比平移前 平移后九月 24MPI并行程序设计174/217通信语句if (不是最下一个) 从下面接收边界数据MPI_RECVif (不是最上面一个

119、),向上面发送边界数据 MPI_SEND九月 24MPI并行程序设计175/217通信得到或者发出边界数据向下平移,上面的发送,下面的接收九月 24MPI并行程序设计176/217平移前后的对比平移前 平移后九月 24MPI并行程序设计177/217通信语句if (不是最上面一个) 从上面接收边界数据MPI_RECVif (不是最下面一个),向下面发送边界数据 MPI_SEND九月 24MPI并行程序设计178/217计算部分循环从第?行开始,到倒数第?行结束执行迭代过程更新数组九月 24MPI并行程序设计179/217程序#include mpi.h#define arysize 100#d

120、efine myarysize arysize/4int main(int argc, char *argv) int n, myid, numprocs, i, j, nsteps=10; float amyarysize+2arysize,bmyarysize+2arysize; int begin_row,end_row; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&myid);九月 24MPI并行程序设计180/217 begin_row=1; end_row=myarysize; if

121、 (myid = 0) begin_row=2; if (myid = 3) end_row=myarysize-1; for (n=0; nnsteps; n+) if (myid0) MPI_Send(&a10,100,MPI_FLOAT,myid-1,1000,MPI_COMM_WORLD); MPI_Recv(&a00,100,MPI_FLOAT,myid-1,1000,MPI_COMM_WORLD,&status); 九月 24MPI并行程序设计181/217 for (i=begin_row;i=end_row;i+ ) for ( j=1;jarysize-1;j+) bij =

122、 (aij+1+aij-1+ai-1j+ai+1j)*0.25; for (i=begin_row;i=end_row;i+ ) for ( j=1;jarysize-1;j+) aij = bij; MPI_Finalize();九月 24MPI并行程序设计182/217问题123456容易产生死锁九月 24MPI并行程序设计183/217办法采用MPI_SENDRECV语句和MPI_PROCE_NULL九月 24MPI并行程序设计184/217用SENDRECV来重写#include mpi.h#define arysize 100#define myarysize arysize/4in

123、t main(int argc, char *argv) int n,myid, numprocs, i, j, nsteps=10; int up,down; float amyarysize+2arysize,bmyarysize+2arysize; int begin_row,end_row; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&myid); 九月 24MPI并行程序设计185/217 begin_row=1; end_row=myarysize; up=myid-1; if (u

124、p3) down=MPI_PROC_NULL; if (myid = 0) begin_row=2; if (myid = 3) end_row=myarysize-1; for (n=0; nnsteps; n+) MPI_Sendrecv(&a10,100,MPI_FLOAT,up,1000,&amyarysize+10,100,MPI_FLOAT,down,1000,MPI_COMM_WORLD,&status); MPI_Sendrecv(&amyarysize0,100,MPI_FLOAT,down,1000,&a00,100,MPI_FLOAT,up,1000,MPI_COMM_W

125、ORLD,&status);九月 24MPI并行程序设计186/217 for (i=begin_row;i=end_row;i+ ) for ( j=1;jarysize-1;j+) bij = (aij+1+aij-1+ai-1j+ai+1j)*0.25; for (i=begin_row;i=end_row;i+ ) for ( j=1;jarysize-1;j+) aij = bij; MPI_Finalize();九月 24MPI并行程序设计187/217定义新的数据类型定义一行MPI_CONTIGUOUS九月 24MPI并行程序设计188/217程序#include mpi.h#d

126、efine arysize 100#define myarysize arysize/4int main(int argc, char *argv) int n,myid, numprocs, i, j, nsteps=10; int up,down; float amyarysize+2arysize,bmyarysize+2arysize; int begin_row,end_row; MPI_Datatype onerow; MPI_Status status; MPI_Init(&argc,&argv); MPI_Comm_rank(MPI_COMM_WORLD,&myid); MPI

127、_Type_contiguous(100,MPI_FLOAT,&onerow);九月 24MPI并行程序设计189/217 MPI_Type_commit( &onerow ); begin_row=1; end_row=myarysize; up=myid-1; if (up3) down=MPI_PROC_NULL; if (myid = 0) begin_row=2; if (myid = 3) end_row=myarysize-1; for (n=0; nnsteps; n+) MPI_Sendrecv(&a10,1,onerow,up,1000,&amyarysize+10,1,o

128、nerow,down,1000,MPI_COMM_WORLD,&status); MPI_Sendrecv(&amyarysize0,1,onerow,down,1000,&a00,1,onerow,up,1000,MPI_COMM_WORLD,&status);九月 24MPI并行程序设计190/217 for (i=begin_row;i=end_row;i+ ) for ( j=1;jarysize-1;j+) bij = (aij+1+aij-1+ai-1j+ai+1j)*0.25; for (i=begin_row;i=end_row;i+ ) for ( j=1;jarysize-

129、1;j+) aij = bij; MPI_Type_free( &onerow ); MPI_Finalize(); 九月 24MPI并行程序设计191/217定义虚拟进程拓扑块状分布九月 24MPI并行程序设计192/217#include mpi.h#define arysize 256#define arysize2 (arysize/2)int main(int argc, char *argv) int n, myid, numprocs, i, j, nsteps=10; float aarysize2+1arysize2+1,barysize2+1arysize2+1; doub

130、le starttime,endtime; /* float send_bufarysize2,recv_bufarysize2 ;*/ int col_tag,row_tag,send_col,send_row,recv_col,recv_row; int col_neighbor,row_neighbor; MPI_Comm comm2d; MPI_Datatype newtype; int zero=0,one=1; int right,left,down,top,top_bound,left_bound;九月 24MPI并行程序设计193/217 int periods2; int d

131、ims2,begin_row,end_row; MPI_Status status; MPI_Init(&argc,&argv); dims0 = 2; dims1 = 2; periods0=0; periods1=0; MPI_Cart_create( MPI_COMM_WORLD, 2, dims, periods, 0,&comm2d); MPI_Comm_rank(comm2d,&myid); MPI_Type_vector( arysize2, 1, arysize2+1,MPI_FLOAT,&newtype); MPI_Type_commit( &newtype ); MPI_C

132、art_shift( comm2d, 0, 1, &left, &right); MPI_Cart_shift( comm2d, 1, 1, &down, &top);九月 24MPI并行程序设计194/217 for(i=0;iarysize2+1;i+) for(j=0;jarysize2+1;j+) aij=0.0; if (top = MPI_PROC_NULL) for ( i=0;iarysize2+1;i+) a0i=8.0; if (down = MPI_PROC_NULL) for ( i=0;iarysize2+1;i+) aarysize2i=8.0; 九月 24MPI并

133、行程序设计195/217 if (left = MPI_PROC_NULL) for ( i=0;iarysize2+1;i+) ai0=8.0; if (right = MPI_PROC_NULL) for ( i=0;iarysize2+1;i+) aiarysize2=8.0; col_tag = 5; row_tag = 6; printf(Laplace Jacobi#C(BLOCK,BLOCK)#myid=%d#step=%d#total arysize=%d*%dn,myid,nsteps,arysize,arysize); 九月 24MPI并行程序设计196/217 top_b

134、ound=1; left_bound=1; if (top = MPI_PROC_NULL) top_bound=0; if (left = MPI_PROC_NULL) left_bound=0; starttime=MPI_Wtime(); for (n=0; nnsteps; n+) MPI_Sendrecv( &a1left_bound, arysize2, MPI_FLOAT, top, row_tag,& aarysize2left_bound, arysize2, MPI_FLOAT, down, row_tag, comm2d, &status ); MPI_Sendrecv(

135、 &aarysize2-1left_bound, arysize2, MPI_FLOAT, down, row_tag,& a0left_bound, arysize2, MPI_FLOAT, top, row_tag, comm2d, &status );九月 24MPI并行程序设计197/217 MPI_Sendrecv( &atop_bound1, 1,newtype, left, col_tag,& atop_boundarysize2, 1, newtype, right, col_tag, comm2d, &status ); MPI_Sendrecv( &atop_boundar

136、ysize2-1, 1, newtype, right, col_tag, &atop_bound0, 1, newtype, left, col_tag, comm2d, &status ); for ( i=1;iarysize2;i+) for (j=1;jarysize2;j+) bij = (aij+1+aij-1)*0.25; for ( i=1;iarysize2;i+) for (j=1;jarysize2;j+) bij = (ai+1j+ai-1j)*0.25+bij; for ( i=1;iarysize2;i+) for (j=1;jarysize2;j+) aij =

137、 bij; 九月 24MPI并行程序设计198/217 endtime=MPI_Wtime(); printf(elapse time=%fn,endtime-starttime); MPI_Type_free( &newtype ); MPI_Comm_free( &comm2d ); MPI_Finalize();并行拉格朗日元算法九月 24MPI并行程序设计200/217串行拉格朗日元法原理(1)拉格朗日元法的主要特点是:它是一种显式解法。显式解法容易处理非线性和大变形问题,而且当结构出现破坏时,数值上也比较容易处理。它不形成整体刚度矩阵。一方面节省了存储空间,相同条件下,能计算更大规模

138、的问题。另一方面,由于不必进行矩阵求逆的运算,在算法上更容易处理。它采用动态松弛法来求解静力问题。九月 24MPI并行程序设计201/217串行拉格朗日元法原理(2)基本方程几何方程:对于给定的速度场vi,则应变率张量ij为 转动率张量ij为 九月 24MPI并行程序设计202/217串行拉格朗日元法原理(3)本构方程 式中 ij表示Jaumann应力速率张量,Hij表示一个应力应变关系函数,k为考虑加载过程的参数。 九月 24MPI并行程序设计203/217串行拉格朗日元法原理(4)运动方程:对于给定的应力场ij,材料密度,单位质量所受体积力bi,则满足 九月 24MPI并行程序设计204/

139、217串行拉格朗日元法原理(5)空间离散四面体六面体三角形四边形九月 24MPI并行程序设计205/217串行拉格朗日元法原理(6)空间导数的近似采用不规则网格上的差分法对于一个给定的初始速度场vi,假定四面体单元内vi为线性分布,则vi在j方向的导数vi,j是一个常量,外表面的单位法向向量nj在每个面上为常量,应用高斯公式可得到 九月 24MPI并行程序设计206/217串行拉格朗日元法原理(7)时间导数的近似中心差分法九月 24MPI并行程序设计207/217主程序流程图九月 24MPI并行程序设计208/217并行拉格朗日元法设计(1)对算法的并行性分析是否可以并行哪些部分可以并行机群硬

140、件的特点 进程的数据是私有的通信延时大数据如何存储、访问和交换九月 24MPI并行程序设计209/217并行拉格朗日元法设计(2)并行性分析在每一个时步的计算中,计算应变增量和应力是逐单元进行的,节点力和节点速度也是逐个进行计算。因此,拉格朗日元法并行化的基本策略是区域分解法,即把整个计算区域划分为几个子区域,分配给不同的进程进行计算。九月 24MPI并行程序设计210/217并行拉格朗日元法设计(3)网格划分和数据通信密切相关。 单元划分和节点划分九月 24MPI并行程序设计211/217并行拉格朗日元法设计(4)网格划分工具METIS 由G. Karypis和V. Kumar开发 多级k划

141、分(Multilevel k-way Partition)算法 九月 24MPI并行程序设计212/217并行拉格朗日元法设计(5)共享优先算法共享优先算法共享优先算法共享优先算法计算与通信的重叠通信比较耗时,尤其网络性能比较差的时候希望在等待通信完成的同时,能进行一些计算工作共享优先算法先共享节点,后内部节点先共享单元,后内部单元九月 24MPI并行程序设计213/217并行拉格朗日元法设计(6)通信模式主从(Master and Slave)模式和对等(Peer to Peer)模式九月 24MPI并行程序设计214/217九月 24MPI并行程序设计215/217网格1在8个计算结点上的划分 九月 24MPI并行程序设计216/217九月 24MPI并行程序设计217/217并行效率并行效率九月 24MPI并行程序设计218/217并行程序设计的一些建议优化并行算法大并行粒度顾及负载平衡尽量减少通信次数避免大消息(1M)避免消息缓冲区的溢出,且效率较低避免大消息打包内存拷贝开销大九月 24MPI并行程序设计219/217谢谢!

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 医学/心理学 > 基础医学

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号