【问题标题】:pickle faster than cPickle with numeric data?用数字数据泡菜比 cPickle 快吗?
【发布时间】:2013-05-25 20:22:20
【问题描述】:

目前我正在使用 Python 进行图像检索。在此示例中,从图像中提取的关键点和描述符表示为numpy.arrays。形状 (2000, 5) 的第一个和形状 (2000, 128) 的后者。两者都只包含 dtype=numpy.float32 的值。

所以,我想知道使用哪种格式来保存我提取的关键点和描述符。 IE。我总是保存 2 个文件:一个用于关键点,一个用于描述符 - 这算作我测量的一步。我比较了picklecPickle(协议0和2)和NumPy的二进制格式.pny,结果真的让我很困惑:

我一直认为cPickle 应该比pickle 模块更快。但特别是协议 0 的加载时间在结果中确实很突出。 有人对此有解释吗?是因为我只使用数字数据吗?好像很奇怪……

PS:在我的代码中,我基本上在每种技术上循环 1000 次 (number=1000),最后平均测量时间:

    timer = time.time

    print 'npy save...'
    t0 = timer()
    for i in range(number):
        numpy.save(npy_kp_path, kp)
        numpy.save(npy_descr_path, descr)
    t1 = timer()
    results['npy']['save'] = t1 - t0

    print 'npy load...'
    t0 = timer()
    for i in range(number):
        kp = numpy.load(npy_kp_path)
        descr = numpy.load(npy_descr_path)
    t1 = timer()
    results['npy']['load'] = t1 - t0


    print 'pickle protocol 0 save...'
    t0 = timer()
    for i in range(number):
        with open(pkl0_descr_path, 'wb') as f:
            pickle.dump(descr, f, protocol=0)
        with open(pkl0_kp_path, 'wb') as f:
            pickle.dump(kp, f, protocol=0)
    t1 = timer()
    results['pkl0']['save'] = t1 - t0

    print 'pickle protocol 0 load...'
    t0 = timer()
    for i in range(number):
        with open(pkl0_descr_path, 'rb') as f:
            descr = pickle.load(f)
        with open(pkl0_kp_path, 'rb') as f:
            kp = pickle.load(f)
    t1 = timer()
    results['pkl0']['load'] = t1 - t0


    print 'cPickle protocol 0 save...'
    t0 = timer()
    for i in range(number):
        with open(cpkl0_descr_path, 'wb') as f:
            cPickle.dump(descr, f, protocol=0)
        with open(cpkl0_kp_path, 'wb') as f:
            cPickle.dump(kp, f, protocol=0)
    t1 = timer()
    results['cpkl0']['save'] = t1 - t0

    print 'cPickle protocol 0 load...'
    t0 = timer()
    for i in range(number):
        with open(cpkl0_descr_path, 'rb') as f:
            descr = cPickle.load(f)
        with open(cpkl0_kp_path, 'rb') as f:
            kp = cPickle.load(f)
    t1 = timer()
    results['cpkl0']['load'] = t1 - t0


    print 'pickle highest protocol (2) save...'
    t0 = timer()
    for i in range(number):
        with open(pkl2_descr_path, 'wb') as f:
            pickle.dump(descr, f, protocol=pickle.HIGHEST_PROTOCOL)
        with open(pkl2_kp_path, 'wb') as f:
            pickle.dump(kp, f, protocol=pickle.HIGHEST_PROTOCOL)
    t1 = timer()
    results['pkl2']['save'] = t1 - t0

    print 'pickle highest protocol (2) load...'
    t0 = timer()
    for i in range(number):
        with open(pkl2_descr_path, 'rb') as f:
            descr = pickle.load(f)
        with open(pkl2_kp_path, 'rb') as f:
            kp = pickle.load(f)
    t1 = timer()
    results['pkl2']['load'] = t1 - t0


    print 'cPickle highest protocol (2) save...'
    t0 = timer()
    for i in range(number):
        with open(cpkl2_descr_path, 'wb') as f:
            cPickle.dump(descr, f, protocol=cPickle.HIGHEST_PROTOCOL)
        with open(cpkl2_kp_path, 'wb') as f:
            cPickle.dump(kp, f, protocol=cPickle.HIGHEST_PROTOCOL)
    t1 = timer()
    results['cpkl2']['save'] = t1 - t0

    print 'cPickle highest protocol (2) load...'
    t0 = timer()
    for i in range(number):
        with open(cpkl2_descr_path, 'rb') as f:
            descr = cPickle.load(f)
        with open(cpkl2_kp_path, 'rb') as f:
            kp = cPickle.load(f)
    t1 = timer()
    results['cpkl2']['load'] = t1 - t0 

【问题讨论】:

  • 我今天自己才注意到这一点,发现了你的问题,我得到了至少一个数量级的差异。 pickle 肯定比 cpickle 快。

标签: python numpy pickle


【解决方案1】:

ndarray 的数字数据(二进制表示)被腌制为一个长字符串。看来cPickle 确实比pickle 从协议 0 文件中解压大字符串要慢得多。为什么?我的猜测是pickle 使用了标准库中经过良好调整的字符串算法,而cPickle 已经落后了。

以上观察来自于使用 Python 2.7。 Python 3.3 自动使用 C 扩展,比 Python 2.7 上的任何一个模块都快,因此显然问题已得到修复。

【讨论】:

  • 感谢您指出 Python 3.3 的解决方案。我的示例使用 ideed 2.7。将签出 3.3
  • @pklip 但是你为什么要坚持使用协议 0?根据您的时间安排,协议 2 很快。
  • 当然我会使用协议 2,因为我不需要“文本可读”文件。我只是想知道并好奇地尝试一般 3.3 :)
猜你喜欢
  • 1970-01-01
  • 2013-05-06
  • 2021-04-04
  • 1970-01-01
  • 2018-07-29
  • 1970-01-01
  • 1970-01-01
  • 2012-01-02
  • 2017-10-09
相关资源
最近更新 更多