#python #multiprocessing
#python #многопроцессорная обработка
Вопрос:
Я пытаюсь использовать многопроцессорный модуль в python 2.6, но, видимо, есть что-то, чего я не понимаю. Я бы ожидал, что приведенный ниже класс сложит числа, отправленные ему с помощью add(), и вернет сумму в методе get_result() . Приведенный ниже код выводит «0», я бы хотел, чтобы он выводил «2». Что я пропустил?
import multiprocessing
class AdderProcess(multiprocessing.Process):
def __init__(self):
multiprocessing.Process.__init__(self)
self.sum = 0
self.queue = multiprocessing.JoinableQueue(5)
self.daemon = True
self.start()
def run(self):
while True:
number = self.queue.get()
self.sum = number
self.queue.task_done()
def add(self, number):
self.queue.put(number)
def get_result(self):
self.queue.join()
return self.sum
p = AdderProcess()
p.add(1)
p.add(1)
print p.get_result()
PS. Эта проблема решена.Спасибо за ответы! Просто чтобы облегчить читателям, вот полная рабочая версия:
import multiprocessing
class AdderProcess(multiprocessing.Process):
def __init__(self):
multiprocessing.Process.__init__(self)
self.sum = multiprocessing.Value('d', 0.0)
self.queue = multiprocessing.JoinableQueue(5)
self.daemon = True
self.start()
def run(self):
while True:
number = self.queue.get()
self.sum.value = number
self.queue.task_done()
def add(self, number):
self.queue.put(number)
def get_result(self):
self.queue.join()
return self.sum.value
p = AdderProcess()
p.add(1)
p.add(1)
print p.get_result()
Ответ №1:
Измените self.sum = 0
на self.sum = multiprocessing.Value('d', 0.0)
и используйте self.sum.value
для доступа или изменения значения.
class AdderProcess(multiprocessing.Process):
def __init__(self):
...
self.sum = multiprocessing.Value('d', 0.0)
...
def run(self):
while True:
number = self.queue.get()
self.sum.value = number # <-- use self.sum.value
self.queue.task_done()
def get_result(self):
self.queue.join()
return self.sum.value # <-- use self.sum.value
Проблема заключается в следующем: как только вы вызываете self.start()
__init__
, основной процесс разветвляет дочерний процесс. Все значения копируются. Теперь есть две версии p
. В основном процессе p.sum
равно 0. В дочернем процессе run
вызывается метод, p.sum
который увеличивается до 2. Но когда вызывается основной процесс p.get_result()
, его версия p
по-прежнему p.sum
равна 0.
Таким образом, выводится 0.
Когда вы хотите поделиться значением с плавающей запятой между процессами, вам необходимо использовать механизм совместного использования, например mp.Value
.
Дополнительные параметры совместного использования значений см. в разделе «Совместное использование состояния между процессами«.
Комментарии:
1. Предполагая, что вы имеете в виду, что я должен заменить свой инициализатор вашим кодом, этот код вызывает исключение TypeError при выполнении. Это сработало для вас? Не могли бы вы подробнее рассказать о том, что вы здесь делаете?
2. Извините, я запустил код, я просто забыл включить все свои изменения. Вам также необходимо изменить
self.sum
self.sum.value
, чтобы получить доступ или изменить значение.3. Хорошо, я думаю, что теперь я понял. Не существует магии RPC, которая заставляет вызовы методов переходить к другому процессу, единственная общая информация — это та, которая явно используется для типов данных, предоставленных для этой цели. Думаю, это имеет смысл. Спасибо!
Ответ №2:
self.sum
равно 2… в этом процессе:
def run(self):
while True:
number = self.queue.get()
print "got %s from queue" % number
print "Before adding - self.sum = %d" % self.sum
self.sum = number
print "After adding - self.sum = %d" % self.sum
self.queue.task_done()
[ 13:56 jon@host ~ ]$ ./mp.py
got 1 from queue
Before adding - self.sum = 0
After adding - self.sum = 1
got 1 from queue
Before adding - self.sum = 1
After adding - self.sum = 2
Смотрите раздел многопроцессорная обработка 16.3.1.4. — Совместное использование состояния между процессами о том, как добиться self.sum
одинакового состояния в разных процессах.