将大型数组与 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).