记一次使用MPI完成矩阵乘法程序

记录使用MPI完成矩阵乘法程序的过程。

一、MPI安装

在linux系统中,输入命令:

sudo apt-get install mpich

如果要卸载,则输入:

sudo apt-get --purge remove mpich

二、矩阵乘法程序

1.初始化

由于我们要使用MPI传递二维数组,故这里我们创建三个N*N的一维数组A、B、C以便后续数据传输。

    double *A = new double [n*n];
    double *B = new double [n*n];
    double *partA = new double [n*n];
    double *partC = new double [n*n];


    if(myid==0){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i<N && j<N){
                    A[i*n+j] = rand()%10;
                    B[i*n+j] = rand()%10;
                }else{
                    A[i*n+j] = 0;
                    B[i*n+j] = 0;
                }
                
            }
        }
        startWtime = MPI_Wtime();
    }
2.矩阵乘法

普通矩阵乘法只需要3个for循环即可,但考虑到Cache存储,我们可以将一个矩阵转置过来,提高Cache命中率:

void matM(double *A,double *B,double *C,int divideN,int n){//cache
    double mid;
    for(int i=0;i<divideN;i++)for(int j=0;j<i;j++){
        mid=B[i*n+j];
        B[i*n+j]=B[j*n+i];
        B[j*n+i]=mid;
    }
    for(int i=0;i<divideN;i++){
            for(int j=0;j<n;j++){
                C[i*n+j]=0;
                for(int k=0;k<n;k++){
                    C[i*n+j]+=A[i*n+k] * B[j*n+k];
                }
            }
        }
    for(int i=0;i<divideN;i++)for(int j=0;j<i;j++){
        mid=B[i*n+j];
        B[i*n+j]=B[j*n+i];
        B[j*n+i]=mid;
    }
}
3.并行矩阵乘法程序
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <stdbool.h>
#include <iostream>
#include <mpi.h>
#define N 8000

void matM(double *A,double *B,double *C,int divideN,int n){//cache
    double mid;
    for(int i=0;i<divideN;i++)for(int j=0;j<i;j++){
        mid=B[i*n+j];
        B[i*n+j]=B[j*n+i];
        B[j*n+i]=mid;
    }
    for(int i=0;i<divideN;i++){
            for(int j=0;j<n;j++){
                C[i*n+j]=0;
                for(int k=0;k<n;k++){
                    C[i*n+j]+=A[i*n+k] * B[j*n+k];
                }
            }
        }
    for(int i=0;i<divideN;i++)for(int j=0;j<i;j++){
        mid=B[i*n+j];
        B[i*n+j]=B[j*n+i];
        B[j*n+i]=mid;
    }
}

int main(int argc,char *argv[])
{
    double startWtime=0.0,endWtime=0.0;
    int myid,numProcs,jud=0;
    MPI_Init(&argc, &argv );
    MPI_Comm_rank(MPI_COMM_WORLD, &myid );
    MPI_Comm_size(MPI_COMM_WORLD, &numProcs );

    int n=0;
    if (N % numProcs!=0){
        n=N-N%numProcs+numProcs;
    }else{
        n=N;
    }
    int divideN = n/numProcs;

    srand(1);//保持一致性
    double *A = new double [n*n];
    double *B = new double [n*n];
    double *partA = new double [n*n];
    double *partC = new double [n*n];


    if(myid==0){
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(i<N && j<N){
                    A[i*n+j] = rand()%10;
                    B[i*n+j] = rand()%10;
                }else{
                    A[i*n+j] = 0;
                    B[i*n+j] = 0;
                }
                
            }
        }
        startWtime = MPI_Wtime();
    }
    
        MPI_Scatter(&A[0*n+0],divideN *n,MPI_DOUBLE,&partA[0*n+0],divideN *n,MPI_DOUBLE,0,MPI_COMM_WORLD);
        MPI_Bcast(&B[0*n+0],n*n,MPI_DOUBLE,0,MPI_COMM_WORLD);

        matM(partA,B,partC,divideN,n);
        
    double *C = nullptr;
    if(myid==0) C = new double [n*n];
        MPI_Gather(&partC[0*n+0],divideN *n,MPI_DOUBLE,&C[0*n+0],divideN *n,MPI_DOUBLE,0,MPI_COMM_WORLD);
    if(myid==0){
        endWtime = MPI_Wtime();
        printf("用时: %.3f 秒\n", endWtime-startWtime);
    }

    delete []A;
    delete []B;
    delete []C;
    delete []partA;
    delete []partC;
    MPI_Finalize();
    
    return 0;
}

三、结果

参考:

Linux下的MPI安装(类比linux软件的安装方式)_linux安装mpi-CSDN博客

【MPI学习笔记】1:并行化向量和矩阵的乘积_矩阵和向量乘法并行计算mpi-CSDN博客

并行程序设计实验_编写一个矩阵乘法的gpu并行程序,并且与对应规模的串行程序进行运行时间的比对(n=5-CSDN博客

并行矩阵乘法(C++ mpi 并行实现)_分块矩阵乘法并行-CSDN博客

高性能计算实验——矩阵乘法基于MPI的并行实现及优化_mpi矩阵乘法-CSDN博客

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于MPI实现矩阵乘法的示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <mpi.h> #define N 100 int main(int argc, char *argv[]) { int rank, size; int i, j, k; int A[N][N], B[N][N], C[N][N]; int rowA[N], rowC[N]; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); if (size != N) { printf("Error: number of processes must be %d\n", N); MPI_Finalize(); return 0; } // Initialize matrices A and B for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { A[i][j] = i + j; B[i][j] = i - j; C[i][j] = 0; } } // Scatter matrix A to all processes MPI_Scatter(A, N*N/N, MPI_INT, rowA, N, MPI_INT, 0, MPI_COMM_WORLD); // Broadcast matrix B to all processes MPI_Bcast(B, N*N, MPI_INT, 0, MPI_COMM_WORLD); // Compute rows of matrix C for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { rowC[j] = 0; for (k = 0; k < N; k++) { rowC[j] += rowA[k] * B[k][j]; } } MPI_Reduce(rowC, &C[i], N, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD); } // Gather matrix C from all processes MPI_Gather(rowC, N*N/N, MPI_INT, C, N*N/N, MPI_INT, 0, MPI_COMM_WORLD); // Print matrix C if (rank == 0) { printf("Matrix C:\n"); for (i = 0; i < N; i++) { for (j = 0; j < N; j++) { printf("%d ", C[i][j]); } printf("\n"); } } MPI_Finalize(); return 0; } ``` 该程序矩阵A均分给所有进程,每个进程计算矩阵C的一行。使用MPI_Reduce函数将每个进程计算出的行向量相加,得到最终的矩阵C。最后,使用MPI_Gather函数将矩阵C收集到进程0中,并打印输出。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值