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

标签 python numpy

<分区>

所以我正在使用 np.load() 加载一些大小在 150MB 到 250MB 范围内的文件。每个文件包含一个数组,该数组有 5 个带有一些数据的子数组。有些文件在一秒钟内加载完毕,而另一些文件最多需要 5 秒才能加载,而且由于我有很多这些文件,由于加载时间慢,它们需要很长时间才能处理它们。但是,我注意到,如果我将文件分成 5 个较小的文件(每个文件 1 个子数组),那么每 5 个文件的加载时间总是很容易低于一秒。

这可能是什么原因造成的?如何在不将每个文件拆分为更小文件的情况下加快 np.load() 的速度?

最佳答案

问题的根源在于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, optional

Allow saving object arrays using Python pickles. [...] Default: True

所以发生的事情是子数组由 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']

关于python - np.load() 对于较大的文件异常缓慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45587628/

相关文章:

Python Tkinter Tk root.after 延迟

python - 简单 python 模块出错

python - Numpy:3D boolean 索引数组会发生什么

Python pandas - 如果项目在列表中,则为新列的值

python - Python 中的特征值

python - 无法使用 python 从 Json 文件中获取特定值

python - PySpark 平等过滤器问题

python - 它应该更快,cProfile说它更快,但程序实际上运行得更慢

NumPy vectorize() 或 dot() 出现错误

python - 对行的非零元素执行 numpy 乘积