MPI递归并行计算广义斐波那契(算法+源码)


前言

萌新在做作业的时候发现网上搜不到这个题目,做完以后把自己的想法分享一下


一、题目

已知:𝑎[𝑖],𝑏[𝑖],𝑐[𝑖],𝑑[𝑖]
𝑥[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");
}


总结

萌新第一次发,当时期末考试,代码没调试就交了,所以错误一大堆,欢迎批评指正
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值