赞
踩
具体描述如下
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内存不够引起的解决可以参考下文:
建议成倍调小,直到可以运行为止
比如:
- import torch, gc
-
- gc.collect()
- torch.cuda.empty_cache()
- with torch.no_grad():
- for batch in tqdm(dataloader):
(通常出现在main.py 或者数据加载的py文件中:
kwargs = {'num_workers': 6, 'pin_memory': True} if torch.cuda.is_available() else {}
改成false就可以了。
pin_memory就是锁页内存,创建DataLoader时,设置pin_memory=True,则意味着生成的Tensor数据最开始是属于内存中的锁页内存,这样将内存的Tensor转义到GPU的显存就会更快一些。
主机中的内存,有两种存在方式,一是锁页,二是不锁页,锁页内存存放的内容在任何情况下都不会与主机的虚拟内存进行交换(注:虚拟内存就是硬盘),而不锁页内存在主机内存不足时,数据会存放在虚拟内存中。显卡中的显存全部是锁页内存,当计算机的内存充足的时候,可以设置pin_memory=True。当系统卡住,或者交换内存使用过多的时候,设置pin_memory=False。因为pin_memory与电脑硬件性能有关,pytorch开发者不能确保每一个炼丹玩家都有高端设备,因此pin_memory默认为False。
————————————————
版权声明:本文为CSDN博主「xiyou__」的原创文章
看了这部分内容,我只能说是好建议
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这个指令观察显存有没有爆炸,以此定位导致显存爆炸的代码。代码问题就多种多样了,举一些常见例子。
到了要检查代码这一步首先是看batch_size,但如果batch_size太大了应该是一个epoch都跑不了,在前向传播的时候甚至前向传播之前就会出问题了。所以如果代码是一次前向传播都无法完成,应该首先排查batch_size.
这会导致training跑了一些iteration以后才显存爆炸。optimizer.step()这行如果漏掉了的话梯度会一直累积,显存一直不被释放。
这种情况一般也是会导致跑了一些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上运算。
这种情况一般会导致显存占用比较大,有可能导致显存爆炸。比如
- 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
我们不能说为了谁放弃自己,而是要为了谁提升自己
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。