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
; это решило проблему, и мне удалось запустить мой код параллельно.