выбор между подпроцессом, многопроцессорной обработкой и потоком в Python?



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



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



какие мысли по этому поводу? Я бы хотел, чтобы самое простое решение было портативным.

664   5  

5 ответов:

multiprocessing большой швейцарский армейский нож тип модуля. Он является более общим, чем потоки, так как вы можете даже выполнять удаленные вычисления. Поэтому этот модуль я бы предложил вам использовать.

The subprocess модуль также позволит вам запускать несколько процессов, но я обнаружил, что он менее удобен в использовании, чем новый многопроцессорный модуль.

потоки, как известно, тонкие, и, с CPython, вы часто ограничены одним ядром, с ними (хотя, как в одном из комментариев отмечается, что глобальная блокировка интерпретатора (GIL) может быть выпущена в коде C, вызванном из кода Python).

Я считаю, что большинство функций трех модулей, которые вы цитируете, могут использоваться независимо от платформы. На стороне переносимости, обратите внимание, что multiprocessing только входит в стандартную версию с Python 2.6 (версия для некоторых более старых версий Python существует, хотя). Но это отличный модуль!

для меня это на самом деле довольно просто:

The подпроцесс:

subprocess и для запуска других исполняемых файлов - - - это в основном обертка вокруг os.fork() и os.execve() С некоторой поддержкой дополнительной сантехники (настройка труб Для и из подпроцессов. (Очевидно, что могут использоваться другие механизмы межпроцессной связи (IPC), такие как сокеты, общая память SysV и очереди сообщений- - - но вы будете ограничено любыми интерфейсами и каналами IPC, которые поддерживаются программами, которые вы вызываете).

обычно используется subprocess синхронно - - - просто вызывая некоторую внешнюю утилиту и считывая ее вывод или ожидая ее завершения (возможно, читая ее результаты из временного файла или после того, как она отправила их в какую-то базу данных).

однако можно породить сотни подпроцессов и опросить их. Моя личная любимая утилита classh тут именно так. самый большой недостаток на subprocess модуль заключается в том, что его поддержка ввода-вывода обычно блокируется. Есть черновик PEP-3145 чтобы исправить это в какой-то будущей версии Python 3.x и альтернатива asyncproc (предупреждение, которое ведет прямо к загрузке, а не к какой-либо документации или README). Я также обнаружил, что это относительно легко и просто fcntl и управления Popen файловые дескрипторы трубы напрямую - - - хотя я не знаю, переносится ли это на платформы, отличные от UNIX.

subprocessпочти не поддерживает обработку событий ... хотя можно использовать signal модуль и простые сигналы старой школы UNIX / Linux - - - убивая ваши процессы мягко,как это было.

The многопроцессорная обработка:

multiprocessing и для запуска функций в рамках существующего кода (Python) С поддержкой для более гибкого связи между этим семейством процессов. В частности, лучше всего построить свой multiprocessing IPC вокруг модуля Queue объекты, где это возможно, но вы также можете использовать Event объекты и различные другие функции (некоторые из которых, предположительно, построен вокруг mmap поддержка на платформах, где эта поддержка достаточно).

в Python multiprocessing модуль предназначен для обеспечения интерфейса и функций, которые очень аналогичноthreading в то же время позволяя CPython для масштабирования обработки между несколькими процессорами / ядрами, несмотря на Gil (Global Interpreter Lock). Он использует все мелкозернистые SMP блокировки и когерентности усилия, которые были сделаны разработчиками вашего ядра ОС.

The резьбонарезной:

threading и для довольно узкого диапазона приложений, которые связаны с вводом/выводом (не нужно масштабировать через несколько ядер процессора) и которые извлекают выгоду из чрезвычайно низкой задержки и переключения накладные расходы на переключение потоков (с общей памятью ядра) против переключения процесса/контекста. В Linux это почти пустой набор (время переключения процесса Linux чрезвычайно близко к его потоковым переключателям).

threading страдает два основных недостатка в Python.

один, конечно, специфичен для реализации --- в основном влияет на CPython. Это Гил. По большей части, большинство программ CPython не выиграют от наличия более чем два процессора (ядра) и часто производительность страдают от Гиль конфликты блокировок.

большая проблема, которая не является специфичной для реализации, заключается в том, что потоки используют одну и ту же память, обработчики сигналов, файловые дескрипторы и некоторые другие ресурсы ОС. Таким образом, программист должен быть чрезвычайно осторожным в отношении блокировки объектов, обработки исключений и других аспектов их кода, которые являются одновременно тонкими и которые могут убить, остановить или заблокировать весь процесс (набор нити.)

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

  • (Примечание: использование threading С основными системами Python, такими как включает в себя, может страдайте значительно меньше от конкуренции GIL, чем большая часть вашего собственного кода Python. Это потому, что они были специально разработаны для этого).

The витая:

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

чтобы понять, как это возможно, нужно прочитать об особенностях select() (который может быть построен вокруг select () или () или аналогичные системные вызовы ОС). В основном это все обусловлено возможностью сделать запрос ОС на сон в ожидании любой активности в списке файловых дескрипторов или некоторых перерыв.

пробуждение от каждого из этих вызовов select() событие --- ни один, связанные с вводом доступна (для чтения) на несколько розеток или дескрипторов файлов, или буферизации пространство становится доступна на некоторых других (с возможностью записи) дескрипторы и сокеты, каких-то исключительных условиях (протокол TCP-каналу толкать, что пакеты, например), или тайм-аут.

таким образом, скрученная модель программирования построена вокруг обработки этих событий, а затем зацикливается на результирующей " main" обработчик, позволяющий ему отправлять события вашим обработчикам.

я лично думаю, что имя витая как вызывающий воспоминания о модели программирования ... поскольку ваш подход к проблеме должен быть, в некотором смысле, "вывернут" наизнанку. Вместо того чтобы представлять свою программу как серию операций над входными данными и выходами или результатами, вы пишете свою программу как службу или демон и определяете, как она реагирует на различные события. (На самом деле ядром "основного цикла" витой программы является (обычно? всегда?) a reactor().

The основные проблемы с использованием Twisted включайте скручивание вашего ума вокруг модели, управляемой событиями, а также избегание использования любых библиотек классов или наборов инструментов, которые не написаны для сотрудничества в рамках Twisted framework. Вот почему Twisted предоставляет свои собственные модули для обработки протокола SSH, для проклятий, а также свои собственные функции подпроцесса/popen и многие другие модули и протокол обработчики, которые на первый взгляд кажутся дублирующими вещи в стандартных библиотеках Python.

я думаю, что полезно понять Twisted на концептуальном уровне, даже если вы никогда не собираетесь его использовать. Это может дать представление о производительности, конкуренции и обработке событий в потоковой обработке, многопроцессорной обработке и даже обработке подпроцессов, а также любой распределенной обработке, которую вы выполняете.

(Примечание: новые версии Python 3.x включают в себя ввода-вывода (асинхронный ввод / вывод) такие функции, как асинхронный def на @async.корутин декоратор, и ждут ключевое слово выход из будущего поддержка. Все они примерно похожи на витая С точки зрения процесса (совместной многозадачности).

The распределенные:

еще одна область обработки, о которой вы не спрашивали, но которая стоит рассмотреть, что из распределенные обработка. Существует множество инструментов и фреймворков Python для распределенной обработки и параллельных вычислений. Лично я думаю, что самый простой в использовании-это тот, который наименее часто считается в этом пространстве.

это почти тривиально, чтобы построить распределенную обработку вокруг Рэдис. Все хранилище ключей можно использовать для хранения рабочих единиц и результатов, списки Redis можно использовать как Queue() как объект, и паб/SUB поддержка может быть использована для Eventкак обращение. Вы можете хэшировать свои ключи и использовать значения, реплицированные через Свободный кластер экземпляров Redis, для хранения топологии и сопоставлений хэш-маркеров, чтобы обеспечить согласованное хэширование и отказоустойчивость для масштабирования за пределами возможностей любого отдельного экземпляра для координации ваших работников и маршалинга данных (маринованных, JSON, BSON или YAML) среди них.

конечно, как вы начинаете строить в большем масштабе и более сложные решение вокруг Redis вы повторно реализуете многие функции, которые уже были решены с помощью,сельдерей, Apache Spark и Hadoop,Zookeeper,etcd,Кассандра и так далее. Эти все модули для Python доступ к их услугам.

[обновление: несколько ресурсов для рассмотрения, если вы рассматриваете Python для вычислительно интенсивного распределения системы: IPython Parallel и PySpark. Хотя это распределенные вычислительные системы общего назначения, они являются особенно доступными и популярными подсистемами науки о данных и аналитики].

вывод

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

чтобы использовать несколько процессоров в CPython ваш только выбор multiprocessing модуль. CPython держит замок на его внутренностях (Гиль), что предотвращает параллельную работу потоков на других процессорах. Элемент multiprocessing модуль создает новые процессы ( например,subprocess) и управляет связью между ними.

в аналогичном случае я выбрал отдельные процессы и немного необходимой связи через сетевую розетку. Это очень портативно и довольно просто сделать с помощью python, но, вероятно, не проще (в моем случае у меня было еще одно ограничение: связь с другими процессами, написанными на C++).

в вашем случае я бы, вероятно, пошел на мультипроцесс, так как потоки python, по крайней мере, при использовании CPython, не являются реальными потоками. Ну, они являются родными системными потоками, но C модули, вызываемые из Python, могут освобождать или не освобождать GIL и разрешать другим потокам запускать их при вызове кода блокировки.

Shell out и пусть unix, чтобы сделать свою работу:

использовать iterpipes чтобы обернуть подпроцесс, а затем:

С сайта Теда Зюбы

INPUTS_FROM_YOU / xargs-n1 -0-P NUM ./процесс #число параллельных процессов

или

GNU Parallel также будет служить

вы болтаетесь с Гилом, пока вы отправляете закулисных мальчиков, чтобы сделать свою многоядерную работу.

Comments

    Ничего не найдено.