Python: многопроцессорность, пафос и что нет

Я должен заранее извиниться, потому что этот вопрос носит довольно общий характер и может быть недостаточно ясным. Вопрос в том, как бы вы параллельно запустили функцию Python, которая сама использует пул процессов для некоторых подзадач и выполняет много тяжелых операций ввода-вывода? Это даже актуальная задача?

Я постараюсь предоставить больше информации. У меня есть процедура, скажем test_reduce(), что мне нужно запустить параллельно. Я попробовал несколько способов сделать это (см. Ниже), и мне, кажется, не хватает некоторых знаний, чтобы понять, почему все они терпят неудачу.

это test_reduce() Процедура делает много вещей. Некоторые из них более актуальны для вопроса, чем другие (и я перечислю их ниже):

  • Он использует multiprocessing модуль (так!), а именно pool.Pool пример,
  • Он использует подключение MongoDB,
  • Это сильно зависит от numpy а также scikit-learn ЛИЭС,
  • Он использует обратные вызовы и лямбды,
  • Он использует dill либ, чтобы засолить некоторые вещи.

Сначала я попытался использовать multiprocessing.dummy.Pool (который, кажется, пул потоков). Я не знаю, что конкретно в этом пуле и почему он, ну, "дурачок"; все сработало, и я получил свои результаты. Проблема в загрузке процессора. Для распараллеленных участков test_reduce() это было 100% для всех ядер; для синхронных секций это было около 40-50% большую часть времени. Я не могу сказать, что было какое-то увеличение общей скорости для этого типа "параллельного" выполнения.

Затем я попытался использовать multiprocessing.pool.Pool экземпляр для map эта процедура, по моим данным. Не удалось со следующим:

File "/usr/lib/python2.7/multiprocessing/pool.py", line 251, in map
    return self.map_async(func, iterable, chunksize).get()
  File "/usr/lib/python2.7/multiprocessing/pool.py", line 558, in get
    raise self._value
cPickle.PicklingError: Can't pickle <type 'thread.lock'>: attribute lookup thread.lock failed

Я предположил, что cPickle виноват, и нашел pathos lib, которая использует гораздо более продвинутый сборщик dill, Однако это также не помогает:

File "/local/lib/python2.7/site-packages/dill/dill.py", line 199, in load
    obj = pik.load()
  File "/usr/lib/python2.7/pickle.py", line 858, in load
    dispatch[key](self)
  File "/usr/lib/python2.7/pickle.py", line 1083, in load_newobj
    obj = cls.__new__(cls, *args)
TypeError: object.__new__(generator) is not safe, use generator.__new__()

Так вот, эту ошибку я совсем не понимаю. У меня нет выхода на stdout из моей процедуры, когда она работает в пуле, так что трудно догадаться, что происходит. Единственное, что я знаю, это то, что test_reduce() работает успешно, когда не используется многопроцессорная обработка.

Итак, как бы вы запустили параллельно что-то тяжелое и сложное?

1 ответ

Решение

Итак, благодаря ответу @MikeMcKerns, я нашел, как выполнить работу с pathos Lib. Мне нужно было избавиться от всего pymongo курсоры, которые (будучи генераторами) не могут быть выбраны dill; это решило проблему, и мне удалось запустить мой код параллельно.

Другие вопросы по тегам