CNN卷积神经网络模型的GPU显存占用分析

news2025/7/22 21:48:26

一、参考资料

浅谈深度学习:如何计算模型以及中间变量的显存占用大小
如何在Pytorch中精细化利用显存

二、相关介绍

0. 预备知识

为了方便计算,本文按照以下标准进行单位换算

  • 1 G = 1000 MB
  • 1 M = 1000 KB
  • 1 K = 1000 Byte
  • 1 B = 8 bit

1. 模型参数量的计算方法

参考博客:CNN卷积神经网络模型的参数量、计算量计算方法(概念版)

2. 张量的数据类型

Data typedtypeCPU tensorGPU tensor
32-bit floating pointtorch.float32 or torch.floattorch.FloatTensortorch.cuda.FloatTensor
64-bit floating pointtorch.float64 or torch.doubletorch.DoubleTensortorch.cuda.DoubleTensor
16-bit floating pointtorch.float16 or torch.halftorch.HalfTensortorch.cuda.HalfTensor
8-bit integer (unsigned)torch.uint8torch.ByteTensortorch.cuda.ByteTensor
8-bit integer (signed)torch.int8torch.CharTensortorch.cuda.CharTensor
16-bit integer (signed)torch.int16 or torch.shorttorch.ShortTensortorch.cuda.ShartTensor
32-bit integer (signed)torch.int32 or torch.inttorch.IntTensortorch.cuda.IntTensor
64-bit integer (signed)torch.int64 or torch.longtorch.LongTensortorch.cuda.LongTensor

通常,模型训练使用以下两种数据类型:

  • float32 单精度浮点型;
  • int32 整型。

8bit的整型int所占的空间为 1B32bit的浮点型float所占空间为 4B。而double双精度浮点型和长整型long在平常的模型训练中一般不会使用。

消费级显卡对单精度计算有优化,服务器级显卡对双精度计算有优化

3. 关于inplace=False

我们都知道激活函数Relu()有一个默认参数inplace,默认设置为False。当设置为True时,我们在通过relu()计算得到的新值不会占用新的空间,而是直接覆盖原来的值,这也就是为什么当inplace参数设置为True时可以节省一部分内存的缘故。
在这里插入图片描述

三、显存占用相关介绍

0. 引言

torch.FatalError: cuda runtime error (2) : out of memory at /opt/conda/conda-bld/pytorch_1524590031827/work/aten/src/THC/generic/THCStorage.cu:58

由于显存不足,导致程序崩溃。学会计算模型以及中间变量所占显存大小,是很有必要的。

1. 图片的显存占用

假设一张RGB三通道真彩色图片,长宽分别为 500x500,数据类型为单精度浮点型,那么这张图片所占显存的大小为:500x500x3x4B=3MB。而一个 (256, 3, 100, 100)-(N, C, H, W) 的FloatTensor所占的空间为:256x3x100x100x4B = 31MB

2. 模型的显存占用

通常,模型占用的显存来自两个部分:

  • 模型自身的参数(params),即有参数的网络层。
  • 模型在计算时产生的中间参数(memory)
    在这里插入图片描述

一般来说,模型自身参数并不会占用很多的显存空间,主要占用显存空间的是计算时产生的中间参数

2.1 模型自身的参数(params)

有参数的网络层,包括:

  • 卷积层Conv2d(Cin, Cout, K),参数量为 Cin × Cout × K × K
  • 全连接层Linear(M->N),参数量为 M×N
  • BatchNorm层BatchNorm(N),参数量为 2N
  • Embedding层Embedding(N,W),参数量为 N × W

不带参数的网络层,包括:

  • 激活层Relu等;
  • 池化层;
  • Dropout层;

2.2 模型的中间参数(memory)

  • 模型在计算时产生的中间参数,也就是输入图像在计算时每一层产生的输入和输出;
  • backward反向传播计算时产生的额外的中间参数;
  • 优化器在优化时产生的额外的模型参数。

3. 实际显存与理论显存

