1.常用GPU显存不足时的各种Trick
1.1监控GPU
- nvidia-smi,这个安装英伟达的驱动就可以用
- gpustat,这个能动态监视GPU
1.2估计模型显存
GPU的内存占用率主要由两部分组成:
- 一是优化器参数,模型自身的参数,模型中间每一层的缓存
- 二是batch size的大小
1.3显存不足的技巧
- 降低batch size
- 选择更小的数据类型
- 精简模型
- 数据角度
- total_loss
- 释放不需要的张量和变量
- Relu 的 inplace 参数
- 梯度累积
更详细来说, 我们假设 batch size = 4 , accumulation steps = 8 , 梯度积累首先在前向传播的时候以 batch_size=4 来计算梯度,但是不更新参数,将梯度积累下来,直到我们计算了 accumulation steps 个 batch, 我们再更新参数。其实本质上就等价于:
真正的 batch_size = batch_size * accumulation_steps
- 梯度检查点
- 混合精度训练
- 分布式训练Distribution Training
1.4提高GPU内存利用率
当没有设置好CPU的线程数时,Volatile GPU-Util是在反复跳动的,0% → 95% → 0%。这其实是GPU在等待数据从CPU传输过来,当从总线传输到GPU之后,GPU逐渐开始计算,利用率会突然升高,但是GPU的算力很强大,0.5秒就基本能处理完数据,所以利用率接下来又会降下去,等待下一个batch的传入。利用率的主要瓶颈在CPU的数据吞吐量上面.
- 配置更强大的内存条,配合更好的CPU;
- num_workers
为了提高利用率,首先要将num_workers设置合适,4、8、16是几个常选的参数。经过测试,将num_workers设置的非常大,如24、32等,其效率反而降低,因为模型需要将数据平均分配到几个子线程去进行预处理,分发等数据操作,设高了反而影响效率。当然,线程数设置为1,是单个CPU来进行数据的预处理和传输给GPU,效率也会低。 - pin_memory
当服务器或者电脑的内存较大,性能较好的时候,建议用pin_memory。该参数为True时可以直接映射到GPU的相关内存块上,省掉了一点数据传输时间。