如何使用大型阵列防止大量使用RAM?

时间:2014-04-02 10:32:07

标签: python arrays numpy ram

一个文件为我提供了一个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)

load factor

这只是因为appendet数组太大了吗?我附加的输出数组大小为180x20 ......但RAM负载系数每次增加0,12GB。是否有更有效的方法来存储数组,没有临时文件?

感谢和抱歉我的英语。

2 个答案:

答案 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,隐式地在其中部分viewd),并将此视图添加到{{ 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')

由于reshapetranspose都尽可能返回原始数组的视图,因此明确复制结果也是值得的。我们还可以简化索引:

d = l[:20, :180, 0, 0].transpose().copy()

我不认为您选择的特定索引允许NumPy返回视图,但是当它确实返回视图时,视图将导致保留整个原始数组。对于内存映射数组,我相信一个视图也将是内存映射,这可能不是你想要的。