MPI-jacobi迭代(雅克比迭代)C语言

这两天完成了jacobi迭代的算法,在此记录一下心得
算法原理部分是参考的链接

主要有以下注意点:
1.这个算法是需要再来申请一个数组的,如果不申请数组的话求出来的数就是乱的,也就是代码中的B,这个B可以用N/size那么大,但是我还没改。
2.进程:每一个进程负责一部分,然后呢就要说到最后printf这个数组的时候,不能用某一个rank来printf,每个进程只改变了一块的数据,如果想输出的话,需要在每个进程中挨个输出,我之前就是最后想用0进程全部输出出来,但是发现只有0进程的数据进行了更新,其他的并没有更新,后来才改正确。
3.输出的时候最好是设置一个信号量,也就是代码中的x,让进程输出是按照顺序输出的,这样比较好检查。

这个代码中代码重复量比较大,接下来会将大量冗余代码封装成函数,然后传数据的时候采用指针来传送,还有就是,这个代码还没有测性能,这些都等着接下来再高吧!

代码如下,有大量的注释,数组用的是8*8的测试

#include<stdio.h>
#include<stdlib.h>
#include<mpi.h>
#include<time.h>

//int N = 8; // 这个代表的意思是本身的矩阵是400行的矩阵,然后在各个分块的上下各加一行,用来进程传递信息 
#define N 8
float B[N][N];


int main(int arg, char* argv[]){
	
	MPI_Init(&arg, &argv);
	int size, rank;
	MPI_Comm_size(MPI_COMM_WORLD, &size);
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);
	MPI_Status status;
	
	//首先创建一下二维数组
	int i, j, k, x, y;
	float A[N + 8][N];
	int size2 = (N+8)/4;
