當(dāng)你GPU資源不足時,如何訓(xùn)練大型模型?
- 如果我们微调这个预训练的BERT,我们的结果会更好!但我们很穷,没有足够的GPU……我总是遇到CUDA内存不足的问题 🤯
- 贫穷不是放弃的理由,让我们想办法解决吧。
预处理和注意事项:
0️.1. 确认确实是CUDA问题,尝试在CPU上使用批量大小为1,可能有些操作会触发错误。在CPU上运行时,错误更容易解释。另外,关闭GPU,仅使用一个小批量并检查预期结果等,然后再在GPU上运行,这样可以节省时间和GPU使用。
0️.2. 如果精简版本的模型可用,请检查它(精简模型是从其教师模型中获得知识的学生模型)。精简模型通常更轻,占用更少的GPU内存。
0️.3. 检查更小的批量大小——请注意,使用小批量大小进行训练可能会导致整体结果更差。覆盖率可能会更慢,甚至可能无法达到预期的结果。
注意:
如果你不了解GPU、CPU和TPU,不用担心你不是天生就懂这些知识,可以看看这个视频和这个视频。
大多数情况下,这个问题发生在你尝试在训练过程中分配过多内存时,所以你的操作很重,比如矩阵乘法,你的模型很重,优化器也很重,网络很深,并且你还保存了节点的梯度。
当我终于能把模型放进内存里时
要做什么? 1. 梯度检查点 🏁这是一种技术,当你只在内存中保存网络中用于反向传播的一些节点,然后重新计算它们,这样就在运行时间和内存效率之间做了一个权衡。
重要提示:带有 dropout/BatchNorm 的块不应重新计算,因为两次运行中的随机性会导致不同结果。
如果你使用 hugging face,可以查看 gradient_checkpoints_steps。
tenserflow &explanation
pytorch&explanation
你只需为几个小批量保存损失,并且仅在获得了所需的数量时才进行更新(例如,在主要训练过程中,作者使用了128的批量大小,你无法承担这样的开销,只能使用8的批量大小,优化器仅在经过16次传递后才进行更新,即128 / 8 = 16次)。
你可以在循环中这样做,如果你使用hugging face,可以查看gradient_accumulation_steps。
代码片段 用于常规训练循环中。
修改并“优化”后的优化器允许在非浮点精度下运行操作,这在8位模式下节省了大量的内存。
4. 训练的不同精度 💾精度主要体现在训练过程中数值的准确性,这是一个非常酷的想法,你可以在Hugging Face教程中了解到。Hugging Face为所有fp16、bfp16、tp32提供了非常用户友好的界面。顺便说一下,tp32可以通过一行代码轻松实现,适用于torch。
torch.backends.cuda.matmul.allow_tf32 = True
重要提示:使用不同的精度时,请注意覆盖时间和精度。这通常是在模型大小、速度和精度之间的一种权衡。
此外,如果你需要以后使用你的模型,你可以对其进行量化。我个人只使用过 torch 资源 和 intel openvino。
5. 数据加载器中的参数以及你如何保存数据。即使你的数据可以全部放入GPU中,也不建议这样做。最好和更快的做法是在训练过程中将数据设置在正确的设备上,并利用更大的批次大小。如果你担心时间问题,可以设置pin_memory参数,这样你的数据可以直接从CPU固定到GPU上。
Illustration and details
pin_memory 参数 = True,
6. 注意你可以在CPU上进行哪些操作,哪些可以在GPU上进行
就像计算损失函数可以在CPU上完成,并观察在使用GPU时是否保存了loss.item()
,因为这可能会占用过多的内存。
该线程讨论了何时在GPU上计算损失函数,以及该评论中关于在CPU和GPU同步时使用它的内容。
这还不止,但看起来这是最明显的。你使用了哪些技术?
共同學(xué)習(xí),寫下你的評論
評論加載中...
作者其他優(yōu)質(zhì)文章