Проблема с использованием MPI_SENDRECV с 4 потоками - PullRequest
1 голос
/ 01 апреля 2019

Как минимальная проблема, я пытаюсь отправить целое число между 4 процессорами: 0 -> 3 (ранг 0 отправляет и получает ранг 3), 2 -> 1, 1 -> 2,3 -> 0. Он никогда не завершает выполнение и зависает, вероятно, ожидая ответа от других потоков.

Я компилирую код с mpif90 ... и запускаю с mpiexec -np 4 ....Ниже приведен минимальный фрагмент:

program sendrecv
  implicit none
  include "mpif.h"
  integer :: foo, bar
  integer :: mpi_rank, mpi_size, ierr
  integer :: mpi_sendto, mpi_recvfrom
  integer :: istat(MPI_STATUS_SIZE), status, i

  call MPI_INIT(ierr)
  call MPI_COMM_SIZE(MPI_COMM_WORLD, mpi_size, ierr)
  call MPI_COMM_RANK(MPI_COMM_WORLD, mpi_rank, ierr)
  print *, "SENDING..."

  if (mpi_rank .eq. 0) then
    mpi_sendto = 3; mpi_recvfrom = 3
  else if (mpi_rank .eq. 1) then
    mpi_sendto = 2; mpi_recvfrom = 2
  else if (mpi_rank .eq. 2) then
    mpi_sendto = 1; mpi_recvfrom = 1
  else
    mpi_sendto = 0; mpi_recvfrom = 0
  end if

  foo = mpi_rank
  do i = 1, 5
    foo = mpi_rank
    call MPI_SENDRECV(foo, 1,&
                    & MPI_INTEGER, mpi_sendto, mpi_rank * 10 + i,&
                    & bar, 1,&
                    & MPI_INTEGER, mpi_recvfrom, mpi_rank * 10 + i,&
                    & MPI_COMM_WORLD, istat, ierr)
  end do

  print *, "...DONE"
  call MPI_FINALIZE(ierr)
end

Я не совсем понимаю, почему эта программа зависает, может быть, я что-то упускаю или что-то действительно неправильно.Если я правильно понимаю, MPI_SENDRECV это просто неблокирующая send и recv с двумя wait -ами.В этом случае, скажем, если rank=0 отправляет rank=3, у него не должно возникнуть проблем с получением, верно?

Я пытался отправлять / получать из разных потоков, т. Е. Делал это:

  if (mpi_rank .eq. 0) then
    mpi_sendto = 1; mpi_recvfrom = 3
  else if (mpi_rank .eq. 1) then
    mpi_sendto = 2; mpi_recvfrom = 0
  else if (mpi_rank .eq. 2) then
    mpi_sendto = 3; mpi_recvfrom = 1
  else
    mpi_sendto = 0; mpi_recvfrom = 2
  end if

все еще не работает.

UPD Как было указано, теги должны быть одинаковыми при выполнении SENDRECV, однако в случае, когда этот вызов выполняется внутрицикл, похожие теги мало помогают (см. модифицированный код).Старая версия:

call MPI_SENDRECV(foo, 1,&
                    & MPI_INTEGER, mpi_sendto, 200,&
                    & bar, 1,&
                    & MPI_INTEGER, mpi_recvfrom, 100,&
                    & MPI_COMM_WORLD, status, ierr)

UPD # 2 На самом деле, если кому-то интересно, я нашел обсуждение именно о проблеме, с которой я столкнулся, почему SENDRECV -s может иногда тупиковая

1 Ответ

2 голосов
/ 01 апреля 2019

Термин «поток» вводит в заблуждение, вам следует поговорить о задаче MPI или процессе MPI (оба эквивалентны).

Основной причиной является несоответствие тега.Вы отправляете с тегом 200, но получаете с тегом 100.

Кроме того, вы должны использовать istat вместо status в качестве аргумента состояния MPI_Sendrecv().

Здеськак вы можете исправить вашу программу

call MPI_SENDRECV(foo, 1,&
                & MPI_INTEGER, mpi_sendto, 200,&
                & bar, 1,&
                & MPI_INTEGER, mpi_recvfrom, 200,&
                & MPI_COMM_WORLD, istat, ierr)
...