```c #include <stdio.h> #include <stdlib.h> #include <math.h> #include <mpi.h> #define SIZE 10 #define BLOCK_SIZE (SIZE / 2) int main(int argc, char *argv[]) { int rank, size; int i, j, iter; double u[BLOCK_SIZE + 2][BLOCK_SIZE + 2]; double u_new[BLOCK_SIZE + 2][BLOCK_SIZE + 2]; double start_time, end_time; MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); // 创建一个二维笛卡尔拓扑结构 int dims[2] = {2, 2}; // 行列分块的维度 int periods[2] = {0, 0}; // 不创建周期性拓扑 int coords[2]; // 存储进程在二维拓扑中的坐标 MPI_Comm cart_comm; MPI_Cart_create(MPI_COMM_WORLD, 2, dims, periods, 0, &cart_comm); MPI_Cart_coords(cart_comm, rank, 2, coords); // 初始化子块数据 for (i = 0; i < BLOCK_SIZE + 2; i++) { for (j = 0; j < BLOCK_SIZE + 2; j++) { u[i][j] = 0.0; u_new[i][j] = 0.0; } } if (coords[0] == 0 && coords[1] == 0) { // 初始化左上角子块的边界值 u[1][1] = 1.0; u[BLOCK_SIZE][BLOCK_SIZE] = 1.0; } else if (coords[0] == 0 && coords[1] == 1) { // 初始化右上角子块的边界值 u[1][BLOCK_SIZE] = 2.0; u[BLOCK_SIZE][1] = 2.0; } else if (coords[0] == 1 && coords[1] == 0) { // 初始化左下角子块的边界值 u[BLOCK_SIZE][1] = 3.0; u[1][BLOCK_SIZE] = 3.0; } else if (coords[0] == 1 && coords[1] == 1) { // 初始化右下角子块的边界值 u[BLOCK_SIZE][BLOCK_SIZE] = 4.0; u[1][1] = 4.0; } // 开始迭代计算 iter = 0; start_time = MPI_Wtime(); while (iter < 1000) { // 进行Jacobi迭代计算 for (i = 1; i <= BLOCK_SIZE; i++) { for (j = 1; j <= BLOCK_SIZE; j++) { u_new[i][j] = 0.25 * (u[i-1][j] + u[i+1][j] + u[i][j-1] + u[i][j+1]); } } // 使用非阻塞通信进行边界数据交换 MPI_Request reqs[8]; MPI_Isend(&u_new[1][1], BLOCK_SIZE, MPI_DOUBLE, (coords[0] + 1) % 2, 0, cart_comm, &reqs[0]); MPI_Isend(&u_new[BLOCK_SIZE][1], BLOCK_SIZE, MPI_DOUBLE, (coords[0] + 1) % 2, 1, cart_comm, &reqs[1]); MPI_Isend(&u_new[1][1], 1, MPI_DOUBLE, (coords[1] + 1) % 2, 2, cart_comm, &reqs[2]); MPI_Isend(&u_new[1][BLOCK_SIZE], 1, MPI_DOUBLE, (coords[1] + 1) % 2, 3, cart_comm, &reqs[3]); MPI_Irecv(&u_new[BLOCK_SIZE + 1][1], BLOCK_SIZE, MPI_DOUBLE, (coords[0] + 1) % 2, 0, cart_comm, &reqs[4]); MPI_Irecv(&u_new[0][1], BLOCK_SIZE, MPI_DOUBLE, (coords[0] + 1) % 2, 1, cart_comm, &reqs[5]); MPI_Irecv(&u_new[1][BLOCK_SIZE + 1], 1, MPI_DOUBLE, (coords[1] + 1) % 2, 2, cart_comm, &reqs[6]); MPI_Irecv(&u_new[1][0], 1, MPI_DOUBLE, (coords[1] + 1) % 2, 3, cart_comm, &reqs[7]); // 等待所有通信操作完成 MPI_Waitall(8, reqs, MPI_STATUS_IGNORE); // 更新子块数据 for (i = 1; i <= BLOCK_SIZE; i++) { for (j = 1; j <= BLOCK_SIZE; j++) { u[i][j] = u_new[i][j]; } } iter++; } end_time = MPI_Wtime(); // 打印每个进程的执行时间和结果 double exec_time = end_time - start_time; printf("Process %d: Execution time = %f seconds\n", rank, exec_time); printf("Process %d: u[1][1] = %f, u[%d][%d] = %f\n", rank, u[1][1], BLOCK_SIZE, BLOCK_SIZE, u[BLOCK_SIZE][BLOCK_SIZE]); MPI_Finalize(); return 0; } ``` |
说点什么...