用C语言实现的Jacobi迭代(MPI_SEND和MPI_RECV)

本文介绍使用C语言结合MPI_SEND和MPI_RECV函数实现Jacobi迭代法的并行计算过程。通过四个进程分工合作,每个进程负责矩阵的一部分,并通过MPI消息传递进行数据交换,实现迭代计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

至于原理,在这里我就不再叙述了,网上有很多资料或者教材都写得比较详细。这里仅仅介绍如何用C语言编写利用MPI_SEND和MPI_RECV实现Jacobi迭代。

#include <stdio.h>
#include "mpi.h"
#define totalsize 16 //定义常量,16行
#define mysize totalsize/4  //定义常量,4个进程,每块有totalsize/4列
#define steps 10//定义常量,设置迭代次数


int main(int argc,char **argv ){
	int n, myid, numprocs, i, j,rc; //声明变量
	float a[totalsize][mysize+2],b[totalsize][mysize+2];//定义二维数组
	float temp[totalsize];  //定义一个一维临时数组
	int begin_col,end_col,ierr;//声明变量
	MPI_Status status;
	MPI_Init( &argc, &argv );//初始化MPI
	MPI_Comm_rank( MPI_COMM_WORLD, &myid);//获取进程号
	MPI_Comm_size( MPI_COMM_WORLD, & numprocs);//获取当前通信域的进程总数
	fprintf(stderr,"Process %d of %d is alive\n",myid,numprocs);//打印

	//数组初始化
	/*
	每个进程各自初始化自己的部分,先将所有元素全部赋值为0.0
	C语言中,数组下标从0开始
	*/
	for (i=0;i < totalsize;i++){
		for (j=0;j < mysize+2;j++)
			a[i][j]=0.0;
	}
	/*
	0号进程,将第2列全部赋值为8.0(实际上是数据矩阵的第一列)
	*/
	if(myid==0){
		for(i=0;i < totalsize;i++)
			a[i][1]=8.0;
	}
	/*
	3号进程,将倒数第2列全部赋值为8.0(实际上是数据矩阵的最后一列)
	*/
	if(myid==3) {
        for(i=0;i<totalsize;i++) 
            a[i][mysize]=8.0;
	}
	/*
	每一个进程,将矩阵第1行和最后一行全部赋值为8.0
	*/
	for (j=1;j < mysize+1;j++){
		a[0][j]=8.0;
		a[totalsize-1][j]=8.0;
	}

	//Jacobi迭代部分
	for (n=1;n<=steps;n++){
		/*从右侧的邻居得到数据
		C语言中按行存储
		所以要先定义一个一维临时数组来接收数据
		*/
		if (myid<3){
			MPI_Recv(&temp[0],totalsize,MPI_FLOAT,myid+1,10,MPI_COMM_WORLD,&status);
			for(i=0;i<totalsize;i++){
				a[i][mysize+1]=temp[i];//a[i][mysize+1]为块的最后一列
			}
		}
		/*向左侧的邻居发送数据
		先将块的第2列提取到临时数组,然后再按顺序发送出去
		*/
		if (myid>0){
			for(i=0;i<totalsize;i++){
				temp[i]=a[i][1];//a[i][1]为块的第2列
			}
			MPI_Send(&temp[0],totalsize,MPI_FLOAT,myid-1,10,MPI_COMM_WORLD);
		}
		//向右侧的邻居发送数据
		if (myid<3){
			for(i=0;i<totalsize;i++){
				temp[i]=a[i][mysize];//a[i][mysize]为块的倒数第2列
			}
			MPI_Send(&temp[0],totalsize,MPI_REAL,myid+1,10,MPI_COMM_WORLD);
		}
		//从左侧的邻居得到数据
		if (myid>0){
			MPI_Recv(&temp[0],totalsize,MPI_REAL,myid-1,10,MPI_COMM_WORLD,&status);
			for(i=0;i<totalsize;i++){
				a[i][0]=temp[i];//a[i][0]为块的第一列
			}
		}

		begin_col=1,end_col=mysize;//开始列和结束列的列号
		if(myid==0){
			begin_col=2;//若为0号进程,开始列为块的第3列
		}
		if(myid==3){
			end_col=mysize-1;//若为3号进程,结束列为块的倒数第3列倒数,mysize+2-1-2=mysize-1
		}
		//第一行和最后一行也不参与迭代,所以i从1(第二行)到totalsize-1(最后一行)-1(下标)=totalsize-2
		for(i=1;i<=totalsize-2;i++){
			for(j=begin_col;j<=end_col;j++){
				b[i][j]=(a[i][j+1]+a[i][j-1]+a[i+1][j]+a[i-1][j])*0.25;//迭代计算
			}
		}
		//更新a矩阵 (将b中的元素值分别对应赋给a矩阵)以便进行下一次迭代
		for(i=1;i<=totalsize-2;i++){
			for(j=begin_col;j<=end_col;j++){
				a[i][j]=b[i][j];
			}
		}
	}//迭代结束

	/*输出结果*/
	fprintf(stderr,"\nProcess %d :\n",myid);
	//此处没有打印矩阵的第一行第一列,最后一行最后一列
	for(i=1;i<totalsize-1;i++){
		for(j=begin_col;j<=end_col;j++){
			fprintf(stderr,"%.2f\t",a[i][j]);//打印.(保留两位小数输出)
		}
		fprintf(stderr,"\n");//打印完一行之后换行
	}
	fprintf(stderr,"\n");  
	MPI_Finalize( );//结束MPI
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值