【已解决】探究CUDA out of memory背后原因,如何释放GPU显存?

这篇具有很好参考价值的文章主要介绍了【已解决】探究CUDA out of memory背后原因,如何释放GPU显存?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1 问题背景

研究过深度学习的同学,一定对类似下面这个CUDA显存溢出错误不陌生

RuntimeError: CUDA out of memory. Tried to allocate 916.00 MiB (GPU 0; 6.00 GiB total capacity; 4.47 GiB already allocated; 186.44 MiB free; 4.47 GiB reserved in total by PyTorch)

本文探究CUDA的内存管理机制,并总结该问题的解决办法

【已解决】探究CUDA out of memory背后原因,如何释放GPU显存?

2 问题探索

2.1 CUDA固有显存

在实验开始前,先清空环境,终端输入nvidia-smi

【已解决】探究CUDA out of memory背后原因,如何释放GPU显存?
接下来向GPU存入一个小的张量

import torch
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
torch.randn((2, 3), device=device)

占用显存情况如下,共计448M

【已解决】探究CUDA out of memory背后原因,如何释放GPU显存?
而当我们增大张量的尺寸,例如

torch.randn((200, 300, 200, 20), device=device)

此时GPU占用也随之上升,共计1362M

【已解决】探究CUDA out of memory背后原因,如何释放GPU显存?

这表明:GPU显存占用率和存入的数据尺寸成正相关,越大的数据占用显存越多,这其实是废话,但是把这句话反过来:越小的数据占用显存越小吗?做个实验

torch.randn((1, 1), device=device)

仍然占用448M

【已解决】探究CUDA out of memory背后原因,如何释放GPU显存?
事实上,这是因为CUDA运行时,其固件会占用一定的显存,在本机软硬件环境下是448M,不同的CUDA版本或显卡型号固件显存不同。换言之,只要使用了GPU,就至少会占 x x x M的显存,且这部分显存无法被释放

2.2 显存激活与失活

给出以下代码,请问哪一个会报错?

  • 代码A
    x1 = torch.randn((200, 300, 200, 20), device=device)
    x2 = torch.randn((200, 300, 200, 20), device=device)
    x3 = torch.randn((200, 300, 200, 20), device=device)
    x4 = torch.randn((200, 300, 200, 20), device=device)
    x5 = torch.randn((200, 300, 200, 20), device=device)
    x6 = torch.randn((200, 300, 200, 20), device=device)
    
  • 代码B
    x = torch.randn((200, 300, 200, 20), device=device)
    x = torch.randn((200, 300, 200, 20), device=device)
    x = torch.randn((200, 300, 200, 20), device=device)
    x = torch.randn((200, 300, 200, 20), device=device)
    x = torch.randn((200, 300, 200, 20), device=device)
    x = torch.randn((200, 300, 200, 20), device=device)
    

答案可以猜到,代码A报错了,这与CUDA显存的激活机制有关。可以把CUDA当前的数据空间看成一个队列,队列中有两种内存——激活内存(Activate Memory)和失活内存(Unactivate Memory)。当一块内存不再被变量所引用时,这块内存就由激活内存转为失活内存,但它仍然存在于这个数据队列中。

接下来,一块新的数据被添加进来,CUDA就会释放掉一部分失活内存,用于存放新的数据。如果新的数据占用空间大于队列中的所有失活内存,就会从显存再申请一部分空间添加到队列,相当于队列的容量被扩充了;如果新的数据占用空间约等于队列中的失活内存,那么CUDA显存的占用率就几乎不变

可以实验验证,运行

x = torch.randn((200, 300, 200, 20), device=device)
x = torch.randn((200, 300), device=device)

的显存占用为1364M,与单独运行

x = torch.randn((200, 300, 200, 20), device=device)

1362M相比差不多,但是新的数据占用空间大于队列中的所有失活内存时

x = torch.randn((200, 300, 200, 20), device=device)
x = torch.randn((300, 300, 300, 20), device=device)

