2015-04-22 3 views
33

Desidero utilizzare la multiprocessing di Python per eseguire la ricerca della griglia per un modello predittivo. Quando guardo l'utilizzo di base, sembra che stia usando solo un core. Qualche idea su cosa sto facendo male?La multiprocessing di Python non sembra utilizzare più di un core

import multiprocessing 
from sklearn import svm 
import itertools 

#first read some data 
#X will be my feature Numpy 2D array 
#y will be my 1D Numpy array of labels 

#define the grid   
C = [0.1, 1] 
gamma = [0.0] 
params = [C, gamma] 
grid = list(itertools.product(*params)) 
GRID_hx = [] 

def worker(par, grid_list): 
    #define a sklearn model 
    clf = svm.SVC(C=g[0], gamma=g[1],probability=True,random_state=SEED) 
    #run a cross validation function: returns error 
    ll = my_cross_validation_function(X, y, model=clf, n=1, test_size=0.2) 
    print(par, ll) 
    grid_list.append((par, ll)) 


if __name__ == '__main__': 
    manager = multiprocessing.Manager() 
    GRID_hx = manager.list() 
    jobs = [] 
    for g in grid: 
     p = multiprocessing.Process(target=worker, args=(g,GRID_hx)) 
     jobs.append(p) 
     p.start() 
     p.join() 

    print("\n-------------------") 
    print("SORTED LIST") 
    print("-------------------") 
    L = sorted(GRID_hx, key=itemgetter(1)) 
    for l in L[:5]: 
     print l 
+1

Una volta risolto il join, è possibile anche leggere il Global Interpreter Lock (GIL). Python non può eseguire codice Python su due thread contemporaneamente. Tuttavia, nel caso di librerie C per python come numpy, queste librerie possono * scegliere * per abbandonare il GIL mentre svolgono compiti molto intensi dal punto di vista computazionale. Se si desidera utilizzare più core in modo efficace, assicurarsi che la maggior parte del lavoro sia svolto in una di quelle librerie C che rilascia GIL mentre si lavora. –

+0

Nota: probabilmente si desidera utilizzare un ['Pool'] (https://docs.python.org/3/library/multiprocessing.html#multiprocessing.pool.Pool) anziché creare e unire manualmente ogni singolo processo. Basta fare 'pool.map (worker, args = zip (grid, [GRID_hx] * len (grid))])' e questo avvierà automaticamente i diversi processi (in parallelo) e li unirà. – Bakuriu

+5

@CortAmmon Quello che stai scrivendo è completamente irrilevante. Sta usando multi ** processing ** non multi * threading *, quindi GIL non ha * un ruolo * * in quel codice. Inoltre: il fatto che stia usando 'multiprocessing' invece di' threading' probabilmente significa che già conosce il GIL. – Bakuriu

risposta

49

Il tuo problema è che si uniscono ogni posto di lavoro subito dopo si è iniziato:

for g in grid: 
    p = multiprocessing.Process(target=worker, args=(g,GRID_hx)) 
    jobs.append(p) 
    p.start() 
    p.join() 

unirsi blocchi fino a quando il relativo processo è finito di lavorare. Ciò significa che il tuo codice inizia un solo processo alla volta, attende fino al suo completamento e quindi avvia il successivo.

Al fine di tutti i processi per l'esecuzione in parallelo, è necessario prima avviarli tutti e poi unirsi a loro tutto:

jobs = [] 
for g in grid: 
    p = multiprocessing.Process(target=worker, args=(g,GRID_hx)) 
    jobs.append(p) 
    p.start() 

for j in jobs: 
    j.join() 

Documentazione: link

6

direi:

for g in grid: 
    g.p = multiprocessing.Process(target=worker, args=(g,GRID_hx)) 
    jobs.append(g.p) 
    g.p.start() 
for g in grid: 
    g.p.join() 

Attualmente il gioco è la deposizione delle uova di un lavoro, poi waithing per essere fatta, andando poi a quello successivo.

+0

La riga 'p.start()' solleverà un 'NameError' poichè 'p' non esiste. –

6

Secondo the documentation il join() blocca il thread corrente fino a quando non viene restituito il thread specificato. Quindi in pratica stai iniziando ogni thread nel ciclo for e poi aspetti che finisca, PRIMA di procedere alla successiva iterazione.

Suggerirei di spostare i join all'esterno del ciclo!

Problemi correlati