一个文件为我提供了一个400x400x200x1阵列和一个形状。根据阵列传输的数据,形状会发生变化。我的任务是使400x400x200x1阵列适应其包含的数据 例如:
shape = np.array([20,180,1,1])
b= []
l = np.load("testfile.npy")
d = (np.reshape(l[:shape[0],:shape[1],:shape[2],:shape[3]],(shape[0],shape[1]))).transpose()
append(d)
我们的想法是创建一个新数组,其大小适合其数据。 现在出现了问题:我必须多次执行此过程,但每次执行此操作时,我的RAM加载因子都会增加。:
shape = np.array([20,180,1,1])
b= []
for j in range(9):
l = np.load("testfile.npy")
d = (np.reshape(l[:shape[0],:shape[1],:shape[2],:shape[3]],(shape[0],shape[1]))).transpose()
time.sleep(2)
b.append(d)
这只是因为appendet数组太大了吗?我附加的输出数组大小为180x20 ......但RAM负载系数每次增加0,12GB。是否有更有效的方法来存储数组,没有临时文件?
感谢和抱歉我的英语。
答案 0 :(得分:4)
在您的示例中,您的错误是您在for循环的每次迭代中重新加载文件。 尝试:
l = np.load("testfile.npy")
shape = np.array([20,180,1,1])
b = []
for j in range(9):
d = (np.reshape(l[:shape[0],:shape[1],:shape[2],:shape[3]],(shape[0],shape[1]))).transpose()
time.sleep(2)
b.append(d)
解决了这个问题。
现在,原因是:在每次迭代中,您从文件加载l
,隐式地在其中部分view
(d
),并将此视图添加到{{ 1}}。视图实际上包含对整个数组的引用。所以每次加载整个数组并存储一个带有引用的对象,从而禁止垃圾收集器释放内存。
如果由于任何原因每次都必须重新加载文件,另一个解决方案是明确地复制以便丢失对整个数组的引用。在您的示例中,将最后一行替换为:
b
注意1:实际上,因为与b.append(d.copy())
相比,观看次数d
可以忽略不计,所以您应该始终制作副本
注2:断言l
保留对d
的引用
l
d.base.base.base is l # True
是对已查看数组的引用。在您的情况下,有3个深度:.base
切片,重塑和转置。
答案 1 :(得分:2)
您的大部分RAM使用来自将整个400x400x200x1阵列读入内存。告诉numpy对内存映射输入数组,它应该能够避免读取大部分内容:
l = np.load("testfile.npy", mmap_mode='r')
由于reshape
和transpose
都尽可能返回原始数组的视图,因此明确复制结果也是值得的。我们还可以简化索引:
d = l[:20, :180, 0, 0].transpose().copy()
我不认为您选择的特定索引允许NumPy返回视图,但是当它确实返回视图时,视图将导致保留整个原始数组。对于内存映射数组,我相信一个视图也将是内存映射,这可能不是你想要的。