《MPI并行程序设计.ppt》由会员分享,可在线阅读,更多相关《MPI并行程序设计.ppt(80页珍藏版)》请在优知文库上搜索。
1、消息传递并行程序设计消息传递并行程序设计:指用户必须通过显式地发送和接收消息来实现处理机间的数据交换。在这种并行编程中,每个并行进程均有自己独立的地址空间,相互之间访问不能直接进行,必须通过显式的消息传递来实现。这种编程方式是大规模并行处理机(MPP)和机群(Cluster)采用的主要编程方式。消息传递并行程序设计并行计算粒度大,特别适合于大规模可扩展并行算法:由于消息传递程序设计要求用户很好地分解问题,组织不同进程间的数据交换,并行计算粒度大,特别适合于大规模可扩展并行算法。消息传递是当前并行计算领域的一个非常重要的并行程序设计方式。什么是MPI?MPI(Massage Passing In
2、terface):是消息传递函数库的标准规范,由MPI论坛开发,支持Fortran和C。 一种新的库描述,不是一种语言。共有上百个函数调用接口,在Fortran和C语言中可以直接对这些函数进行调用。从语法上,它遵守所有对库函数/过程的调用规则,与一般的函数/过程没有区别。MPI是一种标准或规范的代表,而不是特指某一个对它的具体实现。一个正确的MPI程序,可不加修改在所有的并行机上运行。MPI是一种消息传递编程模型,并成为这种编程模型的代表和事实上的标准。最终目标是服务于进程间通信。MPI的发展过程发展的两个阶段:MPI 1.1:1995 MPICH:是一种最重要的MPI实现,每当MPI推出新的
3、版本,就会有相应的MPICH的实现版本。由美国Argonne国家实验室和密西西比州立大学联合开学,具有更好的可移植性。MPI 1.22.0:动态进程,并行I/O,支持F90和C+。为什么要用MPI?优点高可移植性:MPI已在IBM PC机上、MS Windows上、所有主要的Unix工作站上和所有主流的并行机上得到实现。使用MPI作消息传递的C或Fortran并行程序可不加改变地运行在IBM PC、MS Windows、Unix工作站、以及各种并行机上。消息传递方式是广泛应用于多类并行机的一种模式,特别是分布存储并行机。这种模式在一些重要的计算应用中已取得了实质性进步。为什么要用MPI?优点M
4、PI是被正式的详细说明的:它已经成为一个标准。消息传递标准的定义能提供给生产商清晰定义的程序库,以便他们能有效地实现这些库或在某些情况下为库程序提供硬件支持,因此加强了扩展性。MPI有完备的异步通信:使得send,receive能与计算重叠。可以有效的在MPP上或Cluster上用MPI编程。MPI+C 实现的“Hello World!”#include #include mpi.h main( int argc, char *argv ) MPI_Init( &argc, &argv ); printf( Hello, world!n ); MPI_Finalize();MPI+C实现的“H
5、ello World!”umpi.h是MPI标准规定的,每个MPI实现都要包含。它提供用户MPI程序需要的所有必要的原型和外部变量声明。MPI函数返回出错代码或MPI_SUCCESS成功标志。MPI-前缀,且只有MPI以及MPI_标志后的第一个字母大写,其余小写。uMPI函数的参数被标志为以下三种类型:IN:参数在例程的调用中不会被修正。OUT:参数在例程的调用中可能会被修正。INOUT:参数在一些例程中为IN,而在另一些例程中为OUT.MPI初始化-MPI_Initint MPI_Init(int *argc, char *argv)MPI_INIT(IERROR)MPI_Init是MPI程
6、序的第一个调用,它完成MPI程序的所有初始化工作。所有的MPI程序的第一条可执行语句都是这条语句。启动MPI环境,标志并行代码的开始。并行代码之前,第一个mpi函数(除MPI_Initialize()外)。要求main必须带参数运行,否则出错。MPI结束-MPI_Finalizeint MPI_Finalize(void)MPI_FINALIZE(IERROR)MPI_Finalize是MPI程序的最后一个调用,它结束MPI程序的运行,它是MPI程序的最后一条可执行语句,否则程序的运行结果是不可预知的。标志并行代码的结束,清理和关闭除主进程外的其它进程。之后串行代码仍可在主进程(rank =
7、0)上运行(如果必须)。MPI程序的的编译与运行u mpif77 hello.f 或 mpicc hello.c 默认生成a.out的可执行代码。u mpif77 o hello hello.f 或 mpicc o hello hello.c生成hello的可执行代码。u mpirun np 4 a.out mpirun np 4 hello4 指定np的实参,表示进程数,由用户指定。a.out / hello 要运行的MPI并行程序。输出文件命名Hello是如何被执行的?u SPMD: Single Program Multiple Data(SPMD)开始写MPI并行程序u在写MPI程序时
8、,我们常需要知道以下两个问题的答案:由由多少多少个进程来进行并行计算?个进程来进行并行计算?我是我是哪一个哪一个进程进程? ?两个函数uMPI 提供了下面两个函数来回答上述问题:用MPI_Comm_sizeMPI_Comm_size 获得进程个数 p int MPI_Comm_size(MPI_Comm comm, int *size);这一调用返回给定的通信域中所包含的进程的个数,不同的进程通过这一调用得知在给定的通信域中一共有多少个进程在并行执行。用MPI_Comm_rankMPI_Comm_rank 获得进程的一个叫rank的值,该 rank值为0到p-1间的整数,相当于进程的IDint
9、 MPI_Comm_rank(MPI_Comm comm, int *rank);这一调用返回调用进程在给定的通信域中的进程标识号,有了这个标识号,不同的进程就可以将自身和其它的进程区分开,实现进程的并行和协作。更新的“Hello World!”#include #include mpi.h int main(int argc, char *argv) int myid, numprocs; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &size); MPI_Comm_rank(MPI_COMM_WORLD, &rank); pr
10、intf(“Hello, World! I am %d of %d. /n, myid, numprocs); MPI_Finalize(); return 0;运行结果dairnode01 $ mpicc o hello1 hello1.cdairnode01 $ mpirun -np 4 hello1Hello, World! I am 0 of 4Hello, World! I am 1 of 4Hello, World! I am 2 of 4Hello, World! I am 3 of 4dairnode01 $计算机打印字符输入的命令通信字MPI_COMM_WORLDMPI_Co
11、mm_size和MPI_Comm_rank两个函数都用到了同一个参数MPI_COMM_WORLD。MPI_COMM_WORLD是一个预定的通信域(communicator),+ + 包括进程组和通信上下文,用于描述进程间的通信关系。+ + 进程组是进程的有限,有序集。+ 通信上下文如同系统设计的超级标签,用于安全地区别不同的通信,以免互相干扰。每个通信域的上下文都不同,一个上下文中的消息发送不能在另一个上下文中被接收,通信上下文不是显示的MPI对象,它们仅作为通信域实现的一部分出现。+ + 它在执行MPI_Initb函数后自动生成。MPI通信操作函数中必不可少的参数,用于限定参加通信的进程的范
12、围。函数MPI_Comm_size和MPI_Comm_rank查询MPI_COMM_WORLD以获得应用中MPI进程的总数并为这些MPI进程分别获得一个唯一的编号。获取的值放在变量size和rank。MPI程序的框架结构消息发送和接收MPI_SEND(buf, count, datatype, dest, tag, comm) IN buf 发送缓冲区的起始地址(可选类型) IN count 将发送的数据的个数(非负整数) IN datatype 发送数据的数据类型 IN dest 目的进程标识号rank(整型) IN tag 消息标签,用于识别不同的消息(整型) IN comm 通信域(句柄
13、)int MPI_Send(void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm) 一个消息好似一封信。需要定义消息的内容,还需要定义消息的发送者或接收者,前者(buf,count,datatype)称为消息缓冲,后者(dest,tag,comm)称为消息信封。说明MPI_Send将发送缓冲区中的count个datatype数据类型的数据发送到目的进程,目的进程在通信域的标识号是dest,本次发送的消息标志是tag,这一标志的目的是把本次发送的消息和本进程向同一目的进程发送的其他消息区别开来。
14、MPI_Send操作指定的发送缓冲区是由count个类型为datatype的连续数据空间组成,起始地址为buf。注意:不是以字节计数,而是以数据类型为单位指定消息的长度。其中datatype数据类型:MPI的预定义类型或用户自定义。通过使用不同的数据类型调用MPI_Send,可以发送不同类型的数据。消息发送和接收MPI_RECV(buf, count, datatype, source, tag, comm,status) OUT buf 接收缓冲区的起始地址(可选类型) IN count 最多可接收的数据的个数(非负整数) IN datatype 接收数据的数据类型 IN source 接收
15、数据的来源 即发送数据的进程的进程标识号(整型) IN tag 消息标志,与相应的发送操作的消息标识rank相匹配(整型) IN comm 本进程和发送进程所在的通信域(句柄) OUT status 返回状态,status对象,包含实际接收到的消息的有关信息int MPI_Recv(void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)说明MPI_Recv从指定的进程source接收消息,并且该消息的数据类型和接收进程指定的datatype和tag相
16、一致,接收到的消息所包含的数据元素的个数最多不能超过count。接收缓冲区是由count个类型为datatype的连续元素空间组成,起始地址为buf。接收到消息的长度被确定。如果大小缓冲区的长度会发生溢出;如果一个短于接收缓冲区的消息到达,那么只有相应于这个消息的那些地址被修改。count可以为零,此时消息的数据部分是空的。其中datatype数据类型:MPI的预定义类型或用户自定义。通过指定不同的数据类型调用MPI_Recv,可以发送不同类型的数据。返回状态status返回状态变量status用途很广,它是MPI定义的一个数据类型,使用之前需要用户为它分配空间。在C实现中,状态变量是由至少三个域组成的结构类型,这三个域分别是:MPI_SOURCE,MPI_TAG,MPI_ERROR。它还可以包括其他的附加域。通过对status.MPI_SOURCE,status.MPI_TAG和staus. MPI_ERROR的引用就可以得到返回状态中所包含的发送数据进程的标识、发送数据使用的tag标识和本接收操作返回的错误代码。除了以上三个信息之外,对status变量执行MPI_GET_COUNT