2015-04-22 74 views
33

我想使用Python多处理为预测模型运行网格搜索。 当我看看核心使用情况时,它似乎总是只使用一个核心。任何想法我做错了什么?Python多处理似乎不使用多个核心

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

修复该连接后,您可能还需要阅读全局解释器锁(GIL)。 Python不能同时在两个线程上执行python代码。但是,对于像numpy这样的python的C库,这些库可以在执行计算密集型任务时选择放弃GIL。如果您想要有效地使用多个内核,请确保您的大部分工作都在C库中的一个C库中完成,这些C库在工作时丢弃GIL。 –

+0

注意:您可能希望使用['Pool'](https://docs.python.org/3/library/multiprocessing.html#multiprocessing.pool.Pool),而不是手动创建和连接每个进程。只要执行'pool.map(worker,args = zip(grid,[GRID_hx] * len(grid))])',这将自动启动不同的进程(并行)并加入它们。 – Bakuriu

+5

@CortAmmon你写的东西是完全不相关的。他正在使用多**处理**而不是多线程*,因此GIL在该代码中不会显示任何*作用。另外:他使用'multiprocessing'而不是'threading'可能意味着他已经知道GIL。 – Bakuriu

回答

49

你的问题是,你立即加入每个作业你开始后:

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

加入块,直到相应的进程已经完成的工作。这意味着您的代码只能同时启动一个进程,等待完成,然后启动下一个进程

为了让所有进程并行运行,你需要先启动所有这些,然后加入他们所有

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

文档:link

6

我会说:

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

目前你正在产卵的作业,然后waithing为它完成,然后转到下一个。

+0

'p.start()'行会因'p'不存在而引发'NameError'。 –

6

根据the documentation联接()命令锁定当前线程,直到指定的线程返回。所以你基本上是在for循环中启动每个线程,然后等待它完成,然后再继续下一次迭代。

我会建议移动循环外的连接!