我需要从给定的根位置开始读取目录树中的每个文件。我想尽可能快地使用并行性来做到这一点。我有48个内核和1 TB内存,所以线程资源不是问题。我还需要记录每个已读取的文件。
我查看了使用joblib,但无法将joblib与os.walk结合使用。
我可以想到两种方式:
还是有更好的方法吗?
编辑存储的性能不是问题。假设有一个无限快速的存储,可以处理无限数量的并行读取
编辑删除多节点情况以保持对并行目录步行的关注
答案 0 :(得分:5)
最简单的方法可能是使用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速度稍快,进程之间通信的开销也可能会耗尽所有收益。