pytorch的显存释放机制torch.cuda.empty_cache()
参考:
https://cloud.tencent.com/developer/article/1626387
据说在pytorch中使用torch.cuda.empty_cache()可以释放缓存空间,于是做了些尝试:
上代码:
import torch
import time
import os #os.environ["CUDA_VISIBLE_DEVICES"] = "3" device='cuda:2' dummy_tensor_4 = torch.randn(120, 3, 512, 512).float().to(device) # 120*3*512*512*4/1024/1024 = 360.0M memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第一阶段:")
print("变量类型:", dummy_tensor_4.dtype)
print("变量实际占用内存空间:", 120*3*512*512*4/1024/1024, "M")
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M") torch.cuda.empty_cache() time.sleep(15) memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第二阶段:")
print("释放缓存后:", "."*100)
print("变量实际占用内存空间:", 120*3*512*512*4/1024/1024, "M")
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M") del dummy_tensor_4 torch.cuda.empty_cache() time.sleep(15) memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第三阶段:")
print("删除变量后释放缓存后:", "."*100)
print("变量实际占用内存空间:", 0, "M")
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M") time.sleep(60)
运行结果:

第一阶段:

第二阶段:

第三阶段:

===================================================
可以看到在pytorch中显存创建360M的变量其实总占有了1321M空间,其中变量自身占了360M空间,缓存也占了360M空间,中间多出了那1321-360*2=601M空间却无法解释,十分诡异。
总的来说 torch.cuda.empty_cache() 操作有一定用处,但是用处不太大。
===================================================
更改代码:
import torch
import time
import os #os.environ["CUDA_VISIBLE_DEVICES"] = "3" device='cuda:2' dummy_tensor_4 = torch.randn(120, 3, 512, 512).float().to(device) # 120*3*512*512*4/1024/1024 = 360.0M
dummy_tensor_5 = torch.randn(120, 3, 512, 512).float().to(device) # 120*3*512*512*4/1024/1024 = 360.0M memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第一阶段:")
print("变量类型:", dummy_tensor_4.dtype)
print("变量实际占用内存空间:", 2*120*3*512*512*4/1024/1024, "M")
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M") torch.cuda.empty_cache() time.sleep(15) memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第二阶段:")
print("释放缓存后:", "."*100)
print("变量实际占用内存空间:", 2*120*3*512*512*4/1024/1024, "M")
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M") del dummy_tensor_4
del dummy_tensor_5 torch.cuda.empty_cache() time.sleep(15) memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第三阶段:")
print("删除变量后释放缓存后:", "."*100)
print("变量实际占用内存空间:", 0, "M")
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M") time.sleep(60)

第一阶段:

第二阶段:

第三阶段:

发现依然有显存空间无法解释。
=============================================
上面的操作都是在24G显存的titan上进行的,最后决定用1060显卡试验下,6G显存比较好尝试。
代码:
import torch
import time
import os
import functools #os.environ["CUDA_VISIBLE_DEVICES"] = "3" device='cuda:0' shape_ = (4, 1024, 512, 512) # 4GB
# dummy_tensor_4 = torch.randn(120, 3, 512, 512).float().to(device) # 120*3*512*512*4/1024/1024 = 360.0M
# dummy_tensor_5 = torch.randn(10, 120, 3, 512, 512).float().to(device) # 120*3*512*512*4/1024/1024 = 360.0M
dummy_tensor_6 = torch.randn(*shape_).float().to(device) memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第一阶段:")
print("变量类型:", dummy_tensor_6.dtype)
print("变量实际占用内存空间:", functools.reduce(lambda x, y: x*y, shape_)*4/1024/1024, "M")
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M") torch.cuda.empty_cache() time.sleep(15) memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第二阶段:")
print("释放缓存后:", "."*100)
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M") del dummy_tensor_6 torch.cuda.empty_cache() time.sleep(15) memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第三阶段:")
print("删除变量后释放缓存后:", "."*100)
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M") time.sleep(60)
输出结果:

第一阶段:

第二阶段:

第三阶段:

