




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
..目录一、题目及要求11、题目12、要求1二、设计算法、算法原理1三、算法描述、设计流程23.1算法描述23.2设计流程4四、源程序代码及运行结果61、超立方61.1超立方的源程序代码61.2运行结果112、网孔连接112.1源程序代码112.2运行结果183、在数学软件中的计算结果19五、算法分析、优缺点191、简单的并行分块乘法的过程为192、使用Cannon算法时的算法分析203、算法的优缺点21六、总结22参考文献23一、题目及要求1、题目简单并行分块乘法:〔1情形1:超立方连接;〔2情形2:二维环绕网孔连接已知求。2、要求〔1题目分析、查阅与题目相关的资料;〔2设计算法;〔3算法实现、代码编写;〔4结果分析和性能分析与改进;〔5论文撰写、答辩;二、设计算法、算法原理要考虑的计算问题是C=AB,其中A与B分别是矩阵。=1\*GB3①A、B和C分成的方块阵,和,大小均为,p个处理器编号为,存放,和。=2\*GB3②通讯:每行处理器进行A矩阵块的多到多播送<得到,k=0~>每列处理器进行B矩阵块的多到多播送<得到,k=0~>=3\*GB3③乘-加运算:做三、算法描述、设计流程3.1算法描述超立方情形下矩阵的简单并行分块算法输入:待选路的信包在源处理器中输出:将原处理器中的信包送至其目的地Beginfori=1tondoendfor<2><3>whiledo<3.1>ifthen从当前节点V选路到节点为V1〔3.2endwhileEnd二维网孔情形下矩阵的简单并行分块算法输入:待选路的信包处于源处理器中输出:将各信包送至各自的目的地中Begin沿x维将信包向左或向右选路至目的地的处理器所在的列沿y维将信包向上或向下选路至目的地的处理器所在的行分块乘法算法//输入:,;子快大小均为输出:nBegin<1>fori=0todoforallpar-doifi>kthenendififj>kthenB<i+1>mod,jendifendforendforfori=0todoforallpar-do=+endforEndforEnd3.2设计流程以下是二维网孔与超立方连接设计流程。如图3-1二维网孔步骤:<1>先进行行播送;<2>再同时进行列播送;337625149804444444442233331111213141510图3-1二维网孔示意图超立方步骤:依次从低维到高维播送,d-立方,d=0,1,2,3,4…;算法流程如图所示:包括包括mpi的头文件相关变量声明MPI_INIT<>MPI_COMM_RANK<>MPI_COMM_SIZE<>进入MPI系统矩阵内部的通信应用控制实体:矩阵内部的计算程序MPI_FINALIZE<>退出MPI系统结束开始循环直至结束图3-2算法流程四、源程序代码及运行结果1、超立方1.1超立方的源程序代码#include"stdio.h"#include"stdlib.h"#include"mpi.h"#defineintsizesizeof<int>#definefloatsizesizeof<float>#definecharsizesizeof<char>#defineA<x,y>A[x*K+y]#defineB<x,y>B[x*N+y]#defineC<x,y>C[x*N+y]#definea<x,y>a[x*K+y]#defineb<x,y>b[x*n+y]#definebuffer<x,y>buffer[x*n+y]#definec<l,x,y>c[x*N+y+l*n]float*a,*b,*c,*buffer;ints;float*A,*B,*C;intM,N,K,P;intm,n;intmyid;intp;FILE*dataFile;MPI_Statusstatus;doubletime1;doublestarttime,endtime;voidreadData<>{inti,j;starttime=MPI_Wtime<>;dataFile=fopen<"yin.txt","r">;fscanf<dataFile,"%d%d",&M,&K>;A=<float*>malloc<floatsize*M*K>;for<i=0;i<M;i++>{for<j=0;j<K;j++>{fscanf<dataFile,"%f",A+i*K+j>;}}fscanf<dataFile,"%d%d",&P,&N>;if<K!=P>{printf<"theinputiswrong\n">;exit<1>;}B=<float*>malloc<floatsize*K*N>;for<i=0;i<K;i++>{for<j=0;j<N;j++>{fscanf<dataFile,"%f",B+i*N+j>;}}fclose<dataFile>;printf<"Inputoffile\"yin.txt\"\n">;printf<"%d\t%d\n",M,K>;for<i=0;i<M;i++>{for<j=0;j<K;j++>printf<"%f\t",A<i,j>>;printf<"\n">;}printf<"%d\t%d\n",K,N>;for<i=0;i<K;i++>{for<j=0;j<N;j++>printf<"%f\t",B<i,j>>;printf<"\n">;}C=<float*>malloc<floatsize*M*N>;}intgcd<intM,intN,intgroup_size>{inti;for<i=M;i>0;i-->{if<<M%i==0>&&<N%i==0>&&<i<=group_size>>returni;}return1;}voidprintResult<>{inti,j;printf<"\nOutputofMatrixC=AB\n">;for<i=0;i<M;i++>{for<j=0;j<N;j++>printf<"%f\t",C<i,j>>;printf<"\n">;}endtime=MPI_Wtime<>;printf<"\n">;printf<"Wholerunningtime=%fseconds\n",endtime-starttime>;printf<"Distributedatatime=%fseconds\n",time1-starttime>;printf<"Parallelcomputetime=%fseconds\n",endtime-time1>;}intmain<intargc,char**argv>{inti,j,k,l,group_size,mp1,mm1;MPI_Init<&argc,&argv>;MPI_Comm_size<MPI_COMM_WORLD,&group_size>;MPI_Comm_rank<MPI_COMM_WORLD,&myid>;p=group_size;if<myid==0>{readData<>;}if<myid==0>for<i=1;i<p;i++>{MPI_Send<&M,1,MPI_INT,i,i,MPI_COMM_WORLD>;MPI_Send<&K,1,MPI_INT,i,i,MPI_COMM_WORLD>;MPI_Send<&N,1,MPI_INT,i,i,MPI_COMM_WORLD>;}else{MPI_Recv<&M,1,MPI_INT,0,myid,MPI_COMM_WORLD,&status>;MPI_Recv<&K,1,MPI_INT,0,myid,MPI_COMM_WORLD,&status>;MPI_Recv<&N,1,MPI_INT,0,myid,MPI_COMM_WORLD,&status>;}p=gcd<M,N,group_size>;m=M/p;n=N/p;if<myid<p>{a=<float*>malloc<floatsize*m*K>;b=<float*>malloc<floatsize*K*n>;c=<float*>malloc<floatsize*m*N>;if<myid%2!=0>buffer=<float*>malloc<K*n*floatsize>;if<a==NULL||b==NULL||c==NULL>printf<"Allocatespacefora,borcfail!">;if<myid==0>{for<i=0;i<m;i++>for<j=0;j<K;j++>a<i,j>=A<i,j>;for<i=0;i<K;i++>for<j=0;j<n;j++>b<i,j>=B<i,j>;}if<myid==0>{for<i=1;i<p;i++>{MPI_Send<&A<m*i,0>,K*m,MPI_FLOAT,i,i,MPI_COMM_WORLD>;for<j=0;j<K;j++>MPI_Send<&B<j,n*i>,n,MPI_FLOAT,i,i,MPI_COMM_WORLD>;}free<A>;free<B>;}else{MPI_Recv<a,K*m,MPI_FLOAT,0,myid,MPI_COMM_WORLD,&status>;for<j=0;j<K;j++>MPI_Recv<&b<j,0>,n,MPI_FLOAT,0,myid,MPI_COMM_WORLD,&status>;}if<myid==0>time1=MPI_Wtime<>;for<i=0;i<p;i++>{l=<i+myid>%p;for<k=0;k<m;k++>for<j=0;j<n;j++>for<c<l,k,j>=0,s=0;s<K;s++>c<l,k,j>+=a<k,s>*b<s,j>;mm1=<p+myid-1>%p;mp1=<myid+1>%p;if<i!=p-1>{if<myid%2==0>{MPI_Send<b,K*n,MPI_FLOAT,mm1,mm1,MPI_COMM_WORLD>;MPI_Recv<b,K*n,MPI_FLOAT,mp1,myid,MPI_COMM_WORLD,&status>;}else{for<k=0;k<K;k++>for<j=0;j<n;j++>buffer<k,j>=b<k,j>;MPI_Recv<b,K*n,MPI_FLOAT,mp1,myid,MPI_COMM_WORLD,&status>;MPI_Send<buffer,K*n,MPI_FLOAT,mm1,mm1,MPI_COMM_WORLD>;}}}if<myid==0>for<i=0;i<m;i++>for<j=0;j<N;j++>C<i,j>=*<c+i*N+j>;if<myid!=0>MPI_Send<c,m*N,MPI_FLOAT,0,myid,MPI_COMM_WORLD>;else{for<k=1;k<p;k++>{MPI_Recv<c,m*N,MPI_FLOAT,k,k,MPI_COMM_WORLD,&status>;for<i=0;i<m;i++>for<j=0;j<N;j++>C<<k*m+i>,j>=*<c+i*N+j>;}}if<myid==0>printResult<>;}MPI_Finalize<>;if<myid<p>{free<a>;free<b>;free<c>;if<myid==0>free<C>;if<myid%2!=0>free<buffer>;}return<0>;}1.2运行结果图4.14个处理器的运行结果2、网孔连接2.1源程序代码#include<stdlib.h>#include<string.h>#include<mpi.h>#include<time.h>#include<stdio.h>#include<math.h>/*全局变量声明*/float**A,**B,**C;/*总矩阵,C=A*B*/float*a,*b,*c,*tmp_a,*tmp_b;/*a、b、c表分块,tmp_a、tmp_b表缓冲区*/intdg,dl,dl2,p,sp;/*dg:总矩阵维数;dl:矩阵块维数;dl2=dl*dl;p:处理器个数;sp=sqrt<p>*/intmy_rank,my_row,my_col;/*my_rank:处理器ID;<my_row,my_col>:处理器逻辑阵列坐标*/MPI_Statusstatus;/**函数名:get_index*功能:处理器逻辑阵列坐标至rank号的转换*输入:坐标、逻辑阵列维数*输出:rank号*/intget_index<introw,intcol,intsp>{return<<row+sp>%sp>*sp+<col+sp>%sp;}/**函数名:random_A_B*功能:随机生成矩阵A和B*/voidrandom_A_B<>{inti,j;floatm;//srand<<unsignedint>time<NULL>>;/*设随机数种子* /*随机生成A,B,并初始化C*/for<i=0;i<dg;i++>for<j=0;j<dg;j++> { scanf<"%f",&m>;A[i][j]=m;C[i][j]=0.0; m=0; } for<i=0;i<dg;i++>for<j=0;j<dg;j++> {scanf<"%f",&m>;B[i][j]=m; m=0; }}/*函数名:scatter_A_B*功能:rank为0的处理器向其他处理器发送A、B矩阵的相关块*/voidscatter_A_B<>{inti,j,k,l;intp_imin,p_imax,p_jmin,p_jmax;for<k=0;k<p;k++>{ /*计算相应处理器所分得的矩阵块在总矩阵中的坐标范围*/ p_jmin=<k%sp>*dl; p_jmax=<k%sp+1>*dl-1; p_imin=<k-<k%sp>>/sp*dl; p_imax=<<k-<k%sp>>/sp+1>*dl-1;l=0;/*rank=0的处理器将A,B中的相应块拷至tmp_a,tmp_b,准备向其他处理器发送*/for<i=p_imin;i<=p_imax;i++>{ for<j=p_jmin;j<=p_jmax;j++> {tmp_a[l]=A[i][j]; tmp_b[l]=B[i][j]; l++;}}/*rank=0的处理器直接将自己对应的矩阵块从tmp_a,tmp_b拷至a,b*/if<k==0>{memcpy<a,tmp_a,dl2*sizeof<float>>; memcpy<b,tmp_b,dl2*sizeof<float>>;}else/*rank=0的处理器向其他处理器发送tmp_a,tmp_b中相关的矩阵块*/{MPI_Send<tmp_a,dl2,MPI_FLOAT,k,1,MPI_COMM_WORLD>; MPI_Send<tmp_b,dl2,MPI_FLOAT,k,2,MPI_COMM_WORLD>;}}}/**函数名:init_alignment*功能:矩阵A和B初始对准*/voidinit_alignment<>{MPI_Sendrecv<a,dl2,MPI_FLOAT,get_index<my_row,my_col-my_row,sp>,1,tmp_a,dl2,MPI_FLOAT,get_index<my_row,my_col+my_row,sp>,1,MPI_COMM_WORLD,&status>;memcpy<a,tmp_a,dl2*sizeof<float>>;/*将B中坐标为<i,j>的分块B<i,j>向上循环移动j步*/MPI_Sendrecv<b,dl2,MPI_FLOAT,get_index<my_row-my_col,my_col,sp>,1,tmp_b,dl2,MPI_FLOAT,get_index<my_row+my_col,my_col,sp>,1,MPI_COMM_WORLD,&status>;memcpy<b,tmp_b,dl2*sizeof<float>>;}/**函数名:main_shift*功能:分块矩阵左移和上移,并计算分块c*/voidmain_shift<>{inti,j,k,l;for<l=0;l<sp;l++>{/*矩阵块相乘,c+=a*b*/for<i=0;i<dl;i++>for<j=0;j<dl;j++>for<k=0;k<dl;k++>c[i*dl+j]+=a[i*dl+k]*b[k*dl+j];/*将分块a左移1位*/MPI_Send<a,dl2,MPI_FLOAT,get_index<my_row,my_col-1,sp>,1,MPI_COMM_WORLD>;MPI_Recv<a,dl2,MPI_FLOAT,get_index<my_row,my_col+1,sp>,1,MPI_COMM_WORLD,&status>;/*将分块b上移1位*/MPI_Send<b,dl2,MPI_FLOAT,get_index<my_row-1,my_col,sp>,1,MPI_COMM_WORLD>;MPI_Recv<b,dl2,MPI_FLOAT,get_index<my_row+1,my_col,sp>,1,MPI_COMM_WORLD,&status>;}}/**函数名:collect_c*功能:rank为0的处理器从其余处理器收集分块矩阵c*/voidcollect_C<>{inti,j,i2,j2,k;intp_imin,p_imax,p_jmin,p_jmax;/*分块矩阵在总矩阵中顶点边界值*//*将rank为0的处理器中分块矩阵c结果赋给总矩阵C对应位置*/for<i=0;i<dl;i++> for<j=0;j<dl;j++> C[i][j]=c[i*dl+j];for<k=1;k<p;k++>{/*将rank为0的处理器从其他处理器接收相应的分块c*/MPI_Recv<c,dl2,MPI_FLOAT,k,1,MPI_COMM_WORLD,&status>;p_jmin=<k%sp>*dl;p_jmax=<k%sp+1>*dl-1;p_imin=<k-<k%sp>>/sp*dl;p_imax=<<k-<k%sp>>/sp+1>*dl-1;i2=0;/*将接收到的c拷至C中的相应位置,从而构造出C*/for<i=p_imin;i<=p_imax;i++>{j2=0;for<j=p_jmin;j<=p_jmax;j++>{C[i][j]=c[i2*dl+j2];j2++;}i2++;}}}/*函数名:print*功能:打印矩阵*输入:指向矩阵指针的指针,字符串*/voidprint<float**m,char*str>{inti,j;printf<"%s",str>;/*打印矩阵m*/for<i=0;i<dg;i++>{for<j=0;j<dg;j++>printf<"%15.0f",m[i][j]>;printf<"\n">;}printf<"\n">;}/**函数名:main*功能:主过程,Cannon算法,矩阵相乘*输入:argc为命令行参数个数,argv为每个命令行参数组成的字符串数组*/intmain<intargc,char*argv[]>{inti;MPI_Init<&argc,&argv>;/*启动MPI计算*/MPI_Comm_size<MPI_COMM_WORLD,&p>;/*确定处理器个数*/MPI_Comm_rank<MPI_COMM_WORLD,&my_rank>;/*确定各自的处理器标识符*/sp=sqrt<p>;/*确保处理器个数是完全平方数,否则打印错误信息,程序退出*/if<sp*sp!=p>{if<my_rank==0> printf<"Numberofprocessorsisnotaquadraticnumber!\n">;MPI_Finalize<>;exit<1>;}if<argc!=2>{if<my_rank==0>printf<"usage:mpirun-npProcNumcannonMatrixDimension\n">;MPI_Finalize<>;exit<1>;}dg=atoi<argv[1]>;/*总矩阵维数*/dl=dg/sp;/*计算分块矩阵维数*/dl2=dl*dl;/*计算处理器在逻辑阵列中的坐标*/my_col=my_rank%sp;my_row=<my_rank-my_col>/sp;/*为a、b、c分配空间*/a=<float*>malloc<dl2*sizeof<float>>;b=<float*>malloc<dl2*sizeof<float>>;c=<float*>malloc<dl2*sizeof<float>>;/*初始化c*/for<i=0;i<dl2;i++>c[i]=0.0;/*为tmp_a、tmp_b分配空间*/tmp_a=<float*>malloc<dl2*sizeof<float>>;tmp_b=<float*>malloc<dl2*sizeof<float>>;if<my_rank==0>{/*rank为0的处理器为A、B、C分配空间*/A=<float**>malloc<dg*sizeof<float*>>;B=<float**>malloc<dg*sizeof<float*>>;C=<float**>malloc<dg*sizeof<float*>>;for<i=0;i<dg;i++>{A[i]=<float*>malloc<dg*sizeof<float>>;B[i]=<float*>malloc<dg*sizeof<float>>;C[i]=<float*>malloc<dg*sizeof<float>>;}random_A_B<>;/*rank为0的处理器随机化生成A、B矩阵*/scatter_A_B<>;/*rank为0的处理器向其他处理器发送A、B矩阵的相关块*/}else/*rank不为0的处理器接收来自rank为0的处理器的相应矩阵分块*/{MPI_Recv<a,dl2,MPI_FLOAT,0,1,MPI_COMM_WORLD,&status>;MPI_Recv<b,dl2,MPI_FLOAT,0,2,MPI_COMM_WORLD,&status>;}init_alignment<>;/*A、B矩阵的初始对准*/main_shift<>;/*分块矩阵左移、上移,cannon算法的主过程*/if<my_rank==0>{collect_C<>;/*rank为0的处理器从其余处理器收集分块矩阵c*/print<A,"ra
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年度能源行业员工安全生产责任合同
- 养老院院民2025年度健康疗养外出服务协议
- 二零二五年度科幻题材电影导演聘请与未来科技合作合同
- 二零二五年度收养子女健康保障及医疗费用承担协议
- 2025年度销售业绩提成激励聘用合同
- 二零二五年度委托中介出售手房并享受优先购买权合同
- 二零二五年度企业股权律师费合作协议
- 2025年度装配式建筑架子工劳务施工合作协议书
- 2025年度道路桥梁施工环境保护与治理合同
- 二零二五年度南京市新能源行业劳务派遣协议书
- 保障性住房资格申请表
- PEP五年级上册Unit3-字母组合ow的发音
- 篮球特色学校实施方案
- 单人心肺复苏技术操作考核评分标准
- 水稻种子生产技术
- 第四章 学习心理导论
- 旅游政策与法规教案
- 征兵心理测试
- 2023年江苏农林职业技术学院高职单招(语文)试题库含答案解析
- GB/T 15622-2005液压缸试验方法
- 旋挖桩安全专项施工方案
评论
0/150
提交评论