dimitris diamond
dimitris diamond

Reputation: 69

MPI in c. I don't receive what I send

I am new in MPI. I am trying to write some simple code. Here it is:

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

#define ONE 0
#define TWO 1

int main(int argc, char * argv[])
{
    int dimension = 5;
    float ** matrix;
    float * mat1;
    float * mat2;
    int i,j,numNeighbor, processReceived,rank,size,retval;
    int k = 0;
    retval = MPI_Init(&argc, &argv);

    MPI_Request sendRequest[2], recvRequest[2];
    MPI_Status status[2];
    MPI_Datatype row;

    MPI_Type_vector(dimension, 1, dimension, MPI_FLOAT, &row);
    MPI_Type_commit(&row);

    if(retval != MPI_SUCCESS)
    {
        MPI_Abort(MPI_COMM_WORLD, retval);
        return EXIT_FAILURE;
    }
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
    MPI_Comm_size(MPI_COMM_WORLD, &size);
    mat1 = malloc(dimension*sizeof(float));
    mat2 = malloc(dimension*sizeof(float));
    matrix = malloc(dimension*sizeof(float*));
    for(i=0; i<dimension; i++)
    {
        matrix[i] = malloc(dimension*sizeof(float));        
    }

    printf("MATRIX OF RANK %d\n", rank);
    for(i=0; i<dimension; i++)
    {
        for(j=0; j<dimension; j++)
        {
            matrix[i][j] = (float)(rank+1)*(i*2+j);
            printf("%2.1f ",matrix[i][j]);
        }
        printf("\n");
    }
    printf("\n");

    MPI_Isend(&(matrix[0][0]), 1, row, 1-rank, rank, MPI_COMM_WORLD, sendRequest + ONE);
    MPI_Isend(&(matrix[0][0]), dimension, MPI_FLOAT, 1-rank, rank, MPI_COMM_WORLD, sendRequest + TWO);

    MPI_Irecv(mat1,dimension, MPI_FLOAT, 1-rank, 1-rank, MPI_COMM_WORLD, recvRequest + ONE);
    MPI_Irecv(mat2,dimension, MPI_FLOAT, 1-rank, 1-rank, MPI_COMM_WORLD, recvRequest + TWO);


    for(i=0; i<2; i++)
    {
        MPI_Waitany(2,recvRequest, &processReceived, status);
        printf("Process Received : %d of rank : %d\n", processReceived,rank);
        if(processReceived == ONE)
        {
            printf("%d ",rank);
            for(j=0; j<dimension; j++)  printf("# %6.1f ",mat1[j]);
            printf("\n");
        }

        if(processReceived == TWO)
        {
            printf("%d ",rank);
            for(j=0; j<dimension; j++)  printf("@ %6.1f ",mat2[j]);
            printf("\n");
        }
    }

    MPI_Waitall(2, sendRequest, status);
    free(mat1);
    free(mat2);
    for(i=0;i<dimension;i++) free(matrix[i]);
    free(matrix);
    MPI_Type_free(&row);
    MPI_Finalize();
    return 0;
}

This is my output:

MATRIX OF RANK 1
0.0 2.0 4.0 6.0 8.0 
4.0 6.0 8.0 10.0 12.0 
8.0 10.0 12.0 14.0 16.0 
12.0 14.0 16.0 18.0 20.0 
16.0 18.0 20.0 22.0 24.0 

MATRIX OF RANK 0
0.0 1.0 2.0 3.0 4.0 
2.0 3.0 4.0 5.0 6.0 
4.0 5.0 6.0 7.0 8.0 
6.0 7.0 8.0 9.0 10.0 
8.0 9.0 10.0 11.0 12.0 

Process Received : 0 of rank : 0
0 #    0.0 #    0.0 #   12.0 #   14.0 #   16.0 
Process Received : 1 of rank : 0
0 @    0.0 @    0.0 @   12.0 @   14.0 @   16.0 
Process Received : 0 of rank : 1
1 #    0.0 #    0.0 #    6.0 #    7.0 #    8.0 
Process Received : 1 of rank : 1
1 @    0.0 @    0.0 @    6.0 @    7.0 @    8.0 

What I think I am doing with this program is that I send one row and one column of each process to the other process. Then I print whatever i received in each process. But as you can see this is not the output i thought i would have. What i am waiting for is something like:

example of output:

Process Received : 0 of rank : 0
    0 #    0.0 #    2.0 #   4.0 #   6.0 #   8.0

Process Received : 1 of rank : 0
    0 #    0.0 #    4.0 #   8.0 #   12.0 #   16.0

Can anyone explain me what i haven't got very well? This is the only function that i use so you can run it in your own machines. For this example you can use only 2 processes.

mpiexec -n 2 ./name_exe

Upvotes: 0

Views: 130

Answers (1)

Gilles
Gilles

Reputation: 9519

The issue comes from the fact that the data storage in matrix isn't linear. As it is defined in the code at the moment, matrix is an array of pointers, all of which point to some independent memory segments.

However, your code assumes that &matrix[0][0] points to the beginning of a linearised row-major matrix.

Well, to solve the issue, you simply need to comply with this by allocating matrix the following way:

matrix = malloc(dimension*sizeof(float*)); //nothing new here
matrix[0] = malloc(dimension*dimension*sizeof(float));
for(i=1; i<dimension; i++) matrix[i]=matrix[i-1]+dimension;

Then you use matrix exactly as before, but for the freeing part, which becomes:

free(matrix[0]);
free(matrix);

With this, the code should work.

Upvotes: 2

Related Questions