2015-06-28 174 views
1

我试图运行一个函数与多处理。这是代码:蟒蛇多处理找不到错误

import multiprocessing as mu 

output = [] 
def f(x): 
    output.append(x*x) 


jobs = [] 
np = mu.cpu_count() 

for n in range(np*500): 
    p = mu.Process(target=f, args=(n,)) 
    jobs.append(p) 


running = [] 

for i in range(np): 
    p = jobs.pop() 
    running.append(p) 
    p.start() 

while jobs != []: 
    for r in running: 
     if r.exitcode == 0: 
      try: 
       running.remove(r) 
       p = jobs.pop() 
       p.start() 
       running.append(p) 
      except IndexError: 
       break 

print "Done:" 
print output 

输出是[],而它应该是[1,4,9,...]。有人看到我犯了一个错误?

+0

Cursory瞥了一下代码,你在哪里等待工作完成? 'jobs.join()'在哪里?似乎也缺乏锁定,但我还没有弄清楚你的逻辑。 – cdarke

+0

用while和if if r.exitcode == 0,我认为 –

+0

@cdarke是什么? 'None!= 0' – jonrsharpe

回答

0

编辑: 感谢@罗兰史密斯指出。 主要问题是功能f(x)。当子进程调用这个函数时,它无法为它们修改output变量(因为它不是共享)。

编辑: 正如@cdarke说,在多处理你要仔细控制共享对象,子进程可以访问(也许锁),这是相当复杂和难以调试。

我个人建议为此使用Pool.map方法。

举例来说,我认为你直接运行这个代码,而不是作为一个模块,那么你的代码将是:

import multiprocessing as mu 

def f(x): 
    return x*x 

if __name__ == '__main__': 
    np = mu.cpu_count() 
    args = [n for n in range(np*500)] 

    pool = mu.Pool(processes=np) 
    result = pool.map(f, args) 
    pool.close() 
    pool.join() 
    print result 

但有些事情你必须知道

  1. 如果你只是运行这个文件但不能导入模块,if __name__ == '__main__':是很重要的,因为python会加载这个文件作为其他进程的模块,如果你不把函数'f'放在if __name__ == '__main__':之外,子进程将无法找到你的函数'f' **编辑:** th anks @Roland史密斯指出的是,我们可以使用元组
  2. ,如果你有一个以上args作为函数f,那么你可能需要一个元组这样做,例如

     
    def f((x,y)) 
        return x*y 
    
    args = [(n,1) for n in range(np*500)] 
    result = pool.map(f, args) 
    

    或检查here为更详细的讨论

+0

关于2,你可以把所有参数放在一个'tuple'中。 –

+0

是的,你是对的,我与其他需要lamdba功能的方法混淆,我会编辑这个。 – Jkm

+1

并且使用多处理,问题代码中的输出列表* *不共享。 –

1

您正在使用multiprocessing而不是threading。所以你的output列表是而不是之间共享的进程。

有几种可能的解决方案;

  1. 保留大部分程序,但使用multiprocessing.Queue而不是列表。让工人把他们的结果放在队列中,并从主程序中读取。它会将数据从流程复制到流程,因此对于大数据量的数据来说,这会产生很大的开销。
  2. 您可以使用multiprocessing.Array的形式共享内存。如果处理的数据很大,这可能是最好的解决方案。
  3. 使用Pool。这为您处理所有流程管理。就像使用队列一样,它将数据从流程复制到流程。这可能是最容易使用的。如果发送给每个工作人员的数据很小,那么IMO是最好的选择。
  4. 使用threading,以便output列表在线程之间共享。 CPython中的线程有一个限制,一次只有一个线程可以执行Python字节码,因此可能不会获得与预期相同的性能优势。与多处理解决方案不同,它不会利用多核。