【问题标题】:Why is dill much faster and more disk-efficient than pickle for numpy arrays为什么 dill 比用于 numpy 数组的 pickle 更快且磁盘效率更高
【发布时间】:2017-06-22 10:56:27
【问题描述】:

我在 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,但我在一个框架中工作,我将许多不同的对象存储在一个文件中,所有对象都位于字典中。

【问题讨论】:

  • 使用 python 3.6 和 numpy 1.12.1 我得到两个文件的大小相同,你可以尝试升级 numpy
  • @EdChum 升级到 1.13.0 不会改变任何东西。使用 Python3 确实
  • 好的,我不知道具体的区别,但看起来这可能是某种只在 python 3 中有效的优化,这很奇怪
  • 你知道反对将 dill 用于 numpy 数组的任何论据吗?否则我会选择那个
  • 不是真的,我从未使用过dill,但它似乎是pickle 的扩展,而且您可以保存会话状态,所以它应该可以正常工作。

标签: python numpy serialization pickle dill


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

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

    在 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)
    

    【讨论】:

    • 在这里,有一些声誉:)(完美答案)
    • 呵呵,谢谢:)
    猜你喜欢
    • 2022-01-24
    • 2022-11-22
    • 2016-05-15
    • 1970-01-01
    • 2013-09-26
    • 2017-04-14
    • 1970-01-01
    相关资源
    最近更新 更多