为什么实际占用的显存空间比理论计算的大?
大概原因是深度学习框架一些额外的开销。不过,通过上面公式计算出来的显存理论值和实际值不会相差太多。

4. 计算显存占用大小

4.1 方法一(推荐)

使用 torchstat 工具,计算模型的显存占用大小。参考博客:CNN卷积神经网络模型的参数量计算方法(经验版)

4.2 方法二

当然,也可以自定义函数计算显存占用大小,代码如下所示:

# 模型显存占用监测函数
# model:输入的模型
# input:实际中需要输入的Tensor变量
# type_size 默认为 4 默认类型为 float32 

def modelsize(model, input, type_size=4):
    para = sum([np.prod(list(p.size())) for p in model.parameters()])
    print('Model {} : params: {:4f}M'.format(model._get_name(), para * type_size / 1000 / 1000))

    input_ = input.clone()
    input_.requires_grad_(requires_grad=False)

    mods = list(model.modules())
    out_sizes = []

    for i in range(1, len(mods)):
        m = mods[i]
        if isinstance(m, nn.ReLU):
            if m.inplace:
                continue
        out = m(input_)
        out_sizes.append(np.array(out.size()))
        input_ = out

    total_nums = 0
    for i in range(len(out_sizes)):
        s = out_sizes[i]
        nums = np.prod(np.array(s))
        total_nums += nums


    print('Model {} : intermedite variables: {:3f} M (without backward)'
          .format(model._get_name(), total_nums * type_size / 1000 / 1000))
    print('Model {} : intermedite variables: {:3f} M (with backward)'
          .format(model._get_name(), total_nums * type_size*2 / 1000 / 1000))

重要说明:当然,我们计算出来的显存占用理论值仅仅是做参考作用,因为Pytorch在运行的时候需要额外的显存开销,所以实际的显存会比我们计算的稍微大一些。

5. 显存优化方法

在Pytorch中优化显存是我们处理大量数据时必要的做法,因为我们并不可能拥有无限的显存。显存是有限的,而数据是无限的,我们只有优化显存的使用量才能够最大化地利用我们的数据。

优化除了算法层的优化,最基本的显存优化无非也就以下几点:

  • 减少输入图像的尺寸;
  • 减少batch,减少每次的输入图像数量;
  • 多使用下采样,池化层;
  • 一些神经网络层可以进行小优化,利用relu层中设置inplace
  • 购买显存更大的显卡;
  • 从深度学习框架上面进行优化。

5.1 牺牲计算速度减少显存使用量

在PyTorch中,如果一个模型占用的显存太大了,可以将一个计算过程分成两半,先计算前一半,保存后一半需要的中间结果,然后再计算后一半。

# 首先设置输入的input=>requires_grad=True
# 如果不设置可能会导致得到的gradient为0

# 输入
input = torch.rand(1, 10, requires_grad=True)

# 假设我们有一个非常深的网络
layers = [nn.Linear(10, 10) for _ in range(1000)]


# 定义要计算的层函数,可以看到我们定义了两个
# 一个计算前500个层,另一个计算后500个层

def run_first_half(*args):
    x = args[0]
    for layer in layers[:500]:
        x = layer(x)
    return x

def run_second_half(*args):
    x = args[0]
    for layer in layers[500:-1]:
        x = layer(x)
    return x

# 我们引入新加的checkpoint
from torch.utils.checkpoint import checkpoint

x = checkpoint(run_first_half, input)
x = checkpoint(run_second_half, x)

# 最后一层单独调出来执行
x = layers[-1](x)
x.sum.backward() 

对于Sequential-model来说,因为Sequential()中可以包含很多的block,所以官方提供了另一个功能包:

input = torch.rand(1, 10, requires_grad=True)
layers = [nn.Linear(10, 10) for _ in range(1000)]
model = nn.Sequential(*layers)

from torch.utils.checkpoint import checkpoint_sequential

# 分成两个部分
num_segments = 2
x = checkpoint_sequential(model, num_segments, input)
x.sum().backward()  

