当前位置:文档之家› 并行处理实验报告:用MPI实现的矩阵乘法的加速比分析

并行处理实验报告:用MPI实现的矩阵乘法的加速比分析

华中科技大学课程名称并行处理实验名称矩阵乘法的实现及加速比分析考生姓名李佩佩考生学号 M*********系、年级计算机软件与理论2013级类别硕士研究生考试日期 2014年1月3日一. 实验目的1) 学会如何使用集群2) 掌握怎么用并行或分布式的方式编程3) 掌握如何以并行的角度分析一个特定的问题二. 实验环境1) 硬件环境:4核CPU、2GB内存计算机;2) 软件环境:Windows XP、MPICH2、VS2010、Xmanager Enterprise3;3) 集群登录方式:通过远程桌面连接211.69.198.2,用户名:pppusr,密码:AE2Q3P0。

三. 实验内容1. 实验代码编写四个.c文件,分别为DenseMulMatrixMPI.c、DenseMulMatrixSerial.c、SparseMulMatrixMPI.c和SparseMulMatrixSerial.c,用于比较并行和串行矩阵乘法的加速比,以及稀疏矩阵和稠密矩阵的加速比。

这里需要说明一下,一开始的时候我是把串、并行放在一个程序中,那么就只有两个.c文件DenseMulMatrix.c 和SparseMulMatrix.c,把串行计算矩阵乘的部分放到了主进程中,即procsID=0的进程,但是结果发现执行完串行后,再执行并行就特别的慢。

另外,对于稀疏矩阵的处理方面可能不太好,在生成稀疏矩阵的过程中非0元素位置的生成做到了随机化,但是在进行稀疏矩阵乘法时没有对矩阵压缩,所以跟稠密矩阵乘法在计算时间上没多大区别。

方阵A和B的初始值是利用rand()和srand()函数随机生成的。

根据稀疏矩阵和稠密矩阵的定义,对于稀疏矩阵和稠密矩阵的初始化方法InitMatrix(int *M,int *N,int len)会有所不同。

这里需要说明一下,一开始对于矩阵A和B的初始化是两次调用InitMatrix(int *M ,int len),生成A和B矩阵,但是随后我发现,由于两次调用方法InitMatrix的时间间隔非常短,又由于srand()函数的特点,导致生成的矩阵A和B完全一样;然后,我就在两次调用之间加入了语句“Sleep(1000);”,加入头文件“#include <windows.h>”,这样生成的A、B矩阵就不一样了,但很快问题又出现了,在Xshell中不能识别头文件“#include <windows.h>”。

所以,最后决定用下面的方法生成矩阵A和B,B是A的转置。

//稠密矩阵的生成方法void InitMatrix(int *M,int *N,int len){srand((unsigned)time( NULL));for(i=0; i < len*len; i++){M[i] = rand() % 2;}for(i=0;i<len;i++){for(j=0;j<len;j++){N[i*len+j]=M[j*len+i];}}}//稀疏矩阵的生成方法void InitMatrix(int *M, int *N, int len){for(i=0;i<len*len;i++)M[i]=0;srand((unsigned)time( NULL));for(m=0;m<224;m++){for(n=0;n<224;n++){i=rand()%len;j=rand()%len;M[i*len+j]=1;}}for(i=0;i<len;i++){for(j=0;j<len;j++){N[i*len+j]=M[j*len+i];}}}输入:并行执行的进程数procsNum,对于串行计算,只需要np=1;输出:程序的执行时间。

在Windows XP下使用Microsoft Visual Studio2010编程,由于稀疏矩阵和稠密矩阵的代码只是初始化部分不同,所以以稠密矩阵乘法为例,列出并行和串行的源代码。

