MPI并行程序设计(1).ppt

上传人:清**** 文档编号:88542181 上传时间:2023-04-26 格式:PPT 页数:42 大小:248KB
返回 下载 相关 举报
MPI并行程序设计(1).ppt_第1页
第1页 / 共42页
MPI并行程序设计(1).ppt_第2页
第2页 / 共42页
点击查看更多>>
资源描述

《MPI并行程序设计(1).ppt》由会员分享,可在线阅读,更多相关《MPI并行程序设计(1).ppt(42页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。

1、MPI并行程序设计n nMPI是目前最重要的并行编程工具,它具有移植性好、功能强大、效率高等多种优点,而且有多种不同免费、高效、实用的实现版本,几乎所有的并行计算机厂商都提供对它的支持,这是其他的并行编程环境所无法比拟的。2023/4/232023/4/231 1什么是MPI?MPI(Message Passing Interface)n nMPI是一个库,而不是一门语言;n nMPI是一种标准或规范的代表,而不特指某一个对它的具体实现;n nMPI是一种消息传递编程模型,并成为这种编程模型的代表和事实上的标准;2023/4/232023/4/232 2消息传递模型假设底层的消息传递模型是一组

2、处理器,每一个假设底层的消息传递模型是一组处理器,每一个处理器有自己的本地内存,并且通过互连网络实处理器有自己的本地内存,并且通过互连网络实现与其他处理器的消息传递现与其他处理器的消息传递处理器内存处理器内存处理器内存处理器内存处理器内存处理器内存处理器内存互连网络处理器内存2023/4/232023/4/233 3MPI并行程序设计n nMPI历史n n机房集群环境n n六个接口构成的MPI子集n nMPI并行程序的两种基本模式n nMPI并行程序的通信模式2023/4/232023/4/234 4MPI的历史nMPI初稿:美国并行计算中心工作会议(92年4月)nMPI-1公布:第一届MPI

3、大会(93年2月)nMPI标准正式发布:1994年5月nMPI-1.1发布:1995年6月nMPI-2发布:(以前的版本统称MPI-1)1997年7月 2023/4/232023/4/235 5MPI的实现MPICH:最重要的MPI实现n与MPI-1规范同步发展的版本n支持部分MPI-2的特征(如动态生成进程等)LAM(Local Area Multicomputer)nOhio State University开发n它主要用于异构的计算机网络计算系统2023/4/232023/4/236 6下载地址n nMPICH2(最新版本1.0.3)http:/www-unix.mcs.anl.gov/

4、mpi/mpich/n nLAM-MPI(最新版本7.1.2)http:/www.lam-mpi.org/download/2023/4/232023/4/237 7机房环境n n软件部分软件部分 操作系统:操作系统:Windows Server 2003 MPI MPI实现:实现:MPICH-1.2.5MPICH-1.2.5n n硬件部分硬件部分 集群系统有集群系统有4 4个刀片个刀片(每片主要参数每片主要参数):2CPU(Xeon3.2GHZ)2CPU(Xeon3.2GHZ),2GB RAM2GB RAM,2(4)2(4)个千兆网个千兆网卡卡,2,2个个SCSISCSI硬盘硬盘 2023/

5、4/232023/4/238 8机房集群环境n n一个主节点(一个刀片)启用双网卡,设置内/外网IP地址,用于用户登陆、提交调试程序、管理员管理集群等。主节点开启SSH、Ftp等服务。n n三个从节点 用于从主节点接受计算任务并执行计算(返回结果)。从节点开启SSH服务。节点之间的通信通过SSH协议来实现2023/4/232023/4/239 9六个接口构成的MPI子集n n在在MPI-1MPI-1中,共有中,共有128128个调用接口,在个调用接口,在MPI-2MPI-2中有中有287287个,个,应该说应该说MPIMPI是比较庞大的。但是从理论上说,是比较庞大的。但是从理论上说,MPIMP

6、I所有的所有的通信功能可以用它的通信功能可以用它的6 6个基本的调用来实现,掌握了这个基本的调用来实现,掌握了这6 6个个调用,就可以实现所有的消息传递并行程序的功能。调用,就可以实现所有的消息传递并行程序的功能。n n所有的所有的MPIMPI标识符,都以标识符,都以MPIMPI前缀开头,后面紧跟一个大前缀开头,后面紧跟一个大写字母和一系列小写字母以及下划线。写字母和一系列小写字母以及下划线。n nMPIMPIMPIMPI调用的参数说明调用的参数说明调用的参数说明调用的参数说明IN:IN:调用部分传递给调用部分传递给MPIMPI的参数,的参数,MPIMPI除了使用该参数外不除了使用该参数外不允

7、许对这一参数做任何修改允许对这一参数做任何修改OUT:MPIOUT:MPI返回给调用部分的结果参数,该参数的初始值返回给调用部分的结果参数,该参数的初始值对对MPIMPI没有任何意义没有任何意义INOUT:INOUT:调用部分首先将该参数传递给调用部分首先将该参数传递给MPIMPI,MPIMPI对这一参对这一参数引用、修改后,将结果返回给外部调用,该参数的初始数引用、修改后,将结果返回给外部调用,该参数的初始值和返回结果都有意义值和返回结果都有意义2023/4/232023/4/231010n n、MPIMPI初始化:初始化:MPI_InitMPI_Init函数函数用法:用法:MPI_Init

8、MPI_Init(&argc,&argv&argc,&argv)每一个每一个MPIMPI进程调用的第一个进程调用的第一个MPIMPI函数都是函数都是MPI_InitMPI_Init。该函数指示系统完成所有的初始化工。该函数指示系统完成所有的初始化工作,以备对后续作,以备对后续MPIMPI库的调用进行处理。库的调用进行处理。n n、MPIMPI结束:结束:MPI_FinalizeMPI_Finalize函数函数用法:用法:MPI_FinalizeMPI_Finalize()()在一个进程执行完其全部在一个进程执行完其全部MPIMPI库函数调用后,将库函数调用后,将调用函数调用函数 MPI_Fin

9、alize MPI_Finalize,从而让系统释放分配给,从而让系统释放分配给MPIMPI的资源。它是的资源。它是MPIMPI程序的最后一条可执行语句,程序的最后一条可执行语句,否则程序的运行结果是不可预知的。否则程序的运行结果是不可预知的。2023/4/232023/4/231111n n、确定进程的标识符、确定进程的标识符用法:用法:MPI_Comm_rankMPI_Comm_rank(MPI_COMM_WORLDMPI_COMM_WORLD ,&id&id)当当MPIMPI初始化后,每一个活动进程变成了一个叫做初始化后,每一个活动进程变成了一个叫做MPI_COMM_WORLDMPI_C

10、OMM_WORLD的通信域中的成员。通信域是一个不的通信域中的成员。通信域是一个不透明的对象,提供了在进程之间传递消息的环境。透明的对象,提供了在进程之间传递消息的环境。在一个通信域内的进程是有序的。在一个有在一个通信域内的进程是有序的。在一个有p p个进程的通信个进程的通信域中,每一个进程有一个唯一的序号(域中,每一个进程有一个唯一的序号(IDID号),取值为号),取值为0p0p。进程可以通过调用函数进程可以通过调用函数MPI_Comm_rankMPI_Comm_rank来确定它在通信来确定它在通信域中的序号。域中的序号。n n4 4、确定进程数量、确定进程数量 用法:用法:MPI_Comm

11、_sizeMPI_Comm_size(MPI_COMM_WORLDMPI_COMM_WORLD ,&p&p)进程通过调用函数进程通过调用函数MPI_Comm_sizeMPI_Comm_size来确定一个通信域中来确定一个通信域中 的进程总数。的进程总数。2023/4/232023/4/231212n n、消息发送函数、消息发送函数MPI_SEND(buf,count,datatype,dest,tag,commMPI_SEND(buf,count,datatype,dest,tag,comm)参数说明:参数说明:IN buf:IN buf:发送缓冲区的起始地址发送缓冲区的起始地址IN coun

12、t:IN count:将要发送的数据的个数将要发送的数据的个数IN datatype:IN datatype:发送数据的数据类型发送数据的数据类型IN dest:IN dest:目的进程标识号目的进程标识号IN tag:IN tag:消息标志消息标志IN commIN comm:通信域:通信域MPI_SENDMPI_SEND将发送缓冲区中的将发送缓冲区中的countcount个个datatypedatatype数据类型数据类型的数据发送到目的进程,目的进程在通信域中的标识号是的数据发送到目的进程,目的进程在通信域中的标识号是dest,dest,本次发送的消息标志是本次发送的消息标志是tag,t

13、ag,使用这一标志,就可以把使用这一标志,就可以把本次发送的消息和本进程向同一目的进程发送的其他消息区本次发送的消息和本进程向同一目的进程发送的其他消息区别开。别开。2023/4/232023/4/231313n n、消息接收函数MPI_RECV(buf,count,datatype,source,tag,comm,status)参数说明:参数说明:OUTOUT buf:buf:发送缓冲区的起始地址发送缓冲区的起始地址 ININ count:count:将发送的数据的个数将发送的数据的个数 ININ datatype:datatype:发送数据的数据类型发送数据的数据类型 ININ dest:

14、dest:目的进程标识号目的进程标识号 ININ tag:tag:消息标志消息标志 ININ commcomm:通信域:通信域 OUT OUT status:status:返回类型返回类型(是由三个域组成的结构类型,是由三个域组成的结构类型,这三个域分别是这三个域分别是:MPI_SOURCE:MPI_SOURCE、MPI_TAGMPI_TAG和和MPI_ERROR)MPI_ERROR)MPI_RECVMPI_RECV从指定的进程从指定的进程sourcesource接收消息,并且该消息的接收消息,并且该消息的数据类型和消息标识和本接收进程的数据类型和消息标识和本接收进程的datatypedata

15、type和和tagtag相一相一致,接收到的消息所包含的数据元素的个数最多不能超过致,接收到的消息所包含的数据元素的个数最多不能超过countcount。2023/4/232023/4/231414MPI预定义数据类型n nMPIMPI预定义类型与预定义类型与C C数据类型对应关系数据类型对应关系2023/4/232023/4/231515一般的MPI程序设计流程图 MPI_Init()MPI_Comm_rank()MPI_Comm_size()建立新的通信器、定义新的数据类型和进程拓扑结构应用程序实体:计算控制程序体;进程间通信;MPI_Finalize()退出MPI系统程序参数说明End2

16、023/4/232023/4/231616一个简单的发送和接收的例子n n首先输出几个进程分别运行在哪一台机子首先输出几个进程分别运行在哪一台机子.这里调这里调用一个用一个MPI_Get_processor_nameMPI_Get_processor_name获得本机的获得本机的名字名字.n n接着进程接着进程0 0向其他进程发送问候信息向其他进程发送问候信息,其他进程接收其他进程接收进程进程0 0的消息的消息.并输出这一过程并输出这一过程.2023/4/232023/4/231717n n#includempi.h#includempi.hn n#include#includen n#inc

17、lude#includen nvoid main(int argc,char*argv)void main(int argc,char*argv)n n n nchar message20;char message20;n nint i,myid,numprocs;int i,myid,numprocs;n nint namelen;int namelen;n nMPI_Status status;MPI_Status status;n nchar processor_nameMPI_MAX_PROCESSOR_NAME;char processor_nameMPI_MAX_PROCESSOR

18、_NAME;n nMPI_InitMPI_Init(&argc,&argv);(&argc,&argv);n n MPI_Comm_size(MPI_COMM_WORLD,&numprocs);MPI_Comm_size(MPI_COMM_WORLD,&numprocs);n nMPI_Comm_rank(MPI_COMM_WORLD,&myid);MPI_Comm_rank(MPI_COMM_WORLD,&myid);n nMPI_Get_processor_name(processor_name,&namelen);MPI_Get_processor_name(processor_name

19、,&namelen);n ncoutHello World!processmyid of numprocs on processor_nameendl;coutHello World!processmyid of numprocs on processor_nameendl;n n if(myid=0)if(myid=0)n n strcpystrcpy(message,“(message,“Hello,Hello,World!);World!);n nforfor(i=1;inumprocs;(i=1;inumprocs;i+)i+)n n MPI_Send(message,strlen(m

20、essage),MPI_CHAR,i,99,MPI_COMM_WORLD);MPI_Send(message,strlen(message),MPI_CHAR,i,99,MPI_COMM_WORLD);n n coutprocess 0 sendmessageto process myidendl;coutprocess 0 sendmessageto process myidendl;n n n n n nelse else n n MPI_Recv(message,20,MPI_CHAR,MPI_ANY_SOURCE,0,MPI_COMM_WORLD,&status);MPI_Recv(m

21、essage,20,MPI_CHAR,MPI_ANY_SOURCE,0,MPI_COMM_WORLD,&status);n n coutprocessmyidrecvivedmessagefrom process 0endl;coutprocessmyidrecvivedmessagefrom process 0endl;n n n n MPI_Finalize();MPI_Finalize();n n 2023/4/232023/4/231818开启个进程运行结果:2023/4/232023/4/231919开启个进程运行结果:2023/4/232023/4/232020MPI并行程序的两种

22、基本模式n n两种最基本的并行程序设计模式:n n对等模式:各个部分地位相同,功能和代码基本一致,只不过是处理的数据或对象不同,也容易用同样的程序来实现。(典型应用如Jacobi迭代)n n主从模式:具有主进程和从进程,主进程接收从进程的处理结果,并进行汇总处理(典型应用如矩阵向量乘法)2023/4/232023/4/232121对等模式并行jacobi程序 这里的这里的 jacobijacobi迭代是计算一个矩阵的数据二维数组迭代是计算一个矩阵的数据二维数组A A(M(M,M)M)。其边界值边界赋为。其边界值边界赋为8 8,内部初值为,内部初值为0 0,通过通过迭代求矩阵各点的值迭代求矩阵各

23、点的值.假设需要迭代的数据是假设需要迭代的数据是M*MM*M的二维数组的二维数组A(M,M),A(M,M),令令M=4*N,M=4*N,按按上图进行数据划分,则分布在上图进行数据划分,则分布在4 4个不同进程上的数据分别是:个不同进程上的数据分别是:进程进程0 0:A(M,1:N);A(M,1:N);进程进程1 1:A(M,N+1:2*N);A(M,N+1:2*N);进程进程2 2:A(M,2*N+1:3*N);A(M,2*N+1:3*N);进程进程3 3:A(M,3*N+1:4*N).A(M,3*N+1:4*N).由于在迭代过程中,边界点新值的计算需要相邻边界其他块的由于在迭代过程中,边界点

24、新值的计算需要相邻边界其他块的数据,因此在每一个数据块的两侧各增加数据,因此在每一个数据块的两侧各增加1 1列的数据空间,用列的数据空间,用于存放从相邻数据块通信得到的数据。每个数据块的大小就于存放从相邻数据块通信得到的数据。每个数据块的大小就从从M*NM*N扩大到扩大到M*(N+2)M*(N+2)。2023/4/232023/4/232222n为了并行求解,这里将参加迭代的数据按列进行分割,假设有4个进程同时并行计算,数据的分割结果如图:n n边界点新值的计算需边界点新值的计算需要相邻边界其他块的要相邻边界其他块的数据,因此在每一个数据,因此在每一个数据块的两侧各增加数据块的两侧各增加1 1

25、列列进程0进程1进程2进程3按列划分2023/4/232023/4/232323进程进程0进程进程1进程进程2进程进程3发送发送发送发送发送发送发送发送发送发送发送发送接收接收接收接收接收接收接收接收接收接收接收接收2023/4/232023/4/232424例子:并行jacobi程序program mainprogram maininclude mpif.hinclude mpif.hinteger totalsize,mysize,stepsinteger totalsize,mysize,stepsParameter(totalsize=16)Parameter(totalsize=16

26、)(定义全局数组的规模)定义全局数组的规模)parameter(mysize=totalsize/4,steps=10)parameter(mysize=totalsize/4,steps=10)integer n,myid,numprocs,i,j,rcinteger n,myid,numprocs,i,j,rcReal a(totalsize,mysize+2),b(totalsize,mysize+2)Real a(totalsize,mysize+2),b(totalsize,mysize+2)Integer begin_col,end_col,ierrInteger begin_co

