Ho pensato di semplificare gli esempi più semplici copiati dall'alto, lavorando per me su Py3.6. Il più semplice è multiprocessing.Pool:
import multiprocessing
import time
def worker(x):
time.sleep(1)
return x
pool = multiprocessing.Pool()
print(pool.map(worker, range(10)))
È possibile impostare il numero di processi in piscina con, ad esempio, Pool(processes=5). Tuttavia, per impostazione predefinita è il conteggio della CPU, quindi lasciarlo vuoto per le attività associate alla CPU. (Le attività associate a I / O spesso si adattano comunque ai thread, poiché i thread sono in gran parte in attesa, quindi possono condividere un core della CPU.) PoolApplica anche l'ottimizzazione del chunking .
(Si noti che il metodo worker non può essere nidificato all'interno di un metodo. Inizialmente ho definito il mio metodo worker all'interno del metodo che effettua la chiamata pool.map, per mantenerlo tutto autonomo, ma quindi i processi non sono riusciti a importarlo e ho lanciato "AttributeError : Impossibile decapare l'oggetto locale outer_method..inner_method ". Altro qui . Può essere all'interno di una classe.)
(Apprezzo la domanda originale specificata stampando 'represent!'piuttosto che time.sleep(), ma senza di essa pensavo che un po 'di codice fosse in esecuzione contemporaneamente quando non lo era.)
Py3 ha ProcessPoolExecutoranche due righe ( .maprestituisce un generatore quindi è necessario il list()):
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor() as executor:
print(list(executor.map(worker, range(10))))
Con semplici 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())
Utilizzare SimpleQueuese tutto ciò che serve è pute get. Il primo ciclo avvia tutti i processi, prima che il secondo effettui le queue.getchiamate di blocco . Non penso che ci sia alcun motivo per chiamare p.join()anche.
multiprocessing.Queue, piuttosto cheManagerqui. L'uso di aManagerrichiede la generazione di un processo completamente nuovo, che è eccessivo quandoQueuelo farebbe.