并行目录walk python

pow*_*rox 1 python parallel-processing multithreading

我需要从给定的根位置开始读取目录树中的每个文件.我想尽可能快地使用并行性来做到这一点.我有48个内核和1 TB内存,所以线程资源不是问题.我还需要记录每个被读取的文件.

我查看了使用joblib,但无法将joblib与os.walk结合使用.

我可以想到两种方式:

  • 遍历树并将所有文件添加到队列或列表中,并使工作线程队列出队列文件 - 最佳负载平衡,可能由于初始步行和队列开销而导致更多时间
  • 产生线程并静态地为每个线程分配树的部分 - 低负载平衡,没有初始步行,基于某种散列分配目录.

或者,还有更好的方法?

编辑存储的性能不是问题.假设有一个无限快速的存储,可以处理无限数量的并行读取

EDIT删除了多节点情况,以便将重点放在并行目录上

Blc*_*ght 8

最简单的方法可能是使用a multiprocessing.Pool来处理os.walk主进程中执行的结果输出.

这假定您要并行化的主要工作是对单个文件进行的任何处理,而不是递归扫描目录结构的工作.如果您的文件很小并且您不需要对其内容进行大量处理,则可能不是这样.我还假设为您处理的进程创建multiprocessing将能够在您的集群上正确分配负载(这可能是也可能不是).

import itertools
import multiprocessing

def worker(filename):
    pass   # do something here!

def main():
    with multiprocessing.Pool(48) as Pool: # pool of 48 processes

        walk = os.walk("some/path")
        fn_gen = itertools.chain.from_iterable((os.path.join(root, file)
                                                for file in files)
                                               for root, dirs, files in walk)

        results_of_work = pool.map(worker, fn_gen) # this does the parallel processing
Run Code Online (Sandbox Code Playgroud)

以这种方式并行化工作完全有可能比仅在单个进程中完成工作要慢.这是因为共享文件系统底层硬盘上的IO可能是瓶颈,如果磁盘需要更频繁地寻找而不是读取更长的线性数据部分,并行尝试多次磁盘读取会使它们变得更慢.即使IO速度稍快,进程之间通信的开销也会耗尽所有收益.