Python 在将大型阵列与Numpy集成时避免内存错误
我有一个Python 在将大型阵列与Numpy集成时避免内存错误,python,arrays,numpy,out-of-memory,Python,Arrays,Numpy,Out Of Memory,我有一个601x350x200x146numpyfloat64数组,根据我的计算,这个数组需要大约22.3 Gb的内存。我的free-m输出告诉我,我有大约100Gb的可用内存,所以它非常适合。但是,当与 result = np.trapz(large_arr, axis=3) 我有一个记忆错误。我知道这是因为numpy.trapz必须创建中间数组来执行集成。但我想看看是否有办法解决这个问题,或者至少有办法减少额外的内存使用 我读过关于内存错误的书,知道一些可以避免的事情:一是在集成之前放置一
601x350x200x146
numpyfloat64
数组,根据我的计算,这个数组需要大约22.3 Gb的内存。我的free-m
输出告诉我,我有大约100Gb的可用内存,所以它非常适合。但是,当与
result = np.trapz(large_arr, axis=3)
我有一个记忆错误。我知道这是因为numpy.trapz
必须创建中间数组来执行集成。但我想看看是否有办法解决这个问题,或者至少有办法减少额外的内存使用
我读过关于内存错误的书,知道一些可以避免的事情:一是在集成之前放置一个gc.collect()
调用。我试过了,但没用
另一个是使用*=
操作符,比如写入arr*=a
,而不是arr=arr*a
,我在这里不能这么做。所以我不知道还能尝试什么
有人知道在不引起内存错误的情况下执行此操作的方法吗
您可以使用以下方法再现错误:
arr = np.ones((601,350,200,146), dtype=np.float64)
arr=np.trapz(arr, axis=3)
虽然您必须缩小大小以匹配内存大小。
numpy.trapz
提供了一些便利,但实际计算非常简单。要避免使用大型临时阵列,只需自己实现即可:
In [37]: x.shape
Out[37]: (2, 4, 4, 10)
下面是numpy.trapz(x,轴=3)
的结果:
这里的计算是为了不使用大型中间数组而编写的。(切片x[:,:,:,1:-1]
不会复制与数组关联的数据。)
如果
x
具有形状(m,n,p,q)
,则在该表达式中生成的少数临时数组都具有形状(m,n,p)
numpy。trapz
提供了一些便利,但实际计算非常简单。要避免使用大型临时阵列,只需自己实现即可:
In [37]: x.shape
Out[37]: (2, 4, 4, 10)
下面是numpy.trapz(x,轴=3)
的结果:
这里的计算是为了不使用大型中间数组而编写的。(切片x[:,:,:,1:-1]
不会复制与数组关联的数据。)
如果
x
具有形状(m,n,p,q)
,则在该表达式中生成的少数临时数组都具有形状(m,n,p)
,在我看来,该数组是49 GB。NumPy大量使用中间划痕阵列;np.trapz
实现需要比内存容量更大的内存。你知道trapz
在做什么吗?即使``arr`本身适合,由trapz
创建的临时数组也可能不适合。@user2357112是的,我就是这么想的。但您的意思是根本没有办法?Numexpr、Numba或Cython可能会有所帮助,尽管您需要重写np.trapz
实现,而不是调用np.trapz
。不过,里面只有一行实际的数学知识,而且你不需要大部分的样板文件,所以大部分的麻烦都是在安装和阅读一个新的工具上。我认为你可以在纯NumPy中通过小心就地操作来充分降低内存使用率,但是你仍然不能使用np.trapz
来完成这项工作。在我看来,这个数组是49GB。NumPy大量使用中间划痕阵列;np.trapz
实现需要比内存容量更大的内存。你知道trapz
在做什么吗?即使``arr`本身适合,由trapz
创建的临时数组也可能不适合。@user2357112是的,我就是这么想的。但您的意思是根本没有办法?Numexpr、Numba或Cython可能会有所帮助,尽管您需要重写np.trapz
实现,而不是调用np.trapz
。不过,里面只有一行实际的数学知识,而且你不需要大部分的样板文件,所以大部分的麻烦都是在安装和阅读一个新的工具上。我认为你可以在纯NumPy中通过小心就地操作来充分降低内存使用率,但是你仍然不能使用np.trapz
来完成这项工作。啊,当然。我们可以立即缩小尺寸,而不是在最后一步。您可以通过使用+=
和*=
来消除剩余的临时数组,这在沿短轴缩小时可能有点帮助,但是与输入大小和np.trapz
的临时数组的大小相比,内存节省很小。啊,当然。我们可以立即缩小尺寸,而不是在最后一步。您可以通过使用+=
和*=
来消除剩余的临时数组,这在沿短轴缩小时可能会有点帮助,但与输入大小和np.trapz
的临时数组大小相比,内存节省很小。
In [48]: 0.5*(x[:,:,:,0] + 2*x[:,:,:,1:-1].sum(axis=3) + x[:,:,:,-1])
Out[48]:
array([[[ 43. , 48.5, 46.5, 67. ],
[ 35.5, 39.5, 52.5, 35. ],
[ 44.5, 47.5, 34.5, 39.5],
[ 54. , 40. , 46.5, 50.5]],
[[ 42. , 60. , 55.5, 51. ],
[ 51.5, 40. , 52. , 42.5],
[ 48.5, 43. , 32. , 36.5],
[ 42.5, 38. , 38. , 45. ]]])