这个Python内存优化如何工作?

时间:2018-04-27 20:17:47

标签: python memory

OpenAI发布了一套称为“打开AI健身房”的机器学习/强化学习环境。一些环境是基于图像的,因此当与存储10万或数百万帧的环境观察的算法一起使用时,可能具有非常大的存储器占用空间。

在深入学习DeepQ Learning的参考实现时,我找到了一对类LazyFrameStackLazyFrames,声称"确保观察之间的公共帧只存储一次。 ..优化内存使用量,这对于DQN的1M帧重放缓冲区来说可能是巨大的。"

在参考实现中,DeepQ代理获取以四个为一组堆叠在一起的帧,然后将这些帧放入重放缓冲区。看过这两个类的实现后,对我来说这些如何节省内存并不明显 - 如果有的话,因为LazyFrames基本上是围绕一组四个numpy数组的容器对象,不应该LazyFrame有更大的内存空间吗?

1 个答案:

答案 0 :(得分:2)

在Python中,对象作为参考传递。这意味着,即使LazyFrame对象可能是一个非常大的numpy数组的列表,该LazyFrame对象本身的大小仍然很小,因为它仅存储对np.ndarray的引用。换句话说,您可以认为LazyFrame只是指向np.ndarray数据,而不是在其内部实际存储单个数组的每个副本。

import numpy as np
a = np.ones((2,3))
b = np.ones((2,3))
X = [a, b]

print(X)
>>> [array([[1., 1., 1.],
            [1., 1., 1.]]),
     array([[1., 1., 1.],
            [1., 1., 1.]])]

X_stacked = np.stack(X)

print(X_stacked)
>>> array([[[1., 1., 1.],
            [1., 1., 1.]],

           [[1., 1., 1.],
            [1., 1., 1.]]])

a[0] = 2
print(X)
>>> [array([[2., 2., 2.],
            [1., 1., 1.]]),
     array([[1., 1., 1.],
            [1., 1., 1.]])]

print(X_stacked)
>>> array([[[1., 1., 1.],
            [1., 1., 1.]],

           [[1., 1., 1.],
            [1., 1., 1.]]])

正如您在此处看到的,X(这是一个数组列表)仅存储对ab的引用,因此,当我们执行a[0] = 2时,通过打印X可以看到更改。但是一旦堆叠了阵列,实际上就创建了一个具有那么多内存的新阵列。

为了更直接地解决“如何节省内存”这个问题,下面是一个示例。

import sys

a = np.random.randn(210, 160, 3)
b = np.random.randn(210, 160, 3)

X = [a,b]
X_stacked = np.stack(X)

print(sys.getsizeof(X))
>>> 80

print(sys.getsizeof(X_stacked))
>>> 1612944