Несоответствие тегов
Теги должны совпадать для каждой пары операций связи, т. Е. Должны быть отправка и получение с одним и тем же тегом. В вашем случае два отправителя имеют свои собственные теги, а получатели - разные. Измените его так, чтобы при отправке вниз и при получении от вверх был один и тот же тег, и наоборот, например,
if (my_rank < my_size-1) {
/*send top most strip up one node to be recieved as bottom halo*/
MPI_Isend(&phi[1][0], grid_size , MPI_DOUBLE, down, 1, MPI_COMM_WORLD, &sreqU);
/*recv top halo from up one node*/
MPI_Irecv(&phi[slice+1][0], grid_size, MPI_DOUBLE, down, 2, MPI_COMM_WORLD, &reqU);
}
if (my_rank > 0) {
/*recv top halo from down one node*/
MPI_Irecv(&phi[0][0], grid_size , MPI_DOUBLE, up, 1, MPI_COMM_WORLD, &reqD);
/*send bottom most strip down one node to be recieved as top halo*/
MPI_Isend(&phi[slice][0], grid_size , MPI_DOUBLE, up, 2, MPI_COMM_WORLD, &sreqD);
}
Несоответствие объектов запроса
На границах вы ожидаете неправильных запросов, это просто исправляется путем замены MPI_Wait
if body.
Ожидание нескольких неблокирующих операций
Вопреки некоторым обсуждениям в теперь удаленных ответах, правильно ждать нескольких текущих неблокирующих соединений с несколькими ожиданиями 1 .
Тем не менее, строго лучше использовать массив запросов и MPI_Waitall
. Это приводит к более чистому коду, предотвратил бы ошибку смешивания запросов в первую очередь. Это также дает реализации MPI больше свободы для оптимизации. Это может выглядеть следующим образом:
MPI_Request requests[MAX_REQUESTS];
int num_requests = 0;
// ...
MPI_Isend(..., requests[num_requests++]);
// ...
MPI_Waitall(num_requests, requests, statuses);
Или вы можете использовать тот факт, что MPI_Waitall
разрешает элементам массива запросов быть MPI_REQUEST_NULL
. Это позволяет вам соотносить конкретные запросы и в конечном итоге является вопросом стиля.
typedef enum {
RECV_UP, RECV_DOWN, SEND_UP, SEND_DOWN, MAX_REQUESTS
} MyRequests;
MPI_Request requests[MAX_REQUESTS];
MPI_Status statuses[MAX_REQUESTS];
if (my_rank < my_size-1) {
/*send top most strip up one node to be recieved as bottom halo*/
MPI_Isend(&phi[1][0], grid_size , MPI_DOUBLE, down, 1, MPI_COMM_WORLD, &requests[SEND_DOWN]);
/*recv top halo from up one node*/
MPI_Irecv(&phi[slice+1][0], grid_size, MPI_DOUBLE, down, 2, MPI_COMM_WORLD, &requests[RECV_DOWN]);
} else {
requests[RECV_DOWN] = requests[SEND_DOWN] = MPI_REQUEST_NULL;
}
if (my_rank > 0) {
/*recv top halo from down one node*/
MPI_Irecv(&phi[0][0], grid_size , MPI_DOUBLE, up, 1, MPI_COMM_WORLD, &requests[RECV_UP]);
/*send bottom most strip down one node to be recieved as top halo*/
MPI_Isend(&phi[slice][0], grid_size , MPI_DOUBLE, up, 2, MPI_COMM_WORLD, &requests[SEND_UP]);
} else {
requests[RECV_UP] = requests[SEND_UP] = MPI_REQUEST_NULL;
}
// ...
MPI_Waitall(MAX_REQUESTS, requests, statuses);
1: Это предусмотрено неблокирующей гарантией прогресса в стандарте MPI (3.7.4)
Progress Вызов MPI_WAIT
, который завершает получение, в конечном итоге завершится и вернется, если начался соответствующий отправка, если отправка не будет удовлетворена другим получением. В частности, если соответствующая отправка является неблокирующей, то получение должно завершиться, даже если отправитель не выполнил никакого вызова для завершения отправки. Аналогичным образом, вызов к MPI_WAIT
, который завершает отправку, в конечном итоге вернется, если соответствующий прием был начат, если только прием не удовлетворен другой отправкой, и даже если вызов не выполнен для завершения приема.