820 likes | 993 Views
MPI 分布内存并行 程序开发. 联想高性能服务器事业部. 目录. 第一章 并行计算概述 第二章 MPI 简介 第三章 MPI 编程. 目录. 第一章 并行计算概述. 第二章 MPI 简介 第三章 MPI 编程. 计算机的三种计算模型. 计算机的指令和进程与数据的关系:. 多机. 单机. 并行计算机数据存储方式:. 共享内存 ccNUMA (Cache Coherence Non Uniform Memory Access )
E N D
MPI分布内存并行 程序开发 联想高性能服务器事业部
目录 • 第一章 并行计算概述 • 第二章MPI简介 • 第三章 MPI编程
目录 • 第一章 并行计算概述 • 第二章MPI简介 • 第三章 MPI编程
计算机的指令和进程与数据的关系: 多机 单机
并行计算机数据存储方式: • 共享内存 • ccNUMA (Cache Coherence Non Uniform Memory Access ) 体系中各个处理器访问本节点内存与访问其它内存时所需时间的不一致性;同时由于所有的内存为处理器所共享,就必须保证各个处理器中相关缓存的一致性,单一系统镜像 • SMP (Symmetric Multi-Processing) 单一系统镜像 • 分布式内存 • MPP 大规模并行处理 • Cluster 非单一系统镜像,节点间CPU通过网络通信
为什麽要采用并行计算? • 串行程序局限考虑:串行程序速度提升缓慢 • 时间考虑,可以加快速度——更短的时间内解决相同的问题;相同的时间内解决更多更复杂的问题 • 空间考虑,可以加大规模——计算更大规模的问题
并行化分解方法 • 任务分解 • 多任务并发执行,面向多任务的,例如寻找外星人计划 • 功能分解 • 分解被执行的计算,面向大规模计算的,流体力学方程计算 • 区域分解 • 分解被执行的数据,面向大规模数据处理的,例如石油工业地震资料处理
并行程序设计语言实现方式 • 设计全新的并行语言 • 扩展原来的串行语言的语法成分,使他支持并行 • 不改变串行语言,仅为串行语言提供可调用的数学库
并行编程模型 • 数据并行编程模型:编程级别高,相对简单,仅适用于数据并行问题(OpenMP) • 消息传递编程模型:编程级别低,应用广泛,一般面向分布式内存。(MPI) 这两种编程方法可以混合使用.
目录 • 第一章 并行计算概述 • 第二章MPI简介 • 第三章 MPI编程
什么是MPI? • MPI (Message Passing Interface ) • 1994年5月发布的一种消息传递接口 • MPI是一个库,而不是一门语言 • MPI是一种标准或规范的代表 • MPI是一个消息传递编程模型 • MPI提供与C和Fortran语言的绑定
MPI的优点 • 较高的通信性能 • 较好的程序可移植性 • 通用性 • 易于掌握
MPI的历史 • MPI初稿:美国并行计算中心工作会议(92年4月) • MPI-1公布:第一届MPI大会(93年1月); • MPI标准正式发布:1994年5月; • MPI-2发布:MPI论坛(97年)。 MPI-2新功能:并行I/O;远程存储访问和动态进程管理
当前MPI的部分产品 • MPICH:最重要的MPI实现(www-unix.mcs.anl.gov/mpi/ mpich),与MPI-1规范同步发展的版本,支持部 分MPI-2的特征如动态生成进程等 • CHIMP:EPCC (Edinburgh Parallel Computing Center) 开发。 ftp://ftp.epcc.ed.ac.uk/pub/packages/chimp/release下载。 • LAM(Local Area Multicomputer):Ohio State University开发。 http://www.lam-mpi.org/download/下载。 • SCALI mpi :.由Scali Inc开发,经营,维护,升级.主要用于石油行业
MPI的编译和运行 • mpicc/mpiCC/mpif77/mpif90 -o hello hello.c 生成执行文件hello • mpirun -np n hello 加载n个进程运行,0号进程发送,1号进程接受并打印字符串
目录 • 第一章 并行计算概述 • 第二章MPI简介 • 第三章 MPI编程
MPI是个复杂的系统,它为程序员提供一个并行环境库,程序员通过调用MPI的库程序来达到程序员所要达到的并行目的,MPI提供C语言和Fortran语言接口,它包含了129个函数(根据1994年发布的MPI标准)。事实上,1997年修订的标准(MPI-2),已超过200多个,目前最常用的也有约30个。MPI是个复杂的系统,它为程序员提供一个并行环境库,程序员通过调用MPI的库程序来达到程序员所要达到的并行目的,MPI提供C语言和Fortran语言接口,它包含了129个函数(根据1994年发布的MPI标准)。事实上,1997年修订的标准(MPI-2),已超过200多个,目前最常用的也有约30个。 可以只使用其中的6个最基本的函数就能编写一个完整的MPI程序去求解很多问题。这6个基本函数,包括启动和结束MPI环境,识别进程以及发送和接收消息。
MPI_INIT: 启动MPI环境 • MPI_COMM_SIZE: 确定进程数 • MPI_COMM_RANK: 确定自己的进程标识符 • MPI_SEND: 发送一条消息 • MPI_RECV: 接收一条消息 • MPI_FINALIZE: 结束MPI环境
程序1、第一个FORTRAN77+MPI程序 program main include 'mpif.h' character * (MPI_MAX_PROCESSOR_NAME) processor_name integer myid,numprocs,namelen,rc,ierr call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr) call MPI_GET_PROCESSOR_NAME(processor_name,namelen,ierr) write (*,10) myid,numprocs,processor_name 10 FORMAT('Hello World! Process',I2,' of ',I1,' on ',20A) call MPI_FINALIZE(rc) end
程序1在一台机器上执行的结果: 程序1在四台机器上执行的结果:
程序2、 简单C+MPI的例子 (上面FORTRAN77+MPI程序改造) #include “mpi.h main(int argc, char **argv) { int numprocs,myrank,i,j,k; MPI_Status status; char msg[20]; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
程序2、 简单C+MPI的例子(cont.) if(myrank == 0) { strcpy(msg,”Hello World”); MPI_Send(msg,strlen(msg) + 1,MPI_CHAR,1,99, MPI_COMM_WORLD); } else if(myrank ==1) { MPI_Recv(msg,20,MPI_CHAR,0,99, MPI_COMM_WORLD,&status); printf(“Receive message = %s\n”,msg); } MPI_Finalize(); }
MPI程序的一般结构 包含MPI头文件 相关变量声明 初始化MPI环境 程序体计算与通信 退出MPI环境
头文件: • MPI程序要求:所有包含MPI调用的程序文件头应加入:
通信因子和组 • MPI通过指定通信因子和组来对进程进行一种逻辑上的划分,通讯因子定义了进程组内或组间通讯的上下文(具体就是指明通讯链路的数据结构指针)。 • 通信因子是在MPI环境初始化过程中创建
进程号(rank) • 在一个通信因子中,每个进程都有一个唯一的整数标识符,称作“进程ID”,进程号是从0开始的连续整数。 if (rank ==0) { 第0进程运行的程序段 } else if(rank == 1) { 第1进程运行的程序段 }
MPI消息结构 • MPI消息包括信封和数据两个部分,信封指出了发送或接收消息的对象及相关信息,而数据是本消息将要传递的内容。 • 数据:<起始地址,数据个数,数据类型> • 信封:<源/目,标识,通信域>
MPI_Send(buf,count,datatype,dest,tag,comm) 消息数据 消息信封 MPI_Recv(buf,count,datatype,source,tag,comm,status) 消息数据 消息信封
MPI的六个基本函数详细介绍 • MPI_Init • MPI_Comm_size • MPI_Comm_rank • MPI_Send • MPI_Recv • MPI_Finalize
MPI_Init() • MPI的初始化例行函数,用于初始化MPI运行环境。 • 必须调用;首先调用;调用一次。 • MPI_Init (*argc,*argv)。
MPI_Comm_size() • 该函数返回与该组通信因子相关的进程数,显然这里的通讯因子必须是组内通讯因子。 • MPI_Comm_size (comm,*size)
MPI_Comm_rank() • 该函数返回该进程在指定通信因子中的进程号(0 ~ 进程数-1),一个进程在不同通信因子中的进程号可能不同: • MPI_Comm_rank (comm,*rank)
MPI_Send() • 该函数将发送缓冲区中的count个datatype数据类型的数据发送到目的进程 • MPI_Send(buf,count,datatype,dest,tag,comm)
MPI_Recv() • 该函数从指定的进程source接收消息,并且该消息的数据类型和消息标识和本接收进程指定的数据类型和消息标识相一致,收到的消息所包含的数据元素的个数最多不能超过count. • MPI_Recv(buf,count,datatype,source,tag,comm,status)
MPI_Finalize() • 结束MPI执行环境。该函数一旦被应用程序调用时,就不能调用MPI的其它例行函数(包括MPI_Init),用户必须保证在进程调用MPI_Finalize之前把与完成进程有关的所有通信结束。 • MPI_Finalize ()
MPI函数的部分参数说明 • 缓冲区(buffer) • 数据个数(count) • 数据类型(type) • 目的地 (dest) • 源 (source) • 标识符(tag) • 通信因子(comm) • 状态(status)
缓冲区(buffer) • 指应用程序定义地用于发送或接收数据的消息缓冲区。
数据个数(count) • 指发送或接收指定数据类型的个数。
数据类型(type) • MPI定义了一些缺省的数据类型,用户也可以根据需要建立自己的数据类型
目的地 (dest) • 发送进程指定的接收该消息的目的进程,也就是接收进程的进程号(注意组间通讯的情况)。
源 (source) • 接收进程指定的发送该消息的源进程,也就是发送进程的进程号。如果该值为MPI_ANY_SOURCE表示接收任意源进程发来的消息。
标识符(tag) • 由程序员指定地为标识一个消息的唯一非负整数值(0-32767),发送操作和接收操作的标识符一定要匹配,但对于接收操作来说,如果tag指定为MPI_ANY_TAG则可与任何发送操作的tag相匹配。
通信因子(comm) • 包含源与目的进程的一组上下文相关的进程集合,除非用户自己定义(创建)了新的通信因子,否则一般使用系统预先定义的全局通信因子MPI_COMM_WORLD。
状态(status) • 对于接收操作,包含了接收消息的源进程(source)和消息的标识符(tag)。在FORTRAN程序中,这个参数是包含MPI_STATUS_SIZE个整数的数组,status(MPI_SOURCE)、status(MPI_TAG)和status(MPI_ERROR)分别表示数据的进程标识、发送数据使用tag 标识和接收操作返回的错误代码。 • 相当于一种在接受方对消息的监测机制,并且以其为依据对消息作出不同的处理(当用通配符接受消息时)。
程序2、 简单C+MPI的例子 #include “mpi.h main(int argc, char **argv) { int numprocs,myrank,i,j,k; MPI_Status status; char msg[20]; MPI_Init(&argc,&argv); MPI_Comm_size(MPI_COMM_WORLD,&numprocs); MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
if(myrank == 0) { strcpy(msg,”Hello World”); MPI_Send(msg,strlen(msg) + 1,MPI_CHAR,1,99, MPI_COMM_WORLD); } else if(myrank ==1) { MPI_Recv(msg,20,MPI_CHAR,0,99, MPI_COMM_WORLD,&status); printf(“Receive message = %s\n”,msg); } MPI_Finalize(); }
MPI程序的一些惯例 • 自己程序中避免使用以前缀“MPI_”开头的变量和函数 • FORTRAN语言的MPI调用一般全为大写: MPI_AAAA_AAAA • C语言的MPI调用“MPI_”后的首字母大写,其余为小写 :MPI_Aaaa_aaaa • MPI标志符限于30个有效符号