OpenAI发布了一套称为“打开AI健身房”的机器学习/强化学习环境。一些环境是基于图像的,因此当与存储10万或数百万帧的环境观察的算法一起使用时,可能具有非常大的存储器占用空间。
在深入学习DeepQ Learning的参考实现时,我找到了一对类LazyFrameStack
和LazyFrames
,声称"确保观察之间的公共帧只存储一次。 ..优化内存使用量,这对于DQN的1M帧重放缓冲区来说可能是巨大的。"
在参考实现中,DeepQ代理获取以四个为一组堆叠在一起的帧,然后将这些帧放入重放缓冲区。看过这两个类的实现后,对我来说这些如何节省内存并不明显 - 如果有的话,因为LazyFrames
基本上是围绕一组四个numpy
数组的容器对象,不应该LazyFrame
有更大的内存空间吗?
答案 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
(这是一个数组列表)仅存储对a
和b
的引用,因此,当我们执行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