代码之家  ›  专栏  ›  技术社区  ›  SuperCiocia

为什么腌菜比np.save要长这么多时间?

  •  1
  • SuperCiocia  · 技术社区  · 8 年前

    dict 或数组。

    我都试过了 np.save 和 pickle

    我的实际数据要大得多,但我在这里只展示了一小部分,用于演示:

    import numpy as np
    #import numpy.array as array
    import time
    import pickle
    
    b = {0: [np.array([0, 0, 0, 0])], 1: [np.array([1, 0, 0, 0]), np.array([0, 1, 0, 0]), np.array([0, 0, 1, 0]), np.array([0, 0, 0, 1]), np.array([-1,  0,  0,  0]), np.array([ 0, -1,  0,  0]), np.array([ 0,  0, -1,  0]), np.array([ 0,  0,  0, -1])], 2: [np.array([2, 0, 0, 0]), np.array([1, 1, 0, 0]), np.array([1, 0, 1, 0]), np.array([1, 0, 0, 1]), np.array([ 1, -1,  0,  0]), np.array([ 1,  0, -1,  0]), np.array([ 1,  0,  0, -1])], 3: [np.array([1, 0, 0, 0]), np.array([0, 1, 0, 0]), np.array([0, 0, 1, 0]), np.array([0, 0, 0, 1]), np.array([-1,  0,  0,  0]), np.array([ 0, -1,  0,  0]), np.array([ 0,  0, -1,  0]), np.array([ 0,  0,  0, -1])], 4: [np.array([2, 0, 0, 0]), np.array([1, 1, 0, 0]), np.array([1, 0, 1, 0]), np.array([1, 0, 0, 1]), np.array([ 1, -1,  0,  0]), np.array([ 1,  0, -1,  0]), np.array([ 1,  0,  0, -1])], 5: [np.array([0, 0, 0, 0])], 6: [np.array([1, 0, 0, 0]), np.array([0, 1, 0, 0]), np.array([0, 0, 1, 0]), np.array([0, 0, 0, 1]), np.array([-1,  0,  0,  0]), np.array([ 0, -1,  0,  0]), np.array([ 0,  0, -1,  0]), np.array([ 0,  0,  0, -1])], 2: [np.array([2, 0, 0, 0]), np.array([1, 1, 0, 0]), np.array([1, 0, 1, 0]), np.array([1, 0, 0, 1]), np.array([ 1, -1,  0,  0]), np.array([ 1,  0, -1,  0]), np.array([ 1,  0,  0, -1])], 7: [np.array([1, 0, 0, 0]), np.array([0, 1, 0, 0]), np.array([0, 0, 1, 0]), np.array([0, 0, 0, 1]), np.array([-1,  0,  0,  0]), np.array([ 0, -1,  0,  0]), np.array([ 0,  0, -1,  0]), np.array([ 0,  0,  0, -1])], 8: [np.array([2, 0, 0, 0]), np.array([1, 1, 0, 0]), np.array([1, 0, 1, 0]), np.array([1, 0, 0, 1]), np.array([ 1, -1,  0,  0]), np.array([ 1,  0, -1,  0]), np.array([ 1,  0,  0, -1])]}
    
    
    start_time = time.time()
    with open('testpickle', 'wb') as myfile:
        pickle.dump(b, myfile)
    print("--- Time to save with pickle: %s milliseconds ---" % (1000*time.time() - 1000*start_time))
    
    start_time = time.time()
    np.save('numpy', b)
    print("--- Time to save with numpy: %s milliseconds ---" % (1000*time.time() - 1000*start_time))
    
    start_time = time.time()
    with open('testpickle', 'rb') as myfile:
        g1 = pickle.load(myfile)
    print("--- Time to load with pickle: %s milliseconds ---" % (1000*time.time() - 1000*start_time))
    
    start_time = time.time()
    g2 = np.load('numpy.npy')
    print("--- Time to load with numpy: %s milliseconds ---" % (1000*time.time() - 1000*start_time))
    

    --- Time to save with pickle: 4.0 milliseconds ---
    --- Time to save with numpy: 1.0 milliseconds ---
    --- Time to load with pickle: 2.0 milliseconds ---
    --- Time to load with numpy: 1.0 milliseconds ---
    

    我的实际大小(dict中大约有100000个键)的时差更为明显。

    为什么pickle要比np.save花费更长的时间来保存和加载呢?

    我应该什么时候用 ?

    3 回复  |  直到 8 年前
        1
  •  4
  •   Amadan    8 年前

    因为只要写的对象不包含Python数据,

    • numpy对象在内存中的表示方式比Python对象简单得多
    • numpy.save是用C编写的
    • 以需要最少处理的超级简单格式保存写入

    同时

    • pickle是用Python编写的

    请注意,如果numpy数组确实包含Python对象,那么numpy只会对数组进行pickle操作,所有的胜利都会消失在窗口之外。

        2
  •  4
  •   hpaulj    8 年前

    我认为你需要更好的时间安排。我也不同意接受的答案。

    b 是一个有9个键的字典;值是数组列表。这意味着两者 pickle.dump 和 np.save pickle 使用 save 对数组进行pickle, 节约 泡菜 保存字典和列表。

    节约 写入数组。这意味着它必须将字典包装在对象数据类型数组中才能保存它。

    In [6]: np.save('test1',b)
    In [7]: d=np.load('test1.npy')
    In [8]: d
    Out[8]: 
    array({0: [array([0, 0, 0, 0])], 1: [array([1, 0, 0, 0]), array([0, 1, 0, 0]), .... array([ 1, -1,  0,  0]), array([ 1,  0, -1,  0]), array([ 1,  0,  0, -1])]},
          dtype=object)
    In [9]: d.shape
    Out[9]: ()
    In [11]: list(d[()].keys())
    Out[11]: [0, 1, 2, 3, 4, 5, 6, 7, 8]
    

    一些时间安排:

    In [12]: timeit np.save('test1',b)
    850 µs ± 36.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    In [13]: timeit d=np.load('test1.npy')
    566 µs ± 6.44 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    
    In [20]: %%timeit 
        ...: with open('testpickle', 'wb') as myfile:
        ...:     pickle.dump(b, myfile)
        ...:     
    505 µs ± 9.24 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
    In [21]: %%timeit 
        ...: with open('testpickle', 'rb') as myfile:
        ...:     g1 = pickle.load(myfile)
        ...:     
    152 µs ± 4.83 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)
    

    在我的时间里 更快。

    In [23]: ll test1.npy testpickle
    -rw-rw-r-- 1 paul 5740 Aug 14 08:40 test1.npy
    -rw-rw-r-- 1 paul 4204 Aug 14 08:43 testpickle
    
        3
  •  0
  •   Chris    8 年前

    这是因为 pickle 在各种Python对象上工作,并用纯Python编写,而 np.save 为数组设计并以有效格式保存它们。

    从 numpy.save documentation

    有用的参考: This answer