在Python的multiprocessing模块中,在for循环中调用工作池是好习惯吗?
在一个循环里调用 pool.map 这样做是不是个好习惯,以减少内存使用?
比如,在我的代码里,我想通过一次只处理一个目录来减少内存使用:
路径 = /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)
但是,上面的代码在测试时,实际上会占用我所有的内存,即使脚本已经结束。
1 个回答
3
这里可能有几个问题。首先,你的进程池里进程数量太多了。因为你在做的是需要大量计算的任务,如果你启动的工作进程超过了 multiprocessing.cpu_count()
的数量,效果就会变差。比如说,如果你有32个进程在做计算任务,但实际上只有4个CPU可用,那就会有28个进程在那儿闲着,根本没在工作,却还浪费内存。
你可能在结束脚本后仍然看到内存使用量很高,因为一个或多个子进程还在运行。你可以在结束主脚本后查看进程列表,确保没有子进程留在那儿。
如果你发现内存使用量随着时间的推移仍然过高,可以尝试在创建进程池时设置 maxtasksperchild
这个参数。这样每个子进程在完成一定数量的任务后会被重启,从而释放可能泄漏的内存。
至于在循环中调用 map
带来的内存使用优势,这样做的好处是你不需要把每次调用 readMedia
的结果都存储在一个内存列表里。如果你要处理的文件列表很大,这样确实能节省内存。