为什么 dill.dump 的字典列表(81,000,000 字节)需要很长时间?

Why dill.dump of a list of dictionary (81,000,000 bytes) takes forever?

我生成了一个 8100000 字节的字典列表,包含 900 万多个元素。每个元素都有一个包含 32 对值和键的字典,尽管每个元素中使用的是同一组键。

我想保存它以备将来分析。我试过 dill.dump,但我不得不中断内核花了很长时间(超过 1 小时)。这应该是快速和简单的,对吧?

这是我尝试过的:

import dill
output_file=open('result_list', 'wb')
dill.dump(result_list, output_file)
output_file.close()

我也试过 pickle 和 bzip2

import bz2
import pickle
output_file=bz2.BZ2File('result_list', 'w')
pickle.dump(result_list, output_file)

但是运行进入内存错误。

有什么技巧可以使这变得可行并减少耗时吗? 谢谢!

我是 dill 的作者。对于这种情况,您可能想尝试 kleptodill(实际上是任何序列化程序)会将整个 dict 视为一个对象......以及那种大小的东西,你可能希望更像是一个条目数据库......这就是 klepto可以做到。最快的方法可能是使用将每个条目视为磁盘上单个目录中的不同文件的存档:

>>> import klepto
>>> x = range(10000)
>>> d = dict(zip(x,x))
>>> a = klepto.archives.dir_archive('foo', d)
>>> a.dump()

上面创建了一个包含 10000 个子目录的目录,每个子目录中有一个条目。键和值都被存储。请注意,您也可以稍微调整序列化方法,因此请查看文档以了解如何为您的自定义案例执行此操作。

或者,您可以遍历字典,并在来自 multiprocess.Pool.

的并行映射中使用转储序列化每个条目

(旁注,我也是 multiprocessklepto 的作者)。

更新:随着问题从序列化一个巨大的字典变为序列化一个巨大的小字典列表……这改变了答案。

klepto 是为类似 dict 的大型结构构建的,因此它可能不是您想要的。您可能想尝试 dask,它是为类似 array 的大型结构构建的。

我认为您还可以遍历列表,分别序列化每个列表条目...只要您以相同的顺序加载它们,您就可以重新构建结果。你可以做一些事情,比如用值存储位置,这样你就可以恢复列表,然后在它们乱序时进行排序。

我还请您考虑是否可以将结果重组为更好的形式...