machine_memory

  1. 模型加载:将模型参数移动到GPU,当前内存使用量为模型的大小。

  2. 前向传播:输入通过模型并存储中间输出(激活)。存储这些激活占用了记忆体。

  3. 反向传播:计算从网络末端到开始的梯度,并在进行时丢弃前向激活,因为我们有了一致的出价,当前内存使用量为模型加梯度的大小。

  4. 优化器步骤:更新参数并保留运行中的梯度估计,如一阶和二阶动量。这将占用模型大小的两倍内存对于使用动量的Adam优化器,对于使用一个动量的RMSprop,以及对于不使用动量的SGD,占用等同于模型大小的内存。

  5. 后续迭代:梯度计算后,优化器采取了一步,梯度和梯度动量仍然存在。所以你在未来迭代中的最大内存使用量将是模型+激活+梯度+梯度动量。

model+activation+gradient+gradient momentum

计算

max memory consumption = m+ f batch_size b + d g + o m

m 是模型占用的内存。

f 是单个数据样本前向传递所消耗的内存。 batch_size 是批量大小。

b 是训练过程中使用的精度因子(如果使用混合精度训练,则为0.5;如果使用全精度训练,则为1)。

d 是分布式训练的因子(如果在一个GPU上训练,则为1;如果在多个GPU上训练,则为2)。

g 是梯度占用的内存。

o 是优化器存储的动量的数量(通常是0、1或2,取决于是否使用动量以及使用的动量类型)。

trick

  1. with torch.no_grad():
    1. 用于减少内存使用量,因为它不会跟踪梯度。