Почему MPI Sendrecv блокирует?


Предположим, что у меня есть n процессов и каждый из них обладает частью локальных данных, скажем, int.

Теперь я хочу повторно реализовать функцию MPI_Allreduce(), то есть вычислить глобальную сумму всех этих ints, а затем передать полученную сумму обратно в процессы.

Я попытался сделать это, как в приведенном ниже коде:

  int temp;
  int my_sum = temp = my_data;
  for (int i = 1; i < size; ++i) {
    int partner = (my_rank + 1) % size;
    MPI_Sendrecv_replace(&temp, 1, MPI_INT, 
                         partner, 0, 
                         my_rank, 0, 
                         MPI_COMM_WORLD, MPI_STATUS_IGNORE);
    my_sum += temp;
  }

Так что процессы общаются в кольце fahion, но оно блокирует. Почему? Как изменить код, чтобы он работал как следует?

Примечание: пожалуйста, не предлагайте альтернативные (лучшие) решения проблемы (очевидно, что одно из них-использовать функцию MPI_Allreduce () ). Моя цель-понять, почему этот фрагмент кода не работает так, как я думаю.

1   3   2012-08-29 02:46:28

1 ответ:

Все пытаются получить от самих себя, но они посылают к partner; так как partner никогда не получит отправляемое сообщение, а my_rank никогда не получит сообщение от самого себя, здесь есть зависание.

Если вы пытаетесь отправить данные в parter, то вам нужно убедиться, что partner получает от вас, что означает, что все должны получать от (myrank - 1 + size) % size:

int spartner = (my_rank + 1) % size;
int rpartner = (my_rank - 1 + size) % size;
MPI_Sendrecv_replace(&temp, 1, MPI_INT,
                     spartner, i,
                     rpartner, i,
                     MPI_COMM_WORLD, MPI_STATUS_IGNORE);

Таким образом, ранг 3 (скажем) отправляет в 4, а ранг 4 получает от ранга 3 на каждой итерации, и поэтому sendrecv завершает работу. (Я также взял на себя смелость дать каждой итерации через цикл свой собственный тег, который на самом деле не нужен здесь, но часто помогает найти ошибки, если есть другие ошибки типа несоответствующего сообщения.)