Search code examples
cmpihpc

How to MPI Send and Recv Nested struct with Pointer Array of Struct?


Here are the struct declaration and code below:

struct cell_struct {
    int x, y;
    bool isWater, isPort, isRock;
    struct port_struct port_data;
    struct ship_struct *ships_data[MAX_SHIPS_PER_CELL];
    int number_ships;
};

struct ship_struct {
    int route, totalHoursAtSea, hoursAtSeaThisJourney, id, numberPassengers, euclideanPlannedDistance;
    bool willMoveThisTimestep;
};

// Data associated with each port
struct port_struct {
    int shipsInPastHundredHours[10];
    int port_index, passengersShipped;
    double totalFeesCollected;
};

struct cell_struct *domain_test;

domain_test = (struct cell_struct *) malloc(
            sizeof(struct cell_struct) * (mpi_info->local_size_x + 2) * simulation_configuration->size_y);

Using the following Send and Recv, I was able to send and receive, domain_test, but was not able to access ships_data from domain_test after sending and receiving. Any help in this?

MPI_Send(&domain_test[mpi_info->local_size_x_end * simulation_configuration->size_y + i], sizeof(struct cell_struct), MPI_BYTE, 1, i, MPI_COMM_WORLD);

MPI_Recv(&domain_test[0],sizeof(struct cell_struct) * simulation_configuration->size_y, MPI_BYTE, 0, 0, MPI_COMM_WORLD, &status);



Solution

  • The main problem in your code is that the cell_struct stores a static array of pointers to ships, which means the data of the ships itself may be all over the place. If you instead store a static array of ships, as suggested by Gilles in the comments, you have a contiguous chunk of memory that needs to be sent. You can even send it using count=sizeof(cell_struct) and type=MPI_BYTE then (like you do now), or any of the methods indicated by @Gilles.

    The consequence for your code is that the ships are now copied when assigned to a cell, rather than just setting a pointer. This is not a problem if the ships have little data, as shown here, but if copying is expensive, it may make the code slower.