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.) Pool
Applica 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 ProcessPoolExecutor
anche due righe ( .map
restituisce un generatore quindi è necessario il list()
):
from concurrent.futures import ProcessPoolExecutor
with ProcessPoolExecutor() as executor:
print(list(executor.map(worker, range(10))))
Con semplici Process
es:
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 SimpleQueue
se tutto ciò che serve è put
e get
. Il primo ciclo avvia tutti i processi, prima che il secondo effettui le queue.get
chiamate di blocco . Non penso che ci sia alcun motivo per chiamare p.join()
anche.
multiprocessing.Queue
, piuttosto cheManager
qui. L'uso di aManager
richiede la generazione di un processo completamente nuovo, che è eccessivo quandoQueue
lo farebbe.