参考:

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()的更多相关文章

  1. 显卡、显卡驱动、显存、GPU、CUDA、cuDNN

    显卡 Video card,Graphics card,又叫显示接口卡,是一个硬件概念(相似的还有网卡),执行计算机到显示设备的数模信号转换任务,安装在计算机的主板上,将计算机的数字信号转换成模拟 ...

  2. 【原创】Linux环境下的图形系统和AMD R600显卡编程(4)——AMD显卡显存管理机制

    显卡使用的内存分为两部分,一部分是显卡自带的显存称为VRAM内存,另外一部分是系统主存称为GTT内存(graphics translation table和后面的GART含义相同,都是指显卡的页表,G ...

  3. GPU 显存释放

    我们在使用tensorflow 的时候, 有时候会在控制台终止掉正在运行的程序,但是有时候程序已经结束了,nvidia-smi也看到没有程序了,但是GPU的内存并没有释放,那么怎么解决该问题呢? 首先 ...

  4. GPU显存释放

    一.当程序没有运行,但GPU仍被占用, 可通过nvidia-smi查看,被占用的pid是什么 或通过sudo fuser -v /dev/nvidia* #查找占用GPU资源的PID 然后采用kill ...

  5. Pytorch显存动态分配规律探索

    下面通过实验来探索Pytorch分配显存的方式. 实验 显存到主存 我使用VSCode的jupyter来进行实验,首先只导入pytorch,代码如下: import torch 打开任务管理器查看主存 ...

  6. Ubuntu-Tensorflow 程序结束掉GPU显存没有释放的问题

    笔者在ubuntu上跑Tensorflow的程序的时候,中途使用了Win+C键结束了程序的进行,但是GPU的显存却显示没有释放,一直处于被占用状态. 使用命令 nvidia-smi 显示如下 两个GP ...

  7. TensorFlow中的显存管理器——BFC Allocator

    背景 作者:DeepLearningStack,阿里巴巴算法工程师,开源TensorFlow Contributor] 使用GPU训练时,一次训练任务无论是模型参数还是中间结果都需要占用大量显存.为了 ...

  8. [Pytorch]深度模型的显存计算以及优化

    原文链接:https://oldpan.me/archives/how-to-calculate-gpu-memory 前言 亲,显存炸了,你的显卡快冒烟了! torch.FatalError: cu ...

  9. Pytorch训练时显存分配过程探究

    对于显存不充足的炼丹研究者来说,弄清楚Pytorch显存的分配机制是很有必要的.下面直接通过实验来推出Pytorch显存的分配过程. 实验实验代码如下: import torch from torch ...

  10. 解决GPU显存未释放问题

    前言 今早我想用多块GPU测试模型,于是就用了PyTorch里的torch.nn.parallel.DistributedDataParallel来支持用多块GPU的同时使用(下面简称其为Dist). ...

随机推荐

  1. 高并发缓存中间件Redis

    https://tech.meituan.com/2020/07/01/kv-squirrel-cellar.html 美团万亿级 KV 存储架构与实践 阿里云 redis文档 https://hel ...

  2. 暴走漫画系列之高仿淘宝收货地址(附demo)

    引语: 我是个程序猿,一天我坐在路边一边喝水一边苦苦检查bug. 这时一个乞丐在我边上坐下了,开始要饭,我觉得可怜,就给了他1块钱. 然后接着调试程序.他可能生意不好,就无聊的看看我在干什么,然后过了 ...

  3. jqurey基础知识和常用事件方法

    样式文件不需要<style>标签 引用style文件的方法 <link href="main.css" rel="stylesheet" st ...

  4. Java的运行机制和JDK,JRE,JVM的区别

    源文件(Java文件)   >  编译器  > 字节码(class文件)  >  JVM(java虚拟机)  >  操作系统  1.java首先利用文本编辑器写java源程序, ...

  5. Linux 内核:设备树(4)设备树中各个节点是谁转换的

    Linux 内核:设备树(4)设备树中各个节点是谁转换的 背景 之前,我们在<把device_node转换成platfrom_device>中提到在设备树的device_node到plat ...

  6. AI Agent实战:智能检索在Kingbase数据库管理中的优势应用

    前言 在信息技术飞速发展的今天,数据库管理已成为IT专业人员日常工作中不可或缺的一部分.然而,面对复杂的SQL问题,传统的web搜索往往难以提供精准的答案,尤其是在针对特定数据库系统,如金仓数据库时, ...

  7. (Java)日志框架体系整理

    # JUL 指的是Java Util Logging包,它是Java原生的日志框架,使用时不需要另外引用第三方的类库,相对其他的框架使用方便,学习简单,主要是使用在小型应用中.@紫邪情 # JUL的组 ...

  8. 重复消费Java Stream的三种方法。你选择哪种?

    Java中的Stream一旦被消费就会关闭,不能再次使用了.如果的确有需要该怎么办呢? 这里介绍三种重复消费Stream的方法. 1. 从集合再次创建 这里你都不用往下继续看就知道该怎么办,不过我还是 ...

  9. 洛谷P3009

    #include<iostream> #include<utility> using namespace std; typedef long long ll; #define ...

  10. pyspark集成访问hive数据踩坑记录

    当前环境anaconda3.python3.9.13.jupyter 需要安装的pyspark.py4j pyspark和py4j的离线安装包地址Links for pyspark (tsinghua ...