2015-11-18 11 views
14

Sto provando a eseguire un ciclo parallelo su un semplice esempio.
Cosa sto sbagliando?Scrittura di un ciclo parallelo

from joblib import Parallel, delayed 
import multiprocessing 

def processInput(i): 
     return i * i 

if __name__ == '__main__': 

    # what are your inputs, and what operation do you want to 
    # perform on each input. For example... 
    inputs = range(1000000)  

    num_cores = multiprocessing.cpu_count() 

    results = Parallel(n_jobs=4)(delayed(processInput)(i) for i in inputs) 

    print(results) 

Il problema con il codice è che quando viene eseguito in ambienti Windows in Python 3, si apre num_cores istanze di Python per eseguire i lavori paralleli, ma solo uno è attivo. Questo non dovrebbe essere il caso in quanto l'attività del processore dovrebbe essere del 100% anziché del 14% (in i7 - 8 core logici).

Perché le istanze aggiuntive non stanno facendo nulla?

+0

Si riceve un messaggio di errore? Funziona bene per me ... Il rientro dovrebbe essere di 4 spazi invece di uno ... –

+0

Ho lo stesso problema. Il problema è che il codice gira solo su un core e non sui core N. –

risposta

17

Proseguendo la richiesta di fornire un codice di lavoro multiprocessing, io suggerisco di utilizzare pool_map (se la funzionalità ritardata non è importante), ti darò un esempio, se stai lavorando su python3 vale la pena menzionare che puoi usare starmap. Vale anche la pena ricordare che è possibile utilizzare map_sync/starmap_async se l'ordine dei risultati restituiti non deve corrispondere all'ordine degli input.

import multiprocessing as mp 

def processInput(i): 
     return i * i 

if __name__ == '__main__': 

    # what are your inputs, and what operation do you want to 
    # perform on each input. For example... 
    inputs = range(1000000) 
    # removing processes argument makes the code run on all available cores 
    pool = mp.Pool(processes=4) 
    results = pool.map(processInput, inputs) 
    print(results) 
+0

Adoro la semplicità di questo, quindi l'ho provato. Ottengo un errore TypeE: impossibile serializzare l'oggetto '_io.TextIOWrapper'. La mia funzione è complessa, e non ho il tempo di immergerci, solo un commento su se hai una funzione complessa, questo potrebbe non funzionare immediatamente – Nick

+0

La serializzazione è una parte importante di ogni programma multiprocesso. Per provare a mitigare tali problemi, ti consiglio di esaminare la tua funzione complessa e verificare quale parte di essa abbia realmente bisogno della soluzione multi-processing e provare a separarla dalla funzione complessa, questo faciliterà la serializzazione e potrebbe addirittura renderla non necessaria. – Fanchi

2

Su Windows, il modulo di multiprocessing utilizza il metodo 'spawn' per avviare più processi dell'interprete python. Questo è relativamente lento. Parallel tenta di essere intelligente sull'esecuzione del codice. In particolare, cerca di regolare le dimensioni del batch in modo che un batch impieghi circa mezzo secondo per essere eseguito. (Vedere l'argomento batch_size a https://pythonhosted.org/joblib/parallel.html)

La funzione processInput() corre così veloce che in parallelo determina che è più veloce per eseguire i lavori in serie su un processore che per far girare il backup di più interpreti di pitone ed eseguire il codice in parallelo.

Se si desidera forzare l'esempio per l'esecuzione su più core, provare a impostare batch_size su 1000 o rendere processInput() più complicato, quindi è necessario più tempo per l'esecuzione.

Edit: Esempio di applicazione su Windows che mostra più processi in uso (sto usando Windows 7):

from joblib import Parallel, delayed 
from os import getpid 

def modfib(n): 
    # print the process id to see that multiple processes are used, and 
    # re-used during the job. 
    if n%400 == 0: 
     print(getpid(), n) 

    # fibonacci sequence mod 1000000 
    a,b = 0,1 
    for i in range(n): 
     a,b = b,(a+b)%1000000 
    return b 

if __name__ == "__main__": 
    Parallel(n_jobs=-1, verbose=5)(delayed(modfib)(j) for j in range(1000, 4000)) 
+0

Puoi proporre una modifica del codice in modo che l'attività venga effettivamente eseguita in parallelo? Dato che il codice sopra riportato è un esempio di utilizzo di joblib, dovrebbe esserci un esempio che funzioni effettivamente. –