python:使用多处理共享大型词典

2024-10-01 13:43:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在处理大量的数据,存储在字典中,使用多重处理。基本上,我所做的就是加载一些签名,存储在字典中,从中构建一个共享dict对象(获取经理.dict())并将此代理作为参数传递给必须在多处理中执行的函数。在

只是想澄清一下:

signatures = dict()
load_signatures(signatures)
[...]
manager = Manager()
signaturesProxy = manager.dict(signatures)
[...]
result = pool.map ( myfunction , [ signaturesProxy ]*NUM_CORES )

现在,如果签名少于200万个条目,那么一切都会完美地工作。无论如何,我必须处理一个有5.8M键的字典(二进制格式的pickling签名生成一个4.8GB的文件)。在这种情况下,进程在创建代理对象的过程中终止:

^{pr2}$

我知道数据结构是巨大的,但是我正在一台配备32GB内存的机器上工作,运行top我发现在加载签名之后,这个进程占用了7GB的RAM。然后,它开始构建代理对象,RAM的使用量增加到~17GB的RAM,但从未接近32。在这一点上,RAM使用量开始迅速减少,并且进程以上述错误终止。所以我想这不是因为内存不足。。。在

有什么想法或建议吗?在

谢谢你

戴维德


Tags: 数据对象函数代理字典进程managerload
3条回答

为了节省时间和不必调试系统级问题,也许可以将580万条记录字典拆分为三组,每组约200万条,然后运行该作业3次。在

如果字典是只读的,那么在大多数操作系统中不需要代理对象。在

只需在启动worker之前加载字典,并将它们放在可以访问的地方;最简单的地方是全局访问模块。工人们可以看出来。在

from multiprocessing import Pool

buf = ""

def f(x):
    buf.find("x")
    return 0

if __name__ == '__main__':
    buf = "a" * 1024 * 1024 * 1024
    pool = Pool(processes=1)
    result = pool.apply_async(f, [10])
    print result.get(timeout=5)

这只使用1GB的内存组合,而不是每个进程使用1GB内存,因为任何现代操作系统都会对fork之前创建的数据进行写时拷贝。请记住,对数据的更改不会被其他工作线程看到,当然,内存将分配给您更改的任何数据。在

它将使用一些内存:包含引用计数的每个对象的页都将被修改,因此它将被分配。这是否重要取决于数据。在

这将适用于任何实现普通分叉的操作系统。它不能在Windows上运行;它的(残废的)进程模型需要为每个工作进程重新启动整个进程,所以它不太擅长共享数据。在

你为什么不试试数据库呢?数据库不仅限于可寻址/物理ram,而且对于多线程/进程使用是安全的。在

相关问题 更多 >