Многопроцессорная или потоковая в python?

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

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

Ответ 1

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

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

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

Ответ 4

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

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

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

Ответ 5

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

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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