如何在Python中有效地将大块数据扇出到多个并发子流程中?

时间:2016-10-30 02:04:08

标签: python multiprocessing shared-memory python-multiprocessing

[我在Windows中使用Python 3.5.2(x64)。]

我正在以大块(大约数兆字节)读取二进制数据,并希望有效地将这些数据共享到' n'并发Python子流程(每个流程将以独特且计算成本高的方式处理数据)。

数据是只读的,并且每个顺序块都不会被视为"已处理"直到完成所有子流程。

我专注于共享内存(数组(锁定/解锁)和RawArray):将数据块从文件读取到缓冲区非常快,但将该块复制到共享内存的速度明显变慢。 / p>

对于队列,相对于共享内存,将会有大量冗余数据复制。我选择了共享内存,因为它涉及一个副本而不是' n'数据副本)。

在架构上,如何在Python 3.5中有效地处理这个问题?

编辑:到目前为止,我已经收集了两件事:Windows中的内存映射很麻烦,因为实现了这一点,并且multiprocessing.Queue(更具体地,JoinableQueue )虽然不是(尚)最佳,但速度更快。

编辑2:我收集的另一件事是,如果你有很多工作要做(特别是在Windows中,spawn()是唯一的选择并且成本也很高),运行并行流程比一次又一次地创建它们更好。

建议 - 最好是使用multiprocessing组件的建议 - 仍然非常受欢迎!

1 个答案:

答案 0 :(得分:1)

在Unix中,这可能是易处理的,因为fork()用于多处理,但在Windows中,spawn()的唯一方式确实限制了选项。但是,这应该是一个多平台解决方案(我主要在Windows中使用),所以我在这个约束下工作。

我可以在每个子流程中打开数据源,但是根据数据源的不同,带宽可能很昂贵,如果它是一个流,则会受到限制。这就是我采用一次性读取方法的原因。

通过mmap共享内存和匿名内存分配似乎是理想的,但是将对象传递给子进程需要对它进行pickle - 但是你不能挑选mmap个对象。这么多。

通过cython模块共享内存可能是不可能的,也可能不是,但它几乎肯定是禁止的 - 并且要求使用更合适的语言来完成任务。

通过共享ArrayRawArray功能共享内存在性能方面成本很高。

队列效果最好 - 但由于我认为在后台腌制的内部I / O非常惊人。但是,少数并行流程的性能损失并不明显(这可能是对更快系统的限制因素)。

我可能会用另一种语言重新考虑这个因素a)体验!和b)看看我是否可以避免Python队列导致的I / O需求。进程之间的快速内存缓存(我希望在这里实现)可以避免大量冗余I / O.

虽然Python广泛适用,但没有任何工具适用于每项工作,这只是其中一种情况。在此过程中,我学到了很多关于Python multiprocessing模块的知识!

在这一点上,看起来我已经走了标准CPython,但仍然欢迎提出建议!