将大型数组与 Numpy 集成时避免内存错误
Avoid memory errors when integrating large array with Numpy
我有一个 601x350x200x146
numpy float64
数组,根据我的计算,它占用大约 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, axis=3)
的结果:
In [38]: np.trapz(x, axis=3)
Out[38]:
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. ]]])
这里是使用没有大中间数组的计算。 (切片 x[:,:,:,1:-1]
不复制与数组关联的数据。)
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. ]]])
如果 x
的形状为 (m, n, p, q)
,则该表达式中生成的少数临时数组的形状均为 (m, n, p)
.
我有一个 601x350x200x146
numpy float64
数组,根据我的计算,它占用大约 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, axis=3)
的结果:
In [38]: np.trapz(x, axis=3)
Out[38]:
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. ]]])
这里是使用没有大中间数组的计算。 (切片 x[:,:,:,1:-1]
不复制与数组关联的数据。)
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. ]]])
如果 x
的形状为 (m, n, p, q)
,则该表达式中生成的少数临时数组的形状均为 (m, n, p)
.