MPI_Allreduce не синхронизируется должным образом - PullRequest
0 голосов
/ 25 мая 2019

Немного новичок в MPI, но я смотрю на код, и не похоже, что они правильно используют MPI_Allreduce().

Вот фрагмент кода (на Фортране, но он должен быть доступен для чтения другим).

      do n = 1, ntts_total    !ntts_total is some large number
         send_buffer(1) = some_array(n)        !send_buffer is a size 2 array of doubles
         send_buffer(2) = proc_id

         !recv_buffer is a size 2 array of doubles
         call MPI_Allreduce(send_buffer, recv_buffer, nprocs, MPI_2DOUBLE_PRECISION, MPI_MINLOC, MPI_COMM_WORLD, ierr) 

         if (proc_id == INT(recv_buffer(2))) then
            this%n_tots = this%n_tots + 1
            my_id(this%n_tots) = n
         end if
      end do

То, что они пытаются сделать, это для каждого прохода в цикле, каждый процесс сохраняет некоторое значение в some_array и идентификатор процессора в качестве первого и второго элементов в send_buffer, соответственно. Затем они используют MPI_Allreduce, чтобы найти минимальный элемент, а также ранг процессора, в котором расположен элемент min, и затем распространяют результат среди всех процессоров.

Затем они делают проверку if.

Но я думаю, что в текущем состоянии синхронизация выключена. Я думаю, что MPI_barrier() следует вызывать прямо до и после MPI_Allreduce(), примерно так:

         call MPI_barrier(MPI_COMM_WORLD, ierr)
         !recv_buffer is a size 2 array of doubles
         call MPI_Allreduce(send_buffer, recv_buffer, nprocs, MPI_2DOUBLE_PRECISION, MPI_MINLOC, MPI_COMM_WORLD, ierr) 
         call MPI_barrier(MPI_COMM_WORLD, ierr)

Если до и после нет барьеров, то каждый процессор не будет синхронизироваться, и это может привести к тому, что процессор 1 отправит данные с n = 1, а процессор 2 отправит данные с n = 2, и сокращение будет выполнено для разных итераций.

Правильно ли я думаю?

...