我需要从给定的根位置开始读取目录树中的每个文件。我想使用并行性尽快完成此操作。我有 48 个内核和 1 TB 内存,因此线程资源不是问题。我还需要记录读取的每个文件。
我查看了使用 joblib,但无法将 joblib 与 os.walk 结合使用。
我可以想到两种方法:
- 遍历树并将所有文件添加到队列或列表,并有一个工作线程池使文件出队 - 最佳负载平衡,由于初始遍历和队列开销,可能需要更多时间
- 生成线程并将树的部分静态分配给每个线程 - 低负载平衡、无初始遍历、根据某种哈希分配目录。
或者有更好的方法吗?
EDIT 存储性能不是问题。假设有一个无限快的存储可以处理无限数量的并行读取
编辑 删除了多节点情况以将重点放在并行目录遍历上
最佳答案
最简单的方法可能是使用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
以这种方式并行化工作完全有可能比仅在单个进程中完成工作要慢。这是因为共享文件系统下的硬盘上的 IO 可能是瓶颈,如果磁盘需要更频繁地查找而不是读取较长的线性数据部分,则尝试并行读取多个磁盘可能会使它们都变慢。即使 IO 稍微快一点,进程之间通信的开销也可能会耗尽所有 yield 。
关于python - 并行目录遍历 python,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29614584/