为什么 pickle 花费的时间比 np.save 长得多?
Why does pickle take so much longer than np.save?
我想保存一个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 ---
时间差异与我的实际大小(字典中约 100,000 个键)更加明显。
为什么 pickle 的保存和加载时间都比 np.save 长?
什么时候应该使用pickle
?
因为只要写入对象不包含Python数据,
- numpy 对象在内存中的表示方式比 Python 对象
简单得多
- numpy.save是用C写的
- numpy.save 以需要最少处理的超简单格式写入
同时
- Python 对象有很多开销
- pickle 写在Python
- pickle 将数据从内存中的底层表示显着转换为写入磁盘的字节
请注意,如果一个 numpy 数组确实包含 Python 个对象,那么 numpy 只会对数组进行 pickle,而所有的胜利都会消失 window。
这是因为 pickle
适用于各种 Python 对象并且是用纯 Python 编写的,而 np.save
是为数组设计的并将它们保存在一个高效格式。
从numpy.save documentation开始,它实际上可以在幕后使用pickle。这可能会限制 Python 版本之间的可移植性,并冒着执行任意代码的风险(这是解封未知对象时的一般风险)。
有用参考:
我认为你需要更好的时机。我也不同意接受的答案。
b
是一个有 9 个键的字典;值是数组列表。这意味着 pickle.dump
和 np.save
将相互使用 - pickle
使用 save
来 pickle 数组, save
使用 pickle
来保存字典和列表。
save
写入数组。这意味着它必须将您的字典包装在一个对象 dtype 数组中才能保存它。
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)
在我的计时中 pickle
更快。
泡菜文件略小:
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
我想保存一个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 ---
时间差异与我的实际大小(字典中约 100,000 个键)更加明显。
为什么 pickle 的保存和加载时间都比 np.save 长?
什么时候应该使用pickle
?
因为只要写入对象不包含Python数据,
- numpy 对象在内存中的表示方式比 Python 对象 简单得多
- numpy.save是用C写的
- numpy.save 以需要最少处理的超简单格式写入
同时
- Python 对象有很多开销
- pickle 写在Python
- pickle 将数据从内存中的底层表示显着转换为写入磁盘的字节
请注意,如果一个 numpy 数组确实包含 Python 个对象,那么 numpy 只会对数组进行 pickle,而所有的胜利都会消失 window。
这是因为 pickle
适用于各种 Python 对象并且是用纯 Python 编写的,而 np.save
是为数组设计的并将它们保存在一个高效格式。
从numpy.save documentation开始,它实际上可以在幕后使用pickle。这可能会限制 Python 版本之间的可移植性,并冒着执行任意代码的风险(这是解封未知对象时的一般风险)。
有用参考:
我认为你需要更好的时机。我也不同意接受的答案。
b
是一个有 9 个键的字典;值是数组列表。这意味着 pickle.dump
和 np.save
将相互使用 - pickle
使用 save
来 pickle 数组, save
使用 pickle
来保存字典和列表。
save
写入数组。这意味着它必须将您的字典包装在一个对象 dtype 数组中才能保存它。
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)
在我的计时中 pickle
更快。
泡菜文件略小:
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