Повторяющиеся последовательные вызовы subprocess.Popen() в сценарии, распараллеленном с mpi4py, в конечном итоге вызывают то, что кажется повреждением данных во время связи, что проявляется в виде ошибки pickle.unpickling различных типов (я видел ошибки распаковки: EOF, недопустимый символ юникода, неверный ключ загрузки, потеря значимости стека распаковки). Кажется, это происходит только тогда, когда передаваемые данные велики, количество последовательных вызовов подпроцесса велико или количество процессов mpi велико.
Я могу воспроизвести ошибку с помощью python>=2.7, mpi4py>=3.0.1 и openmpi>=3.0.0. В конечном итоге я хотел бы общаться с объектами python, поэтому я использую методы mpi4py в нижнем регистре. Вот минимальный код, который воспроизводит ошибку:
#!/usr/bin/env python
from mpi4py import MPI
from copy import deepcopy
import subprocess
nr_calcs = 4
tasks_per_calc = 44
data_size = 55000
# --------------------------------------------------------------------
def run_test(nr_calcs, tasks_per_calc, data_size):
# Init MPI
comm = MPI.COMM_WORLD
rank = comm.Get_rank()
comm_size = comm.Get_size()
# Run Moc Calcs
icalc = 0
while True:
if icalc > nr_calcs - 1: break
index = icalc
icalc += 1
# Init Moc Tasks
task_list = []
moc_task = data_size*"x"
if rank==0:
task_list = [deepcopy(moc_task) for i in range(tasks_per_calc)]
task_list = comm.bcast(task_list)
# Moc Run Tasks
itmp = rank
while True:
if itmp > len(task_list)-1: break
itmp += comm_size
proc = subprocess.Popen(["echo", "TEST CALL TO SUBPROCESS"],
stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
out,err = proc.communicate()
print("Rank {:3d} Finished Calc {:3d}".format(rank, index))
# --------------------------------------------------------------------
if __name__ == '__main__':
run_test(nr_calcs, tasks_per_calc, data_size)
Запуск этого на одном 44-ядерном узле с процессами 44 mpi успешно завершает первые 3 «вычисления», но в последнем цикле возникают некоторые процессы:
Traceback (most recent call last):
File "./run_test.py", line 54, in <module>
run_test(nr_calcs, tasks_per_calc, data_size)
File "./run_test.py", line 39, in run_test
task_list = comm.bcast(task_list)
File "mpi4py/MPI/Comm.pyx", line 1257, in mpi4py.MPI.Comm.bcast
File "mpi4py/MPI/msgpickle.pxi", line 639, in mpi4py.MPI.PyMPI_bcast
File "mpi4py/MPI/msgpickle.pxi", line 111, in mpi4py.MPI.Pickle.load
File "mpi4py/MPI/msgpickle.pxi", line 101, in mpi4py.MPI.Pickle.cloads
_pickle.UnpicklingError
Иногда UnpicklingError имеет дескриптор, такой как неверный ключ загрузки «x» или ошибка EOF, недопустимый символ Unicode или опустошение стека распаковки.
Редактировать: похоже, проблема исчезает с openmpi‹3.0.0 и с использованием mvapich2, но все же было бы хорошо понять, что происходит.