CVHub手把手帮你榨干GPU的显存

简介: CVHub手把手帮你榨干GPU的显存

引言

Out Of Memory, 一个炼丹师们熟悉得不能再熟悉的异常,其解决方法也很简单,减少输入图像的尺寸或者Batch Size就好了。但是,且不说输入尺寸对模型精度的影响,当BatchSize过小的时候网络甚至无法收敛的。

下图来源知乎:

深度学习中的batch的大小对学习效果有何影响?

6a1ad542f3a8223219f3dd8c58bf6d82.png

作者使用LeNet在MNIST数据集上进行测试,验证不同大小的BatchSize对训练结果的影响。我们可以看到,虽然说BatchSize并不是越大越好,但是过小的BatchSize的结果往往更差甚至无法收敛。


因此本文将会介绍如何在不减少输入数据尺寸以及BatchSize的情况下,进一步榨干GPU的显存。

什么在占用显存

显存主要是被以下三部分内容占用:1、网络模型,2、模型计算的过程中的中间变量,3、框架自身的显存开销。

网络模型的占用的显存主要是来自于所有有参数的层,包括:卷积、全连接、BN等;而不占用显存的有:激活函数、池化层以及Dropout等。

计算过程中产生的显存主要有:优化器、中间过程的特征图、backward过程产生的参数

而框架自身的显存开销一般不大,并且我们也不好优化,所以我们只能考虑从前面两点对显存进行优化,针对这两个部分,本文接下来将会介绍常用的显存占用优化策略。

模型显存优化

尽量使用Inplace

在PyTorch中,inplce操作指的是改变一个tensor值的时候,不经过复制操作而是直接在原来的内存上修改它的值,也就是原地操作。基本上,所有提供inplace参数的操作都可以使用inplace,并且官方文档也说了,如果你使用了inplace operation而没有报错的话,那么你可以确定你的梯度计算是正确的。


335e3e53f71c93e3c869aa02b94af75f.png


pytorch中所有inplace操作一般都是以_为后缀,如tensor.add_()、tensor.scatter_()等。除了自带的一些函数提供inplace操作外,一些运算法也存在inplace操作。如上图展示的是两个向量相加操作使用inplace与否的区别,但是要注意写法:


x = x+y属于case 1

x += y属于case2

同理, *=也是inplace操作


尽量少产生中间结果

下面两份代码,效果是一样的,但是占用显存却是不一样的。

不推荐写法

def forward(self, x):
  out_1 = self.conv_1(x)
  out_2 = self.conv_2(out_1)
  out_3 = self.conv_3(out_2)
  return out_3

推荐写法

def forward(self, x):
  x = self.conv_1(x)
  x = self.conv_2(x)
  x = self.conv_3(x)
  return x


不需要的中间变量尽可能的都是用一个变量来代替,因为这些变量都是会占用显存的。因此,网络中如果存在一些较长的连接(比如第10层的网络需要使用来自网络第一层的输出结果),这部分的特征图就会一直占用显存。

不使用过大全连接


相比于卷积的参数,全连接的参数量可就大多了。因为卷积只是一个局部的连接,而全连接则是一个全局的连接。举个栗子:


卷积的参数只与输出的通道数、卷积核大小相关。在不考虑偏置的情况下,卷积核大小为3,输入通道为32,输出通道数为64的时候,参数量大小为3 ∗ 3 ∗ 32 ∗ 64 = 18432

image.png

所以一般来说,特征图比较大的时候,直接用全连接显卡会直接冒烟。因此往往只能在深层或者特征进行压缩之后才能够使用全连接。比如像SENet中,就是先将特征图使用GAP(Global Average Pooling)之后,才使用全连接,并且在全连接的中间层还是用了一定的压缩倍率。


亦或者可以像ECA-Net那般,不使用全连接,采用邻域连接的方式来减少计算量。


计算过程优化

使用checkpoint


PyTorch在0.4版本后推出了一个新功能,可以将一个模型的计算过程分为两半。也就是说,如果一个模型训练需要占用的显存太大,可以先计算网络的一半,保存后半部分所需要的中奖结果,再计算后半部分。当然,这样的操作显然是一个牺牲时间换空间的方法没,其使用方式如下:


# 常规写法
def forward(self, x):
  x = self.conv_1(x)
  x = self.conv_2(x)
  x = self.conv_3(x)
  return x
