Я пишу некоторый код, который выполняет вычисления на большой трехмерной сетке и использует процедуру обмена гало, чтобы он мог работать с использованием 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]
(у него две копии, потому что мне нужно по одному обновляться каждый раз с помощью процедуры обновления, как только я произвожу обмен гало).
Может кто-нибудьскажите, правильно ли я общаюсь?В частности, определение векторных типов.Будут ли векторные типы, определенные в коде, извлекать каждую грань трехмерного массива?И выглядят ли вызовы MPI_Sendrecv правильными?
Я совершенно не понимаю, почему мой код не работает, но я почти уверен, что он связан с коммуникациями.