Pool.map из многопроцессорной обработки вызывает IndexError

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

Любая идея об источнике этой ошибки и возможном исправлении?


person Jolfulorc    schedule 01.04.2014    source источник


Ответы (1)


raise self._value означает, что do_calculations вызвало исключение в дочернем процессе, а multiprocessing повторно вызывает его для вас в основном процессе.

Чтобы избавиться от исключения, исправьте функцию do_calculations(). Оберните его try/except и распечатайте полную трассировку/локальные данные, чтобы понять, где ошибка.

person jfs    schedule 01.04.2014
comment
Ладно, спасибо, начинаю изолировать ошибку, пусть она совсем не тривиальна. - person Jolfulorc; 03.04.2014