由于显卡总共6G显存,所以
memory_allocated
memory_reserved
这两部分应该是指的相同显存空间,因为这两个部分都是显示4G空间,总共6G空间。
可以看到单独执行:torch.cuda.empty_cache()
并没有释放显存,还是4775MB,但是执行:
del dummy_tensor_6
torch.cuda.empty_cache()
显存就进行了释放,为679MB。
更改代码:
import torch
import time
import os
import functools #os.environ["CUDA_VISIBLE_DEVICES"] = "3" device='cuda:0' shape_ = (4, 1024, 512, 512) # 4GB
# dummy_tensor_4 = torch.randn(120, 3, 512, 512).float().to(device) # 120*3*512*512*4/1024/1024 = 360.0M
# dummy_tensor_5 = torch.randn(10, 120, 3, 512, 512).float().to(device) # 120*3*512*512*4/1024/1024 = 360.0M
dummy_tensor_6 = torch.randn(*shape_).float().to(device) memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第一阶段:")
print("生成变量后:", "."*100)
print("变量类型:", dummy_tensor_6.dtype)
print("变量实际占用内存空间:", functools.reduce(lambda x, y: x*y, shape_)*4/1024/1024, "M")
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M") torch.cuda.empty_cache() time.sleep(15) memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第二阶段:")
print("释放缓存后:", "."*100)
print("变量类型:", dummy_tensor_6.dtype)
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M")
# for _ in range(10000):
# dummy_tensor_6 += 0.001
# print(torch.sum(dummy_tensor_6)) del dummy_tensor_6 time.sleep(15) memory_allocated = torch.cuda.memory_allocated(device)/1024/1024 memory_reserved = torch.cuda.memory_reserved(device)/1024/1024 print("第三阶段:")
print("删除变量后释放缓存后:", "."*100)
print("GPU实际分配给的可用内存", memory_allocated, "M")
print("GPU实际分配给的缓存", memory_reserved, "M") time.sleep(60)
运行结果:

NVIDIA显存显示第一,二,,三阶段均为:

