Я использую многопроцессорность для выполнения множества последовательных задач. Эти задачи каждый раз одинаковы для разных файлов, расположенных в разных папках. Каждая задача состоит из вызовов нескольких других модулей и программ на C++. Существует оболочка высокого уровня, которая управляет вызовами других модулей/функций. В начале выполнения многопроцессорного кода создается список с идентификатором и экземпляром этого высокоуровневого класса. Затем пул процессов выполняет задачи.
Он работает нормально до тех пор, пока не возникнет неясное исключение:
Traceback (most recent call last):
File "test_parallel.py", line 197, in <module>
pool_outputs = pool.map(do_calculations, zip(list_instances, list_IDs), )
File "/usr/lib64/python2.6/multiprocessing/pool.py", line 148, in map
return self.map_async(func, iterable, chunksize).get()
File "/usr/lib64/python2.6/multiprocessing/pool.py", line 422, in get
raise self._value
IndexError: tuple index out of range
Он обычно возникает, когда задачи выполнялись много раз (~100-я задача из 200 запланированных).
Сокращенная версия кода:
import multiprocessing
if __name__=="__main__":
which_subfields=range(200)
pool_size = int( multiprocessing.cpu_count() )
run = WrapperAroundModule.run(version = "parallel")
if pool_size == 0:
pool_size=1
list_IDs = list(which_subfields)
lock=multiprocessing.Lock()
runs = []
for _ in which_subfields:
runs.append(copy.deepcopy(run))
pool = multiprocessing.Pool(processes=pool_size, )
pool_outputs = pool.map(do_calculations, zip(list_instances, list_IDs), )
pool.close()
pool.join()
с сигнатурой функции do_calculations
: do_calculations((instance, id))
Убедился, что функция do_calculations
потокобезопасна, но ситуацию это не изменило, потом хотел использовать maxtasksperchild
, но к сожалению приходится использовать python 2.6 и модуль Billard не может быть установлен на сервере (запустите Scientific Linux), который я использую. Поэтому я написал обходной путь: выполняемые задачи делятся на куски длиной pool_size*maxtasksperchild
. Сценарии выполняют эти задачи в пуле, используя аналогичный код. По завершении пул и все переменные вокруг него удаляются, и создается новый пул со следующими задачами. К сожалению, ошибка все еще возникает в какой-то момент. Более того, я убедился, что два списка, переданные в качестве аргументов, достаточно длинные. Функция do_calculations
без проблем работает с одиночными задачами, которые терпят неудачу в многопроцессорной версии.
Любая идея об источнике этой ошибки и возможном исправлении?