矩阵乘法-MPI函数Scatte,Bcast

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include <mpi.h>
#include <malloc.h>
#include <time.h>

#define M 4
#define K 4
#define N 4


void initial(int *array, int size)
{
	for (int i = 0; i < size; i++)
	{
		array[i] = (int)(rand() % 10 + 1);
	}
}


void printMatrix(int *array, int row, int col)
{
	int *p = array;
	for (int y = 0; y < row; y++)
	{
		printf("第%d行:", y);
		for (int x = 0; x < col; x++)
		{
			printf("%5d", p[x]);
		}
		p = p + col;
		printf("\n");
	}

}



void  multiplicateMatrix(int *array_A, int *array_B, int *array_C, int MM, int KK, int NN)
{
	for (int i = 0; i < MM; i++)
	{

		for (int j = 0; j < NN; j++)
		{
			int sum = 0;
			for (int k = 0; k < KK; k++)
			{
				sum += array_A[i*KK + k] * array_B[k*NN + j];
			}
			array_C[i*NN + j] = sum;              /*结果矩阵和*/
		}
	}
}



int main(int argc, char *argv[])
{
	int numprocs,my_rank;
	int *A, *B, *result, *local_a, *local_result;
	double start,finish,time;
	double beginTime, endTime; // time record
	int local_m;
	int A_xy = M * K;
	int B_xy = K * N;
	int result_xy = M * N;
	A = (int*)malloc(A_xy * sizeof(int));
	B = (int*)malloc(B_xy * sizeof(int));
	result = (int*)malloc(result_xy * sizeof(int));
	
	MPI_Init(NULL, NULL);
	MPI_Comm_size(MPI_COMM_WORLD, &numprocs);
	MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);
	
	
	
	
	if (numprocs == 1)
	{
		initial(A, M*K);
		printf("\n");
		printf("   Matrix_A: (%d×%d)\n", M, K);
		printMatrix(A, M, K);
		initial(B, K*N);
		printf("   Matrix_B: (%d×%d)\n", K, N);
		printMatrix(B, K, N);

		printf("\n");
		printf("   ------------------------------------------------------------------------------------\n");
		printf("   Computing matrix product using multiplicateMatrix \n");
		printf("   ------------------------------------------------------------------------------------\n\n");


		/*调用multiplicateMatrixOnHost并进行计时*/
		start = clock();
		multiplicateMatrix(A, B, result, M, N, K);
		finish = clock();
		time = (int)(finish - start) / CLOCKS_PER_SEC;
		printf("   Matrix_C: (%d×%d)  CPU运行时间为:%lfs\n\n\n", M, N, time);
		printMatrix(result, M, N);

		free(A);
		free(B);
		free(result);

	}
	else {

		//0号进程用于读取矩阵,分发数据,一部分计算和聚集打印数据MPI_INT
		if (my_rank == 0) {

			initial(A, M*K);
			printf("\n");
			printf("   Matrix_A: (%d×%d)\n", M, K);
			printMatrix(A, M, K);
			initial(B, K*N);
			printf("   Matrix_B: (%d×%d)\n", K, N);
			printMatrix(B, K, N);

			printf("\n");
			printf("   ------------------------------------------------------------------------------------\n");
			printf("   Computing matrix product using MPI_matrix_scatter \n");
			printf("   ------------------------------------------------------------------------------------\n\n");


			

			beginTime = MPI_Wtime();
			//分发数据
			local_m = M / numprocs;
			local_a = (int *)malloc(sizeof(int)*local_m*K);                //内存
			MPI_Scatter(A, local_m*K, MPI_INT, local_a, local_m*K, MPI_INT, 0, MPI_COMM_WORLD);
			//   数组A地址  给每个进程发送数据个数  数据类型  接受缓存地址  接受个数 数据类型  进程编号 通信子
			//将b矩阵广播到其他进程
			MPI_Bcast(B, K*N, MPI_INT, 0, MPI_COMM_WORLD);

			//进行分得的部分计算
			local_result = (int *)malloc(sizeof(int)*local_m*N);
			int p;
			for (int i = 0; i < local_m; i++)
				for (int j = 0; j < N; j++)
				{
					local_result[i*N + j] = 0;
					for (p = 0; p < K; p++)
						local_result[i*N + j] += local_a[i*K + p] * B[p*N + j];
				}

		
			
			printf("==============================================================================================\n");
			printf("进程号:%d     local_result值:\n", my_rank);
				for (int i = 0; i < local_m; i++)
				{
					printf("第%d行:",i);
					for (int j = 0; j < K; j++)
					{
						printf("%3d  ", local_result[i*K+j]);
					}
					printf("\n");
				}
			printf("==============================================================================================\n");
				

		

			//将各进程结果聚集到result矩阵
			MPI_Gather(local_result, local_m*N, MPI_INT, result, local_m*N, MPI_INT, 0, MPI_COMM_WORLD);

			
	
			

			printf("==============================================================================================\n");
			printf("进程号:%d result值:\n", my_rank);
			for (int i = 0; i <M; i++)
			{
				printf("第%d行:", i);
				for (int j = 0; j < N; j++)
				{
					printf("%3d  ", result[i*N + j]);
				}
				printf("\n");
			}
			printf("==============================================================================================\n");






			//不能整除的情况下a剩余行的处理
			int rest = M % numprocs;
			if (rest != 0) {
				for (int i = M - rest; i < M; i++)
				{
					for (int j = 0; j < N; j++)
					{
						result[i*N + j] = 0;
						//		printf("result 下标:%d,值:%d\n", i*N + j, result[i*N + j]);
						for (p = 0; p < K; p++)
						{
							result[i*N + j] += A[i*K + p] * B[p*N + j];
							//		printf("进程号:%d,未能整除:i=%d,j=%d,p=%d,A下标:%d,A值:%10lf, B下标:%d, B值:%10lf, result下标:%d, result值:%10lf \n",
							//		my_rank, i, j, p, i*K + p, A[i*K + p], p*N + j, B[p*N + j], i*N + j, result[i*N + j]);
						}

					}
				}
			}

			endTime = MPI_Wtime();

		//	printf("   Matrix_hostRef: (%d×%d)  numprocs:%d  CPU运行时间为:%lfs\n\n\n\n", M, N, numprocs, endTime - beginTime);
			//	将result中结果打印出来
			printf("   Matrix_hostRef: (%d×%d)  numprocs:%d \n", M, N, numprocs);
			printMatrix(result, M, N);

			free(A);
			free(B);
			free(local_a);
			free(local_result);
			free(result);
		}
		else {
			//其他进程所做的工作和0号进程的计算是一模一样的,所以可以直接复制代码
			local_m = M / numprocs;
			local_a = (int *)malloc(sizeof(int)*local_m*K);
			MPI_Scatter(A, local_m*K, MPI_INT, local_a, local_m*K, MPI_INT, 0, MPI_COMM_WORLD);

			MPI_Bcast(B, K*N, MPI_INT, 0, MPI_COMM_WORLD);
			local_result = (int *)malloc(sizeof(int)*local_m*N);

			for (int i = 0; i < local_m; i++)
				for (int j = 0; j < N; j++)
				{
					local_result[i*N + j] = 0;
					for (int p = 0; p < K; p++)
					{
						local_result[i*N + j] += local_a[i*K + p] * B[p*N + j];
					}
				}

			
		


			
			printf("==============================================================================================\n");
			printf("进程号:%d     local_result值:\n", my_rank);
			for (int i = 0; i < local_m; i++)
			{
				printf("第%d行: ", i);
				for (int j = 0; j < K; j++)
				{
					printf("%3d  ", local_result[i*K + j]);
				}
				printf("\n");
			}
			printf("==============================================================================================\n");





			MPI_Gather(local_result, local_m*N, MPI_INT, result, local_m*N, MPI_INT, 0, MPI_COMM_WORLD);


			free(A);
			free(B);
			free(local_a);
			free(local_result);
			free(result);
		}

	}



	


	MPI_Finalize();

	return 0;
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值