并行计算的矩阵乘法源代码:DenseMulMatrixMPI.c#include<stdio.h>#include<stdlib.h>#include<mpi.h>#include<time.h>#define Length 1000int *A,*B,*C,*buffer,*ans;int temp,i,j,k;int procsID,procsNum,line;double startTime,endTime,totalTime;void InitMatrix(int *M,int *N,int len);//实现部分见上面void del(){free(A);free(B);free(C);free(buffer);free(ans);}int main(int argc,char *argv[]){MPI_Status status;MPI_Init(&argc,&argv);MPI_Comm_rank(MPI_COMM_WORLD,&procsID);//获取当前进程号 MPI_Comm_size(MPI_COMM_WORLD,&procsNum);//获取进程数目line = Length/procsNum;//将数据分为(进程数)个块A = (int*)malloc(sizeof(int)*Length*Length);B = (int*)malloc(sizeof(int)*Length*Length);C = (int*)malloc(sizeof(int)*Length*Length);buffer = (int*)malloc(sizeof(int)*Length*line);ans = (int*)malloc(sizeof(int)*Length*line);if (procsID==0){InitMatrix(A,B,Length);startTime = MPI_Wtime();for (i=1;i<procsNum;i++){MPI_Send(B,Length*Length,MPI_INT,i,0,MPI_COMM_WORLD);}for (i=1;i<procsNum;i++){MPI_Send(A+(i-1)*line*Length,Length*line,MPI_INT,i,1,MPI_COMM_WORLD);}for (k=1;k<procsNum;k++){MPI_Recv(ans,line*Length,MPI_INT,k,3,MPI_COMM_WORLD,&status);for (i=0;i<line;i++){for (j=0;j<Length;j++){C[((k-1)*line+i)*Length+j] =ans[i*Length+j];}}}for (i=(procsNum-1)*line;i<Length;i++){for (j=0;j<Length;j++){temp=0;for (k=0;k<Length;k++)temp += A[i*Length+k]*B[k*Length+j];C[i*Length+j]=temp;}}endTime = MPI_Wtime();totalTime=endTime-startTime;printf("并行稠密矩阵乘法过程总共花的时间:%.4fs\n", totalTime);}//ifelse{MPI_Recv(B,Length*Length,MPI_INT,0,0,MPI_COMM_WORLD,&status);MPI_Recv(buffer,Length*line,MPI_INT,0,1,MPI_COMM_WORLD,&status);for (i=0;i<line;i++){for (j=0;j<Length;j++){temp=0;for(k=0;k<Length;k++)temp += buffer[i*Length+k]*B[k*Length+j]; ans[i*Length+j]=temp;}}MPI_Send(ans,line*Length,MPI_INT,0,3,MPI_COMM_WORLD);}//elseMPI_Finalize();del();}串行计算的矩阵乘法源代码:DenseMulMatrixSerial.c#include<stdio.h>#include<stdlib.h>#include<time.h>#define Length 1000int *A,*B,*C;int i,j,k;clock_t startTime, endTime;double totalTime;void InitMatrix(int *M,int *N,int len);//实现部分见上面void del(){free(A);free(B);free(C);}int main(){A = (int *)malloc(sizeof(int)*Length*Length);B = (int *)malloc(sizeof(int)*Length*Length);C = (int *)malloc(sizeof(int)*Length*Length);InitMatrix(A,B,Length);startTime = clock();for(i = 0; i < Length; i ++){for(j = 0; j < Length; j ++){C[i * Length + j] = 0;for (k = 0; k < Length; ++k){C[i * Length + j] += A[i * Length + k] *B[k * Length + j];}}}//forendTime = clock();totalTime = (double)(endTime - startTime) / CLOCKS_PER_SEC;printf("串行稠密矩阵乘法过程总共花的时间:%.4fs\n",totalTime);del();}2.执行时间截图代码部分完成后,就要传到集群上去运行。

以下的截图是我在集群上运行程序的时间。

DensMulMatrixSerial.c:图1 稠密矩阵串行乘法DenseMulMatrixMPI.c,np=2:图2 np=2的稠密矩阵并行乘法DenseMulMatrixMPI.c,np=4:图3 np=4的稠密矩阵并行乘法DenseMulMatrixMPI.c,np=8:图4 np=8的稠密矩阵并行乘法DenseMulMatrixMPI.c,np=16:图5 np=16的稠密矩阵并行乘法DenseMulMatrixMPI.c,np=32:图6 np=32的稠密矩阵并行乘法SparseMulMatrixSerial.c图7稀疏矩阵串行乘法SparseMulMatrixMPI.c,np=2:图8 np=2的稀疏矩阵并行乘法SparseMulMatrixMPI.c,np=4:图9 np=4的稀疏矩阵并行乘法SparseMulMatrixMPI.c,np=8:图10 np=8的稀疏矩阵并行乘法SparseMulMatrixMPI.c,np=16:图11 np=16的稀疏矩阵并行乘法SparseMulMatrixMPI.c,np=32:图12 np=32的稀疏矩阵并行乘法3.统计数据分析矩阵相乘程序的执行时间、加速比:方阵阶固定为1000,为减少误差,每项实验进行5次,取平均值作为实验结果(一切时间数据均以以上截图为准)。

相关主题