问题:多处理和垃圾回收

在 py2.6+ 中,multiprocessing模块提供了一个Pool类,所以可以这样做:

class Volatile(object):
    def do_stuff(self, ...):
        pool = multiprocessing.Pool()
        return pool.imap(...)

但是,使用 2.7.2 的标准 Python 实现,这种方法很快就会导致“IOError: [Errno 24] Too many open files”。显然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并没有真正的好处,我个人只是更喜欢迭代器。

Logo

Python社区为您提供最前沿的新闻资讯和知识内容

更多推荐