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
来传递与生成过程相关的内容。对我做错了什么的想法?
答案 0 :(得分:1)
评论变得无法遵循,所以我在这里重复评论:
在Linux-y系统上,新进程由fork()
创建,因此在创建时获取整个父进程地址空间的副本。它写了#34;复制#34;虚拟"更多的是"虚拟"复制而不是"真实"复制,但仍然... ;-)首先,尝试在创建巨型数据结构之前创建Pool
。然后子进程将继承一个小得多的地址空间。
然后回答一些问题:
所以在python 2.7中,没有办法产生一个新进程?
在Linux-y系统上,没有。能够使用"产生"这些是在Python 3.4中首次添加的。在Windows系统上," spawn"一直是唯一的选择(Windows上没有fork()
。)
大字典作为参数传递给函数而我 只能在此功能中创建池。我怎么能够 在大词典之前创建池
这很简单:将这两行作为程序中的前两行:
import multiprocessing
pool = multiprocessing.Pool()
您可以随时创建池(只要它存在某个时间,然后才能实际使用它),并且工作进程将在当时继承整个地址空间 / em>调用Pool
构造函数。
如果你在创建dict之后没有改变dict,请尝试使用它:
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()):