【发布时间】:2010-12-21 20:27:18
【问题描述】:
我遇到了很多“令人尴尬的并行”项目,我想与 multiprocessing 模块并行化。但是,它们通常涉及读取大文件(大于 2gb),逐行处理它们,运行基本计算,然后写入结果。使用 Python 的多处理模块拆分文件并处理它的最佳方法是什么?应该使用multiprocessing 中的Queue 或JoinableQueue 吗?还是Queue 模块本身?或者,我应该使用multiprocessing 将可迭代的文件映射到进程池吗?我已经尝试过这些方法,但是逐行分发数据的开销是巨大的。我已经通过使用cat file | process1 --out-file out1 --num-processes 2 | process2 --out-file out2 确定了轻量级管道过滤器设计,它将第一个进程的输入的一定百分比直接传递给第二个输入(参见this post),但我希望有一个完全包含的解决方案在 Python 中。
令人惊讶的是,Python 文档并没有建议这样做的规范方法(尽管multiprocessing 文档中关于编程指南的部分很长)。
谢谢, 文斯
附加信息:每行的处理时间各不相同。有些问题很快,几乎不受 I/O 限制,有些受 CPU 限制。受 CPU 限制的非依赖任务将从并行化中获得优势,因此即使将数据分配给处理功能的低效方式在挂钟时间方面仍然是有益的。
一个典型的例子是一个脚本,它从行中提取字段,检查各种按位标志,并将带有某些标志的行以全新的格式写入新文件。这似乎是一个 I/O 绑定问题,但是当我使用带有管道的廉价并发版本运行它时,它快了大约 20%。当我使用 pool 和 map 运行它,或者在 multiprocessing 中排队时,它总是慢 100% 以上。
【问题讨论】:
-
这是我对原本花哨的脚本语言的一大抱怨——简单的并发计算是没有线程的痛苦。当然,您可以完成它,但是使用线程和锁模型,有些工作会简单得多。
-
线程“并行”版本(我相信)永远不会更快,除了线程比进程创建速度更快。 GIL 是 CPU 密集型多线程程序的一个巨大瓶颈。此外,没有需要在进程/线程之间共享的可变对象,因此多线程并不真正需要多处理。
-
@Vince 实际上,这完全取决于具体情况。在你的,它可能永远不会。在其他情况下,它可能。我的观点是,对于我需要执行的大多数并发操作(在 C 中),当线程和锁提供更简单的模型时,很少有理由使用正确 IPC 所需的额外操作。对于需要更好地扩展并跨不同机器的更大问题,情况就不同了。
-
@san,我不应该说“从不”——我同意。对于某些网络绑定或 I/O 绑定的情况,线程肯定会更快。
-
@Vince 是的,这就是我的来历。除了我的硕士研究(我在 Python 中完成的)之外,我的实际并发编程一直处于这种情况下:要么从慢速物理设备读取并在另一个线程上做出反应或计算,要么只是试图在我 / O 正在进行中。
标签: python concurrency multiprocessing bioinformatics