2013-08-11 3 views
23

Я новичок в многопроцессорности на Python и пытаюсь выяснить, должен ли я использовать Pool или Process для вызова двух функций async. Две функции, которые я выполняю, вызывают завихрения и анализируют информацию в 2 отдельных списках. В зависимости от подключения к Интернету каждая функция может занимать около 4 секунд. Я понимаю, что узкое место находится в соединении с ISP, и многопроцессорность не ускорит его, но было бы неплохо, если бы они оба начали асинхронный запуск. Кроме того, это отличный опыт для меня, чтобы перейти на многопроцессорную обработку python, потому что я буду использовать его более позднее.Процесс обработки или пула Python для того, что я делаю?

Я читал Python multiprocessing.Pool: when to use apply, apply_async or map?, и это было полезно, но у меня были свои вопросы.

Так один способ, которым я мог бы сделать это:

Вопросы у меня есть для этой реализации является: 1) Так как присоединиться блоки до тех пор, пока вызывающий процесс будет завершен ... означает ли этот процесс p1 должен закончить до начала процесса p2? Я всегда понимал, что .join() будет таким же, как pool.apply() и pool.apply_sync(). Get(), когда родительский процесс не может запустить другой процесс (задачу) до тех пор, пока текущий исполняемый файл не будет завершен.

Другой альтернативой было бы что-то вроде:

def foo(): 
    pass 

def bar(): 
    pass 
pool = Pool(processes=2)    
p1 = pool.apply_async(foo) 
p1 = pool.apply_async(bar) 

Вопросы у меня есть для реализации этого будет: 1) Мне нужен pool.close Do(), pool.join()? 2) Будет ли pool.map() сделать их полностью законченными, прежде чем я смогу получить результаты? И если да, то они все еще бегут асинч? 3) Как pool.apply_async() отличается от выполнения каждого процесса с помощью pool.apply() 4) Как это отличается от предыдущей реализации процессом?

ответ

22

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

Первый сценарий запускает два отдельных процесса (называет их P1 и P2) и запускает P1 с запуском foo и P2 работает bar, а затем ждет, пока оба процесса не закончат свои соответствующие задачи.

Второй сценарий запускает два процесса (называет их Q1 и Q2) и сначала запускает foo на Q1 или Q2, а затем начинает bar на Q1 или Q2. Затем код ждет, пока оба вызова функций не вернутся.

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

Что касается конкретных вопросов, которые вы имели о параллельности, то .join() метод на Process не действительно блокирует, пока процесс завершится, а потому, что вы назвали .start() как на P1 и P2 (в вашем первом сценарии) до вступления, то оба процессы будут выполняться асинхронно. Однако интерпретатор ждет, пока P1 не закончит работу, прежде чем пытаться дождаться завершения P2.

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

9

Поскольку вы извлекаете данные из вызовов curl, вы привязаны к IO. В таком случае grequests может пригодиться. На самом деле это ни процессы, ни потоки, но сопрограммы - легкие потоки. Это позволит вам отправлять асинхронно HTTP-запросы, а затем использовать multiprocessing.Pool для ускорения части, связанной с процессором.

1) Поскольку блоки объединения до завершения процесса вызова ... это означает, что процесс p1 должен завершиться до того, как начнется процесс p2?

Да, p2.join() вызывается после p1.join() вернулся означая p1 закончил.

1) Нужна ли мне pool.close(), pool.join()

Вы могли бы в конечном итоге с сиротами процессов, не делая close() и join() (если процессы служат indefinetly)

2) Будет ли pool.map() сделать их все законченными, прежде чем я смогу получить результаты? И если да, то они все еще бегут асинч?

Они запускаются асинхронно, но map() заблокирован, пока все задачи не будут выполнены.

3) Как бы pool.apply_async() отличаются от выполнения каждого процесса с pool.apply()

pool.apply() блокирует, так что в основном вы могли бы сделать обработку синхронно.

4) Как это отличается от предыдущей реализации с процессом

Скорее всего, рабочий делается с foo, прежде чем применять bar так что вы могли бы в конечном итоге с одного рабочего делает всю работу. Кроме того, если один из ваших работников умирает Pool, автоматически генерируется новый (вам нужно будет повторно применить задачу).

Подводя итог: Я предпочел бы пойти с Pool - он идеально подходит для производителей-потребителей случаев и заботится о всех задачах распределения логики в.

+1

Вы уверены, что процесс p1 должен завершиться до того, как процесс p2 стартует, потому что join()? вывод из http://bpaste.net/show/ruHgFTAAMkN4UT2INPqu/ выглядит как на p2 стартует до завершения p1. – dman

+2

Я имел в виду, что 'p2' будет соединен после завершения' p1'. Извините за недопонимание. Конечно, оба процесса запускаются, как только возвращается 'start()'. –

Смежные вопросы