我的代码生成大小为 (1, 1, n, n, m, m) 的 numpy 数组列表,其中 n 可能在 50-100 之间变化,m 可能在 5-10 之间变化,具体取决于当前的情况。列表本身的长度可能达到 10,000,并在代码末尾使用 pickle 写入/转储。对于这些数字较高端的情况或当文件大小超过 5-6 GB 时,我会收到内存不足错误。下面是一个虚构的情况示例,
import numpy as np
list, list_length = [], 1000
n = 100
m = 3
for i in range(0, list_length):
list.append(np.random.random((1, 1, n, n, m, m)))
file_path = 'C:/Users/Desktop/Temp/'
with open(file_path, 'wb') as file:
pickle.dump(list, file)
我正在寻找一种可以帮助我的方法
- 拆分数据,以便消除内存错误,并且
- 稍后需要时以原始形式重新加入数据
我能想到的是:
for i in range(0, list_length):
data = np.random.random((1, 1, n, n, m, m))
file_path = 'C:/Users/Desktop/Temp/'+str(i)
with open(file_path, 'wb') as file:
pickle.dump(data, file)
然后使用以下组合:
combined_list = []
for i in range(0, list_length):
file_path = 'C:/Users/Desktop/Temp/single' + str(i)
with open(file_path, 'rb') as file:
data = pickle.load(file)
combined_list.append(data)
使用这种方式,由于多个文件,文件大小肯定会减小,但由于多个文件 I/O 操作,这也会增加处理时间。
是否有更优雅、更好的方法来做到这一点?
最佳答案
使用 savez
、savez_compressed
甚至像 h5py
这样的东西可能会很有用,正如 @tel 提到的,但这需要额外的努力“重新发明”缓存机制。如果适用,有两种更简单的方法可以处理大于内存的 ndarray
:
最简单方法当然是在 Windows 上启用
pagefile
(或其他名称)或在 Linux 上启用swap
(不确定)关于 OS X 对应部分)。这实际上创建了足够大的内存,因此您根本不需要担心内存。它将相应地保存到磁盘/从磁盘加载如果由于没有管理员权限等原因导致第一种方式不适用,
numpy
提供了另一种方式:np.memmap
。此函数将 ndarray 映射到磁盘,以便您可以像在内存中一样对其进行索引。从技术上讲,IO 是直接对硬盘完成的,但操作系统会相应地进行缓存
对于第二种方式,您可以使用以下方法创建硬盘端ndarray
:
np.memmap('yourFileName', 'float32', 'w+', 0, 2**32)
这会立即创建一个 16GB float32
数组(包含 4G 号码)。然后你就可以对其进行 IO 操作。许多函数都有一个 out
参数。您可以相应地设置 out
参数,以便输出不会从内存“复制”到磁盘
如果您想使用第二种方法保存 ndarray
列表,请创建大量 memmap
,或者将它们连接到单个数组
关于python - 如何拆分大数据并稍后重新加入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53752371/