【发布时间】:2015-09-17 18:33:57
【问题描述】:
我已经阅读了这篇帖子,Python multiprocessing: sharing a large read-only object between processes?,但仍不确定下一步如何进行。
这是我的问题:
我正在使用 multiprocessing 分析数百万个字符串的数组,并且每个字符串都需要与一个包含大约 200 万个(可能更多)键的大字典进行检查。它的值是名为Bloomfilter 的自定义 Python 类的对象(因此它们不仅仅是简单的 int 或 float 或数组),它们的大小从几个字节到 1.5 Gb 不等。对每个字符串的分析,基本上就是检查一个字符串是否在字典中一定数量的bloomfilters中。它取决于字符串本身来决定哪些bloomfilters 是相关的。字典是一个 30G sqlite3 db 的转换。动机是将整个 sqlite3 db 加载到内存中以加快处理速度,但我还没有找到有效共享 dict 的方法。我的系统中有大约 100G 内存。
这是我尝试过的:
每个字符串的分析都受 CPU 限制,因此我选择了多处理而不是多线程。关键是如何在不复制的情况下在进程之间共享大字典。 multiprocess.Value 和 multiprocessing.Array 不能处理像字典这样的复杂对象。我试过multiprocessing.Manager(),但由于字典太大,我得到IOError: bad message length 错误。我也尝试过在 localhost 上使用像 Redis 这样的内存数据库,但是用于在获取后构造 Bloomfilter 的 bitarray 太大而无法容纳,这让我认为在进程之间传递大消息也太贵(是吗?)
我的问题:
在不同进程(或线程,如果有办法绕过 GIL)之间共享此类字典的正确方法是什么?如果我需要使用数据库,我应该使用哪一个?我需要非常快速的读取,并且数据库应该能够存储非常大的值。 (虽然我不认为数据库会起作用,因为传递非常大的值是行不通的,对吧?如果我错了,请纠正我)
【问题讨论】:
-
您使用的是 Unix 吗?您可以根据需要多次 fork(),这将为您提供每个进程中数据结构的副本。如果您使用的是 windows,它可能会更复杂,因为我不认为 fork 是这样实现的。
-
是的,我在 linux 上。您能否详细谈谈
fork(),或者请给我一些参考资料? -
好的,请记住 fork 是一个非常低级的工具,但它在 os 模块中:docs.python.org/2/library/os.html#os.fork(与 python 3 中的想法相同)。它从字面上克隆了该过程,因此它们具有所有相同的数据;如果之后不对数据结构进行任何写操作,进程应该共享相关的内存页。然后,您可能必须编写自己的方法来计算最后的计算数据。
-
看起来很有趣。我真的没有想法,会看看。我听说过写时复制的事情。
-
在 Unix Multiprocessing 中使用 fork 创建子进程。因此,如果您只需要读取权限,只需将字典设为全局,然后照常进行。
标签: python multithreading python-2.7 sqlite python-multiprocessing