显存占用就飙升到3422M当数据队列达到某个阈值时,CUDA会触发垃圾回收机制,清理失活内存

上述实验解释了深度学习中非常常见的代码

for images, labels in train_bar:
	images, labels = images.to(config.device), labels.to(config.device)
	# 梯度清零
	opt.zero_grad()
	# 正向传播
	outputs = model(images)
	# 计算损失
	loss = F.cross_entropy(outputs, labels)
	# 反向传播
	loss.backward()
	# 模型更新
	opt.step()

为什么能维持GPU显存不变。本质上,这就是上面代码B的执行过程。

2.3 释放GPU显存

运行下面的命令可以手动清理GPU数据队列中的失活内存

torch.cuda.empty_cache()

需要注意的是,上述命令可能要运行多次才会释放空间,比如

x = torch.randn((200, 300, 200, 20), device=device)
x = torch.randn((200, 300, 200, 20), device=device)
x = torch.randn((200, 300, 200, 20), device=device)
x = torch.randn((200, 300, 200, 20), device=device)
x = torch.randn((200, 300, 200, 20), device=device)
x = torch.randn((200, 300, 200, 20), device=device)
x = 1

此时x指向了int型,所以GPU数据队列中的空间均未被变量引用,说明队列中全部都是失活内存,但此时运行nvidia-smi仍有2278M的占用,进一步运行torch.cuda.empty_cache()后即可恢复到448M的基础占用——虽然现在没有数据在GPU上,但固件已经开始运行,因此占用无法被释放。

3 问题总结

关于CUDA GPU显存管理的总结:

  • GPU显存占用率和存入的数据尺寸成正相关,越大的数据占用显存越多
  • 只要使用了GPU,就至少会占 x x x M的显存,且这部分显存无法被释放
  • 当一块内存不再被变量所引用时,这块内存就由激活内存转为失活内存,但它仍然存在于这个数据队列中
  • 当数据队列达到某个阈值时,CUDA会触发垃圾回收机制,清理失活内存
  • 运行torch.cuda.empty_cache()可以手动清理失活内存

那么根据上述理论,就可以得到对应的问题解决方案

  • 调小batch_size

    本质上是防止GPU数据队列向显存申请的空间大于显存本身

  • 检查是否有数据持续存入GPU而未释放

    举个例子:

    app = []
    for _ in range(1000):
    	app.append(torch.randn((200, 300, 200, 20), device=device))
    

    这里append函数相当于获得张量torch.randn((200, 300, 200, 20), device=device)的拷贝存入列表,因此每次存入的张量都会被隐式地引用,GPU持续地增加激活内存而不被释放,导致崩溃。

  • 训练过程中的测试阶段和验证阶段前插入代码with torch.no_grad()

    原理是不计算梯度,从而不用GPU加速运算,不会把数据再加到数据队列中

4 告别Bug

本文收录于《告别Bug》专栏,该专栏记录人工智能领域中各类Bug以备复查,文章形式为:问题背景 + 问题探索 + 问题解决,订阅专栏+关注博主后可通过下方名片联系我进入AI技术交流群帮忙解决问题


🔥 更多精彩专栏文章来源地址https://www.toymoban.com/news/detail-419579.html

  • 《ROS从入门到精通》
  • 《Pytorch深度学习实战》
  • 《机器学习强基计划》
  • 《运动规划实战精讲》

👇源码获取 · 技术交流 · 抱团学习 · 咨询分享 请联系👇

