显存优化 | Pytorch的显存机制torch.cuda.empty_cache及周边概念

news/2024/11/24 13:55:31/

注:文中涉及一些内部底层实现机制,可能和大家外界看到的不一样,这里略过不做介绍。借着笔记,分享平时碰到的技术点,不高端,不炫酷,对你有用更好了。

最近在做模型的优化工作,主要涉及精度,速度和显存优化,今天主要针对显存优化分享下关于Pytorch显存机制的笔记。

显存优化还涉及显存量查看,训练中显存使用分布查看,还有一些节省显存的tricks。我在这篇文章中没有体现,mentor看到文章“嫌弃”说“看的不过瘾”。大佬的视角果然要求高🤷‍♀️。

我只能弱弱回复:慢慢来。下次碰到其他的再分享也不迟。第一次写,瑟瑟发抖。

0x00 问题

大模型训练容易爆显存,模型训练batch size设置受限,需要短时间内解决眼前的爆炸问题。 (模型本身及数据输入都比较大)

0001 现象

bs较小时候,训练推理正常;bs增大调试过程中,当bs为某个值时,训练正常,但推理会显存爆炸;再增大bs时候,直接爆炸。

注:文中的推理,也可理解为验证或测试。

0010 猜测

  1. 模型某层申请了特别大的 tensor,可以考虑释放它的缓存。
  2. 训练过程占用了较多缓存,可以考虑推理前释放训练的缓存。

0011 方法

#释放未被使用的缓存,tensor占用的显存不会被释放
#可以减少碎片,提高利用率
torch.cuda.empty_cache() 

注:这只是一个解决的切入口,速效丸,并不是优化显存的最优/最根本方案。

0100 结果

在训练结束,推理前,加上:

 torch.cuda.empty_cache()

释放未被使用的缓存,重新分配。一定程度解决增大bs时显存爆炸问题,满足暂时需求;

更进一步增大bs的训练需要在模型本身和更底层分配机制入手。

0101 注意

非必要情况不要经常用,比如可以训练结束调用一下。

该操作会有设备同步,某些场景下会增加时间消耗,具体问题具体分析。

0110 理解

Pytorch可以自动回收我们不用的显存,类似于Python的引用机制,当某一内存内的数据不再有任何变量引用时,这部分的内存便会被释放[1]。

但有一点需要注意,当有一部分显存不再使用的时候,这部分释放的显存通过Nvidia-smi命令是看不到的,举个🌰:

device = torch.device('cuda:0')# 定义两个tensor# 120*3*512*512*4/1000/1000 = 377.48M
tensor_4 = torch.randn(120, 3, 512, 512).float().to(device)# 80*3*512*512*4/1000/1000 = 251.64M
tensor_2 = torch.randn(80, 3, 512, 512).float().to(device)  # 释放
tensor_4 = tensor_4.cpu()
tensor_2 = tensor_2.cpu()
# 这里虽然将上面的显存释放了,但是我们通过Nvidia-smi命令看到显存依然在占用torch.cuda.empty_cache()
# 只有执行完上面这句,显存才会在Nvidia-smi中释放

Pytorch的开发者也对此进行说明了,这部分释放后的显存通常可以用,只不过不在Nvidia-smi中显示。

也可以理解为释放的显存没有还给Nvidia,被Pytorch当做缓存使用。

但是缓存会有碎片,比如10个1M的tensor释放了不一定能凑成一个10M的空间。还可能有底层分配机制的原因,所以有时候分配不出来,导致空间不够用。

因此需要手动清空下,缓存清空以后就可以从Nvidia再分配。

0111 显卡和显存、GPU的关系[2]

显卡主要由PCB板、GPU、显存构成。

接触过硬件专业的同学应该比较熟悉PCB板,焊板子嘛,焊锡,电烙铁,松香…

GPU是一个附属型的处理器,主要处理计算机中与图形计算有关的工作,并将数据更好地呈现在显示器中。

在处理信息的过程中,它会产生大量的临时数据(未处的、正在处理的、已经处理完成的),这就需要一个专门的地方来存放这些临时数据,即显存。

显卡可能是一个芯片,也可能只是芯片的一部分,具体看硬件的设计,有独立显卡或者集成显卡。

1000 显存和GPU的关系[3]

显存和GPU的关系类似于内存和CPU的关系。

显存用来存放模型、数据,显存越大,所能够运行的网络就越大。

