如何通过MPI收发包含二维数组的C语言结构体?
Hey there! Let's walk through how to send and receive that C struct with a 2D array using MPI. I see you've already made progress with serialization, so let's break down the approach and confirm the key steps that make this work.
方法1:手动序列化(你目前采用的方案)
手动序列化 involves unpacking the struct into basic data types for transmission, then reassembling them on the receiving end. Here's a breakdown of your modified code with key explanations:
typedef struct a_s { double array[3][3]; int err; } a; int main(int argc, char** argv) { // Initialize the MPI environment MPI_Init(NULL, NULL); int rank, size; MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); a my_data; // Rank 0 prepares the data to send if (rank == 0) { // Populate the 2D array for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { my_data.array[i][j] = i * 3.0 + j; } } my_data.err = 0; // Send the 2D array as a contiguous block of 9 doubles MPI_Send(my_data.array, 9, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD); // Send the err integer separately MPI_Send(&my_data.err, 1, MPI_INT, 1, 1, MPI_COMM_WORLD); } // Rank 1 receives and reassembles the data else if (rank == 1) { MPI_Recv(my_data.array, 9, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); MPI_Recv(&my_data.err, 1, MPI_INT, 0, 1, MPI_COMM_WORLD, MPI_STATUS_IGNORE); // Verify the received data printf("Received 3x3 array:\n"); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { printf("%.1f ", my_data.array[i][j]); } printf("\n"); } printf("Received error code: %d\n", my_data.err); } // Clean up MPI resources MPI_Finalize(); return 0; }
关键注意事项:
- The 2D array
array[3][3]is stored contiguously in memory, so we can treat it as a 1D array of 9doublevalues for transmission—no need to send each row individually. - Use distinct message tags (like
0for the array and1for the error code) to avoid mixing up messages during reception. - Ensure the receiving order matches the sending order exactly to correctly reconstruct the struct.
方法2:自定义MPI数据类型(更简洁的替代方案)
If you want to avoid manual serialization, you can create a custom MPI datatype that matches your struct. This lets MPI handle the transmission as a single unit:
typedef struct a_s { double array[3][3]; int err; } a; int main(int argc, char** argv) { MPI_Init(NULL, NULL); int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); // Define custom MPI datatype for the struct MPI_Datatype MPI_A_STRUCT; MPI_Aint offsets[2]; int blocklengths[2] = {9, 1}; // 9 doubles for the array, 1 int for err MPI_Datatype types[2] = {MPI_DOUBLE, MPI_INT}; // Calculate offsets of each member in the struct offsets[0] = offsetof(a, array); offsets[1] = offsetof(a, err); // Create and commit the custom type MPI_Type_create_struct(2, blocklengths, offsets, types, &MPI_A_STRUCT); MPI_Type_commit(&MPI_A_STRUCT); a my_data; if (rank == 0) { // Populate data... MPI_Send(&my_data, 1, MPI_A_STRUCT, 1, 0, MPI_COMM_WORLD); } else if (rank == 1) { MPI_Recv(&my_data, 1, MPI_A_STRUCT, 0, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE); // Verify data... } // Free the custom datatype when done MPI_Type_free(&MPI_A_STRUCT); MPI_Finalize(); return 0; }
This approach is cleaner for complex structs, as you don't have to manage separate send/receive calls for each member. Both methods work reliably—pick whichever fits your code style better!
内容的提问来源于stack exchange,提问作者L. Hidalgo

