Установка
Я использую mpi4py для поэлементного уменьшения массива numpy в нескольких процессах. Идея состоит в том, что массивы numpy суммируются поэлементно, так что если у меня есть два процесса, и у каждого есть массивы:
Rank 0: [1, 1, 1]
Rank 1: [2, 3, 4]
после сокращения у меня должно было быть
[3, 4, 5]
Этот случай с такими короткими массивами работает нормально.
Эта проблема
Однако в моем реальном случае использования эти массивы довольно длинные (array_length
в моем примере кода ниже). У меня нет проблем, если я отправляю массивы numpy длиной меньше или равной 505 элементам, но выше этого я получаю следующий вывод:
[83621b291fb8:01112] Read -1, expected 4048, errno = 1
и я не смог найти какой-либо документированной причины, почему это может быть. Интересно, однако, что 506 * 8 = 4048, что - при условии некоторых данных заголовка - заставляет меня подозревать, что я достиг предела буфера в 4 КБ где-то внутри mpi4py или самого MPI.
Один из возможных обходных путей
Мне удалось обойти эту проблему, разбив массив numpy, который я хочу поэлементно уменьшить, на куски размером 200 (просто произвольное число меньше 505) и вызвав Reduce () для каждого фрагмента, а затем повторная сборка на мастер процесс. Однако это несколько медленно.
Мои вопросы:
Кто-нибудь знает, действительно ли это связано с ограничением буфера в 4 КБ (или аналогичным) в mpi4py/MPI?
Есть ли лучшее решение, чем разрезать массив на части и делать много вызовов Reduce(), как я сейчас делаю, так как это кажется немного медленным.
Несколько примеров
Ниже приведен код, иллюстрирующий
- проблема, и
- одно возможное решение, основанное на разрезании массива на более короткие части и выполнении большого количества вызовов MPI Reduce(), а не только одного (управляется логическим значением
use_slices
)
С case=0
и use_slices=False
видно ошибку (длина массива 506)
С case=1
и use_slices=False
ошибка исчезает (длина массива 505)
С use_slices=True
ошибка исчезает, независимо от case
, и даже если case
установлен в очень длинный массив (case=2
)
Пример кода
import mpi4py, mpi4py.MPI
import numpy as np
###### CASE FLAGS ########
# Whether or not to break the array into 200-element pieces
# before calling MPI Reduce()
use_slices = False
# The total length of the array to be reduced:
case = 0
if case == 0:
array_length= 506
elif case == 1:
array_length= 505
elif case == 2:
array_length= 1000000
comm = mpi4py.MPI.COMM_WORLD
rank = comm.Get_rank()
nprocs = comm.Get_size()
array_to_reduce = np.ones(array_length)*(rank+1) #just some different numbers per rank
reduced_array = np.zeros(array_length)
if not use_slices:
comm.Reduce(array_to_reduce,
reduced_array,
op = mpi4py.MPI.SUM,
root = 0)
if rank==0:
print(reduced_array)
else: # in this case, use_slices is True
array_slice_length = 200
sliced_array = np.array_split(array_to_reduce, range(200, array_length, 200))
reduced_array_using_slices = np.array([])
for array_slice in sliced_array:
returnedval = np.zeros(shape=array_slice.shape)
comm.Reduce(array_slice,
returnedval,
op = mpi4py.MPI.SUM,
root = 0)
reduced_array_using_slices=np.concatenate((reduced_array_using_slices, returnedval))
comm.Barrier()
if rank==0:
print(reduced_array_using_slices)
Версии библиотеки
Собрано из исходников - openmpi 3.1.4
mpi4py 3.0.3
mpirun --mca coll ^tuned ...
и посмотрите, поможет ли это - person Gilles Gouaillardet   schedule 18.05.2020create_dataset()
h5py
(скомпилированной противMPI
), которую я сейчас пытаюсь обойти. Мог ли я неправильно скомпилировать openMPI? - хотя я подозреваю, что пробовал репозиторий ОС openMPI по крайней мере на некоторых из этих хостов... - person carthurs   schedule 18.05.2020h5py
create_dataset()
, не указавmaxshape=
в этом вызове. Это очень похоже на эту предыдущую (нерешенную) проблему, с которой я столкнулся в другой системе: of-mpi-threads" title="hdf5 h5py segfault с mpi с определенным количеством потоков mpi"> stackoverflow.com/questions/56131655/ - я был бы удивлен, если бы это не было связано с проблемойReduce()
Я вижу сейчас. - person carthurs   schedule 18.05.2020mpirun
внутри своего контейнера, и, следовательно, ваши 2 задачи MPI будут выполняться внутри одного и того же контейнера? - person Gilles Gouaillardet   schedule 18.05.2020mpirun
... в оболочку контейнера. - person carthurs   schedule 18.05.2020EPERM
, и для меня это указывает на проблему, связанную с контейнером. - person Gilles Gouaillardet   schedule 18.05.2020mpirun --mca btl_tcp_if_include eth0 ...
- person Gilles Gouaillardet   schedule 18.05.2020case = 2, use_slices = False
отлично работает на Ubuntu 16.04 с Open MPI 2.1.1 из дистрибутива. - person Hristo Iliev   schedule 18.05.2020eth0
- (плюс петля). Использованиеbtl_tcp_if_include eth0
дает ту же ошибку. - person carthurs   schedule 18.05.2020mpirun -mca btl vader,self...
илиmpirun -mca btl sm,self
илиmpirun -mca tcp,self
? - person Gilles Gouaillardet   schedule 18.05.2020mpirun -mca btl tcp,self
(сbtl
). Это не отображает ошибку. Любые мысли о том, почему? Мне все еще интересно, является ли это UB, а не исправлением, потому что я пересобрал свой контейнер с помощью openMPI 1.10.7 (из исходного кода, поскольку эта версия, по-видимому, изначально работала в моей системе), и вместо исходной ошибки возникает ошибка сообщение, независимо от того, использую ли я tcp. Других версий MPI в контейнере нет. - person carthurs   schedule 18.05.2020mpirun -mca btl_vader_single_copy_mechanism none ...
? - person Gilles Gouaillardet   schedule 18.05.2020btl/vader
использует механизм единственного копирования, основанный наprocess_vm_readv()
иprocess_vm_writev()
, и эти системные вызовы не разрешены внутри контейнера докера по умолчанию. - person Gilles Gouaillardet   schedule 18.05.2020CAP_SYS_PTRACE
. Попробуйте запустить контейнер с--add-cap=SYS_PTRACE
, а затем попробуйте без установкиbtl_vader_single_copy_mechanism
. - person Hristo Iliev   schedule 19.05.2020docker run --cap-add=SYS_PTRACE
... без установкиbtl_vader_single_copy_mechanism
наnone
. (Обратите внимание, что синтаксис--cap-add
, а не--add-cap
). В моем случае я не заметил разницы в производительности между двумя решениями. - person carthurs   schedule 19.05.2020