在Python的多处理模块中,在for循环中调用工作池是一种好习惯吗?

时间:2014-07-06 14:33:14

标签: python multiprocessing python-multithreading

在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)

上面的代码经过测试,即使脚本终止,实际上也会占用我所有的内存。

1 个答案:

答案 0 :(得分:3)

这里可能存在一些问题。首先,您在池中使用了太多进程。因为您正在执行CPU密集型任务,所以如果您的工作人数超过multiprocessing.cpu_count(),您的收益将会减少;如果你有32名工作人员从事CPU密集型任务但只有4个CPU,那么28个进程总是会坐着不做任何工作,而是浪费内存。

由于一个或多个子进程仍在运行,因此在杀死脚本后您可能仍然会看到高内存使用率。杀死主脚本后,请查看进程列表,确保没有留下任何子进程。

如果您仍然看到内存使用量随着时间的推移而变得过高,您可以尝试在创建池时设置maxtasksperchild关键字参数,一旦运行给定的数量,它将重新启动每个子进程任务,释放任何可能泄露的内存。

对于通过在for循环中调用map获得的内存使用量增加,您的确可以获得以下优势:不必将每个调用的结果存储到一个内存列表中readMedia。如果有一个巨大的文件列表被迭代,肯定会节省内存。