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

int size;

typedef struct process_struct
{
    int start;
    int end;
} process_tag;

int main(int argc, char **argv)
{   //array size
    size=11;

    int rc, myrank, world_size;
    rc = MPI_Init(&argc, &argv);
    if (rc != MPI_SUCCESS) {
        printf ("Error starting MPI program\n");
        MPI_Abort(MPI_COMM_WORLD, rc);
    }
    MPI_Comm_rank(MPI_COMM_WORLD, &myrank);
    MPI_Comm_size(MPI_COMM_WORLD, &world_size);

    int i, j;

    int process_num=4;
    int processs_i;
    int start, end;

    double **a = malloc(size*sizeof(double*));
    if (a == NULL) { printf("malloc failed\n"); return 1; }

    for (i = 0;  i < size;  i++) {
        a[i] = malloc(size*sizeof(double));
        if (a[i] == NULL) { printf("malloc failed\n"); return 1; }
    }
    //initialize array "a"
    a=ini(a);

    if(myrank == 0 ) {
        printarray(a,size);
    }

    // store starting row and ending row for each process
    process_tag process[process_num];

    int chunk_size = (size - 2 )  / process_num ;
    int remain = (size - 2) - chunk_size * process_num ;

    start = 1;
    end = 1;
    int process_i =0;

    while(start < size) {

        start = end;
        end = start + chunk_size;

        if (remain > 0) {
            end++;
            remain--;
        }

        process[process_i].start = start;
        process[process_i].end = end;
        process_i++;

    }

    int send_count[process_num];
    for (process_i = 0; process_i < process_num; process_i++) {
        send_count[process_i] = process[process_i].end - process[process_i].start;
    }

    int receive_count = send_count[myrank];

    int *displs = malloc(sizeof(int)*size);
    int sum =1;
    for (i = 0; i < process_num; i++) {

        displs[i] = sum;
        sum += send_count[i];

    }

    double **blocal;

    blocal = malloc(receive_count*sizeof(double*));
    if (blocal == NULL)
        { printf("malloc failed\n"); return 1; }

    for (i = 0;  i < size;  i++) {
        blocal[i] = malloc(size*sizeof(double));
        if (blocal[i] == NULL)
            { printf("malloc failed\n"); return 1; }
    }

    MPI_Scatterv(a, send_count, displs, MPI_DOUBLE, blocal,
        receive_count, MPI_DOUBLE, 0, MPI_COMM_WORLD);


    printarray(blocal,receive_count);
    printf("from rank %d  \n", myrank);
}

output is:

array a is 
1.000000 3.700000 2.000000 6.000000 5.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
1.000000 8.200000 3.000000 7.000000 3.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
1.000000 6.000000 9.000000 1.000000 6.300000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
1.000000 5.000000 1.000000 3.000000 4.300000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
1.000000 4.500000 6.000000 4.000000 7.600000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
1.000000 1.000000 1.000000 1.000000 1.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
1.000000 1.000000 1.000000 1.000000 1.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
1.000000 1.000000 1.000000 1.000000 1.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
1.000000 1.000000 1.000000 1.000000 1.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
1.000000 1.000000 1.000000 1.000000 1.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000
1.000000 1.000000 1.000000 1.000000 1.000000 3.000000 3.000000 3.000000 3.000000 3.000000 3.000000

blocal from rank 0
1.000000 8.200000 3.000000 7.000000 3.000000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
1.000000 6.000000 9.000000 1.000000 6.300000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000
1.000000 5.000000 1.000000 3.000000 4.300000 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000

blocal from rank 1
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000

blocal from rank 2
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000

blocal from rank 3
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000
0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000

I want to scatter the elements of 11*11 sendbuf array "a" to arrays "blocal" (receivebuf).
What I want to achieve is that blocal at process 0 get row 1 to 3, process 1 get row 4 to 5, process 2 get row 6 to 7, and process 3 get row 8 to 9. Row 0 and row 10 are ignored.
However in my output only process 0 got the sub-array from array "a".
Could anybody spot any error in my code? I think the problem might be the displacement.

F. Zhao
  • 13
  • 4
  • Welcome to Stackoveflow! The problem is likely due to the fact that the 2D array is not a single block of memory as `malloc()` is called once for each row. See http://stackoverflow.com/questions/5901476/sending-and-receiving-2d-array-over-mpi to allocate a contiguous 2D array. Lastly, `MPI_Scatterv()` need the pointer to the start of the buffer. Here, it is `&a[0][0]` or `a[0]` and `&blocal[0][0]` or `blocal[0]`. But not `a` or `blocal`, which are pointers to pointers to first items of the rows. – francis Jan 07 '17 at 19:36
  • I just edited my question after modifying my code. I still got wrong output. Could you have a look at it? – F. Zhao Jan 07 '17 at 20:16
  • Now, the problem must be due to wrong sendcount and displacements. For instance, the first displacement is 1, while it should be 11 if you don't want to send the first row. Try `sum=11` and make sure that the sendcounts are all multiples of 11. – francis Jan 07 '17 at 20:44

0 Answers0