我的代码生成了一个大小为(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操作,这也会增加处理时间。
是否有更优雅,更好的方法来做到这一点?
答案 0 :(得分:0)
不要使用pickle来存储大数据,这不是序列化任何内容的有效方法。而是通过numpy.savez_compressed
和numpy.load
函数使用内置的numpy序列化格式/函数。
系统内存不是无限的,因此在某些时候您仍然需要拆分文件(或使用更重的解决方案,例如h5py
软件包提供的解决方案)。但是,如果您能够将原始列表放入内存中,那么savez_compressed
和load
应该可以满足您的需求。
答案 1 :(得分:0)
使用@ {tel},使用savez
,savez_compressed
或什至是h5py
之类的东西也很有用,但是尝试“重塑”缓存机制需要花费额外的精力。如果适用,有两种更简单的方法可以处理大于内存的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
,或将它们合并到单个数组中