7

我在 Ubuntu 16.04 上使用 Python 2.7 和 NumPy 1.11.2,以及最新版本的 dill(我刚刚做了pip install dill)。

使用 pickle 存储 NumPy 数组时,我发现 pickle 非常慢,并且以几乎三倍于“必要”大小的方式存储数组。

例如,在以下代码中,pickle 大约慢了 50 倍(1 秒对 50 秒),并创建了一个 2.2GB 而不是 800MB 的文件。

 import numpy 
 import pickle
 import dill
 B=numpy.random.rand(10000,10000)
 with open('dill','wb') as fp:
    dill.dump(B,fp)
 with open('pickle','wb') as fp:
    pickle.dump(B,fp)

我以为莳萝只是泡菜的包装。如果这是真的,有没有办法可以自己提高泡菜的性能?通常不建议对 NumPy 数组使用 pickle 吗?

编辑:使用 Python3,我得到相同的pickle性能dill

PS:我知道numpy.save,但我正在一个框架中工作,我将许多不同的对象(全部位于字典中)存储到文件中。

4

2 回答 2

12

我是dill作者。 dill是 的扩展,但它确实为和其他对象pickle添加了一些备用酸洗方法。numpy例如,dill利用numpy数组酸洗的方法。

此外,(我相信)默认dill使用DEFAULT_PROTOCOL(不是HIGHEST_PROTOCOL),对于python3,对于python2,它HIGHEST_PROTOCOL默认使用。

于 2017-09-20T14:54:35.957 回答
11

这应该是一个评论,但我没有足够的声誉......我的猜测是这是由于使用的泡菜协议。

在 Python 2 上,默认协议为 0,支持的最高协议为 2。在 Python 3 上,默认协议为 3,支持的最高协议为 4(从 Python 3.6 开始)。

每个协议版本都对前一个版本进行了改进,但协议 0 对于大型对象尤其慢。在大多数情况下应该避免使用它,除非您需要能够使用非常旧的 Python 版本来读取泡菜。协议 2 已经好很多了。

现在,我dill 默认使用 pickle.HIGHEST_PROTOCOL ,如果确实如此,那可能是导致速度差异很大的原因。您可以尝试使用 pickle.HIGHEST_PROTOCOL 来查看使用 dill 和标准 pickle 是否获得类似的性能。

with open('dill', 'wb') as fp:
    dill.dump(B, fp, protocol=pickle.HIGHEST_PROTOCOL)
with open('pickle', 'wb') as fp:
    pickle.dump(B, fp, protocol=pickle.HIGHEST_PROTOCOL)
于 2017-09-20T10:15:23.423 回答