# 引入checkpoint
from torch.utils.checkpoint import checkpoint
def forward(self, x):
  x = checkpoint(self.conv_1(x), x)
  x = checkpoint(self.conv_2(x), x)
  x = checkpoint(self.conv_3(x),x)
  return x

梯度累加

大多数情况下,其实我们降低显存就是为了获得更大的Batchsize,因此使用gradient accumulation(梯度累加)也可以达到类似的效果。一般来说,我们使用pytorch写网络的训练过程主要是下面这个流程:


for i in range(epochs):
        optimizer.zero_grad()                   # 梯度清零
        outputs = network(input)                   # 正向传播
        loss = criterion(output, label)       # 计算损失
        loss.backward()                         # 反向传播,计算梯度
        optimizer.step()                        # 更新参数

而梯度累加的代码则只需要多一步:

for i in range(epochs):
        optimizer.zero_grad()                   # 梯度清零
        outputs = network(input)                   # 正向传播
        loss = criterion(output, label)/accumulation_steps
        if (i+1) % accumulation_steps == 0: 
            optimizer.step()                    # 更新参数
            optimizer.zero_grad()               # 梯度清零

通过这种方法能够比较简单的在有限的内存下模拟更大batchsize 的效果,并且效果也比较接近。

降低计算精度


PyTorch中,所有Tensor默认的精度都是FP32,也就是说每一个浮点型参数都需要占用32bit的显存。因此,如果直接把精度降低到FP16,那理论上直接就能减少一半的显存占用。那么,古尔丹,代价是什么呢?代价就是,在反向传播的过程中,大多数更新值都非常小但不为零。反向传播的舍入误差可以把这些数字变成0或者nans,使得梯度更新不准确,影响网络的收敛。ICLR2018论文中Mixed Precision Training发现,使用FP16进行训练的网络约有5%的梯度都会被“吞掉”。


4246534d78798cf330670b5f0c4711f7.png

在PyTorch1.6之前,降低训练进度普遍使用的都是NVIDIA提供的apex库。而在1.6版本之后,PyTorch推出了AMP(Automatic mixed precision),自动混合精度训练。这套技术并不是简单的将所有的参数降低精度,而是根据不同向量的不同操作对于误差的敏感程度来决定其使用的是FP16还是FP32。其使用起来也十分简单,下面是一个简单的例子,代码参考知乎:

from torch.cuda.amp import autocast,GradScaler
# 创建model,默认是torch.FloatTensor
model = Net().cuda()
optimizer = optim.SGD(model.parameters(), ...)
# 在训练最开始之前实例化一个GradScaler对象
scaler = GradScaler()
for epoch in epochs:
    for input, target in data:
        optimizer.zero_grad()
        # 前向过程(model + loss)开启 autocast
        with autocast():
            output = model(input)
            loss = loss_fn(output, target)
        # Scales loss. 为了梯度放大.
        scaler.scale(loss).backward()
        # scaler.step() 首先把梯度的值unscale回来.
        # 如果梯度的值不是 infs 或者 NaNs, 那么调用optimizer.step()来更新权重,
        # 否则,忽略step调用,从而保证权重不更新(不被破坏)
        scaler.step(optimizer)
        # 准备着,看是否要增大scaler
        scaler.update()


终极解决办法

加钱

写在最后

如果您也对人工智能和计算机视觉全栈领域感兴趣,强烈推荐您关注有料、有趣、有爱的公众号『CVHub』,每日为大家带来精品原创、多领域、有深度的前沿科技论文解读及工业成熟解决方案!欢迎添加小编微信号:cv_huber,一起探讨更多有趣的话题!


