2017-07-18 22 views
2

我遇到一个非常特殊的问题,可以用Python 3使用多池慢...见下面的代码:Python 3里多处理池与大变量

import multiprocessing as MP          

class c(object):             
    def __init__(self):            
     self.foo = ""            

    def a(self, b):             
     return b             

    def main(self):             
     with open("/path/to/2million/lines/file", "r") as f: 
      self.foo = f.readlines()        

o = c()                
o.main()               
p = MP.Pool(5)              
for r in p.imap(o.a, range(1,10)):         
    print(r)              

如果我因为是执行该代码,这是我极为缓慢结果:

1 
2 
3 
4 
5 
6 
7 
8 
9 

real 0m6.641s 
user 0m7.256s 
sys  0m1.824s      

但是,如果我删除行o.main(),然后我得到更快的执行时间:

1 
2 
3 
4 
5 
6 
7 
8 
9 

real 0m0.155s 
user 0m0.048s 
sys  0m0.004s 

我的环境有很大的力量,我确信我没有遇到任何内存限制。我还用一个较小的文件对它进行了测试,并且执行时间更加可以接受。任何见解?

编辑:我删除了磁盘IO部分,而只是创建了一个列表。我可以证明磁盘IO无关的问题...

for i in range(1,500000): 
    self.foo.append("foobar%d\n"%i) 

real 0m1.763s user 0m1.944s sys  0m0.452s 

for i in range(1,1000000): 
    self.foo.append("foobar%d\n"%i) 
real 0m3.808s user 0m4.064s sys  0m1.016s 
+0

o.main()自己需要多长时间? (没有下面的MP代码) – viraptor

+0

'真0m0.182s用户0m0.112s sys 0m0.068s' 文件大小实际上只有27M。 –

+0

你可以用['threadpoolexecutor'](https://docs.python.org/3/library/concurrent.futures.html#threadpoolexecutor)和/或['ThreadPool'](https://stackoverflow.com)/a/3386632/1189040)以查看它是否与流程开销有关? – Himal

回答

2

引擎盖下,multiprocessing.Pool使用Pipe将数据从父进程传送到池的工人。

由于整个o对象被序列化为Pickle对象并通过OS管道传输,因此这会增加任务调度的隐藏成本。

这是为每一个你正在调度的任务完成的(在你的例子中是10次)。如果您的文件大小为10 Mb,则会移动100 MB的数据。

按照multiprocessing Programming Guidelines

尽可能一个应该尽量避免换档大量进程之间的数据。

一个简单的方法,以加快你的逻辑将计算在你的文件中的行量,在相等的块分裂他们,只发送线指标的工作进程,让他们open文件,seek权线和处理数据。