6. 跟踪显存使用情况

再次浅谈Pytorch中的显存利用问题(附完善显存跟踪代码)

我们借用 Pytorch-Memory-Utils 这个工具来检测我们在训练过程中关于显存的变化情况,分析出我们如何正确释放多余的显存。

通过Pytorch-Memory-Utils工具,我们在使用显存的代码中间插入检测函数,就可以输出类似于下面的信息,At __main__ <module>: line 13 Total Used Memory:696.5 Mb表示在当前行代码时所占用的显存,即在我们的代码中执行到13行的时候所占显存为695.5Mb。At __main__ <module>: line 15 Total Used Memory:1142.0 Mb表示程序执行到15行时所占的显存为1142.0Mb。两条数据之间表示所占显存的tensor变量。

# 12-Sep-18-21:48:45-gpu_mem_track.txt

GPU Memory Track | 12-Sep-18-21:48:45 | Total Used Memory:696.5  Mb

At __main__ <module>: line 13                        Total Used Memory:696.5  Mb

+ | 7 * Size:(512, 512, 3, 3)     | Memory: 66.060 M | <class 'torch.nn.parameter.Parameter'>
+ | 1 * Size:(512, 256, 3, 3)     | Memory: 4.7185 M | <class 'torch.nn.parameter.Parameter'>
+ | 1 * Size:(64, 64, 3, 3)       | Memory: 0.1474 M | <class 'torch.nn.parameter.Parameter'>
+ | 1 * Size:(128, 64, 3, 3)      | Memory: 0.2949 M | <class 'torch.nn.parameter.Parameter'>
+ | 1 * Size:(128, 128, 3, 3)     | Memory: 0.5898 M | <class 'torch.nn.parameter.Parameter'>
+ | 8 * Size:(512,)               | Memory: 0.0163 M | <class 'torch.nn.parameter.Parameter'>
+ | 3 * Size:(256, 256, 3, 3)     | Memory: 7.0778 M | <class 'torch.nn.parameter.Parameter'>
+ | 1 * Size:(256, 128, 3, 3)     | Memory: 1.1796 M | <class 'torch.nn.parameter.Parameter'>
+ | 2 * Size:(64,)                | Memory: 0.0005 M | <class 'torch.nn.parameter.Parameter'>
+ | 4 * Size:(256,)               | Memory: 0.0040 M | <class 'torch.nn.parameter.Parameter'>
+ | 2 * Size:(128,)               | Memory: 0.0010 M | <class 'torch.nn.parameter.Parameter'>
+ | 1 * Size:(64, 3, 3, 3)        | Memory: 0.0069 M | <class 'torch.nn.parameter.Parameter'>

At __main__ <module>: line 15                        Total Used Memory:1142.0 Mb

+ | 1 * Size:(60, 3, 512, 512)    | Memory: 188.74 M | <class 'torch.Tensor'>
+ | 1 * Size:(30, 3, 512, 512)    | Memory: 94.371 M | <class 'torch.Tensor'>
+ | 1 * Size:(40, 3, 512, 512)    | Memory: 125.82 M | <class 'torch.Tensor'>

At __main__ <module>: line 21                        Total Used Memory:1550.9 Mb

+ | 1 * Size:(120, 3, 512, 512)   | Memory: 377.48 M | <class 'torch.Tensor'>
+ | 1 * Size:(80, 3, 512, 512)    | Memory: 251.65 M | <class 'torch.Tensor'>

At __main__ <module>: line 26                        Total Used Memory:2180.1 Mb

- | 1 * Size:(120, 3, 512, 512)   | Memory: 377.48 M | <class 'torch.Tensor'> 
- | 1 * Size:(40, 3, 512, 512)    | Memory: 125.82 M | <class 'torch.Tensor'> 

At __main__ <module>: line 32                        Total Used Memory:1676.8 Mb

