前言
萌新在做作业的时候发现网上搜不到这个题目,做完以后把自己的想法分享一下
一、题目
已知:𝑎[𝑖],𝑏[𝑖],𝑐[𝑖],𝑑[𝑖]
𝑥[0] , 𝑥[1], 𝑥[2]
x[i]=a[i]*x[i-1]+b[i] ∗ x[i-2]+c[i]*x[i-3] +d[i], i≥ 3
设计并行算法并用MPI实现,求: 𝑥[n]
二、分析
1.算法
2.MPI代码
代码如下:
#include <stdio.h>
#include "mpi.h"
#include<Windows.h>
#define M 200//设置一个比较大的值
#define N 4
int main(int argc, char*argv[])
{
int rank,size,n,s;//rank为进程号,size为最大进程号,s为进程数,n为x[n]的角标
doubleE[M][N],x[M],F[M][N];//F[i][0]=a[i],F[i][1]=b[i],F[i][2]=c[i],F[i][3]=d[i],E为子进程需要计算出的系数矩阵,x为未知数矩阵
int i,j,k;//定义循环变量
FILE *fp;//定义指针
MPI_Status status;
MPI_Init(&argc,&argv);
MPI_Comm_rank(MPI_COMM_WORLD,&rank);
MPI_Comm_size(MPI_COMM_WORLD,&size);
if(rank==0)
{
fp=fopen("D:\\1.txt","r+");
if(fp==NULL)//F:\\h.txt为文件地址
{
printf("cannot open file\n");
return 0;
}
printf("呵呵1哒");//调试的时候用于输出看看到底执行到哪里出错了
fscanf(fp,"%lf,%lf,%lf\n%d\n",&x[0],&x[1],&x[2],&n);//读取x[0],x[1],x[2],n
for(i=3;i<=n;i++)//从i=3处开始为F[i][j]赋值,因为i<3时F[i][j]无意义
{
fscanf(fp,"%lf,%lf,%lf,%lf",&F[i][0],&F[i][1],&F[i][2],&F[i][3]);
fscanf(fp,"\n");
}
fclose(fp);
printf("%d\n",n);
for(i=3;i<=n;i++) //验证数据读入是否正确
{
for(j=0;j<N;j++)
printf("%lf ",F[i][j]);
printf("\n");
}
for(i=0;i<size;i++)//i此时为进程号
{
printf("first level loop %d\n",size);
for(j=0;j<=((n-2)/size);j++)//j为第i个子进程的第j次计算,(n-1)/size为每个子进程计算计算次数
{
printf("second level loop \n");
for(k=0;k<=3;k++)
{
printf("third level loop \n");
MPI_Send(&F[i*(n-2)/size+j+3][k],1,MPI_DOUBLE,i,j,MPI_COMM_WORLD);//主进程发送递归矩阵,F[i*(n-2)/size+j+3][k]为i号进程第j次计算所需要的系数值,k=0时为a[i*(n-2)/size+j+3],k=1时为b[i*(n-2)/size+j+3],以此类推是c[i*(n-2)/size+j+3]和d[i*(n-2)/size+j+3]
}
}
}
}
//各进程计算E矩阵
for(j=0;j<=((n-2)/size-1);j++)//j为i号进程的第j次计算
for(k=0;k<=3;k++)
{
MPI_Recv(&F[(n-2)/size*rank+j+3][k],1,MPI_DOUBLE,0,j,MPI_COMM_WORLD,&status);//各进程接收数据
}
E[rank*(n-2)/size+2][0]=1;//为初始系数矩阵赋值
E[rank*(n-2)/size+2][1]=0;printf("1");//printf用于调试
E[rank*(n-2)/size+2][2]=0;printf("2");
E[rank*(n-2)/size+2][3]=0;
E[rank*(n-2)/size+1][0]=0;printf("4");
E[rank*(n-2)/size+1][1]=1;printf("5");
E[rank*(n-2)/size+1][2]=0;
E[rank*(n-2)/size+1][3]=0;
E[rank*(n-2)/size][0]=0;
E[rank*(n-2)/size][1]=0;
E[rank*(n-2)/size][2]=1;
E[rank*(n-2)/size][3]=0;
for(i=rank*(n-2)/size+3;i<=((rank+1)*(n-2)/size+2);i++) //求出E矩阵
{
for(k=0;k<=2;k++)//a[i],b[i],c[i]的代入计算
{
E[i][k]=F[i][0]*E[i-1][k]+F[i][1]*E[i-2][k]+F[i][2]*E[i-3][k];//k指的是假设已知的前三个x[i-k-1]值里面的k,E[i][k]代表其对应系数,如k=0指的是x[i-1]
}
E[i][3]=F[i][0]*E[i-1][3]+F[i][1]*E[i-2][3]+F[i][2]*E[i-3][3]+F[i][3];//d[i]的代入计算
}
for(k=0;k<=2;k++)
for(j=0;j<=2;j++)
{
MPI_Send(&E[(rank-2)*(n-2)/size+j][k],1,MPI_DOUBLE,0,k,MPI_COMM_WORLD);//各子进程将系数矩阵发送给0号进程
}
//0号进程负责最终计算
if(rank==0)
{
for(i=0;i<size;i++)
for(j=0;j<=2;j++)
for(k=0;k<=2;k++)
MPI_Recv(&E[(i+1)*(n-2)/size+j][k],1,MPI_DOUBLE,i,k,MPI_COMM_WORLD,&status);//各进程接收数据
for(i=0;i<=(size-1);i++)
for(j=0;j<=2;j++)
x[(i+1)*(n-2)/size+j]= E[(i+1)*(n-2)/size+j][0]*x[i*(n-2)/size+2] + E[(i+1)*(n-2)/size+j][1]*x[i*(n-2)/size+1] + E[(i+1)*(n-2)/size+j][2]*x[i*(n-2)/size] + E[(i+1)*(n-2)/size+3+j][3];//主进程计算出x[n]
fp=(fopen("D:\\1.txt","r+"));
fprintf(fp,"\n x[n]=:%lf \n",x[n]); //写入
fclose(fp);
printf("\nx[n]=%d",x[n]);
}
MPI_Finalize();
return 0;
system("pause");
}