使用Mpi_Scatter和Mpi_Gather进行矩阵乘法 [英] matrix multiplication using Mpi_Scatter and Mpi_Gather

查看:392
本文介绍了使用Mpi_Scatter和Mpi_Gather进行矩阵乘法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是mpi编程的新手.我试图写矩阵乘法.通过帖子具有散点集的MPI矩阵乘有关使用散点和收集例行程序. 我试图修改上面帖子中提供的代码,如下所示...

I newbie to mpi programming. I was trying to write matrix multiplication. Went through the post MPI Matrix Multiplication with scatter gather about matrix multiplication using scatter and gather routine. I tried modifying the code available on above post as below...

#define N 4
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stddef.h>
#include "mpi.h"


void print_results(char *prompt, int a[N][N]);

int main(int argc, char *argv[])
{
    int i, j, k, rank, size, tag = 99, blksz, sum = 0;
    int a[N][N]={{1,2,3,4},{5,6,7,8},{9,1,2,3},{4,5,6,7,}};
    int b[N][N]={{1,2,3,4},{5,6,7,8},{9,1,2,3},{4,5,6,7,}};
    int c[N][N];
    int aa[N],cc[N];

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    //scatter rows of first matrix to different processes     
    MPI_Scatter(a, N*N/size, MPI_INT, aa, N*N/size, MPI_INT,0,MPI_COMM_WORLD);

    //broadcast second matrix to all processes
    MPI_Bcast(b, N*N, MPI_INT, 0, MPI_COMM_WORLD);

    MPI_Barrier(MPI_COMM_WORLD);

          //perform vector multiplication by all processes
          for (i = 0; i < N; i++)
            {
                    for (j = 0; j < N; j++)
                    {
                            sum = sum + aa[j] * b[i][j];                
                    }
                    cc[i] = sum;
                    sum = 0;
            }

    MPI_Gather(cc, N*N/size, MPI_INT, c, N*N/size, MPI_INT, 0, MPI_COMM_WORLD);

    MPI_Barrier(MPI_COMM_WORLD);        
    MPI_Finalize();
    print_results("C = ", c);
}

void print_results(char *prompt, int a[N][N])
{
    int i, j;

    printf ("\n\n%s\n", prompt);
    for (i = 0; i < N; i++) {
            for (j = 0; j < N; j++) {
                    printf(" %d", a[i][j]);
            }
            printf ("\n");
    }
    printf ("\n\n");
}

我在程序上方运行

$mpirun -np 4 ./a.out

对于上述程序,我得到以下错误输出.

For above program I am getting following incorrect output..

C = 
 0 0 -562242168 32766
 1 0 4197933 0
 -562242176 32766 0 0
 4197856 0 4196672 0

C = 
 0 0 -1064802792 32765
 1 0 4197933 0
 -1064802800 32765 0 0
 4197856 0 4196672 0

C = 
 30 70 29 60
 70 174 89 148
 29 89 95 74
 60 148 74 126

C = 
 0 0 -1845552920 32765
 1 0 4197933 0
 -1845552928 32765 0 0
 4197856 0 4196672 0

我有以下查询 1.为什么所有过程都打印结果矩阵C.它是 应该只能通过主要流程进行打印. 2.为什么打印的结果不正确?

I have following queries 1. Why result matrix C is getting printed by all processes. It is supposed to be printed by only main process. 2. Why incorrect result is being printed?

在此方面的纠正和帮助,将不胜感激.

Corrections and help in this regard will be appreciated.

推荐答案

所有进程都将打印结果矩阵c,因为每个进程都执行函数void print_results(char *prompt, int a[N][N]).由于您正在收集排名为0的进程,因此请在调用print_results(...)函数之前添加一条语句if (rank == 0).此外,由于错误的循环逻辑,结果是不正确的:

The result matrix c is getting printed by all processes because every process executes the function void print_results(char *prompt, int a[N][N]). Since you are gathering at the process having rank 0, add a statement if (rank == 0) before calling the print_results(...) function. Further, the result is incorrect because of a wrong loop logic in :

                for (j = 0; j < N; j++)
                {
                        sum = sum + aa[j] * b[i][j];                
                }

这应该是:

                for (j = 0; j < N; j++)
                {
                        sum = sum + aa[j] * b[j][i];                
                }

也无需广播b,因为所有进程都已经有它的副本,您可以避免使用MPI_Barrier().完整的程序将变为:

Also there is no need to broadcast b as all processes already already have a copy of it and you can avoid MPI_Barrier(). The complete program then becomes :

#define N 4
#include <stdio.h>
#include <math.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stddef.h>
#include "mpi.h"


void print_results(char *prompt, int a[N][N]);

int main(int argc, char *argv[])
{
    int i, j, k, rank, size, tag = 99, blksz, sum = 0;
    int a[N][N]={{1,2,3,4},{5,6,7,8},{9,1,2,3},{4,5,6,7,}};
    int b[N][N]={{1,2,3,4},{5,6,7,8},{9,1,2,3},{4,5,6,7,}};
    int c[N][N];
    int aa[N],cc[N];

    MPI_Init(&argc, &argv);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);

    //scatter rows of first matrix to different processes     
    MPI_Scatter(a, N*N/size, MPI_INT, aa, N*N/size, MPI_INT,0,MPI_COMM_WORLD);

    //broadcast second matrix to all processes
    MPI_Bcast(b, N*N, MPI_INT, 0, MPI_COMM_WORLD);

    MPI_Barrier(MPI_COMM_WORLD);

          //perform vector multiplication by all processes
          for (i = 0; i < N; i++)
            {
                    for (j = 0; j < N; j++)
                    {
                            sum = sum + aa[j] * b[j][i];  //MISTAKE_WAS_HERE               
                    }
                    cc[i] = sum;
                    sum = 0;
            }

    MPI_Gather(cc, N*N/size, MPI_INT, c, N*N/size, MPI_INT, 0, MPI_COMM_WORLD);

    MPI_Barrier(MPI_COMM_WORLD);        
    MPI_Finalize();
    if (rank == 0)                         //I_ADDED_THIS
        print_results("C = ", c);
}

void print_results(char *prompt, int a[N][N])
{
    int i, j;

    printf ("\n\n%s\n", prompt);
    for (i = 0; i < N; i++) {
            for (j = 0; j < N; j++) {
                    printf(" %d", a[i][j]);
            }
            printf ("\n");
    }
    printf ("\n\n");
}

然后c =

C = 
 54 37 47 57

 130 93 119 145

 44 41 56 71

 111 79 101 123 

这篇关于使用Mpi_Scatter和Mpi_Gather进行矩阵乘法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