0

what I need to do is to distribute a given number of strings to all nodes in a network. I'm using MPI in C. I had a lot of trouble doing this using dynamic allocation and array of pointers, and I came to the conclusion that I have to use MPI_Datatypes.

So my new idea is to use a struct like this one:

typedef struct {
    char data[10];
} Payload;

and building a new MPI_Datatype based on this struct, in order to, hopefully, being able to Scatter an array of struct.

I wrote some code in the attempt of doing so (assume comm_sz/number of nodes is 3):

MPI_Datatype MPI_Payload, tmp_type;
int array_of_blocklengths[] = {10};
MPI_Aint array_of_displacements[] = {0};
MPI_Datatype array_of_types[] = {MPI_CHAR};
MPI_Aint lb, extent;

MPI_Type_create_struct(1, array_of_blocklengths, array_of_displacements, array_of_types, &tmp_type);
MPI_Type_get_extent(tmp_type, &lb, &extent);
MPI_Type_create_resized(tmp_type, lb, extent, &MPI_Payload);
MPI_Type_commit(&MPI_Payload);

int n = 3; //total number of packets
int local_n = n/comm_sz; //number of packets for single node

Payload *local_buff = malloc(local_n*sizeof(Payload));
Payload *a = NULL;
if (my_rank == 0) {
    a = malloc(n*sizeof(Payload));
    char msg[10];
    for (int i = 0; i < n; i++) {
        printf("Enter a max 9 character length string\n");
        scanf("%s", msg);
        strcpy(a[i].data, msg);
    }
    //MPI_Send(&a[1], 1, MPI_Payload, 1, 0, MPI_COMM_WORLD);
    //MPI_Send(&a[2], 1, MPI_Payload, 2, 0, MPI_COMM_WORLD);
    MPI_Scatter(a, n, MPI_Payload, local_buff, local_n, MPI_Payload, 0, MPI_COMM_WORLD);
    free(a);
}
else {
    //MPI_Recv(&local_buff[0], 1, MPI_Payload, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    MPI_Scatter(a, n, MPI_Payload, local_buff, local_n, MPI_Payload, 0, MPI_COMM_WORLD);
    printf("Hi from process %d, here's the string:\n", my_rank);
    printf("%s\n", local_buff[0].data);
}

I've read here: Trouble Understanding MPI_Type_create_struct how to resize my struct in order to send an array of them, but unfortunatly, this code yields me the following:

[node1:2267] *** An error occurred in MPI_Scatter

[node1:2267] *** reported by process [1136394241,0]

[node1:2267] *** on communicator MPI_COMM_WORLD

[node1:2267] *** MPI_ERR_TRUNCATE: message truncated

[node1:2267] *** MPI_ERRORS_ARE_FATAL (processes in this communicator will now abort,

[node1:2267] *** and potentially your MPI job)

You can see in the code that I commented some lines, I tried to send the structures with Sends and Recvs and in that case it works, I can't figure out why it does not work with Scatter. Could you please help me? Thank you.

Lemnon95
  • 11
  • 1
  • you have to use `local_n` as the send count. As a side note, I strongly encourage you to move the call to `MPI_Scatter()` **outside** of the `if (rank...)` block to improve readability. – Gilles Gouaillardet Dec 17 '20 at 01:42
  • FWIW, there is no point in resizing the datatype with its current size. – Gilles Gouaillardet Dec 17 '20 at 04:03
  • Thank you @GillesGouaillardet, now my code works and I've also made the improvements that you suggested. I didn't quite understand the use of MPI_Type_create_resized, when is it needed and how should it be used? Thank you. – Lemnon95 Dec 17 '20 at 14:46
  • You would typically use `MPI_Type_create_resized()` when building a derived datatype do describe the column of a `C` matrix `double a[n][n]`. you want the second column to start at `a[0][1]` instead of `a[n][0]`, so you have to `MPI_Type_create_resized(..., lb=0, extent=sizeof(double), ...)`. – Gilles Gouaillardet Dec 18 '20 at 02:47

0 Answers0