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。对我做错了什么有什么想法吗?
发布于 2016-07-14 21:24:41
这些评论正变得不可能被理解,所以我在这里贴上了我的重要评论:
在Linux-y系统上,新进程由fork()创建,因此在创建父进程地址空间时获取整个父进程地址空间的副本。它是“写上的复制”,所以与其说是“真实的”拷贝,不如说是“虚拟的”副本,但是.-)首先,在创建巨大的数据结构之前尝试创建您的Pool。然后子进程将继承一个更小的地址空间。
然后回答一些问题:
所以在python2.7中,没有办法产生一个新的过程?
在Linux-y系统上,没有。第一次在Python3.4中添加了在这些文件上使用“派生”的功能。在Windows系统上,“派生”一直是唯一的选择(在Windows上没有fork() )。
大字典作为参数传递给函数,我只能在这个函数中创建池。我怎样才能在大字典之前创建池呢?
如下所示:使这两行成为程序中的前两行:
import multiprocessing
pool = multiprocessing.Pool()您可以在任何时候创建池(只要它在实际使用之前就存在),并且在调用Pool构造函数时,工作进程将继承整个地址空间。
另一项建议
如果在创建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()):https://stackoverflow.com/questions/38383981
复制相似问题