我有一个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_CCWP
和map_AvgIAC
的每个迭代参数都会发生变化,我发现pool.map
将使用map_CCWP
初始length
和map_AvgIAC
最初S
。
如何在更改每次迭代并且不会增加内存使用量的函数上运行Pool?
答案 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循环只将任务添加到该池中,该怎么办?这样,从概念上讲,您的并行进程受到池大小的限制,因此应该控制内存消耗。