//	float (*p)[N + 8] = A; 等完事了用指针试一下 ,直接传一个指针 
	srand(time(0));
	for(i = 0; i < N + 8; i++){
		if(i != 0 && i != size2 - 1 && i != size2 && i != 2*size2 - 1 && i != 2*size2 && i != 3*size2 - 1 && i != 3*size2 && i != 4*size2 - 1) 
			for(j = 0; j < N; j++){
				A[i][j] = rand() % 10;
			}
		else{
			for(k = 0; k < N; k++){
				A[i][k] = 0.0;
			}
		}
	}
	
	if(rank == 0){
		for(i = 0; i < N + 8;i++){
			if(i != 0 && i != size2 - 1 && i != size2 && i != 2*size2 - 1 && i != 2*size2 && i != 3*size2 - 1 && i != 3*size2 && i != 4*size2 - 1){
				printf("\n");
				for(j = 0;j < N;j++){
					printf("%f ", A[i][j]);
				}
		}
		}
	} 
	
	printf("\n");
	
	int m = 0;
	//int pr = N / 4; //因为本机是4核的, 所以就用4个进程
	if(rank == 0){ // 0号进程处理的是矩阵中第0行到第N/4 - 1行 
		for(k = 0; k < N; k++){
			MPI_Send(&A[size2 - 2][k], 1, MPI_FLOAT, rank + 1, k, MPI_COMM_WORLD); 
			
		} 
		
		for(k = 0; k < N; k++){// 接收1号进程发来的消息 
			MPI_Recv(&A[size2 - 1][k], 1, MPI_FLOAT, rank + 1, k, MPI_COMM_WORLD, &status);
		} 
		
		// 赋值+计算
		for(i = 1; i < size2 - 1;i++){
			if(i == 1){
				for(j = 0;j < N;j++){
					B[i-1][j] = A[i][j];
				}
			}
			else{
				for(j = 0;j < N;j++){
					if(j == 0 || j == N-1){
						
						B[m][j] = A[i][j];
					} 
					else{
//						B[i-1][j] = 0.25 * (A[i-1][j] + A[i][j-1] + A[i+1][j] + A[i][j+1]);
						B[m][j] = 0.25 * (A[i-1][j] + A[i][j-1] + A[i+1][j] + A[i][j+1]);
						
					}
				}
			}
			m += 1;
		}
		
		// 给1发消息阻塞一下 
		MPI_Send(&y, 1, MPI_INT, 1, 200, MPI_COMM_WORLD);
		for(i = 0;i < N/size;i++){
			printf("\n");
			for(j = 0; j < N;j++){
				printf("%f ", B[i][j]);
			}
		}
		
	}
	else if(rank == 1){
		
		for(k = 0; k < N; k++){//不整一些花里胡哨,直接把 N/4 - 1行全传过去	
//			if(k == 0){
//				printf("\n  %d \n", A[size2][k]);
//			}
			// 给2号进程发消息
			MPI_Send(&A[2 * size2 - 2][k], 1, MPI_FLOAT, rank + 1, k, MPI_COMM_WORLD); 
			// 给0号进程发消息
			MPI_Send(&A[size2 + 1][k], 1, MPI_FLOAT, rank - 1, k, MPI_COMM_WORLD); 	
			// 收0号进程给发过来的消息
			MPI_Recv(&A[size2][k], 1, MPI_FLOAT, rank - 1, k, MPI_COMM_WORLD, &status); 
			
		}
		
//		printf("\n=================================================\n");
//		for(i = 0; i < N;i++){
//			printf("%f ",A[size2][i] );
//		}	
		// 接收2号进程发来的消息 
		for(k = 0; k < N; k++){
			MPI_Recv(&A[2*size2 - 1][k], 1, MPI_FLOAT, rank + 1, k, MPI_COMM_WORLD, &status);
			
		}
		
//		printf("\n=================================================\n");
//		
//		for(i = 0; i < N;i++){
//			printf("%f ",A[2*size2 - 1][i] );
//		}	
		
		// 赋值+计算
		for(i = size2 + 1; i < 2*size2 - 1;i++){
			for(j = 0;j < N;j++){
				if(j == 0 || j == N-1){
					B[m][j] = A[i][j];
				} 
				else{
//					B[i-2 * rank - 1][j] = 0.25 * (A[i-1][j] + A[i][j-1] + A[i+1][j] + A[i][j+1]);
					B[m][j] = 0.25 * (A[i-1][j] + A[i][j-1] + A[i+1][j] + A[i][j+1]);
					
				}
			}
			m += 1;
		}
		
		MPI_Recv(&x, 1, MPI_INT, 0, 200, MPI_COMM_WORLD, &status);
		
		
//		for(i = N/size;i < 2 * N/size - 1;i++){
//			printf("\n");
//			for(j = 0; j < N;j++){
//				printf("%f ", B[i][j]);
//			}
//		}
		for(i = 0;i < N/size;i++){
			printf("\n");
			for(j = 0; j < N;j++){
				printf("%f ", B[i][j]);
			}
		}
		MPI_Send(&x, 1, MPI_INT, 2, 200, MPI_COMM_WORLD);
		
		
	
		
		
	}
	else if(rank == 2){
		// 给3号进程和2号进程发消息 
		for(k = 0; k < N; k++){//不整一些花里胡哨,直接把 N/4 - 1行全传过去
			// 接收1号进程发来的消息 
			
			MPI_Send(&A[3 * size2 - 2][k], 1, MPI_FLOAT, rank + 1, k, MPI_COMM_WORLD); 
			MPI_Send(&A[2*size2 + 1][k], 1, MPI_FLOAT, rank - 1, k, MPI_COMM_WORLD); 
			MPI_Recv(&A[2*size2][k], 1, MPI_FLOAT, rank - 1, k, MPI_COMM_WORLD, &status);
			
		} 
//		printf("\n=================================================\n");
//		for(i = 0; i < N;i++){
//			printf("%f ",A[2*size2][i] );
//		}	
		
		// 接收3号进程发来的消息 
		for(k = 0; k < N; k++){
			MPI_Recv(&A[3*size2 - 1][k], 1, MPI_FLOAT, rank + 1, k, MPI_COMM_WORLD, &status); 
		}
		
//		printf("\n=================================================\n");
//		
//		for(i = 0; i < N;i++){
//			printf("%f ",A[3*size2 - 1][i] );
//		}	
		
		// 赋值+计算
		for(i = 2*size2 + 1; i < 3*size2 - 1;i++){
			for(j = 0;j < N;j++){
				if(j == 0 || j == N-1){
					B[m][j] = A[i][j];
				} 
				else{
//					B[i-3 * rank - 1][j] = 0.25 * (A[i-1][j] + A[i][j-1] + A[i+1][j] + A[i][j+1]);
					B[m][j] = 0.25 * (A[i-1][j] + A[i][j-1] + A[i+1][j] + A[i][j+1]);
					
				}
			}
			m += 1;
		}
		
		
		MPI_Recv(&x, 1, MPI_INT, 1, 200, MPI_COMM_WORLD, &status);
		
		
//		for(i = 2*N/size + 1;i < 3*N/size - 1; i++){
//			printf("\n");
//			for(j = 0; j < N;j++){
//				printf("%f ", B[i][j]);
//			}
//		}
		for(i = 0;i < N/size;i++){
			printf("\n");
			for(j = 0; j < N;j++){
				printf("%f ", B[i][j]);
			}
		}
		MPI_Send(&x, 1, MPI_INT, 3, 200, MPI_COMM_WORLD);
		
	
		
	}
	else{
		// 给2号进程发消息 
		for(k = 0; k < N; k++){
			MPI_Send(&A[3*size2 + 1][k], 1, MPI_FLOAT, rank - 1, k, MPI_COMM_WORLD);
		}
		
		// 接收2号进程发来的消息 
		for(k = 0; k < N; k++){
			MPI_Recv(&A[3*size2][k], 1, MPI_FLOAT, rank - 1, k, MPI_COMM_WORLD, &status);
		}
		
		// 赋值+计算
		for(i = 3*size2 + 1; i < 4*size2 - 1;i++){
			if( i == 4*size2 - 2){
				for(j = 0;j < N;j++){
					B[i-4 * rank - 1][j] = A[i][j];
				}
			}
			else{
				for(j = 0;j < N;j++){
					if(j == 0 || j == N-1){
						B[m][j] = A[i][j];
					} 
					else{
//						B[i-4 * rank - 1][j] = 0.25 * (A[i-1][j] + A[i][j-1] + A[i+1][j] + A[i][j+1]);
						B[m][j] = 0.25 * (A[i-1][j] + A[i][j-1] + A[i+1][j] + A[i][j+1]);
						
					}
				}
			}
			m += 1;
		}
		
		MPI_Recv(&x, 1, MPI_INT, 2, 200, MPI_COMM_WORLD, &status);
		
//		for(i = 3* N/size + 1;i < 4*N/size - 1; i++){
//			printf("\n");
//			for(j = 0; j < N;j++){
//				printf("%f ", B[i][j]);
//			}
//		}
		for(i = 0;i < N/size;i++){
			printf("\n");
			for(j = 0; j < N;j++){
				printf("%f ", B[i][j]);
			}
		}
	}
	printf("\n");
	MPI_Barrier(MPI_COMM_WORLD);
	MPI_Finalize();
	return 0;
	
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值