python multiprocessing.pool.map,将参数传递给生成的进程

python multiprocessing.pool.map, passing arguments to spawned processes

def content_generator(applications, dict):
    for app in applications:
        yield(app, dict[app])

with open('abc.pickle', 'r') as f:
    very_large_dict = pickle.load(f)
all_applications = set(very_large_dict.keys())

pool = multiprocessing.Pool()
for result in pool.imap_unordered(func_process_application, content_generator(all_applications, very_large_dict)):
    do some aggregation on result

我有一个非常大的字典,它的键是字符串(应用程序名称),值是关于应用程序的信息。由于应用程序是独立的,所以我想使用多处理来并行处理它们。当字典不是那么大时并行化工作,但当字典太大时所有 python 进程都被杀死。我用 dmesg 检查出了什么问题,发现他们被杀了,因为机器 运行 内存不足。我在池进程运行的时候做了top,发现它们都占用了相同数量的常驻内存(RES),都是3.4G。这让我感到困惑,因为它似乎已将整个词典复制到生成的进程中。我以为我打破了字典并通过只产生 dict[app] 而不是 dict 来仅传递与生成过程相关的内容。想知道我做错了什么吗?

评论越来越跟不上了,所以我在这里粘贴我的重要评论:

在 Linux-y 系统上,新进程由 fork() 创建,因此在创建它们时获取整个父进程地址的副本 space .它是 "copy on write",因此更像是 "virtual" 副本而不是 "real" 副本,但仍然...... ;-) 首先,尝试在创建巨人之前创建你的 Pool数据结构。然后子进程将继承一个小得多的地址 space.

然后是一些问题的回答:

so in python 2.7, there is no way to spawn a new process?

在 Linux-y 系统上,没有。在 Python 3.4 中首次添加了对这些使用 "spawn" 的能力。在 Windows 系统上,"spawn" 一直是唯一的选择(在 Windows 上没有 fork())。

The big dictionary is passed in to a function as an argument and I could only create the pool inside this function. How would I be able to create the pool before the big dictionary

就这么简单:让这两行成为你程序的前两行:

import multiprocessing
pool = multiprocessing.Pool()

您可以随时创建池(只要它存在 某个时间 在您实际使用它之前),工作进程将继承整个地址 space 当时 Pool 构造函数被调用。

另一个建议

如果你不在字典创建后对其进行修改,请尝试改用它:

def content_generator(dict):
    for app in dict:
        yield app, dict[app]

这样你也不必具体化一大组密钥。或者,甚至更好(如果可能),跳过所有这些并直接迭代项目:

for result in pool.imap_unordered(func_process_application, very_large_dict.iteritems()):