为什么 dill 比 numpy 数组的 pickle 更快更磁盘高效

Why is dill much faster and more disk-efficient than pickle for numpy arrays

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

当使用 pickle 存储 NumPy 数组时,我发现 pickle 非常慢,并且存储数组的大小几乎是 'necessary' 的三倍。

例如,在下面的代码中,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,我得到了 pickledill

相同的性能

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

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

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

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

现在,我假设 dill 默认使用pickle.HIGHEST_PROTOCOL,如果确实如此,它可能是造成速度差异很大的原因。您可以尝试使用 pickle.HIGHEST_PROTOCOL 来查看使用莳萝和标准泡菜是否获得类似的性能。

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)

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

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