当然这个检测工具不仅适用于Pytorch,其他的深度学习框架也同样适用,不过需要注意下静态图和动态图在实际运行过程中的区别。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1157040.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于构件的开发(CBD)

基于构件的开发&#xff08;Component-Based Development&#xff0c;简称CBD&#xff09;或基于构件的软件工程&#xff08;Component-Based Software Engineering&#xff0c;简称CBSE&#xff09;是一种软件开发新范型&#xff0c;它是在一定构件模型的支持下&#xff0c;复…

FPGA与ASIC有什么差异?二者该如何选用?

前言 对于一个数字电路的新手来说&#xff0c;这可能是会经常遇到的一个问题&#xff1a;FPGA和ASIC之间的区别是什么? 接下来本文将尝试讲解 “什么是FPGA&#xff1f;” 和 “什么是ASIC&#xff1f;”&#xff0c;然后讲述一些关于FPGA和ASIC的问题&#xff0c;例如它们之间…

【【FIFO to multiplier to RAM的 verilog 代码 和 testbnench 】】

FIFO to multiplier to RAM的 verilog 代码 和 testbnench 只完成了单个数据的传输 大数据需要修改 tb 或者基本连线 FIFO.v //synchronous fifo module FIFO_syn #(parameter WIDTH 16, // the fifo wideparameter DEPTH 1024, …

【MATLAB】全网唯一的7种信号分解+ARIMA联合的时序预测算法全家桶

有意向获取代码&#xff0c;请转文末观看代码获取方式~ 大家吃一顿火锅的价格便可以拥有7种信号分解ARIMA组合的时序预测算法&#xff0c;绝对不亏&#xff0c;知识付费是现今时代的趋势&#xff0c;而且都是我精心制作的教程&#xff0c;有问题可随时反馈~也可单独获取某一算…

【三方登录-Apple】iOS 苹果授权登录(sign in with Apple)之开发者配置一

记录一下sign in with Apple的开发者配置 前言 关于使用 Apple 登录 使用“通过 Apple 登录”可让用户设置帐户并使用其Apple ID登录您的应用程序和关联网站。首先使用“使用 Apple 登录”功能启用应用程序的App ID 。 如果您是首次启用应用程序 ID 或为新应用程序启用应用程序…

加速计算卡设计方案:389-基于KU5P的双路100G光纤网络加速计算卡

基于KU5P的双路100G光纤网络加速计算卡 一、板卡概述 基于Xilinx UltraScale16 nm KU5P芯片方案基础上研发的一款双口100 G FPGA光纤以太网PCI-Express v3.0 x8智能加速计算卡&#xff0c;该智能卡拥有高吞吐量、低延时的网络处理能力以及辅助CPU进行网络功能卸载的能力…

SpringBoot配置文件yml文件基础知识

yaml简介 YAML&#xff08;YAML Aint Markup Language&#xff09;&#xff0c;一种数据序列化格式 优点&#xff1a;容易阅读容易与脚本语言交互以数据为核心&#xff0c;重数据轻格式 YAML文件扩展名.yml&#xff08;主流&#xff09;.yamlyaml语法规则 大小写敏感 属性层级…

10.1 am62x平台怎么从ospi启动uboot

本文主要内容: 1 背景(硬件原理图与分区信息) 2 AM62x平台bootloader组成 3 设置SK-AM62B启动方式 4 烧录镜像到OSPI分区 5 解决Message not acknowledgedAuthentication failed!问题 1 背景 Ti的SK-AM62B评估板,通过OSPI接口,连接了一个Nor Flash:S28HS512TGABHM01…

聊天室系统源码 匿名聊天系统源码 在线聊天室系统源码 可发语音 图片 适用PC+WAP

PHP匿名在线聊天室系统源码&#xff0c;适用于PC和WAP端&#xff0c;支持语音和图片传输 通过修改数据库config\settings.php&#xff0c;可以将其用于搭建客户聊天专用的网站 要搭建一个专门用于与客户聊天的网站&#xff0c;您可以使用这个PHP匿名在线聊天室系统源码 该源码…

