MPI并行程序设计.ppt_第1页
MPI并行程序设计.ppt_第2页
MPI并行程序设计.ppt_第3页
MPI并行程序设计.ppt_第4页
MPI并行程序设计.ppt_第5页
已阅读5页,还剩37页未读 继续免费阅读

下载本文档

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

文档简介

2019/9/16,1,MPI并行程序设计,MPI是目前最重要的并行编程工具,它具有移植性好、功能强大、效率高等多种优点,而且有多种不同免费、高效、实用的实现版本,几乎所有的并行计算机厂商都提供对它的支持,这是其他的并行编程环境所无法比拟的。,2019/9/16,2,什么是MPI?,MPI(Message Passing Interface ) MPI是一个库,而不是一门语言; MPI是一种标准或规范的代表,而不特指某一个对它的具体实现; MPI是一种消息传递编程模型,并成为这种编程模型的代表和事实上的标准;,2019/9/16,3,消息传递模型,假设底层的消息传递模型是一组处理器,每一个处理器有自己的本地内存,并且通过互连网络实现与其他处理器的消息传递,2019/9/16,4,MPI并行程序设计,MPI历史 机房集群环境 六个接口构成的MPI子集 MPI并行程序的两种基本模式 MPI并行程序的通信模式,2019/9/16,5,MPI的历史,MPI初稿:美国并行计算中心工作会议(92年4月) MPI-1公布:第一届MPI大会(93年2月) MPI标准正式发布:1994年5月 MPI-1.1发布:1995年6月 MPI-2发布:(以前的版本统称MPI-1) 1997年7月,2019/9/16,6,MPI的实现,MPICH:最重要的MPI实现 与MPI-1规范同步发展的版本 支持部分MPI-2的特征(如动态生成进程等) LAM(Local Area Multicomputer) Ohio State University开发 它主要用于异构的计算机网络计算系统,2019/9/16,7,下载地址,MPICH2(最新版本1.0.3 ) /mpi/mpich/ LAM-MPI(最新版本7.1.2) http:/ /download/,2019/9/16,8,机房环境,软件部分 操作系统:Windows Server 2003 MPI实现:MPICH-1.2.5 硬件部分 集群系统有4个刀片(每片主要参数): 2CPU (Xeon3.2GHZ),2GB RAM,2(4)个千兆网卡,2个SCSI硬盘,2019/9/16,9,机房集群环境,一个主节点(一个刀片) 启用双网卡,设置内/外网IP地址,用于用户登陆、提交调试程序、管理员管理集群等。主节点开启SSH、Ftp等服务。 三个从节点 用于从主节点接受计算任务并执行计算(返回结果)。从节点开启SSH服务。 节点之间的通信通过SSH协议来实现,2019/9/16,10,六个接口构成的MPI子集,在MPI-1中,共有128个调用接口,在MPI-2中有287个,应该说MPI是比较庞大的。但是从理论上说,MPI所有的通信功能可以用它的6个基本的调用来实现,掌握了这6个调用,就可以实现所有的消息传递并行程序的功能。 所有的MPI标识符,都以MPI前缀开头,后面紧跟一个大写字母和一系列小写字母以及下划线。 MPI调用的参数说明 IN: 调用部分传递给MPI的参数,MPI除了使用该参数外不允许对这一参数做任何修改 OUT: MPI返回给调用部分的结果参数,该参数的初始值对MPI没有任何意义 INOUT:调用部分首先将该参数传递给MPI,MPI对这一参数引用、修改后,将结果返回给外部调用,该参数的初始值和返回结果都有意义,2019/9/16,11,、MPI初始化:MPI_Init函数 用法:MPI_Init(&argc , &argv) 每一个MPI进程调用的第一个MPI函数都是MPI_Init。该函数指示系统完成所有的初始化工作,以备对后续MPI库的调用进行处理。 、 MPI结束:MPI_Finalize函数 用法:MPI_Finalize() 在一个进程执行完其全部MPI库函数调用后,将调用函数 MPI_Finalize,从而让系统释放分配给MPI的资源。它是MPI程序的最后一条可执行语句,否则程序的运行结果是不可预知的。,2019/9/16,12,、确定进程的标识符 用法:MPI_Comm_rank( MPI_COMM_WORLD ,&id) 当MPI初始化后,每一个活动进程变成了一个叫做MPI_COMM_WORLD的通信域中的成员。通信域是一个不透明的对象,提供了在进程之间传递消息的环境。 在一个通信域内的进程是有序的。在一个有p个进程的通信域中,每一个进程有一个唯一的序号(ID号),取值为0p。 进程可以通过调用函数MPI_Comm_rank来确定它在通信域中的序号。 4、确定进程数量 用法:MPI_Comm_size( MPI_COMM_WORLD ,&p) 进程通过调用函数MPI_Comm_size来确定一个通信域中 的进程总数。,2019/9/16,13,、消息发送函数 MPI_SEND(buf,count,datatype,dest,tag,comm) 参数说明: IN buf:发送缓冲区的起始地址 IN count:将要发送的数据的个数 IN datatype:发送数据的数据类型 IN dest:目的进程标识号 IN tag:消息标志 IN comm:通信域 MPI_SEND将发送缓冲区中的count个datatype数据类型的数据发送到目的进程,目的进程在通信域中的标识号是dest,本次发送的消息标志是tag,使用这一标志,就可以把本次发送的消息和本进程向同一目的进程发送的其他消息区别开。,2019/9/16,14,、消息接收函数 MPI_RECV(buf,count,datatype,source,tag,comm,status) 参数说明: OUT buf:发送缓冲区的起始地址 IN count:将发送的数据的个数 IN datatype:发送数据的数据类型 IN dest:目的进程标识号 IN tag:消息标志 IN comm:通信域 OUT status:返回类型(是由三个域组成的结构类型,这三个域分别是: MPI_SOURCE、MPI_TAG和MPI_ERROR) MPI_RECV从指定的进程source接收消息,并且该消息的数据类型和消息标识和本接收进程的datatype和tag相一致,接收到的消息所包含的数据元素的个数最多不能超过count。,2019/9/16,15,MPI预定义数据类型,MPI预定义类型与C数据类型对应关系,2019/9/16,16,一般的MPI程序设计流程图,2019/9/16,17,一个简单的发送和接收的例子,首先输出几个进程分别运行在哪一台机子.这里调用一个MPI_Get_processor_name获得本机的名字. 接着进程0向其他进程发送问候信息,其他进程接收进程0的消息.并输出这一过程.,2019/9/16,18,#include“mpi.h“ #include #include void main (int argc, char *argv) char message20; int i,myid,numprocs; int namelen; MPI_Status status; char processor_nameMPI_MAX_PROCESSOR_NAME; MPI_Init ( ,2019/9/16,19,开启个进程运行结果:,2019/9/16,20,开启个进程运行结果:,2019/9/16,21,MPI并行程序的两种基本模式,两种最基本的并行程序设计模式: 对等模式:各个部分地位相同,功能和代码基本一致,只不过是处理的数据或对象不同,也容易用同样的程序来实现。(典型应用如Jacobi迭代) 主从模式:具有主进程和从进程,主进程接收从进程的处理结果,并进行汇总处理 (典型应用如矩阵向量乘法),2019/9/16,22,对等模式并行jacobi程序,这里的 jacobi迭代是计算一个矩阵的数据二维数组A(M,M)。其边界值边界赋为8,内部初值为0,通过迭代求矩阵各点的值. 假设需要迭代的数据是M*M的二维数组A(M,M),令M=4*N,按上图进行数据划分,则分布在4个不同进程上的数据分别是: 进程0:A(M,1:N); 进程1:A(M,N+1:2*N); 进程2:A(M,2*N+1:3*N); 进程3:A(M,3*N+1:4*N). 由于在迭代过程中,边界点新值的计算需要相邻边界其他块的数据,因此在每一个数据块的两侧各增加1列的数据空间,用于存放从相邻数据块通信得到的数据。每个数据块的大小就从M*N扩大到M*(N+2)。,2019/9/16,23,为了并行求解,这里将参加迭代的数据按列进行分割,假设有4个进程同时并行计算,数据的分割结果如图:,边界点新值的计算需要相邻边界其他块的数据,因此在每一个数据块的两侧各增加1列,2019/9/16,24,进程0,进程1,进程2,进程3,发送,发送,发送,发送,发送,发送,接收,接收,接收,接收,接收,接收,2019/9/16,25,例子:并行jacobi程序,program main include mpif.h integer totalsize,mysize,steps Parameter (totalsize =16) (定义全局数组的规模) parameter (mysize =totalsize/4,steps=10) integer n,myid,numprocs,i,j,rc Real a(totalsize,mysize+2),b(totalsize,mysize+2) Integer begin_col,end_col,ierr Integer status(MPI_STATUS_SIZE) call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr) print *,”Process”, myid,” of”, numprocs,” is alive”,迭代计算一个二维数组A(M,M),2019/9/16,26,(数组初始化) do j=1,mysize+2 do i=1,totalsize a(i,j)=0.0 end do end do If (myid.eq.0) then do i=1,totalsize a(i,2)=8.0 end do end if If (myid.eq.3) then do i=1,totalsize a(i,mysize+1)=8.0 end do end if do i=1,mysize+2 a(1,i)=8.0 a(totalsize,i)=8.0 end do,2019/9/16,27,(Jacobi迭代部分) do n=1,steps (从右侧的邻居得到数据) if (myid.lt.3)then call MPI_RECV(a(1,mysize+2),totalsize,MPI_REAL,myid+1, 10,MPI_COMM_WORLD,status,ierr) end if (向左侧的邻居发送数据) if (myid.gt.0)then call MPI_SEND(a(1,2),totalsize,MPI_REAL,myid-1, 10,MPI_COMM_WORLD,ierr) end if,2019/9/16,28,(向右侧的邻居发送数据) if (myid.lt.3) then call MPI_SEND(a(1,mysize+1),totalsize,MPI_REAL,myid+1, 10,MPI_COMM_WORLD,ierr) end if (从左侧的邻居接收数据) if (myid.gt.0) then call MPI_RECV(a(1,1),totalsize,MPI_REAL,myid-1, 10,MPI_COMM_WORLD,status,ierr) end if begin_col =2 end_col =mysize+1 if (myid.eq.0) then begin_col =3 end if if (myid.eq.3) then end_col =mysize end if,2019/9/16,29,do j=begin_col, end_col do i=2,totalsize-1 b (i,j)=0.25*(a(i,j+1)+a(i,j-1)+a(i+1,j)+a(i-1,j) end do end do do j=begin_col, end_col do i=2,totalsize-1 a(i,j)=b(i,j) end do end do end do do i=2,totalsize-1 print *,myid, (a(i,j), j=begin_col ,end_col) end do call MPI_FINALIZE(rc) end,2019/9/16,30,主从模式矩阵向量乘,对于矩阵C=A*B,主进程将向量B广播给所有的从进程,然后将矩阵A的各行依次发送给从进程。从进程计算一行和B相乘的结果然后将结果发送给主进程。主进程循环向各个从进程发送一行的数据直到将A各行的数据发送完毕。一旦主进程将A的各行发送完毕则每收到一个结果就向相应的从进程发送结束标志,从进程接收到结束标志后退出执行主进程收集完所有的结果后也结束。,2019/9/16,31,例子:矩阵向量乘,program main include “mpif.h” integer MAX_ROWS,MAX_COLS,rows,cols parameter (MAX_ROWS=1000,MAX_COLS=1000) double precision a(MAX_ROWS,MAX_COLS), b(MAX_COLS), c(MAX_COLS) double presicion buffer(MAX_COLS),ans integer myid,master,numprocs,ierr,status(MPI_STATUS_SIZE) integer i,j,numsent,numrcvd,sender integer anstype,row,计算矩阵,2019/9/16,32,call MPI_INIT(ierr) call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr) call MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr) master=0 rows=100 cols=100 If (myid.eq.master) then (主进程对矩阵A和B赋初值) do i=1,cols b(i)=1 do j=1,rows a(i,j)=i end do end do,2019/9/16,33,numsent =0 numrcvd =0 (将矩阵B发送给所有其他的从进程,通过下面的广播语句实现) call MPI_BCAST(b,cols,MPI_DOUBLE_PRECISION,master, * MPI_COMM_WORLD,ierr) (依次将矩阵A的各行发送给其他的numprocs-1个从进程) do i=1,min(numprocs-1,rows) do j=1,cols (将一行的数据取出来依次放到缓冲区中) buffer(j)=a(i,j) end do (将准备好的一行数据发送出去) call MPI_SEND(buffer,cols,MPI_DOUBLE_PRECISION,i,i, * MPI_COMM_WORLD,ierr) numsent =numsent+1 end do,2019/9/16,34,(对所有的行,依次接收从进程对一行数据的计算结果) do i=1,row call MPI_RECV(ans,1,MPI_DOUBLE_PRECISION,MPI_ANY_SOURCE, * MPI_ANY_TAG,MPI_COMM_WORLD,status,ierr) sender=status (MPI_SOURCE) anstype =status (MPI_TAG) (将该行数据赋给结果数组C的相应单元) c(anstype)=ans (如果还有其他的行没有被计算,则继续发送) if (numsent.lt.rows) then do j=1,cols (准备好新一行的数据) buffer(j)=a(numsent+1,j) end do (将该行数据发送出去) call MPI_SEND(buffer,cols,MPI_DOUBLE_PRECISION,sender, * numsent+1,MPI_COMM_WORLD,ierr) numsent =numsent+1,2019/9/16,35,else (若所有行都已发送出去,则每接收一个消息则向相应的从进程发 送一个标志为0的空消息,终止该从进程的执行) call MPI_SEND(1.0,0,MPI_DOUBLE_PRECISION,sender,0, * MPI_COMM_WORLD,ierr) end if end do else (下面为从进程的执行步骤,首先是接收数组B) call MPI_BCAST(b,cols,MPI_DOUBLE_PRECISION,master, * MPI_COMM_WORLD,ierr) (接收主进程发送过来的矩阵A一行的数据) call MPI_RECV(buffer,cols,MPI_DOUBLE_PRECISION,master, * MPI_ANY_TAG,MPI_COMM_WORLD,status,ierr),2019/9/16,36,(若接收到标志为0的消息,则退出执行) if (status(MPI_TAG).ne.0) then row=status (MPI_TAG) ans =0.0 do I=1,cols ans =ans

温馨提示

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

评论

0/150

提交评论