for循环中Pool的高内存使用率

时间:2014-06-03 06:31:34

标签: python multiprocessing pool

我有一个2循环的for循环:

if __name__ == '__main__':
    for length in range(1, 15, 5):

        def map_CCWP(it):
            return CCWP(G, length, Ep)
        pool = multiprocessing.Pool(processes=multiprocessing.cpu_count())
        Scores = pool.map(map_CCWP, range(R))

        S = []
        # some work to get S

        def map_AvgIAC (it):
            return avgIAC(G, S, Ep, I) 
        pool2 = multiprocessing.Pool(processes=multiprocessing.cpu_count())
        T = pool2.map(map_AvgIAC, range(4))

然而,在运行它时会使用越来越多的内存,因为它每次都会创建新的池工作者。我尝试在每次迭代结束时删除池,但它仍会增加内存量。

另一种选择是将泳池置于条件下:

if pool == None:
    pool = multiprocessing.Pool(processes=multiprocessing.cpu_count())

它确实没有使用这么多内存。但是,函数map_CCWPmap_AvgIAC的每个迭代参数都会发生变化,我发现pool.map将使用map_CCWP初始lengthmap_AvgIAC最初S

如何在更改每次迭代并且不会增加内存使用量的函数上运行Pool?

2 个答案:

答案 0 :(得分:2)

默认情况下,池工作者在开始时创建并直播到最后。你没有初始化它们,所以在你的情况下让它们保持活力没有很大的性能优势。

所以:

pool = multiprocessing.Pool(processes=None, maxtasksperchild=1)

将创建一个worker,运行该进程,将其杀死并创建一个新worker。捕获的任何内存或资源都将被释放。如果你的记忆力增长不是太大,你可以增加每个孩子的任务数量。

请注意,我将流程定义为None。这与使用multiprocessing.cpu_count()相同,但不那么详细。

在其他情况下,我偶尔会遇到(数百万分之一或两次),随机孩子的记忆会失去控制,机器会开始交换,一切都会卡住或者速度变慢。我的解决方法是:

iterations = int(math.ceil(total / b_size))

for block in xrange(iterations):
    restricted_iterator = iterator[block * b_size:(block + 1) * b_size]
    # This works because a slice can end beyond the length of the list.

    pool = multiprocessing.Pool(processes=None, maxtasksperchild=1)
    try:
        peaks = pool.map(caller, restricted_iterator)
    except Exception as e:
        raise e    # I don't expect this to ever happen.
    finally:
        pool.terminate()
                   # Kill the pool very dead.
    # Save the data to disk and free memory.

我将工作拆分成块,然后处理每个工作。这样,如果有一个这个“疯狂的孩子”积累了记忆,其余的将在几分钟内完成,流浪的孩子将独自一段时间,有更多的RAM可用。因此,它将在不到几分钟的时间内完成,因此程序的总延迟不是那么大。通过调整b_size,我可以控制我清理的频率。 (在我的情况下,分成10-20块,并在中间保存到磁盘,我仍然保持平均CPU使用率约97%,所以不会丢失多少。)

答案 1 :(得分:0)

看起来您在程序生命周期中创建了越来越多的池。如果在for循环之前初始化一个固定大小的池,然后你的for循环只将任务添加到该池中,该怎么办?这样,从概念上讲,您的并行进程受到池大小的限制,因此应该控制内存消耗。