Умножение матрицы и вектора в MPI C

#c #matrix #vector #mpi

#c #матрица #вектор #mpi

Вопрос:

У меня есть задача для моего текущего класса MPI, где я должен умножить матрицу 2×3

1 2 3

4 5 6

на вектор 3×1 7 8 9

Мне сказали предположить, что у нас есть только 2 процессора.

У меня есть следующая реализация, но я захожу в тупик и не могу понять, почему.

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

int main(void)
{
    int comm_sz; /* number of processes*/
    int my_rank; /* my process rank */
    int m, n;
    double* Matrix;
    double* Vector;
    double* Resu<
    double* localMatrix;

    MPI_Comm comm;


    FILE *fptr = fopen("mv-data.txt", "r");
    MPI_Init(NULL, NULL);
    comm = MPI_COMM_WORLD;
    MPI_Comm_size(comm, amp;comm_sz);
    MPI_Comm_rank(comm, amp;my_rank);

    if (my_rank == 0)
    {
        fscanf(fptr,"%d", m);
        fscanf(fptr, "%d", n);
    }
    MPI_Bcast(m, 1, MPI_INT, 0, comm);
    MPI_Bcast(n,1,MPI_INT, 0, comm);


    if (my_rank==0)
    {
    Matrix = malloc(m*n * sizeof(double));

    for(int i = 0; i<m; i  )
        for(int j=0; j< n; j  )
            fscanf(fptr, "%lf", amp;Matrix[i*n j]);

    Vector = malloc(n*sizeof(double));

    for (int i = 0; i < n; i  )
        fscanf(fptr,"%lf", amp;Vector[i]);


    Result = malloc(m * sizeof(double));



    for (int row = 0; row < m; row  )
    {
        localMatrix = malloc(m*sizeof(double));
        for(int column = 0; column < n; column  )
            localMatrix[column] = Matrix[row*n   column];

        MPI_Send(localMatrix, n, MPI_DOUBLE, row % comm_sz, 0, comm);
    }

    }
    MPI_Bcast(Vector, n, MPI_DOUBLE, 0,comm);
    MPI_Recv(localMatrix, n, MPI_DOUBLE, 0, 0, comm, MPI_STATUS_IGNORE);
    Result[my_rank] = 0;
    for(int i = 0; i < n; i  )
    {
        Result[my_rank]  = localMatrix[i] * Vector[i];
    }

    if (my_rank = 0)
    {
        for (int i = 0; i < m; i  )
            printf("%d", Result[i]);
    }

    return 0;

}
  

Я не могу придумать никакого другого способа отправить этот процесс на главный процессор, не вызывая взаимоблокировки.
Любая помощь будет оценена.

Комментарии:

1. Используйте коллективные операции: разбросайте матрицу, передайте вектор и соберите результат. if(tank == 0) останется только в самом начале и в самом конце вашего кода.

Ответ №1:

В rank 0 , вы используете блокировку MPI_Send . Затем другие процессы вызывают коллектив MPI_Bcast вместо сопоставления MPI_Recv . Это может привести к взаимоблокировке (буферизация может происходить внутри MPI_Send , а также может избежать взаимоблокировки). Смотрите ниже:

 if (my_rank==0)
{
   for (int row = 0; row < m; row  )
   {
      MPI_Send(localMatrix, n, MPI_DOUBLE, row % comm_sz, 0, comm);
   }
}
MPI_Bcast(Vector, n, MPI_DOUBLE, 0,comm); // COLLECTIVE - PROCESS MAY GET STUCK HERE
MPI_Recv(localMatrix, n, MPI_DOUBLE, 0, 0, comm, MPI_STATUS_IGNORE);
  

Вы можете попробовать что-то вроде этого,

 if (my_rank==0)
{
   for (int row = 0; row < m; row  )
   {
      MPI_Send(localMatrix, n, MPI_DOUBLE, row % comm_sz, 0, comm);
   }
} else
{
      MPI_Recv(localMatrix, n, MPI_DOUBLE, 0, 0, comm, MPI_STATUS_IGNORE);
}
MPI_Bcast(Vector, n, MPI_DOUBLE, 0,comm);
  

что определенно позволит избежать взаимоблокировки. Кроме того, в вашем коде есть проблемы. Например,

 MPI_Recv(localMatrix, n, MPI_DOUBLE, 0, 0, comm, MPI_STATUS_IGNORE);
  

вызовет ошибку сегментации, поскольку память для localMatrix не выделена. Доступ Result , а также Vector также вызывает ошибку сегментации, потому что вы не выделили для него память в других процессах (например: ранги от 1 до N-1), кроме ранга 0.