在for循环中调用pool.map以最小化内存使用量是一个好习惯吗?
例如,在我的代码中,我试图通过一次只处理一个目录来最小化内存使用:
PATH = / dir / files
def readMedia(fname):
""" Do CPU-intensive task
"""
pass
def init(queue):
readMedia.queue = queue
def main():
print("Starting the scanner in root " + PATH)
queue = multiprocessing.Queue()
pool = multiprocessing.Pool(processes=32, initializer=init, initargs=[queue])
for dirpath, dirnames, filenames in os.walk(PATH):
full_path_fnames = map(lambda fn: os.path.join(dirpath, fn),
filenames)
pool.map(readMedia, full_path_fnames)
result = queue.get()
print(result)
上面的代码经过测试,即使脚本终止,实际上也会占用我所有的内存。
答案 0 :(得分:3)
这里可能存在一些问题。首先,您在池中使用了太多进程。因为您正在执行CPU密集型任务,所以如果您的工作人数超过multiprocessing.cpu_count()
,您的收益将会减少;如果你有32名工作人员从事CPU密集型任务但只有4个CPU,那么28个进程总是会坐着不做任何工作,而是浪费内存。
由于一个或多个子进程仍在运行,因此在杀死脚本后您可能仍然会看到高内存使用率。杀死主脚本后,请查看进程列表,确保没有留下任何子进程。
如果您仍然看到内存使用量随着时间的推移而变得过高,您可以尝试在创建池时设置maxtasksperchild
关键字参数,一旦运行给定的数量,它将重新启动每个子进程任务,释放任何可能泄露的内存。
对于通过在for循环中调用map
获得的内存使用量增加,您的确可以获得以下优势:不必将每个调用的结果存储到一个内存列表中readMedia
。如果有一个巨大的文件列表被迭代,肯定会节省内存。