How to use MPI_Scatterv and displacement in C

705 Views Asked by At
#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.

0

There are 0 best solutions below