深度学习训练降低显存指南

2023-05-16

一、小模块API参数inplace设置为True(省一点点)

比如:Relu()有一个默认参数inplace,默认设置为False,当设置为True时,计算时的得到的新值不会占用新的空间而是直接覆盖原来的值,进而可以节省一点点内存。

二、Apex半精度计算(省一半左右)

安装方式

git clone https://github.com/NVIDIA/apex
cd apex
python3 setup.py install

原理:一款Nvidia开发的基于PyTorch的混合精度训练加速神器,可以用短短三行代码(导包、初始化、反向传播)就能实现不同程度的混合精度加速,训练时间直接缩小一半。

from apex import amp
model, optimizer = amp.initialize(model, optimizer, opt_level="O1") # 这里是“欧一”,不是“零一”
with amp.scale_loss(loss, optimizer) as scaled_loss:
    scaled_loss.backward()

其中只有一个opt_level需要用户自行配置(# 这里是“欧x”,不是“零x”):

  • O0:纯FP32训练,可以作为accuracy的baseline;
  • O1:混合精度训练(推荐使用),根据黑白名单自动决定使用FP16(GEMM, 卷积)还是FP32(Softmax)进行计算。
  • O2:“几乎FP16”混合精度训练,不存在黑白名单,除了Batch norm,几乎都是用FP16计算。
  • O3:纯FP16训练,很不稳定,但是可以作为speed的baseline;

注:apex不能和contiguous-params一起用,否则无法实现模型参数优化。(因为这俩模型参数指针要打架)

三、删无用变量并及时清空显存垃圾(省将近一半)

这个的用法比较简单,就是先del变量,再cuda垃圾回收。

del answers_types_emb_all, answers_types_len
torch.cuda.empty_cache()

但这个的使用方式,不能在整个代码中只使用一次torch.cuda.empty_cache()——否则整体的最大显存不会变化。

正确的使用方法是:应该在整体代码的多个位置,分别del变量后,对应位置之后即使用torch.cuda.empty_cache()。

这样整体最大显存,就会下降(del的变量整体显存之和 - max的一坨del变量的显存)——分批清空显存,才能真正地用torch.cuda.empty_cache()降低显存。

四、重计算方法(省一半以上)

用pytorch的checkpoint断点保存机制,将连续的几个函数计算,分为若干段,保存了再计算——用保存加载的时间,换显存计算的空间

原来一个函数的计算方式:

sequence_enc = self.encoder(sequence_emb, sequence_mask, output_all_encoded_layers=False)[-1]

用checkpoint断点保存的方式:

from torch.utils.checkpoint import checkpoint
sequence_enc = checkpoint(self.encoder, sequence_emb, sequence_mask, torch.tensor([0]))[-1]

值得一提的是,checkpoint函数,要求输入的函数(如self.encoder),返回值必须为torch.tensor类型,如果原来函数(self.encoder)的返回值是一个数组

return all_encoder_layers

用torch.stack改造一下,就可以用checkpoint了

return torch.stack(all_encoder_layers, dim=0)

注:checkpoint后没有梯度记忆,解决方法参考Pytorch使用GPU进行训练注意事项 | 文艺数学君 (mathpretty.com)的方法二

五、效果

楼主同时用了上述四项节省显存的技术,将原始显存大于11GB的程序,降低到了只有2GB-3GB的水平

上述技术节省显存的程度(由多到少):

  1. 重计算方法
  2. Apex半精度计算
  3. 删无用变量并及时清空显存垃圾
  4. 小模块API参数inplace设置为True

上述技术实现的复杂程度(由易到难):

  1. 小模块API参数inplace设置为True
  2. Apex半精度计算
  3. 删无用变量并及时清空显存垃圾
  4. 重计算方法

PS 你如果有24GB以上显存的显卡的话,那就当我什么都没说。

当然还有些不是方法的方法:降低Batch的大小,减小模型的超参数,不需要计算显存时用torch.no_grad():等。

此外,代码变量之间的不当依赖,会导致显存持续增长,具体情况详见显存持续缓慢增长的究极原因 - 知乎 (zhihu.com)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深度学习训练降低显存指南 的相关文章

随机推荐

  • Qt Quick 3D中将3D场景(如.obj)转换为.mesh

    Qt 5 15以后提供了Qt Quick 3D的新模块 xff0c 该模块可使用可视化的方式即可进行3D模型的显示 xff0c 并且相较于Qt 3D来说 xff0c 该模块的API更为高级 xff0c 使用者不需要自己设计底层的细节 该模块
  • Qt Quick 3D系列(一):加载3d模型

    如果我们想在QML中使用3D且你之前没有三维程序开发的基础 xff0c 使用Qt Quick 3D是个不错的选择 xff0c 下面我介绍如何使用Qt Quick 3D加载3d模型 注意 xff1a Qt Quick 3D从Qt 5 15之后
  • boa常见错误整理

    错误1 xff1a bison y d boa grammar y gcc g O2 pipe Wall I c o y tab o y tab c y tab c In function yyparse y tab c 1295 warn
  • Qt Quick 3D系列(二):鼠标控制3D模型旋转缩放

    上一篇文章Qt Quick 3D系列 xff08 一 xff09 xff1a 加载3d模型我们讲述了如何在Qt Quick 3D中显示一个3D模型 xff0c 那么显示了3D模型后如何使用鼠标进行旋转呢 xff1f 在Qt 3D中提供了Or
  • Qt Quick 3D系列(三):设置三维模型的金属光泽材质

    前面的博客中介绍了如何在Qt Quick 3D中加载三维模型 xff0c 下面介绍如何设置三维模型的材质 xff0c 例如下图模型 我需要设置为金属材质时 xff0c 设置该Model的materials为PrincipledMateria
  • Qt Quick 3D系列(四):为三维模型添加动画效果

    Qt Quick 3D旨在让那些熟悉QML开发的人能够使用非常少的学习成本实现3D开发 xff0c 因此对于三维模型动画没有类似与Qt 3D中有个专门的Qt3DAnimation来控制动画效果 xff0c 而是直接使用QML中的Animat
  • Qt Quick 3D系列(五):三维模型展示示例

    为了展示一个好看的3D模型 xff0c 需要对模型设置背景 xff0c 设置三维材质 xff0c 设置周围光线 xff0c 设置模型阴影等等 下面示例展示了一个比较好看的三维模型效果 xff0c 大家可以先在C4D等调整好模型效果 xff0
  • QML 地图可拖拽位置标签组件

    在地图上显示位置信息时 xff0c 有时候需要同时显示该位置的详细信息 该组件可在地图上显示一个连接到地图地理位置的标签框 xff0c 该标签框可点击进行拖拽 在地理位置改变 地图缩放 地图平移时 xff0c 该标签框的相对位置保持不变 x
  • 使用QQuaternion对Qt Data Visualization中模型进行旋转

    在Data Visualization中 xff0c 三维显示的OBJ需要旋转时使用rotation属性 xff0c 但是该属性传入的值是一个四元数QQuaternion xff0c 直接赋值四元数很复杂 xff0c 因此使用转化的方式获得
  • QML 可拖拽边框和顶点调整大小组件(新增对主窗口支持)

    QML项目开发过程中 xff0c 有时候需要对控件大小和位置 进行人为调整 xff0c 因此设计该组件 该组件鼠标置于边框和顶点位置时鼠标样式对应改变 xff0c 拖动边框可修改该方向组件大小 xff0c 拖动顶点可修改组件处横纵向组件大小
  • QML 地图修改插件源码(五),Map添加自定义地图类型,并动态修改地图类型

    QML的地图Map中提供了属性activeMapType MapType用于设置当前地图的类型 xff0c 以OSM地图插件为例 xff0c OSM地图提供了多种地图类型 xff0c 下面介绍如何修改OSM插件的源码添加需要的地图类型 xf
  • Qt使用QQuaternion对空间矢量QVector3D进行旋转

    空间中的QVector3D既可以代表空间中的点位置 xff0c 也可以表示空间矢量 为什么要对空间矢量进行旋转呢 xff0c 比如有一个空间矢量在空间中代表了镜头前进的方向 xff08 即第一人称模式 xff09 xff0c 初始时该矢量指
  • QML实现双屏显示

    QML程序中需要分别在主屏幕和分屏幕上显示不同的界面内容 xff0c 但又为了不同界面间能够进行数据交互 xff0c 因此使用如下方法实现双屏显示 xff0c 即由主窗口生成第二个窗口 xff0c 将该窗口移动到第二个屏幕上 xff0c 实
  • ubuntu设置默认内核启动的方法

    本文介绍ubuntu设置默认内核启动的方法 参考如下图 xff0c 修改grub文件 xff1a 修改后 xff0c 执行 xff1a sudo update grub amp amp reboot
  • QML自定义的日历控件

    QML中提供了日历的控件Calendar xff0c 但该控件为QtQuick Controls 1中提供的控件 xff0c 因此只能使用QtQuick Controls Styles的方式对该控件进行设置 xff0c 效果如图 xff1a
  • QML地图Map中使用QPainterPath,并显示任意点经纬度位置

    QML地图Map中提供了供绘制图形的组件 xff0c 例如MapPolyline xff0c MapCircle等 xff0c 但是这些组件在绘制复杂轨迹时就显得功能不够全面 xff0c 因此我将QPainterPath在Map中进行使用并
  • QML地图绘制虚线

    QML提供了MapPolyline用于在地图上绘制线段 xff0c 该线段是实线 xff0c 因此我使用Canvas自定义绘制的方式在地图上绘制线段 xff0c 如图 xff1a 鼠标在地图上点击后 xff0c 在点击位置添加图标 xff0
  • QML无边框最大化窗口时遮住了任务栏,程序默认置顶的问题

    在QML窗口使用无边框 xff0c 并且默认程序最大化显示后 xff0c 此时程序显示默认自动变成了全屏显示 xff0c 程序自动遮挡住了系统任务栏 当使用多屏幕显示时 xff0c 切换不同程序 xff0c 该QML程序的界面显示错误 使用
  • 用VScode写C/C++,从下载安装到配置使用

    介绍 编程的过程大致分为编写代码 代码编译 代码执行三步 xff0c vscode可以完成代码编写 xff0c 但是不能进行编译 也就是将代码翻译为计算机可以听懂的话 xff0c MinGW可以完成这个任务 xff0c 二者配合可以实现在v
  • 深度学习训练降低显存指南

    一 小模块API参数inplace设置为True xff08 省一点点 xff09 比如 xff1a Relu 有一个默认参数inplace xff0c 默认设置为False xff0c 当设置为True时 xff0c 计算时的得到的新值不