相关实践学习
部署Stable Diffusion玩转AI绘画(GPU云服务器)
本实验通过在ECS上从零开始部署Stable Diffusion来进行AI绘画创作,开启AIGC盲盒。
目录
相关文章
|
TensorFlow 算法框架/工具 异构计算
GPU 显存释放
GPU 显存释放
442 1
|
异构计算 算法框架/工具 TensorFlow
|
2月前
|
机器学习/深度学习 编解码 人工智能
阿里云gpu云服务器租用价格:最新收费标准与活动价格及热门实例解析
随着人工智能、大数据和深度学习等领域的快速发展,GPU服务器的需求日益增长。阿里云的GPU服务器凭借强大的计算能力和灵活的资源配置,成为众多用户的首选。很多用户比较关心gpu云服务器的收费标准与活动价格情况,目前计算型gn6v实例云服务器一周价格为2138.27元/1周起,月付价格为3830.00元/1个月起;计算型gn7i实例云服务器一周价格为1793.30元/1周起,月付价格为3213.99元/1个月起;计算型 gn6i实例云服务器一周价格为942.11元/1周起,月付价格为1694.00元/1个月起。本文为大家整理汇总了gpu云服务器的最新收费标准与活动价格情况,以供参考。
阿里云gpu云服务器租用价格:最新收费标准与活动价格及热门实例解析
|
1月前
|
机器学习/深度学习 存储 人工智能
阿里云GPU云服务器实例规格gn6v、gn7i、gn6i实例性能及区别和选择参考
阿里云的GPU云服务器产品线在深度学习、科学计算、图形渲染等多个领域展现出强大的计算能力和广泛的应用价值。本文将详细介绍阿里云GPU云服务器中的gn6v、gn7i、gn6i三个实例规格族的性能特点、区别及选择参考,帮助用户根据自身需求选择合适的GPU云服务器实例。
阿里云GPU云服务器实例规格gn6v、gn7i、gn6i实例性能及区别和选择参考
|
2月前
|
编解码 分布式计算 Linux
最新阿里云服务器、轻量应用服务器、GPU云服务器活动价格参考
阿里云服务器产品包含云服务器、轻量应用服务器、GPU云服务器等,本文汇总了这些云服务器当下最新的实时活动价格情况,包含经济型e实例云服务器价格、通用算力型u1实例云服务器价格、第七代云服务器价格、轻量应用服务器最新价格、GPU云服务器价格,以供大家参考。
最新阿里云服务器、轻量应用服务器、GPU云服务器活动价格参考
|
2月前
|
机器学习/深度学习 人工智能 弹性计算
阿里云AI服务器价格表_GPU服务器租赁费用_AI人工智能高性能计算推理
阿里云AI服务器提供多样化的选择,包括CPU+GPU、CPU+FPGA等多种配置,适用于人工智能、机器学习和深度学习等计算密集型任务。其中,GPU服务器整合高性能CPU平台,单实例可实现最高5PFLOPS的混合精度计算能力。根据不同GPU类型(如NVIDIA A10、V100、T4等)和应用场景(如AI训练、推理、科学计算等),价格从数百到数千元不等。详情及更多实例规格可见阿里云官方页面。
182 1
|
2月前
|
机器学习/深度学习 人工智能 调度
显著提升深度学习 GPU 利用率,阿里云拿下国际网络顶会优胜奖!
显著提升深度学习 GPU 利用率,阿里云拿下国际网络顶会优胜奖!
218 7
|
4月前
|
机器学习/深度学习 人工智能 弹性计算
阿里云GPU云服务器介绍_GPU租用费用_GPU优势和使用场景说明
阿里云GPU云服务器提供NVIDIA A10、V100、T4、P4、P100等GPU卡,结合高性能CPU,单实例计算性能高达5PFLOPS。支持多种实例规格,如A10卡GN7i、V100-16G卡GN6v等,应用于深度学习、科学计算等场景。GPU服务器租用费用因实例规格而异,如A10卡GN7i每月3213.99元起。阿里云还提供GPU加速软件如AIACC-Training、AIACC-Inference等。网络性能强大,VPC支持2400万PPS和160Gbps内网带宽。购买方式灵活,包括包年包月、按量付费等。客户案例包括深势科技、流利说和小牛翻译等。
166 4
|
4月前
|
Kubernetes Cloud Native 调度
《阿里云产品四月刊》—GPU Device-Plugin 相关操作(1)
阿里云瑶池数据库云原生化和一体化产品能力升级,多款产品更新迭代
|
4月前
|
机器学习/深度学习 人工智能 弹性计算
阿里云GPU服务器租用费用_GPU服务器详解_A10、V100、T4、P4、P100
阿里云GPU云服务器提供NVIDIA A10、V100、T4、P4、P100等多种GPU卡,适合深度学习、科学计算等场景。实例性能强劲,单实例可达5PFLOPS混合精度计算,VPC网络支持2400万PPS和160Gbps内网带宽。GPU实例包括A10卡GN7i(3213.99元/月起)、V100-16G卡GN6v(3830.00元/月起)等,价格因配置而异。阿里云还提供GPU加速软件如AIACC-Training和AIACC-Inference,以及弹性计算实例EAIS。客户案例包括深势科技、流利说和小牛翻译等。

热门文章

最新文章