27、l,end_col,ierrInteger status(MPI_STATUS_SIZE)Integer status(MPI_STATUS_SIZE)call MPI_INIT(ierr)call MPI_INIT(ierr)call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)call MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr)call MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr)pr

28、int*,”Process”,myid,”of”,print*,”Process”,myid,”of”,numprocs,”is alive”numprocs,”is alive”n n迭代计算一个二维数组迭代计算一个二维数组A(MA(M,M)M)2023/4/232023/4/232525(数组初始化数组初始化)do j=1,mysize+2do j=1,mysize+2 do i=1,totalsize do i=1,totalsize a(i,j)=0.0 a(i,j)=0.0 end do end doend doend doIf(myid.eq.0)thenIf(myid.eq.0)

29、then do i=1,totalsize do i=1,totalsize a(i,2)=8.0 a(i,2)=8.0 end do end doend ifend ifIf(myid.eq.3)thenIf(myid.eq.3)then do i=1,totalsize do i=1,totalsize a(i,mysize+1)=8.0 a(i,mysize+1)=8.0 end do end doend ifend ifdo i=1,mysize+2do i=1,mysize+2 a(1,i)=8.0 a(1,i)=8.0 a(totalsize,i)=8.0 a(totalsize,

30、i)=8.0end doend do2023/4/232023/4/232626(Jacobi(Jacobi迭代部分迭代部分)do n=1,stepsdo n=1,steps(从右侧的邻居得到数据从右侧的邻居得到数据)if(myid.lt.3)then if(myid.lt.3)then call MPI_RECV(a(1,mysize+2),totalsize,MPI_REAL,myid+1,call MPI_RECV(a(1,mysize+2),totalsize,MPI_REAL,myid+1,10,MPI_COMM_WORLD,status,ierr)10,MPI_COMM_WORLD

31、,status,ierr)end if end if(向左侧的邻居发送数据向左侧的邻居发送数据)if(myid.gt.0)then if(myid.gt.0)then call MPI_SEND(a(1,2),totalsize,MPI_REAL,myid-1,call MPI_SEND(a(1,2),totalsize,MPI_REAL,myid-1,10,MPI_COMM_WORLD,ierr)10,MPI_COMM_WORLD,ierr)end if end if2023/4/232023/4/232727(向右侧的邻居发送数据)(向右侧的邻居发送数据)if(myid.lt.3)then

32、 if(myid.lt.3)then call MPI_SEND(a(1,mysize+1),totalsize,MPI_REAL,myid+1,call MPI_SEND(a(1,mysize+1),totalsize,MPI_REAL,myid+1,10,MPI_COMM_WORLD,ierr)10,MPI_COMM_WORLD,ierr)end if end if(从左侧的邻居接收数据)(从左侧的邻居接收数据)if(myid.gt.0)then if(myid.gt.0)then call MPI_RECV(a(1,1),totalsize,MPI_REAL,myid-1,call MP

33、I_RECV(a(1,1),totalsize,MPI_REAL,myid-1,10,MPI_COMM_WORLD,status,ierr)10,MPI_COMM_WORLD,status,ierr)end if end ifbegin_colbegin_col=2=2end_colend_col=mysize+1=mysize+1if (myid.eq.0)thenif (myid.eq.0)then begin_col begin_col=3=3 end if end ifif (myid.eq.3)thenif (myid.eq.3)then end_col end_col=mysize

34、=mysize end if end if2023/4/232023/4/232828do j=begin_col,do j=begin_col,end_colend_col do i=2,totalsize-1 do i=2,totalsize-1 b b(i,j)=0.25*(a(i,j+1)+a(i,j-1)+a(i+1,j)+a(i-1,j)(i,j)=0.25*(a(i,j+1)+a(i,j-1)+a(i+1,j)+a(i-1,j)end do end do end do end dodo j=begin_col,do j=begin_col,end_colend_col do i=

35、2,totalsize-1 do i=2,totalsize-1 a(i,j)=b(i,j)a(i,j)=b(i,j)end do end doend doend doend doend dodo i=2,totalsize-1do i=2,totalsize-1 print*,myid,print*,myid,(a(i,j),(a(i,j),j=begin_colj=begin_col,end_col),end_col)end doend docall MPI_FINALIZE(rc)call MPI_FINALIZE(rc)endend2023/4/232023/4/232929主从模式矩

36、阵向量乘n n对于矩阵对于矩阵C=A*BC=A*B,主进程,主进程将向量将向量B B广播给所有的从进广播给所有的从进程,然后将矩阵程,然后将矩阵A A的各行依的各行依次发送给从进程。从进程计次发送给从进程。从进程计算一行和算一行和B B相乘的结果然后相乘的结果然后将结果发送给主进程。主进将结果发送给主进程。主进程循环向各个从进程发送一程循环向各个从进程发送一行的数据直到将行的数据直到将A A各行的数各行的数据发送完毕。一旦主进程将据发送完毕。一旦主进程将A A的各行发送完毕则每收到的各行发送完毕则每收到一个结果就向相应的从进程一个结果就向相应的从进程发送结束标志,从进程接收发送结束标志,从进程

37、接收到结束标志后退出执行主进到结束标志后退出执行主进程收集完所有的结果后也结程收集完所有的结果后也结束。束。从进程主进程发送矩阵A的各行数据回收各行与B相乘的结果计算计算计算计算送回结果2023/4/232023/4/233030例子:矩阵向量乘program mainprogram maininclude“mpif.h”include“mpif.h”integer MAX_ROWS,MAX_COLS,rows,colsinteger MAX_ROWS,MAX_COLS,rows,colsparameter(MAX_ROWS=1000,MAX_COLS=1000)parameter(MAX_R

38、OWS=1000,MAX_COLS=1000)double precision a(MAX_ROWS,MAX_COLS),double precision a(MAX_ROWS,MAX_COLS),b(MAX_COLS),b(MAX_COLS),c(MAX_COLS)c(MAX_COLS)double presicion buffer(MAX_COLS),ansdouble presicion buffer(MAX_COLS),ansinteger integer myid,master,numprocs,ierr,status(MPI_STATUS_SIZE)myid,master,nump

39、rocs,ierr,status(MPI_STATUS_SIZE)integer i,j,numsent,numrcvd,senderinteger i,j,numsent,numrcvd,senderinteger anstype,rowinteger anstype,rown n计算矩阵计算矩阵2023/4/232023/4/233131call MPI_INIT(ierr)call MPI_INIT(ierr)call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)call MPI_COMM_RANK(MPI_COMM_WORLD,myid,ierr)ca

40、ll MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr)call MPI_COMM_SIZE(MPI_COMM_WORLD,numprocs,ierr)master=0master=0rows=100rows=100cols=100cols=100If(myid.eq.master)thenIf(myid.eq.master)then (主进程对矩阵主进程对矩阵A A和和B B赋初值赋初值)do i=1,cols do i=1,cols b(i)=1 b(i)=1 do j=1,rows do j=1,rows a(i,j)=i a(i,j)=i end d

41、o end do end do end do2023/4/232023/4/233232numsent=0numsent=0 numrcvd=0 numrcvd=0 (将矩阵将矩阵B B发送给所有其他的从进程,通过下面的广播语句实现发送给所有其他的从进程,通过下面的广播语句实现)call MPI_BCAST(b,cols,MPI_DOUBLE_PRECISION,master,call MPI_BCAST(b,cols,MPI_DOUBLE_PRECISION,master,*MPI_COMM_WORLD,ierr)*MPI_COMM_WORLD,ierr)(依次将矩阵依次将矩阵A A的各行发

42、送给其他的的各行发送给其他的numprocs-1numprocs-1个从进程个从进程)do i=1,min(numprocs-1,rows)do i=1,min(numprocs-1,rows)do j=1,cols do j=1,cols (将一行的数据取出来依次放到缓冲区中将一行的数据取出来依次放到缓冲区中)buffer(j)=a(i,j)buffer(j)=a(i,j)end do end do (将准备好的一行数据发送出去将准备好的一行数据发送出去)call MPI_SEND(buffer,cols,MPI_DOUBLE_PRECISION,i,i,call MPI_SEND(buff

43、er,cols,MPI_DOUBLE_PRECISION,i,i,*MPI_COMM_WORLD,ierr)*MPI_COMM_WORLD,ierr)numsent=numsent+1 numsent=numsent+1 end do end do 2023/4/232023/4/233333(对所有的行,依次接收从进程对一行数据的计算结果对所有的行,依次接收从进程对一行数据的计算结果)do i=1,row do i=1,row call call MPI_RECV(ans,1,MPI_DOUBLE_PRECISION,MPI_ANY_SOURCE,MPI_RECV(ans,1,MPI_DOU

44、BLE_PRECISION,MPI_ANY_SOURCE,*MPI_ANY_TAG,MPI_COMM_WORLD,status,ierr)*MPI_ANY_TAG,MPI_COMM_WORLD,status,ierr)sender=status(MPI_SOURCE)sender=status(MPI_SOURCE)anstype=status(MPI_TAG)anstype=status(MPI_TAG)(将该行数据赋给结果数组将该行数据赋给结果数组C C的相应单元的相应单元)c(anstype)=ansc(anstype)=ans (如果还有其他的行没有被计算,则继续发送如果还有其他的行没

45、有被计算,则继续发送)if(numsent.lt.rows)thenif(numsent.lt.rows)then do j=1,cols do j=1,cols (准备好新一行的数据准备好新一行的数据)buffer(j)=a(numsent+1,j)buffer(j)=a(numsent+1,j)end do end do (将该行数据发送出去将该行数据发送出去)call call MPI_SEND(buffer,cols,MPI_DOUBLE_PRECISION,sender,MPI_SEND(buffer,cols,MPI_DOUBLE_PRECISION,sender,*numsent

46、+1,MPI_COMM_WORLD,ierr)*numsent+1,MPI_COMM_WORLD,ierr)numsent=numsent+1 numsent=numsent+12023/4/232023/4/233434elseelse (若所有行都已发送出去,则每接收一个消息则向相应的从进若所有行都已发送出去,则每接收一个消息则向相应的从进程发程发 送一个标志为送一个标志为0 0的空消息,终止该从进程的执行的空消息,终止该从进程的执行)call call MPI_SEND(1.0,0,MPI_DOUBLE_PRECISION,sender,0,MPI_SEND(1.0,0,MPI_DOUB

47、LE_PRECISION,sender,0,*MPI_COMM_WORLD,ierr)*MPI_COMM_WORLD,ierr)end if end if end do end doelseelse (下面为从进程的执行步骤,首先是接收数组下面为从进程的执行步骤,首先是接收数组B)B)call MPI_BCAST(b,cols,MPI_DOUBLE_PRECISION,master,call MPI_BCAST(b,cols,MPI_DOUBLE_PRECISION,master,*MPI_COMM_WORLD,ierr)*MPI_COMM_WORLD,ierr)(接收主进程发送过来的矩阵接收

48、主进程发送过来的矩阵A A一行的数据一行的数据)call call MPI_RECV(buffer,cols,MPI_DOUBLE_PRECISION,master,MPI_RECV(buffer,cols,MPI_DOUBLE_PRECISION,master,*MPI_ANY_TAG,MPI_COMM_WORLD,status,ierr)MPI_ANY_TAG,MPI_COMM_WORLD,status,ierr)2023/4/232023/4/233535(若接收到标志为若接收到标志为0 0的消息,则退出执行的消息,则退出执行)if(status(MPI_TAG).ne.0)thenif

