2015-04-22 12 views
33

Ich möchte mit Python-Multiprocessing Grid-Suche für ein Vorhersagemodell ausführen. Wenn ich die Kernnutzung betrachte, scheint es immer nur einen Kern zu verwenden. Irgendeine Idee, was ich falsch mache?Python-Multiprocessing scheint nicht mehr als einen Kern zu verwenden

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

Sobald Sie diesen Join behoben haben, können Sie auch die Global Interpreter Lock (GIL) lesen. Python kann Python-Code nicht gleichzeitig auf zwei Threads ausführen. Im Fall von C-Bibliotheken für Python wie numpy können diese Bibliotheken jedoch * wählen *, um die GIL aufzugeben, während sie sehr rechenintensive Aufgaben ausführen. Wenn Sie mehrere Kerne effektiv verwenden möchten, stellen Sie sicher, dass die meiste Arbeit in einer dieser C-Bibliotheken erledigt wird, die die GIL während der Arbeit fallen lässt. –

+0

Hinweis: Sie möchten wahrscheinlich einen ['Pool'] (https://docs.python.org/3/library/multiprocessing.html#multiprocessing.pool.Pool) verwenden, anstatt jeden einzelnen Prozess manuell zu erstellen und beizutreten. Tun Sie einfach 'pool.map (worker, args = zip (Gitter, [GRID_hx] * len (Gitter))]) und das wird automatisch die verschiedenen Prozesse (parallel) starten und ihnen beitreten. – Bakuriu

+5

@CortAmmon Was Sie schreiben, ist völlig irrelevant. Er benutzt Multi ** Processing ** nicht Multi * threading *, also macht die GIL * keine * Rolle in diesem Code. Außerdem: Die Tatsache, dass er "Multiprocessing" statt "Threading" verwendet, bedeutet wahrscheinlich, dass er bereits von der GIL weiß. – Bakuriu

Antwort

49

Ihr Problem ist, dass Sie sofort jeden Job beitreten , nachdem Sie es gestartet:

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

verbinden blockiert, bis der jeweilige Prozess arbeiten beendet ist. Das bedeutet, dass Ihr Code nur einen Prozess auf einmal startet, bis er beendet ist und dann den nächsten startet.

Um für alle Prozesse parallel laufen zu lassen, müssen Sie sie zuerst alle beginnen und dann kommen sie alle:

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() 

Dokumentation: link

6

würde ich sagen:

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() 

Derzeit sind Sie einen Job Laichen, dann waithing es zum nächsten gehen, dann tun.

+0

Die Zeile 'p.start()' wird einen 'NameError' auslösen, da' p' nicht existiert. –

6

-the documentation Nach dem Join() Befehl sperrt den aktuellen Thread, bis der angegebene Thread zurückgegeben wird. So beginnen Sie im Grunde jeden Thread in der for-Schleife und warten dann, bis er beendet ist, BEVOR Sie mit der nächsten Iteration fortfahren.

Ich würde vorschlagen, die Joins außerhalb der Schleife zu verschieben!

Verwandte Themen