np.load()对于较大的文件异常缓慢

时间:2017-08-09 10:08:04

标签: python numpy

所以我使用np.load()加载一些文件,大小范围在150MB到250MB之间。每个文件包含一个包含5个子数组和一些数据的数组。一些文件在一秒钟内加载,而其他文件加载需要5秒钟,因为我有很多这些文件,因为加载时间较慢,所以需要花费很长时间才能使用它们。但是,我注意到如果我将文件分成5个较小的文件(每个文件1个子数组),那么每5个文件的加载时间总是很容易。

可能导致这种情况的原因是什么?如何在不将每个文件拆分成较小文件的情况下加速np.load()?

1 个答案:

答案 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']