многопроцессорность или многопоточность в питоне? - PullRequest
32 голосов
/ 04 августа 2009

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

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

Ответы [ 8 ]

30 голосов
/ 04 августа 2009

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

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

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

Stackless Python также хорошая идея. У Stackless есть проблемы с переносимостью, как указано выше. Unladen Swallow была многообещающей, но теперь несуществующей. Pyston - еще одна (незавершенная) реализация Python, ориентированная на скорость. Он использует подход, отличный от PyPy, который может привести к лучшему (или просто другому) ускорению.

9 голосов
/ 26 января 2010

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

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

Настройка многопроцессорности может быть очень простой:

from multiprocessing import Pool

def worker(input_item):
    output = do_some_work()
    return output

pool = Pool() # it make one process for each CPU (or core) of your PC. Use "Pool(4)" to force to use 4 processes, for example.
list_of_results = pool.map(worker, input_list) # Launch all automatically
7 голосов
/ 04 августа 2009

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

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

Однако Stackless препятствует переносимости, поскольку вам необходимо заменить несколько стандартных библиотек Python - Stackless снимает зависимость от стека C. Он очень переносим, ​​если у следующего пользователя также установлен Stackless, но это будет редко.

7 голосов
/ 04 августа 2009

Для небольших коллекций данных просто создайте подпроцессы с помощью subprocess.Popen .

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

Когда подпроцессы завершены (или истекло время ожидания), вы просто объединяете выходные файлы.

Очень просто.

0 голосов
/ 26 января 2010

Возможно, вы захотите посмотреть на Twisted . Он предназначен для асинхронных сетевых задач.

0 голосов
/ 10 августа 2009

IronPython имеет реальную многопоточность, в отличие от CPython и GIL. Поэтому, в зависимости от того, что вы делаете, стоит посмотреть. Но, похоже, ваш вариант использования лучше подходит для многопроцессорного модуля.

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

0 голосов
/ 04 августа 2009

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

0 голосов
/ 04 августа 2009

Использование потоковой модели CPython не даст вам никакого улучшения производительности, потому что потоки фактически не выполняются параллельно из-за способа обработки сборки мусора. Многопроцессорность позволила бы параллельное выполнение. Очевидно, что в этом случае вам нужно иметь несколько ядер, чтобы перенести ваши параллельные задания на.

В этом вопросе имеется гораздо больше информации .

...