Twisted Threading + MapReduce на одном узле/сервере?

Меня смущает Twisted threading.

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

Однако из того, что я видел до сих пор, похоже, что Twisted использует потоки (pThreads из модуля потоковой обработки Python). И Twisted, кажется, очень хорошо справляется с обработкой большого количества данных.

У меня есть довольно большое количество процессов, которые я хотел бы распределить по обработке с использованием шаблона MapReduce в Python на одном узле/сервере. На самом деле они не выполняют никакого ввода-вывода, они просто много обрабатывают.

Подходит ли искривленный реактор для этой работы?


person bitcycle    schedule 15.02.2011    source источник


Ответы (1)


Короткий ответ на ваш вопрос: нет, скрученная многопоточность не является правильным решением для тяжелой обработки.

Если вам нужно много обрабатывать, потоки Twisted по-прежнему будут подвергаться GIL (Global Interpreter Lock). Не вдаваясь в подробные объяснения, GIL — это то, что позволяет только одному потоку одновременно выполнять код Python. На самом деле это означает, что вы не сможете использовать преимущества нескольких ядер в одном многопоточном скрученном процессе. Тем не менее, некоторые модули C (например, фрагменты SciPy) могут выпускать GIL и работать в многопоточном режиме, хотя связанный код Python по-прежнему является однопоточным.

Потоки Twisted в основном полезны для использования вместе с блокирующими модулями на основе ввода-вывода. Ярким примером этого являются API-интерфейсы баз данных, поскольку спецификация db-api не учитывает асинхронные варианты использования, и большинство модулей баз данных придерживаются этой спецификации. Таким образом, чтобы использовать PostgreSQL, например, из искаженного приложения, нужно либо заблокировать, либо использовать что-то вроде twisted.enterprise.adbapi, который является оболочкой, которая использует twisted.internet.threads.deferToThread, чтобы разрешить выполнение SQL-запроса, в то время как другие вещи происходят. Это может позволить запустить другой код Python, потому что модуль socket (среди большинства других, связанных с вводом-выводом операционной системы) освобождает GIL во время системного вызова.


Тем не менее, вы можете использовать Twisted для написания сетевого приложения, взаимодействующего со многими скрученными (или не скрученными, если хотите) рабочими процессами. Тогда каждый рабочий процесс мог бы работать над небольшими фрагментами работы, и вы не были бы ограничены GIL, потому что каждый рабочий процесс был бы отдельным полностью изолированным процессом. Затем главный процесс может использовать многие асинхронные примитивы Twisted. Например, вы можете использовать DeferredList для ожидания ряда результатов, поступающих от любого количества рабочих процессов, а затем запускать обработчик ответов, когда все Deferred завершены. (что позволяет вам выполнять вызов карты). Если вы хотите пойти по этому пути, я рекомендую взглянуть на twisted.protocols.amp, который является их протоколом асинхронных сообщений, и его можно очень тривиально использовать для реализации сетевого RPC или map-reduce.

Недостатком запуска многих разрозненных процессов по сравнению с чем-то вроде multiprocessing является то, что

  1. вы теряете простое управление процессами, и
  2. подпроцессы не могут совместно использовать память, как если бы они были разветвлены в системе unix.

Хотя для современных систем 2) редко является проблемой, если вы не запускаете сотни подпроцессов. И проблема 1) может быть решена с помощью системы управления процессами, такой как supervisord.


Изменить Чтобы узнать больше о python и GIL, посмотрите доклады Дэйва Бизли. по теме ( веб-сайт , видео, слайды)

person Crast    schedule 15.02.2011
comment
Вы можете использовать такой модуль, как Ampoule, чтобы управлять процессом за вас. Также неясно, насколько процессы Python выигрывают от COW-страниц, производных от fork(), поскольку CPython почти постоянно записывает на страницы (для обновления счетчиков ссылок). - person Jean-Paul Calderone; 15.02.2011