49、(status(MPI_TAG).ne.0)then row=status(MPI_TAG row=status(MPI_TAG)ans=0.0ans=0.0 do I=1,cols do I=1,cols ans=ans+buffer(i)*b(j)ans=ans+buffer(i)*b(j)end do end do (计算一行的结果,并将结果发送给主进程计算一行的结果,并将结果发送给主进程)call call MPI_SEND(ans,1,MPI_DOUBLE_PRECISION,master,row,MPI_SEND(ans,1,MPI_DOUBLE_PRECISION,master,

50、row,MPI_COMM_WORLD,ierr)MPI_COMM_WORLD,ierr)goto 90 goto 90 end if end ifend if end if call MPI_FINALIZE(ierr)call MPI_FINALIZE(ierr)endend2023/4/232023/4/233636MPI并行程序的通信模式n nMPIMPI的四种通信模式:的四种通信模式:n n标准通信模式标准通信模式(MPI_SEND)MPI_SEND)n n缓存通信模式缓存通信模式(MPI_BSEND)MPI_BSEND)n n同步通信模式同步通信模式(MPI_SSEND)MPI_SS

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 教育专区 > 小学资料

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

工信部备案号:黑ICP备15003705号-8 |  经营许可证:黑B2-20190332号 |   黑公网安备:91230400333293403D

© 2020-2023 www.deliwenku.com 得利文库. All Rights Reserved 黑龙江转换宝科技有限公司 

黑龙江省互联网违法和不良信息举报
举报电话:0468-3380021 邮箱:hgswwxb@163.com