大模型炼丹基础--GPU内存计算
一、摘要
选择合适的GPU对成本和效率都至关重要,合理分析GPU
二、硬件计算基础
1 个字节可以表示零(00000000)和 255(11111111)之间的数字
模型参数常用的数据类型如下:
- float(32 位浮点):每个参数 4 个字节
- half/BF16(16 位浮点):每个参数 2 个字节
- int8(8 位整数):每个参数 1 个字节
- int4(4 位整数):每个参数 0.5 个字节
2.1.消耗 GPU 内存因素
2.1.1 模型参数
模型参数是神经网络的可学习组件。它们定义网络的结构和行为,并在训练期间更新以最小化损失函数。通常,我们有权重和偏差参数。
- 参数内存(M)= 参数数量(P)x 精度大小(4 字节)
- M = Px4,16 位 M = P x 精度大小(2 字节)也类似
添加一个缩放因子:例如 GPU 内存中加载额外内容的 20% 开销(Q=1.2),需要算出整体的加载内存后额外乘Q系数因子。
2.1.2 激活内存
当输入数据通过网络时,激活是每层神经元的中间输出。在前向传递过程中,每层处理输入数据,应用权重、偏差和激活函数(如 ReLU、sigmoid 等)来产生激活。然后,这些激活将作为下一层输入。
需要存储每个层的激活,因为它们在反向传播期间用于计算梯度。
激活内存 = 激活数量 x 批次大小 x 精度大小(GPU并行加速时同时计算的数据量)
注意:“每个参数的激活”取决于模型架构、层数和序列长度。对于大型模型,激活通常需要与参数相当或超过参数的内存。将序列长度加倍也可能使激活内存加倍。
2.1.3 梯度
梯度是损失函数关于模型参数的偏导数。在反向传播期间,损失通过网络向后传播,并计算每个参数(权重和偏差)的梯度。优化器使用这些梯度来更新参数,从而减少整体损失。
存储梯度所需的内存等于参数本身所需的内存。由于每个参数都有相应的梯度,因此它们的内存要求相同。
梯度内存 = 参数内存
2.1.4 优化器状态
优化器状态是某些优化算法(如 Adam、RMSprop)维护的附加变量,用于提高训练效率。这些状态有助于根据过去的梯度更新模型参数。
不同的优化器维护不同类型的状态。例如:
- SGD(随机梯度下降):没有附加状态;仅使用梯度来更新参数。
- Adam:为每个参数维护两个状态:一阶矩(梯度平均值)和二阶矩(梯度平方平均值)。这有助于动态调整每个参数的学习率。对于具有 100 万个参数的模型,Adam 需要为每个参数维护 2 个附加值(一阶矩和二阶矩),从而产生 200 万个附加状态。
优化器状态的内存 = 参数数量 x 精度大小 x 优化器乘数