到了这里,关于【已解决】探究CUDA out of memory背后原因,如何释放GPU显存?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • CUDA报错:Out of Memory

    如果报错里提示Pytorch reserved的内存远大于Already allocated的内存,那么就是因为分配显存时单位过大,导致出现大量内存碎片无法继续分配(与操作系统内存管理同理)。 我们可以限制一次分配的最大单位来解决这个问题。 随后代码便可正常运行了。

    2024年02月15日
    浏览(48)
  • torch.cuda.OutOfMemoryError: CUDA out of memory.

    训练清华ChatGLM-6B时报错, 原因是显存不够 torch.cuda.OutOfMemoryError: CUDA out of memory. Tried to allocate 96.00 MiB (GPU 0; 23.70 GiB total capacity; 4.37 GiB already allocated; 64.81 MiB free; 4.37 GiB reserved in total by PyTorch) If reserved memory is allocated memory try setting max_split_size_mb to avoid fragmentation.  See documentatio

    2024年02月06日
    浏览(36)
  • Pycharm报错torch.cuda.OutOfMemoryError: CUDA out of memory.

    报错 做深度学习相关的实验,可以看到我的显卡内存很小(哭了,不过我有时候是在别的电脑上做的,那个电脑比这个好用),网上搜到的说的 max_split_size_mb:128 这个方法我贴到我代码上之后没有效果。 因为我在这个电脑上做的是主实验后面的一些对比实验,也就是代码中很

    2024年02月05日
    浏览(35)
  • 【CUDA OUT OF MEMORY】【Pytorch】计算图与CUDA OOM

    在实践过程中多次碰到了CUDA OOM的问题,有时候这个问题是很好解决的,有时候DEBUG一整天还是头皮发麻。 最近实践对由于计算图积累导致CUDA OOM有一点新的看法,写下来记录一下。 包括对计算图的一些看法和一个由于计算图引发错误的简化实例记录。 本人能力有限,认识片

    2024年02月09日
    浏览(28)
  • 部署stable diffusion 错误torch.cuda.OutOfMemoryError: CUDA out of memory.

    以来安装完毕,开始执行web_ui.bat 错误截图:  猜测原因:GPU用错了 webUI.py加一行代码 在此启动web_ui.bat,成功打开网页页面

    2024年02月11日
    浏览(38)
  • 解决:RuntimeError: CUDA out of memory. Tried to allocate 160.00 MiB (GPU 0; 10.76 GiB total capacity..

    完整报错:   问题分析: 内存分配不足: 需要160MB,,但GPU只剩下135.31MB。 解决办法: 1.减小batch_size。注意batchsize的调整要配合学习率的调整,一般是正比关系,BS增大两倍,LR增大两倍或者根号二倍。减小也是相应更改。 2.运行torch.cuda.empty_cache()函数。加在训练开始前即可

    2024年02月16日
    浏览(34)
  • RuntimeError: CUDA out of memory See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF

    报错: If reserved memory is allocated memory try setting max_split_size_mb to avoid fragmentation. See documentation for Memory Management and PYTORCH_CUDA_ALLOC_CONF 当reserved memory is allocated memory,进行如下设置,可解决此bug: 代码如下:

    2024年02月11日
    浏览(42)
  • Stable Diffusion WebUI内存不够爆CUDA Out of memory怎么办?

    在我们运行SD的时候,我们经常会爆CUDA Out of memory。 我们应该怎么办呢? 这是因为我们的显存或者内存不够了。 如果你是用cpu来跑图的则表示内存不够,这个时候就需要换个大点的内存了。 如果你是用gpu来跑图的就说明你显存不够用咯,这时候咋办呢? 下面我将一一述说解

    2024年02月08日
    浏览(109)
  • RuntimeError:CUDA out of memory.Tried to allocate 20.00MiB.

    这是我遇到的问题,刚开始的时候怎么也解决不了。 然后我去搜了一下解决方法,具体方法如下: 方法一: 仅需减小batchsize 改文件的配置cfg的batchsize=1,一般在cfg文件下的查找batch或batchsize,将batchsize调小后,再次运行,类似于改下面 方法二 :  上述方法还没解决,不改

    2023年04月11日
    浏览(31)
  • Stable Diffusion WebUI rtx 2060 6G 高清修复 爆显存torch.cuda.OutOfMemoryError: CUDA out of memory.

    故障日志 零食解决办法,重启webui.sh进程,重新执行生成图片 日志   确实清晰不少 

    2024年02月04日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包