Pensé que simplificaría los ejemplos más simples copiados desde arriba, trabajando para mí en Py3.6. Más simple es multiprocessing.Pool:
import multiprocessing
import time
def worker(x):
time.sleep(1)
return x
pool = multiprocessing.Pool()
print(pool.map(worker, range(10)))
Puede establecer el número de procesos en la piscina con, por ejemplo, Pool(processes=5). Sin embargo, el valor predeterminado es el recuento de CPU, así que déjelo en blanco para las tareas vinculadas a la CPU. (Las tareas vinculadas a E / S a menudo se adaptan a los subprocesos de todos modos, ya que los subprocesos en su mayoría están esperando, por lo que pueden compartir un núcleo de CPU). PoolTambién se aplica la optimización de fragmentación .
(Tenga en cuenta que el método de trabajo no se puede anidar dentro de un método. Inicialmente definí mi método de trabajo dentro del método al que hace la llamada pool.map, para mantenerlo todo autocontenido, pero luego los procesos no pudieron importarlo, y arrojé "AttributeError : No se puede encurtir el objeto local external_method..inner_method ". Más aquí . Puede estar dentro de una clase.)
(Aprecio la impresión original de la pregunta especificada en 'represent!'lugar de hacerlo time.sleep(), pero sin ella pensé que algunos códigos se ejecutaban simultáneamente cuando no era así).
Py3 ProcessPoolExecutortambién tiene dos líneas ( .mapdevuelve un generador, por lo que necesita list()):
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor() as executor:
print(list(executor.map(worker, range(10))))
Con simples Processes:
import multiprocessing
import time
def worker(x, queue):
time.sleep(1)
queue.put(x)
queue = multiprocessing.SimpleQueue()
tasks = range(10)
for task in tasks:
multiprocessing.Process(target=worker, args=(task, queue,)).start()
for _ in tasks:
print(queue.get())
Úselo SimpleQueuesi todo lo que necesita es puty get. El primer bucle inicia todos los procesos, antes de que el segundo realice las queue.getllamadas de bloqueo . No creo que haya ninguna razón para llamar p.join()también.
multiprocessing.Queue, en lugar de unManageraquí. El uso deManagerrequiere generar un proceso completamente nuevo, que es excesivo cuandoQueuelo haría.