一文带你速通Sentinel限流规则(流控)解读

目录 前置知识速补 基本介绍 流控模式 直接模式 关联模式 链路模式 流控效果 直接失败 Warm Up&#xff08;预热&#xff09; 排队等待 前置知识速补 QPS每秒查询率(Query Per Second)&#xff1a;每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多…

基于阿基米德优化算法的无人机航迹规划-附代码

基于阿基米德优化算法的无人机航迹规划 文章目录 基于阿基米德优化算法的无人机航迹规划1.阿基米德优化搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用阿基米德优化算法来优化无…

综合实验案例配置

目录 核心交换机与出口路由器的连接 网络出口的配置 策略路由的配置 1.教学楼的流量走电信出口&#xff0c;宿舍楼流量走联通出口&#xff08;基于源&#xff09; 2.访问带内心的服务器走电信出口&#xff0c;访问联通服务器走联通出口 案例图如下&#xff1a; acsw的配置…

二叉树问题——平衡二叉树问题

摘要 本博文主要介绍平衡二叉树问题包括&#xff0c;二叉树的高度差&#xff0c;是否为平衡二叉树&#xff0c;有序链表转二叉搜索树&#xff0c;将二叉搜索树变平衡等。 一、平衡二叉树详解 1.1 判断二叉树是否平衡 /*** Definition for a binary tree node.* public class…

一篇博客读懂顺序表 —— Sequence-List

目录 一、顺序表的初始定义 1.1新建头文件和源文件 1.2 SeqList.h 中的准备工作 二、顺序表的初始化与销毁 三、首尾插入元素 四、首尾删除元素 五、中间插入元素 六、中间删除元素 七、查找指定元素下标 八、源代码 一、顺序表的初始定义 1.1新建头文件和源文件 当我…

zip2john 爆破zip工具

1.使用zip2john工具输出zip文件hash Zip2john 1.zip > 1.txt 2.使用john工具进行zip文件爆破 John 1.txt 如图所示&#xff1a; 该zip密码为19950101

面向Three.js开发者的3D自动纹理化开发包

DreamTexture.js 是面向 three.js 开发者的 3D 模型纹理自动生成与设置开发包&#xff0c;可以为 webGL 应用增加 3D 模型的快速自动纹理化能力。 图一为原始模型, 图二图三为贴图后的模型。提示词&#xff1a; city, Realistic , cinematic , Front view ,Game scene graph 1、…

鸿蒙实现类似于安卓的Handler,鸿蒙的延迟和异步操作

在安卓开发的时候我们想要去延迟处理一些事情可以通过 Handler 解决&#xff0c;比如一秒后处理某些事情&#xff1a; new Handler().postDelayed(new Runnable() {Overridepublic void run() {} },1000);鸿蒙也提供了类似的方法&#xff0c;如下: getUITaskDispatcher().del…

C#,数值计算——积分方程与逆理论Fred2的计算方法与源程序

1 文本格式 using System; namespace Legalsoft.Truffer { public abstract class Fred2 { public readonly double a; public readonly double b; public readonly int n; public double[] t; public double[] f; …

ABBYY16最新pdf文档转换图片、Word、Excel和PPT工具

欢迎来到 ABBYY 软件下载中心&#xff0c;FineReader PDF使专业人员能够最大程度地提高数字工作场所的效率。帮助信息工作者轻松地在同一工作流程中对各种文档进行数字化、检索、编辑、加密、共享和协作。 可以对pdf文档进行各种格式转换&#xff0c;任意转换为图片、Word、Ex…

代码版本控制工具GitLab :从安装到使用一步到位

一、GitLab 是什么&#xff1f; 如果听说过 Git 或者 GitHub&#xff0c;那么 GitLab 你一定也听说过。GitLab 是一个用于仓库管理系统的开源项目&#xff0c;使用 Git 作为代码管理工具&#xff0c;并在此基础上搭建起来的 Web 服务。简单理解&#xff1a;GitLab 类似私人版 …