2013-08-11 4 views
8

Я пытаюсь изучить многопроцессорность Python.Пример документации по многопроцессорной обработке Python

http://docs.python.org/2/library/multiprocessing.html на примере «Для того, чтобы показать идентификаторы индивидуальный процесс вовлекаются, вот расширенный пример:»

from multiprocessing import Process 
import os 

def info(title): 
    print title 
    print 'module name:', __name__ 
    if hasattr(os, 'getppid'): # only available on Unix 
     print 'parent process:', os.getppid() 
    print 'process id:', os.getpid() 

def f(name): 
    info('function f') 
    print 'hello', name 

if __name__ == '__main__': 
    info('main line') 
    p = Process(target=f, args=('bob',)) 
    p.start() 
    p.join() 

Что именно я смотрю? Я вижу, что def f (name): вызывается после того, как информация («главная строка») завершена, но этот синхронный вызов будет по умолчанию в любом случае. Я вижу, что одна и та же информация о процессе («главная строка») является родительским PID def f (name): но не уверен, что такое «многопроцессорность».

Кроме того, with join() «Заблокировать вызывающий поток до тех пор, пока процесс, метод join() не будет завершен». Я не понимаю, на что будет направленный поток. В этом примере, что бы join() блокировать?

ответ

25

Как multiprocessing работы, в двух словах:

  • Process() нерестится (fork похожих на Unix-подобных системах) копия исходной программы (на Windows, в которой отсутствует реальный fork, это сложно и требует особой осторожности, указанной в документации к модулю).
  • Копия связывается с оригиналом, чтобы выяснить, что (a) это копия, и (b) она должна исчезнуть и вызвать функцию target= (см. Ниже).
  • На данный момент оригинал и копия теперь отличаются и независимы и могут работать одновременно.

Поскольку они являются независимыми процессами, они теперь имеют независимые глобальные Интерпретатор замки (в CPython), так как можно использовать до 100% ЦП на поле многопроцессорной, до тех пор, пока они не борются за другие ресурсы нижнего уровня (ОС). Это часть «многопроцессорности».

Конечно, в какой-то момент вам нужно отправлять данные назад и вперед между этими якобы независимыми процессами, например, отправлять результаты от одного (или многих) рабочих процессов обратно к «основному» процессу. (Существует случайное исключение, когда все полностью независимы, но это редкость ... плюс есть сама последовательность запуска, начатая p.start().) Поэтому каждый созданный Process экземпляр p, в приведенном выше примере, имеет канал связи его родительскому создателю и наоборот (это симметричное соединение). Модуль multiprocessing использует модуль pickle для преобразования данных в строки - те же строки, которые вы можете хранить в файлах с помощью pickle.dump, - и отправляет данные по каналу «вниз» к работникам для отправки аргументов и т. Д., А «вверх» от рабочих до отправьте результаты.

В конце концов, как только вы закончите получать результаты, работник заканчивает (возвращаясь из функции target=) и сообщает родителям, что это сделано. Чтобы убедиться, что все закрыто и очищено, родитель должен позвонить p.join(), чтобы дождаться сообщения работника «Я сделан» (фактически, на уровне ОС exit на Unix-ish sysems).

Пример немного глупый, так как два печатных сообщения вообще не имеют времени, поэтому запуск их «в то же время» не имеет измеримого усиления. Но предположим, что вместо того, чтобы просто печатать hello, f должны были вычислять первые 100 000 цифр π (3.14159 ...). Затем вы можете создать другую Process, p2 с другой целью g, которая вычисляет первые 100 000 цифр e (2.71828 ...). Они будут работать независимо.Затем родитель мог позвонить p.join() и p2.join(), чтобы дождаться, пока они завершатся (или появятся еще больше работников, чтобы больше работать и занимать больше процессоров, или даже уйти и сделать свою работу некоторое время).

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