【已解决】RuntimeError: CUDA out of memory. Tried to allocate 50.00 MiB (GPU 0; 4.00 GiB total capacity;

问题分析

        具体描述如下

RuntimeError: CUDA out of memory. Tried to allocate 50.00 MiB (GPU 0; 4.00 GiB total capacity; 682.90 MiB already allocated; 1.62 GiB free; 768.00 MiB reserved in total by PyTorch) 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

        也有类似的情况,而且重合度还很高

原因分析及解决办法

         这种问题,是GPU内存不够引起的解决可以参考下文:

        1、调小batch_size可以解决

        建议成倍调小,直到可以运行为止

        2、定时清内存,

        比如:

import torch, gc

gc.collect()
torch.cuda.empty_cache()
        3、该段程序不计算参数梯度,加这个代码就可以了
with torch.no_grad():
     for batch in tqdm(dataloader):
        4、 如果还没解决就查看代码中是否存在一下代码
        4.1、改进方法

        (通常出现在main.py 或者数据加载的py文件中:

kwargs = {'num_workers': 6, 'pin_memory': True} if torch.cuda.is_available() else {}

        改成false就可以了。

        4.2、原因分析(参数解析)

pin_memory就是锁页内存,创建DataLoader时,设置pin_memory=True,则意味着生成的Tensor数据最开始是属于内存中的锁页内存,这样将内存的Tensor转义到GPU的显存就会更快一些。
主机中的内存,有两种存在方式,一是锁页,二是不锁页,锁页内存存放的内容在任何情况下都不会与主机的虚拟内存进行交换(注:虚拟内存就是硬盘),而不锁页内存在主机内存不足时,数据会存放在虚拟内存中。显卡中的显存全部是锁页内存,当计算机的内存充足的时候,可以设置pin_memory=True。当系统卡住,或者交换内存使用过多的时候,设置pin_memory=False。因为pin_memory与电脑硬件性能有关,pytorch开发者不能确保每一个炼丹玩家都有高端设备,因此pin_memory默认为False。
————————————————
版权声明:本文为CSDN博主「xiyou__」的原创文章

还有一些其他的解决办法

        看了这部分内容,我只能说是好建议

延展阅读

        1、batchsize这个调整办法还是值得深究

        2、其他研究

        torch有时候跑着跑着显存吃满了,就会报错: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)

        这种情况怎么办呢?总结一下排查错误的方法。

        看一下显存是不是真的满了。有可能机子上有多张卡,用nvidia-smi看一下有几张卡。这个指令只能输出当前时刻的显存占用。所以题主一般用动态追踪的方式。输入指令:watch -n 1 nvidia-smi这样终端里就会每一秒更新一下显卡状态,如果想更快一点也可以把1换成0.5之类的。输出如下所示。可以看到这个机子有两张A5000,第一张卡显存是23953MiB / 24564MiB,快用完了,第二张是 18372MiB / 24564MiB,还有一点可以用

+-----------------------------------------------------------------------------+
| NVIDIA-SMI 515.65.01    Driver Version: 515.65.01    CUDA Version: 11.7     |
|-------------------------------+----------------------+----------------------+
| GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC |
| Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. |
|                               |                      |               MIG M. |
|===============================+======================+======================|
|   0  NVIDIA RTX A5000    Off  | 00000000:17:00.0 Off |                  Off |
| 51%   67C    P2   111W / 230W |  23953MiB / 24564MiB |     68%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+
|   1  NVIDIA RTX A5000    Off  | 00000000:65:00.0 Off |                  Off |
| 60%   78C    P2   106W / 230W |  18372MiB / 24564MiB |     27%      Default |
|                               |                      |                  N/A |
+-------------------------------+----------------------+----------------------+

+-----------------------------------------------------------------------------+
| Processes:                                                                  |
|  GPU   GI   CI        PID   Type   Process name                  GPU Memory |
|        ID   ID                                                   Usage      |
|=============================================================================|
|    0   N/A  N/A     13291      G   /usr/lib/xorg/Xorg                  4MiB |
|    0   N/A  N/A     13998      G   /usr/lib/xorg/Xorg                  4MiB |
|    0   N/A  N/A     20176      C   python                           7977MiB |
|    0   N/A  N/A     20407      C   python                           7977MiB |
|    0   N/A  N/A     20693      C   python                           7977MiB |
|    0   N/A  N/A     25065      G   /usr/lib/xorg/Xorg                  4MiB |
|    0   N/A  N/A     25369      G   /usr/lib/xorg/Xorg                  4MiB |
|    1   N/A  N/A     13291      G   /usr/lib/xorg/Xorg                 15MiB |
|    1   N/A  N/A     13386      G   /usr/bin/gnome-shell              108MiB |
|    1   N/A  N/A     13998      G   /usr/lib/xorg/Xorg                194MiB |
|    1   N/A  N/A     14085      G   /usr/bin/gnome-shell               82MiB |
|    1   N/A  N/A     14979      G   /usr/lib/firefox/firefox            6MiB |
|    1   N/A  N/A     19570      C   python                           1849MiB |
|    1   N/A  N/A     20200      G   gnome-control-center               27MiB |
|    1   N/A  N/A     20830      C   python                           7977MiB |
|    1   N/A  N/A     23158      C   python                           7977MiB |
|    1   N/A  N/A     25065      G   /usr/lib/xorg/Xorg                 39MiB |
|    1   N/A  N/A     25090      G   /usr/bin/gnome-shell               12MiB |
|    1   N/A  N/A     25369      G   /usr/lib/xorg/Xorg                 16MiB |
|    1   N/A  N/A     25455      G   /usr/bin/gnome-shell               58MiB |
+-----------------------------------------------------------------------------+

        既然第二张卡还剩一些显存,为什么跑代码后还是报错RuntimeError: CUDA out of memory.呢?首先要确保你的代码跑起来之后是第二张卡能塞下的。比如我的程序只占用2000MiB,理论上第二张卡一定是可以塞下的,这个时候报错那就有可能默认放到第一张卡上去了。解决方法是指定用一张卡,一般我会在命令行指定卡,而不是代码里。在原本的命令前加上CUDA_VISIBLE_DEVICES=1就好了。

CUDA_VISIBLE_DEVICES=1  python main.py

        如果上面都检查过了,那有可能就是代码问题了。我debug的思路是每次注释掉一部分代码,再用watch -n 1 nvidia-smi这个指令观察显存有没有爆炸,以此定位导致显存爆炸的代码。代码问题就多种多样了,举一些常见例子。

        3、代码中常见例子 
        3.1 batch_size太大了。

到了要检查代码这一步首先是看batch_size,但如果batch_size太大了应该是一个epoch都跑不了,在前向传播的时候甚至前向传播之前就会出问题了。所以如果代码是一次前向传播都无法完成,应该首先排查batch_size.

        3.2 优化器没有step。

这会导致training跑了一些iteration以后才显存爆炸。optimizer.step()这行如果漏掉了的话梯度会一直累积,显存一直不被释放。

        3.3 把一个cuda上的tensor和一个常量做运算。

这种情况一般也是会导致跑了一些iteration以后才显存爆炸。两个不同设备上的tensor运算,这个错误一般torch会报错的,但是也有非常隐晦的情况,比如不指明在哪个设备上的常量,需要手动发现。你得到的结果其实是在cuda上的,如:

>>> a = torch.Tensor(1).cuda()	
	# 顺便一提 如果要给a赋值1应该是a = torch.Tensor([1]).cuda(),不加中括号赋值是错的
>>> a == 1
tensor([False], device='cuda:0')

        这个时候应该妥善处理结果!如果得到的tensor没有被赋给一个变量,可能会一直放在显存里无法释放。我一般直接移到cpu上运算。

        3.4 需要存下一些cuda tensor的情况

这种情况一般会导致显存占用比较大,有可能导致显存爆炸。比如

 outs = [out.cpu() for out in outs]
 all_outs = torch.cat([all_outs.cpu(),torch.stack(outs).cpu()],dim=1)

这种情况我明明已经把outs这个list里面的每个tensor全部移到cpu,还是会占用很大显存。因为这是在inference时候的代码,我后续不需要它的梯度,解决方法是把梯度detach掉:

outs = [out.detach().cpu() for out in outs]
all_outs = torch.cat([all_outs.cpu(),torch.stack(outs).cpu()],dim=1)

这样就不占显存啦~~

————————————————
版权声明:本文为CSDN博主「盒盒HH」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44935658/article/details/133704723

完结撒花 

        我们不能说为了谁放弃自己,而是要为了谁提升自己

模型推理中出现"RuntimeError: CUDA out of memory"错误是因为在GPU上使用的显存不足。这个错误通常发生在模型的输入数据量过大或模型占用的显存资源过多时。 解决这个问题可以采用以下方法: 1. 减少批处理大小:可以通过减少每次推理时的图像批处理大小来减少内存消耗。较小的批处理大小会减少每个批处理所需的显存量。 2. 减少模型的参数量:如果模型的参数量过大,可以尝试减少参数量来缓解显存不足的问题。可以通过减少模型的深度、宽度或者使用降低维度的技术(如降低卷积核的尺寸)来减少参数量。 3. 使用更高效的模型:可以考虑使用比原始模型更加轻量级和高效的模型结构。例如,可以使用MobileNet、EfficientNet等模型来代替较重的ResNet、VGG等模型。 4. 降低精度:可以尝试将模型的参数精度从32位浮点数降低为16位浮点数,以减少显存的使用量。这通常不会对模型的性能产生显著的影响,但会大幅度减少显存的使用。 5. 使用更大的显存:如果以上方法无法解决问题,可以考虑更换具有更大显存容量的GPU设备来运行模型推理。 总之,修复"RuntimeError: CUDA out of memory"错误的主要思路是通过减少模型参数量、降低精度、优化模型结构或减少输入数据量来减少GPU显存的使用。根据具体问题情况选择适当的解决方法,以确保模型能够在GPU上正常运行。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值