LU 分解,给出采用行连续划分方式下的 MPI 实现
㈠实验并行算法描述:
⑴首先从 dataIn.txt 中读取矩阵数据,读取工作由进程 0 完成,然后是数据的
分发。文件中的头两个元素是矩阵的行列 M,N,它们必须相等,否则输入错误。
为 A 开辟一个 M*M 个 floatsize 大小的内存空间,并将文件中的矩阵数据发给它。
⑵0 号处理器将 M 广播给所有处理器。通信域中的处理器数为 p,则分配至各处理
器的子矩阵大小为 m*M,其中 m=M/p,开辟一个 m*M*floatsize 大小的内存 a 存放
子矩阵,再开辟 M*floatsize 大小内存 f 作为各处理器为主行元素建立发送和接
受缓冲区。0 号处理器再为 l 和 u 矩阵分配内存。
⑶0 号处理器采用连续划分将矩阵 A 划分为大小 m*M 的 p 块子矩阵,依次发送给
1 至 p-1 号处理器
⑷对矩阵进行 LU 分解,外层循环 i 代表处理器号,内存循环 j 是每个处理器中
子矩阵的行数。若当前处理的主行在本处理器,v=i*m+j,是当前处理的主行号,
将主行元素都存到数组 f,向其他所有处理器广播主行元素;若当前处理的主行
不在本处理器,则接收主行所在处理器广播来的主元素。若 i=my_rank,利用主
行元素对其 j+1 至 m-1 行数据作行变换,若 my_rank>i,利用主行元素对其 0 至
m-1 行数据作行变换。
⑸0 号处理器从其余各进程中接收子矩阵 a,得到经过变换的矩阵 A,l 就是其下
三角矩阵,u 就是其上三角矩阵。
㈡程序源代码:
#include "stdio.h"
#include "stdlib.h"
#include "mpi.h"
#define a(x,y) a[x*M+y]
/*A 为 M*M 矩阵*/
#define A(x,y) A[x*M+y]
#define l(x,y) l[x*M+y]
#define u(x,y) u[x*M+y]
#define floatsize sizeof(float)
#define intsize sizeof(int)
int M,N;
int m;
float *A;
int my_rank;
int p;
MPI_Status status;
void fatal(char *message)
{
}
printf("%s\n",message);
exit(1);
void Environment_Finalize(float *a,float *f)
{
free(a);
free(f);
}
int main(int argc, char **argv)
{
int i,j,k,my_rank,group_size;
int i1,i2;
int v,w,MM;
float *a,*f,*l,*u;
FILE *fdA;
double time1,time2;
MPI_Init(&argc,&argv);
MPI_Comm_size(MPI_COMM_WORLD,&group_size);
MPI_Comm_rank(MPI_COMM_WORLD,&my_rank);
p=group_size;
time1=MPI_Wtime();
if (my_rank==0)
{
fdA=fopen("dataIn.txt","r");
fscanf(fdA,"%d",&M);
A=(float *)malloc(floatsize*M*M);
for(i = 0; i < M; i ++)
for(j = 0; j < M; j ++)
fscanf(fdA, "%f", A+i*M+j);
fclose(fdA);
}
/*0 号进程将 M 广播给所有进程*/
MPI_Bcast(&M,1,MPI_INT,0,MPI_COMM_WORLD);
m=M/p;
if (M%p!=0) m++;
/*分配至各进程的子矩阵大小为 m*M*/
a=(float*)malloc(floatsize*m*M);
/*各进程为主行元素建立发送和接收缓冲区*/
f=(float*)malloc(floatsize*M);
/*0 号进程为 l 和 u 矩阵分配内存,以分离出经过变换后的 A 矩阵中的 l 和
u 矩阵*/
if (my_rank==0)
{
l=(float*)malloc(floatsize*M*M);
u=(float*)malloc(floatsize*M*M);
}
if (a==NULL) fatal("allocate error\n");
if (my_rank==0)
{
for(i=0;i
=M) break;
MPI_Recv(&a(i,0),M,MPI_FLOAT,0,i,MPI_COMM_WORLD,&status);
}
}
for(i=0;i=M) break;
for(j=0;j=M) break;
if (my_rank==i)
{
v=i*m+j;
for (k=v;ki)
for(k=0;k=M) break;
MPI_Send(&a(i,0),M,MPI_FLOAT,0,m*my_rank+i,MPI_COMM_WORLD);
}
}
if(my_rank==0)
{
for(i=1;i
=M) break;
MPI_Recv(&a(j,0),M,MPI_FLOAT,i,m*i+j,MPI_COMM_WORLD,&status);
for(k=0;kj)
l(i,j)=A(i,j);
else
u(i,j)=A(i,j);
printf("Input of file \"dataIn.txt\"\n");
printf("%d\t\n",M);
for(i=0;ifor(i=0;i
⑶设置通信域中的进程数为 9
⑷设置通信域中的进程数为 18
⑸设置通信域中的进程数为 25