在pool.imap_unordered上迭代

时间:2012-03-25 16:57:54

标签: python iterator multiprocessing

考虑非常简单的代码:

#!/usr/bin/python

from multiprocessing import Pool
import random

def f(x):
    return x*x

def sampleiter(n):
    num = 0
    while num < n:
     rand = random.random()
     yield rand
     num += 1

if __name__ == '__main__':
    pool = Pool(processes=4)              # start 4 worker processes
    for item in pool.imap_unordered(f, sampleiter(100000000000000), 20):
     print item
    pool.close

在终端中运行时,Python泄漏内存 可能有什么不对?

2 个答案:

答案 0 :(得分:4)

输出缓冲不是问题(或者至少不是唯一的问题),因为(a)Python进程本身在内存中增长,(b)如果你重定向到/dev/null,它仍然会发生。

我认为问题在于,当您打印出结果时,池返回结果的速度远远超过它们可以消耗的速度,因此很多很多结果都存储在内存中。如果您查看the source of the class that does this,则中间结果会存储在名为collections.deque的{​​{1}}中;我打赌_items变得越来越大。

我不完全确定如何测试它,因为即使imap_unordered returns an instance of this class你似乎仍然只能使用生成器方法:

_items

更新:如果您向In [8]: r = pool.imap_unordered(f, sampleiter(1e8), 20) In [9]: print dir(r) ['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__name__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'close', 'gi_code', 'gi_frame', 'gi_running', 'next', 'send', 'throw'] 添加time.sleep(.01),内存使用率将保持不变。所以,是的,问题在于你比你使用它们更快地产生结果。

(顺便说一下:你的意思是代码示例末尾的f(); pool.close()只是对函数的引用,实际上并没有调用它。)

答案 1 :(得分:2)

我在这里看到的导致内存泄漏的唯一变量是print语句。当我用print item替换pass时,内存保持低位且不变。当你打印时,我不确定引擎盖下到底发生了什么,但它显然堆积了一些东西而不是自由。此外,当我将块大小降低到1时,内存增加得更慢(显然),但也需要更长时间。所以它确实会增加内存使用量。

更新

发现这是由于终端的历史缓冲区(而不是python进程本身)而导致内存使用量增加的具体参考:Memory leak when running python in Mac OS Terminal