Multiprocesamiento Python para procesos paralelos.

Lo siento si esto es demasiado simple para algunas personas, pero aún no consigo el truco con el multiprocesamiento de python. he leído
http://docs.python.org/dev/library/multiprocessing
http://pymotw.com/2/multiprocessing/basics.html y muchos otros tutoriales y ejemplos que Google me ofrece … muchos de ellos también desde aquí.

Bueno, mi situación es que tengo que calcular muchas matrices numpy y luego tengo que almacenarlas en una matriz numpy única. Digamos que quiero usar 20 núcleos (o que puedo usar 20 núcleos) pero no he logrado usar con éxito el recurso de la agrupación ya que mantiene los procesos activos hasta que la agrupación “muere”. Así que pensé en hacer algo como esto:

from multiprocessing import Process, Queue import numpy as np def f(q,i): q.put( np.zeros( (4,4) ) ) if __name__ == '__main__': q = Queue() for i in range(30): p = Process(target=f, args=(q,)) p.start() p.join() result = q.get() while q.empty() == False: result += q.get() print result 

pero luego parece que los procesos no se ejecutan en paralelo, pero se ejecutan de forma secuencial (corríjame si me equivoco) y no sé si mueren después de realizar su cálculo (por lo que, para más de 20 procesos, los hay). eso hizo que su parte dejara el núcleo libre para otro proceso). Además, para un número muy grande (digamos 100.000), almacenar todas esas matrices (que también pueden ser muy grandes) en una cola usará mucha memoria, haciendo que el código sea inútil ya que la idea es poner cada resultado en cada iteración en el resultado final, como usar un locking (y sus métodos de adquisición () y liberación ()), pero si este código no es para parallel processing, el locking también es inútil …

Espero que alguien me pueda ayudar.

¡Gracias por adelantado!

Usted es correcto, se están ejecutando secuencialmente en su ejemplo.

p.join() hace que el hilo actual se bloquee hasta que termina de ejecutarse. O bien querrá unir sus procesos individualmente fuera de su bucle for (por ejemplo, almacenándolos en una lista y luego iterándolos) o usar algo como numpy.Pool y apply_async con una callback. Eso también le permitirá agregarlo directamente a sus resultados en lugar de mantener los objetos alrededor.

Por ejemplo:

 def f(i): return i*np.identity(4) if __name__ == '__main__': p=Pool(5) result = np.zeros((4,4)) def adder(value): global result result += value for i in range(30): p.apply_async(f, args=(i,), callback=adder) p.close() p.join() print result 

Cerrar y luego unirse a la agrupación al final garantiza que los procesos de la agrupación se hayan completado y que el objeto de result haya terminado de calcularse. También puede investigar usando Pool.imap como una solución a su problema. Esa solución particular se vería así:

 if __name__ == '__main__': p=Pool(5) result = np.zeros((4,4)) im = p.imap_unordered(f, range(30), chunksize=5) for x in im: result += x print result 

Esto es más limpio para su situación específica, pero puede que no lo sea para lo que esté tratando de hacer.

En cuanto a almacenar todos sus resultados variados, si entiendo su pregunta, puede agregarla a un resultado en el método de callback (como el anterior) o elemento a la vez usando imap / imap_unordered (que aún almacena los resultados , pero lo borrarás a medida que se construye). Entonces, no es necesario almacenarlo por más tiempo del que se necesita para agregarlo al resultado.