在py2.6+中,multiprocessing
模块提供了一个Pool
类,所以可以这样做:
class Volatile(object):
def do_stuff(self, ...):
pool = multiprocessing.Pool()
return pool.imap(...)
但是,对于 2.7.2 的标准 Python 实现,这种方法很快会导致“IOError:[Errno 24] 打开的文件太多”。显然 pool
对象永远不会被垃圾收集,因此它的进程永远不会终止,累积内部打开的任何描述符。我认为这是因为以下工作:
class Volatile(object):
def do_stuff(self, ...):
pool = multiprocessing.Pool()
result = pool.map(...)
pool.terminate()
return result
我想保留 imap
的“惰性”迭代器方法;在这种情况下,垃圾收集器如何工作?如何修复代码?
最佳答案
最后,我最终传递了 pool
引用并在 pool.imap
迭代器完成后手动终止它:
class Volatile(object):
def do_stuff(self, ...):
pool = multiprocessing.Pool()
return pool, pool.imap(...)
def call_stuff(self):
pool, results = self.do_stuff()
for result in results:
# lazy evaluation of the imap
pool.terminate()
以防将来有人偶然发现此解决方案:chunksize 参数在 Pool.imap
中非常重要(与普通 Pool.map
,无关紧要)。我手动设置它,以便每个进程接收 1 + len(input)/len(pool)
作业。将它保留为默认值 chunksize=1
给我的性能就好像我根本不使用并行处理一样……不好。
我想使用有序 imap
与有序 map
并没有真正的好处,我个人更喜欢迭代器。
关于python - 多处理和垃圾收集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9959598/