如果没有执行torch.cuda.empty_cache(),即使删除GPU上的变量显存空间也不会被释放,该部分显存还为缓存空间所占。
================================================
总结:
torch.cuda.memory_reserved() 表示进程所获得分配到总显存大小(包括变量显存和缓存等)
torch.cuda.memory_allocated 表示进程为变量所分配的显存大小
torch.cuda.memory_reserved() - torch.cuda.memory_allocated
表示进程中空闲的显存空间,一般是指进程显存中缓存空间的大小。(不是GPU空闲显存空间,而是进程已获得的显存中未被使用的空间)
================================================
pytorch的显存释放机制torch.cuda.empty_cache()的更多相关文章
- 显卡、显卡驱动、显存、GPU、CUDA、cuDNN
显卡 Video card,Graphics card,又叫显示接口卡,是一个硬件概念(相似的还有网卡),执行计算机到显示设备的数模信号转换任务,安装在计算机的主板上,将计算机的数字信号转换成模拟 ...
- 【原创】Linux环境下的图形系统和AMD R600显卡编程(4)——AMD显卡显存管理机制
显卡使用的内存分为两部分,一部分是显卡自带的显存称为VRAM内存,另外一部分是系统主存称为GTT内存(graphics translation table和后面的GART含义相同,都是指显卡的页表,G ...
- GPU 显存释放
我们在使用tensorflow 的时候, 有时候会在控制台终止掉正在运行的程序,但是有时候程序已经结束了,nvidia-smi也看到没有程序了,但是GPU的内存并没有释放,那么怎么解决该问题呢? 首先 ...
- GPU显存释放
一.当程序没有运行,但GPU仍被占用, 可通过nvidia-smi查看,被占用的pid是什么 或通过sudo fuser -v /dev/nvidia* #查找占用GPU资源的PID 然后采用kill ...
- Pytorch显存动态分配规律探索
下面通过实验来探索Pytorch分配显存的方式. 实验 显存到主存 我使用VSCode的jupyter来进行实验,首先只导入pytorch,代码如下: import torch 打开任务管理器查看主存 ...
- Ubuntu-Tensorflow 程序结束掉GPU显存没有释放的问题
笔者在ubuntu上跑Tensorflow的程序的时候,中途使用了Win+C键结束了程序的进行,但是GPU的显存却显示没有释放,一直处于被占用状态. 使用命令 nvidia-smi 显示如下 两个GP ...
- TensorFlow中的显存管理器——BFC Allocator
背景 作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 使用GPU训练时,一次训练任务无论是模型参数还是中间结果都需要占用大量显存.为了 ...
- [Pytorch]深度模型的显存计算以及优化
原文链接:https://oldpan.me/archives/how-to-calculate-gpu-memory 前言 亲,显存炸了,你的显卡快冒烟了! torch.FatalError: cu ...
- Pytorch训练时显存分配过程探究
对于显存不充足的炼丹研究者来说,弄清楚Pytorch显存的分配机制是很有必要的.下面直接通过实验来推出Pytorch显存的分配过程. 实验实验代码如下: import torch from torch ...
- 解决GPU显存未释放问题
前言 今早我想用多块GPU测试模型,于是就用了PyTorch里的torch.nn.parallel.DistributedDataParallel来支持用多块GPU的同时使用(下面简称其为Dist). ...
随机推荐
- Vue学习:20.综合案例-商品列表
学而时用之,方能融会贯通! 实例:商品列表 实现功能 要求表格组件支持动态数据渲染.自定义表头和主体.标签组件需要双击显示输入框并获得焦点,可以编辑标签信息. 思路 首先是表格组件,动态渲染需要使用组 ...
- vue项目中一些常用的插件
@riophae/vue-treeselect:带选择的树组件 https://vue-treeselect.js.org/ ele-calendar:日历组件 https://www.npmjs.c ...
- 从JDK8升级到JDK17
一.概述 鉴于JDK8已经是老古董,还有性能问题,兼且各个公司已经不再维护1.8的JDK,所以升级公司的核心产品之一的后端到JDK到17是相对要紧的事情. 通过升级到jdk17,具有以下好处: 不要在 ...
- markdown折叠展开代码
背景 有的时候,我们的代码太多,直接用cout<<"hello";很不方便. 我们可以将代码折叠. 效果 代码 普通代码折叠 <details> <s ...
- CLR via C# 笔记 -- 字符、字符串、文本处理(14)
1. 字符串一经创建,便不能以任何方式修改,只能修改引用. 2. ToLowerInvariant() 和 ToUpperInvariant() 以忽略语言文化的方式将字符串转换为小写或大写形式.性能 ...
- 虚拟机安装Linux CENTOS 07 部署NET8 踩坑大全
首先下载centos07镜像,建议使用阿里云推荐的地址: https://mirrors.aliyun.com/centos/7.9.2009/isos/x86_64/?spm=a2c6h.25603 ...
- 多Github账号指定ssh-key提交代码
问题 目前github中代码提交只能通过ssh方式. 每个github账号只能添加一个专用的ssh-key. 如果同时有多个Github账号在用的话就必须给每个账号绑定不同的ssh-key. 方法一: ...
- 在 AWS 平台搭建 DolphinScheduler
AWS平台搭建 DolphinScheduler DolphinScheduler 是当前热门的调度器,提供了完善的可视化.拖拉拽式的调度.在 AWS 平台上提供了 airflow 与 step fu ...
- 详细讲解 Keil Pack Installer,以及通过 Keil 官网获取 Pack
前言 大家好,我是梁国庆. 收到粉丝留言,说 Keil 安装 Pack 不太明白,可不可以详细演示一下? 当然可以有,直接视频+文章全部安排,我就是宠粉. PS:第一次录视频有些紧张,见谅哈. 微信视 ...
- 【Error】mysql的error.log中ranges: 268 max_threads: 4 split: 268 depth: 2是什么意思?
2021-12-08T09:36:39.612332+08:00 44213799 [Note] [MY-011825] [InnoDB] Parallel scan: 4 2021-12-08T09 ...