2011-10-15 26 views
5

Estoy tratando de utilizar el módulo de multiprocesamiento en Python 2.6, pero parece que hay algo que no entiendo. Esperaría que la clase a continuación agregue los números que le envía add() y devuelve la suma en el método get_result(). El siguiente código imprime "0", me gustaría imprimir "2". ¿Qué me he perdido?Con el módulo de multiprocesamiento

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. Este problema ha sido resuelto. ¡Gracias por las respuestas! Sólo para hacer más fácil para los lectores, aquí está la versión de trabajo completa:

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() 

Respuesta

6

Cambio self.sum = 0 a self.sum = multiprocessing.Value('d', 0.0), y utilizar self.sum.value para acceder o cambiar el valor.

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 

El problema es el siguiente: Una vez que se llama a self.start() en __init__, los principales tenedores de proceso de un proceso hijo. Todos los valores son copiados. Ahora hay dos versiones de p. En el proceso principal, p.sum es 0. En el proceso secundario, se llama al método run y p.sum se aumenta a 2. Pero cuando el proceso principal llama a p.get_result(), su versión de p igual tiene igual a 0. Se imprime 0 .

Cuando desee compartir un valor flotante entre los procesos, es necesario utilizar un mecanismo de reparto, tales como mp.Value.

Ver "Sharing state between processes" para más opciones sobre cómo compartir valores.

+0

Suponiendo que quiere decir que debería sustituir a mi inicializador con su código, el código provoca una excepción TypeError cuando se ejecuta. ¿Funcionó para ti? ¿Puedes dar más detalles sobre lo que estás haciendo aquí? –

+0

Lo siento, me he corrido el código, simplemente se olvidó de incluir todos mis cambios. También debe cambiar 'self.sum' por' self.sum.value' para acceder o cambiar el valor. – unutbu

+0

Ok, creo que lo tengo ahora. No hay magia RPC que hace que el método de las llamadas se dirigen a otro proceso, la única información compartida es el compartido de forma explícita con los tipos de datos previstos a tal efecto. Tiene sentido, supongo. ¡Gracias! –

1

self.sum es 2 ... en ese proceso:

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 [email protected] ~ ]$ ./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 

Ver multiprocessing 16.3.1.4. - Sharing state between processes sobre cómo conseguir self.sum a ser el mismo en los diferentes procesos.

Cuestiones relacionadas