利用MPI计算矩阵相乘的简单算法

整理文档很辛苦,赏杯茶钱您下走!

免费阅读已结束,点击下载阅读编辑剩下 ...

阅读已结束,您可以下载文档离线阅读编辑

资源描述

利用MPICH2计算矩阵相乘的简单算法ysmcleverysm@gmail.comMPICH2是用来进行并行运算的平台,而对矩阵算法的分解应该是并行运算应用中很常见的。今天在这里就用MPICH2写一个矩阵乘法的并行计算程序来学习一下MPICH2的使用。首先要复习一下矩阵乘法的算法,我们在线性代数里都学过。假设矩阵A为m行,k列。m=4,k=3。B是k行,n列,k=3,n=2,计算一个矩阵与列数据,或者叫做一个向量vector的乘积,结果矩阵C应当是m行,n列。A:1,2,34,5,67,8,98,7,6B:5,43,21,0A,B,C都按照行主序表示。即A(0,0)=1,A(0,1)=2,A(0,3)=3。则10),(*),(),(kxjxBxiAjiC如C(1,0)=A(1,0)×B(0,0)+A(1,1)×B(1,0)+A(1,2)×B(2,0)=4×5+5×3+6×1=41。C:14,841,2668,4467,46那如何将这个算法进行分解,分配到参与计算的各进程上去呢?简单的做法是可以将矩阵A进行划分,每个计算进程分配若干行,每次与B的一列数据计算的时候分别计算其进程所分配的行与B的这一列相乘的结果。比如有两个进程计算,分别为进程1和进程2。1分配A的0,和2行,2分配A的1和3行,与B的0列计算的时候,1进程将只计算得到C的一列的0和2位置两个数据,而2进程则算得1和3位置的数据。两个进程个子计算完成相应位置的数据后组合起来就是C的一列结果数据。在此,我使用MPI构建一种主-从(master-slave)模式的程序,也就是有一个进程是主进程,负责分发A矩阵的数据,并收集从进程的计算结果,将这些结果合并为最终的结果数据。这样整个程序需要一个主进程和若干个从进程,也就是至少要两个进程。主进程的代码如下://主进程intmaster(){intmyid;//intnumprocs;//MPI_Statusstatus;//获取当前进程的进程编号,保存在myid中MPI_Comm_rank(MPI_COMM_WORLD,&myid);//获取当前进程的进程总数,保存在numprocs中MPI_Comm_size(MPI_COMM_WORLD,&numprocs);intconstM(4),K(3),N(2);//结果矩阵CintC[M*N];intV[M];//将结果矩阵各元素初始化为0for(inti=0;iM*N;i++){C[i]=0;}//C矩阵共N列数据for(inti=0;iN;i++){//从各从进程接受数据for(intj=1;jnumprocs;j++){MPI_Recv(V,M,MPI_INT,j,i,MPI_COMM_WORLD,&status);//将各从进程的部分数据整合成完整的一个向量for(intij=0;ijM;ij++){C[ij*N+i]=C[ij*N+i]+V[ij];}}}//打印结果for(inti=0;iM;i++){for(intj=0;jN;j++){coutC[i*N+j]\t;}coutendl;}return0;}从进程代码://从进程intslave(){intmyid;//intnumprocs;//MPI_Statusstatus;//获取当前进程的进程编号,保存在myid中MPI_Comm_rank(MPI_COMM_WORLD,&myid);//获取当前进程的进程总数,保存在numprocs中MPI_Comm_size(MPI_COMM_WORLD,&numprocs);intconstM(4),K(3),N(2);vectorintindexes;intV[M];intA[M*K]={1,2,3,4,5,6,7,8,9,8,7,6};intB[K*N]={5,4,3,2,1,0};//计算本进程分配A矩阵中哪些行,保存在indexes中//比如2个从进程,A是4行数据,id为1的从进程分配的是0和2行for(inti=myid-1;iM;i+=numprocs-1){indexes.push_back(i);}//依次计算B的N列数据for(inti=0;iN;i++){//将保存列数据的向量V各元素初始化为0for(intj=0;jM;j++){V[j]=0;}if(indexes.size()0){for(intj=0;jindexes.size();j++){for(intij=0;ijK;ij++){V[indexes[j]]+=A[indexes[j]*K+ij]*B[ij*N+i];}}MPI_Send(V,M,MPI_INT,0,i,MPI_COMM_WORLD);}else{//发送全0的VMPI_Send(V,M,MPI_INT,0,i,MPI_COMM_WORLD);}}return0;}main函数代码:#undefSEEK_SET#undefSEEK_END#undefSEEK_CUR#includempi.h#includeiostream#includevectorusingnamespacestd;intmaster();intslave();intmain(void){intmyid;//intnumprocs;//MPI_Statusstatus;//MPI程序的初始化MPI_Init(NULL,NULL);//获取当前进程的进程编号,保存在myid中MPI_Comm_rank(MPI_COMM_WORLD,&myid);//获取当前进程的进程总数,保存在numprocs中MPI_Comm_size(MPI_COMM_WORLD,&numprocs);//如果进程数小于2个,则退出程序if(numprocs2){coutTooFewProcesses!endl;MPI_Abort(MPI_COMM_WORLD,99);}if(myid==0){//id是0的进程作为主进程master();}else{//id是非0的进程作为从进程slave();}//MPI程序释放资源MPI_Finalize();returnEXIT_SUCCESS;}以上算法是按照行划分A矩阵,也可以按照A的列来分配矩阵。算法如下:将第一列中的所有元素与向量中的第一个元素相乘,第二列的元素与向量中的第二个元素相乘,依此类推。采用这种方法,就可以得到一个新的矩阵。然后,将每一行中的所有元素相加,得到一个矩阵,这就是最后的结果。A:1,2,34,5,67,8,98,7,6为简化,B只取第一列B:5311*5+2*3+3*1=144*5+5*3+6*1=417*5+8*3+9*1=688*5+7*3+6*1=67实现此算法的MPI程序与以上代码类似,在此就不说了。

1 / 4
下载文档,编辑使用

©2015-2020 m.777doc.com 三七文档.

备案号:鲁ICP备2024069028号-1 客服联系 QQ:2149211541

×
保存成功