Как преобразовать многопроцессорный код Python в многопоточный код? - PullRequest
4 голосов
/ 04 ноября 2010

Мне нужно преобразовать приложение threading в приложение multiprocessing по нескольким причинам (GIL, утечки памяти). К счастью, потоки достаточно изолированы и общаются только через Queue.Queue s. Этот примитив также доступен в multiprocessing, поэтому все выглядит хорошо. Теперь, прежде чем я войду в это минное поле, я хотел бы получить несколько советов о предстоящих проблемах:

  1. Как обеспечить передачу моих объектов через Queue? Нужно ли предоставить немного __setstate__?
  2. Могу ли я рассчитывать на мгновенный возврат put (как при threading Queue с)?
  3. Общие советы / подсказки?
  4. Что-нибудь стоящее для чтения, кроме документации Python ?

1 Ответ

5 голосов
/ 25 ноября 2010

Ответ на часть 1:

Все, что должно пройти через multiprocessing.Queue (или Pipe или что-то еще), должно быть отборным . Это включает в себя основные типы, такие как tuple s, list s и dict s. Также поддерживаются классы, если они верхнего уровня и не слишком сложны (проверьте детали). Однако попытка передать lambda с не удастся.

Ответ на часть 2:

A put состоит из двух частей: для изменения очереди требуется семафор, а при необходимости запускается поток фидера. Поэтому, если никакой другой Process не попытается put к тому же Queue в одно и то же время (например, потому что в него записывается только один Process), это должно быть быстро. Для меня это оказалось достаточно быстро для всех практических целей.

Частичный ответ на часть 3:

  • На обычном multiprocessing.queue.Queue отсутствует метод task_done, поэтому его нельзя использовать в качестве прямой замены. (Подкласс обеспечивает метод.)
  • В старой версии processing.queue.Queue отсутствует метод qsize, а в более новой версии multiprocessing неточная (просто помните об этом).
  • Поскольку файловые дескрипторы обычно наследуются в fork, необходимо соблюдать осторожность при их закрытии в правильных процессах.
...