1

I'm trying to make an MPI matrix multiplication program but the scatter function doesn't seem to be working for me. Only one row is getting scattered and the rest of the cores receive garbage value.

Also when calling the display_matrix() function before I MPI_Init() seems to be running 4 threads instead of 1 (I have quad core CPU). Why is this happening even before initialisation?

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

int **matrix_generator(int row,int col);
int **multiply_matrices(int **matrix_A,int **matrix_B,int rowsA, int colsA,int rowsB,int colsB);
void display_matrix(int **matrixA,int rows,int cols);

void main(int argc,char *argv[])
{
    srand(time(0));

    int **matrix_A,**matrix_B,**matrix_result,*scattered_matrix,*gathered_matrix, rowsA,colsA,rowsB,colsB,world_rank,world_size,i,j;

    rowsA = atoi(argv[1]);
    colsA = atoi(argv[2]);
    rowsB = atoi(argv[3]);
    colsB = atoi(argv[4]);

    scattered_matrix = (int *)malloc(sizeof(int) * rowsA*colsA/4); 

    if (argc != 5)
    {
        fprintf(stderr,"Usage: mpirun -np <No. of processors> ./a.out <Rows A> <Columns A> <Rows B> <Columns B>\n");
        exit(-1);
    }
    else if(colsA != rowsB)
    {
        printf("Check the dimensions of the matrices!\n\n");
    }

    matrix_A = matrix_generator(rowsA,colsA);
    matrix_B = matrix_generator(rowsB,colsB);

    display_matrix(matrix_A,rowsA,colsA);

    MPI_Init(&argc, &argv);

    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);

    MPI_Scatter(matrix_A, rowsA*colsA/4, MPI_INT, scattered_matrix, rowsA*colsA/4, MPI_INT, 0, MPI_COMM_WORLD);

    for(i=0;i<world_size;i++)
    {  
        printf("Scattering data %d from root to: %d \n",scattered_matrix[i],world_rank);
    }

    MPI_Barrier(MPI_COMM_WORLD);

    MPI_Finalize();
}

int **matrix_generator(int row, int col)
{
    int i, j, **intMatrix;

    intMatrix = (int **)malloc(sizeof(int *) * row); 

    for (i = 0; i < row; i++)
    {
        intMatrix[i] = (int *)malloc(sizeof(int *) * col);
        for (j = 0;j<col;j++)
        {
            intMatrix[i][j]=rand()%10;
        }
    }
    return intMatrix;
}

void display_matrix(int **matrix, int rows,int cols)
{
    int i,j;
    for (i = 0; i < rows; i = i + 1)
    {
        for (j = 0; j < cols; j = j + 1)
            printf("%d ",matrix[i][j]);
        printf("\n");
    }
}
aBDYsINGH
  • 43
  • 1
  • 10
  • 1
    Welcome to Stackoverflow! The way the matrix are allocated, one row at a time, make it non-contigous in memory, see https://stackoverflow.com/questions/25628321/dynamic-memory-allocation-in-mpi/25629279#25629279 for instance. In addition, matrix_A is a pointer to pointers to row while MPI_Scatter() requires a pointer to the buffer to be scattered. Hence, try MPI_Scatter(matrix_A[0],...) or MPI_Scatter(&matrix_A[0][0],...) – francis Mar 29 '18 at 22:08
  • As you can see I have a variable sized matrix. How do I assign contiguous memory to variable sized array? – aBDYsINGH Mar 30 '18 at 14:27

1 Answers1

0

The main issue is your matrices are not allocated in contiguous memory (see the comment section for a link)

The MPI standard does not specify what happens before an app invokes MPI_Init().

The two main MPI implementations choose to spawn all the tasks when mpirun is invoked (that means there are 4 independent processes first, and they "join" into a single MPI job when they all call MPI_Init()). That being said, once upon a time, a vendor chose to have mpirun start a single MPI task, and they use their own remote-fork when MPI_Init() is called.

Bottom line, if you want to write portable code, do as less as possible (and never print anything) before MPI_Init() is called.

Gilles Gouaillardet
  • 8,193
  • 11
  • 24
  • 30