我正在编写一些在大型 3D 网格上进行计算的代码,并使用光环交换程序,以便它可以使用 MPI 工作。我从我的代码中得到了错误的结果,我很确定这是因为光环交换无法正常工作。
基本上我有一个大的 3D 数组,其中的一部分保存在每个进程中。每个进程都有一个数组,该数组的每个维度比它所保存的数据块大 2 个元素 - 这样我们就可以在数组的每个面进行光环交换,而不会影响存储在数组其余部分中的数据。我有以下代码来进行光环交换通信:
MPI_Type_vector(g->ny, g->nx, g->nx, MPI_DOUBLE, &face1);
MPI_Type_commit(&face1);
MPI_Type_vector(2*g->ny, 1, g->nx, MPI_DOUBLE, &face2);
MPI_Type_commit(&face2);
MPI_Type_vector(g->nz, g->nx, g->nx * g->ny, MPI_DOUBLE, &face3);
MPI_Type_commit(&face3);
/* Send to WEST receive from EAST */
MPI_Sendrecv(&(g->data)[current][0][0][0], 1, face1, g->west, tag,
&(g->data)[current][0][0][0], 1, face1, g->east, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
/* Send to EAST receive from WEST */
MPI_Sendrecv(&(g->data)[current][g->nz-1][0][0], 1, face1, g->east, tag,
&(g->data)[current][g->nz-1][0][0], 1, face1, g->west, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
/* Send to NORTH receive from SOUTH */
MPI_Sendrecv(&(g->data)[current][0][0][0], 1, face2, g->north, tag,
&(g->data)[current][0][0][0], 1, face2, g->south, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
/* Send to SOUTH receive from NORTH */
MPI_Sendrecv(&(g->data)[current][0][g->ny-1][0], 1, face2, g->south, tag,
&(g->data)[current][0][0][0], 1, face2, g->north, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
/* Send to UP receive from DOWN */
MPI_Sendrecv(&(g->data)[current][0][0][0], 1, face3, g->up, tag,
&(g->data)[current][0][0][0], 1, face3, g->down, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
/* Send to DOWN receive from UP */
MPI_Sendrecv(&(g->data)[current][0][0][g->nx-1], 1, face3, g->down, tag,
&(g->data)[current][0][0][g->nx-1], 1, face3, g->up, tag, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
g->nx
,g->ny
和g->nz
是该进程所持有的数组块的大小,g->west
, g->east
, g->north
, g->south
,g->up
和g->down
是每个方向上相邻进程的等级,使用以下代码找到:
/* Who are my neighbours in each direction? */
MPI_Cart_shift( cart_comm, 2, 1, &g->north, &g->south);
MPI_Cart_shift( cart_comm, 1, 1, &g->west, &g->east);
MPI_Cart_shift( cart_comm, 0, 1, &g->up, &g->down);
每个进程上的数组定义为:
array[2][g->nz][g->ny][g->nx]
(它有两个副本,因为一旦我完成了光环交换,我每次都需要通过我的更新程序更新一个副本)。
谁能告诉我我是否正确地进行了沟通?特别是向量类型的定义。我在代码中定义的向量类型会提取 3D 数组的每个面吗?MPI_Sendrecv 调用看起来正确吗?
我完全不知道为什么我的代码不起作用,但我很确定它与通信有关。