所以我使用np.load()加载一些文件,大小范围在150MB到250MB之间。每个文件包含一个包含5个子数组和一些数据的数组。一些文件在一秒钟内加载,而其他文件加载需要5秒钟,因为我有很多这些文件,因为加载时间较慢,所以需要花费很长时间才能使用它们。但是,我注意到如果我将文件分成5个较小的文件(每个文件1个子数组),那么每5个文件的加载时间总是很容易。
可能导致这种情况的原因是什么?如何在不将每个文件拆分成较小文件的情况下加速np.load()?
答案 0 :(得分:2)
问题的根源在于numpy中没有真正的子数组概念。
考虑这个例子:
import numpy as np
a1 = np.ones(2**17)
a2 = np.arange(2**18)
a3 = np.random.randn(2**19)
a = np.array([a1, a2, a3])
print(a.dtype) # object
如果将数组放入数组中numpy不知道它们是数组。相反,它将它们视为通用Python对象。这就是documentation of np.save
对此所说的:
allow_pickle :bool,可选
允许使用Python pickles保存对象数组。 [...]默认值:真
所以会发生的是子数组由pickler处理,这是非常低效的。显然,单独保存数组时不会发生这种情况。现在它们被有效地存储为numpy数组。不幸的是,你不能简单地设置allow_pickle=False
因为它不会让你存储对象数组。
解决方案是使用np.savez
来存储多个数组。以下是与上述数组的时序比较:
np.save('test.npy', a)
%timeit np.load('test.npy') # 10 loops, best of 3: 40.4 ms per loop
np.savez('test2.npz', a1, a2, a3)
%timeit np.load('test2.npz') # 1000 loops, best of 3: 339 µs per loop
您可以使用
来检索数组 x = np.load('test2.npz')
a1 = x['arr_0']
a2 = x['arr_1']
# ...
将数组作为关键字参数传递给savez
可能会更好,这会让你为它们命名:
np.savez('test3.npz', a1=a1, a2=a2, timmy=a3)
x = np.load('test3.npz')
a1 = x['a1']
a2 = x['a2']
a3 = x['timmy']