神经网络的显存占用包括但不限于:

1)模型参数的显存占用:只有有参数的层才会有显存占用,这部分的显存占用和输入无关,模型加载完之后就会占用。

有参数的层:卷积层,全连接层,BatchNorm, Embedding层等。

无参数的层:激活层sigmoid(sigmoid,relu),池化层,Dropout等

2)梯度与动量。

3)输入输出。

1001 显存和缓存的关系

GPU计算会频繁使用显存,从显卡中申请一部分显存作为缓存,用完后释放。

如果GPU每次计算都从设备分配显存,那么计算的开销较大,运行速度较慢。如果一开始分配出所有的显存,那么显存占用很高,而利用率很低。

因此有了缓存机制。Pytroch和tensorflow都有自己的缓存机制。

Tensorflow的缓存机制BFC,具体可参考:
https://blog.csdn.net/qq_33096883/article/details/77479647

关于Pytorch 的内存管理机制暂时没有看到具体的定义,后续看到再补充,现在主要涉及就是torch.cuda.empty_cache() 的使用。

附:Pytorch其他节省显存的小技巧,后续有机会实验后再来深究:
https://www.v2ex.com/amp/t/532315

参考链接:
[1]https://blog.csdn.net/qq_29007291/article/details/90451890
[2]http://ask.zol.com.cn/x/5894483.html
[3]https://blog.csdn.net/XYKenny/article/details/89003363?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-1


http://www.ppmy.cn/news/464704.html

相关文章

9. CUDA shared memory使用------GPU的革命

9. CUDA shared memory使用------GPU的革命 序言:明年就毕业了,下半年就要为以后的生活做打算。这半年,或许就是一个抉择的时候,又是到了一个要做选择的时候。或许是自己的危机意识比较强,一直都觉得自己做得不够好&a…

tensorflow释放显存

经过测试,通过sess.close释放资源并不能释放显存,导致重新建立一个session分配资源时失败。 stackoverflow上提到了两种方法: 1.利用numba库(需要安装numba库) 背后原理: Tensorflow只是为GPU分配显存&a…

GPU 显存 - Caffe 内存优化

Caffe - 显存优化 1. Caffe - memory multiloading 功能 原文 - Squeezing Memory out of Caffe Caffe 的一个优化版本 - caffe-yjxiong. 测试了一下, ResNet101 相对于官方 caffe, 能够明显节省显存占用, batchsize 可以增加很多. 显存优化的 Caffe 主要实现的功能: memor…

GPU程序缓存(GPU Program Caching)

GPU程序缓存 翻译文章: GPU Program Caching 总览 / 为什么 因为有一个沙盒, 每一次加载页面, 我们都会转化, 编译和链接它的GPU着色器. 当然不是每一个页面都需要着色器, 合成器使用了一些着色器, 这些着色器需要为tab选项卡重新渲染. 我们应该去缓存一些之前的缓存程序, 并在…

关于CPU cache

1、cache基础 简单来说&#xff0c;cache快&#xff0c;内存慢&#xff0c;硬盘更慢。 L1速度> L2速度> L3速度> RAM L1容量< L2容量< L3容量< RAM L1 Cache也被划分成指令cachaL1i (i for instruction)和数据cacheL1d (d for data)两种专门用途的缓存。…

src/storage/storage.cc: Compile with USE_CUDA=1 to enable GPU usage【MXNET GPU版】

【环境】Win10 一、想在GPU上运行MXNET&#xff0c;报错如下&#xff1a; MXNetError: [23:23:48] src/storage/storage.cc:xxx: Compile with USE_CUDA1 to enable GPU usage【原因】安装的是cpu版的mxnet&#xff0c;不是gpu版的 【解决】卸载原来cpu版本的mxnet&#xff…

Locality-Driven Dynamic GPU Cache Bypassing

文章目录 abstractintroduction问题背景内存请求处理 GPU缓存效率分析过滤器的设计decoupled 设计Decoupled L1D:operationSM Dueling 实验性能评估 abstract 本篇文章主要介绍了一个缓存优化的方法&#xff0c;这个方法专门对大吞吐量的架构&#xff0c;比如GPU应用&#xff…

SpringBoot中集成Redis

目标 在原有SpringBoot项目中&#xff0c;集成Redis&#xff0c;并实现Dao层&#xff0c;Service层&#xff0c;Controller层。 pom.xml <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</…