Немного новичок в 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, и сокращение будет выполнено для разных итераций.
Правильно ли я думаю?