Python 为什么清除对象后GPU中的内存仍在使用?
从零使用开始:Python 为什么清除对象后GPU中的内存仍在使用?,python,memory-leaks,garbage-collection,gpu,pytorch,Python,Memory Leaks,Garbage Collection,Gpu,Pytorch,从零使用开始: >>> import gc >>> import GPUtil >>> import torch >>> GPUtil.showUtilization() | ID | GPU | MEM | ------------------ | 0 | 0% | 0% | | 1 | 0% | 0% | | 2 | 0% | 0% | | 3 | 0% | 0% | 然后我创建一个足够大的张量
>>> import gc
>>> import GPUtil
>>> import torch
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
| 0 | 0% | 0% |
| 1 | 0% | 0% |
| 2 | 0% | 0% |
| 3 | 0% | 0% |
然后我创建一个足够大的张量并占用内存:
>>> x = torch.rand(10000,300,200).cuda()
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
| 0 | 0% | 26% |
| 1 | 0% | 0% |
| 2 | 0% | 0% |
| 3 | 0% | 0% |
然后我尝试了几种方法来看看张量是否消失了
尝试1:分离、发送到CPU并覆盖变量
不,不起作用。
>>> x = x.detach().cpu()
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
| 0 | 0% | 26% |
| 1 | 0% | 0% |
| 2 | 0% | 0% |
| 3 | 0% | 0% |
尝试2:删除变量
不,这也不行
>>> del x
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
| 0 | 0% | 26% |
| 1 | 0% | 0% |
| 2 | 0% | 0% |
| 3 | 0% | 0% |
尝试3:使用torch.cuda.empty\u cache()函数
似乎有效,但似乎有一些挥之不去的日常开支
>>> torch.cuda.empty_cache()
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
| 0 | 0% | 5% |
| 1 | 0% | 0% |
| 2 | 0% | 0% |
| 3 | 0% | 0% |
尝试4:可能会清除垃圾收集器
不,5%的人仍在被抢走
>>> gc.collect()
0
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
| 0 | 0% | 5% |
| 1 | 0% | 0% |
| 2 | 0% | 0% |
| 3 | 0% | 0% |
尝试5:尝试将火炬
一起删除(好像当del x
不起作用时,这会起作用-)
不,它没有...*
>>> del torch
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
| 0 | 0% | 5% |
| 1 | 0% | 0% |
| 2 | 0% | 0% |
| 3 | 0% | 0% |
然后我试着检查gc.get_objects()
,看起来里面还有很多奇怪的THCTensor
东西
知道为什么清除缓存后内存仍在使用吗?看起来PyTorch的缓存分配器保留了一些固定数量的内存,即使没有张量,这种分配也是由第一次CUDA内存访问触发的
(torch.cuda.empty_cache()
从缓存中删除未使用的张量,但缓存本身仍使用一些内存)
即使使用一个很小的单元素张量,在del
和torch.cuda.empty_cache()
之后,GPUtil.showUtilization(all=True)
报告的GPU内存使用量与使用一个大张量的GPU内存使用量完全相同(两者都torch.cuda.memory_cached()
和torch.cuda.memory_allocated()
返回零).PyTorch文档中有一部分似乎非常相关:
内存管理
PyTorch使用缓存内存分配器来加速内存
拨款。这允许在没有设备的情况下快速释放内存
同步。但是,分配器管理的未使用内存
仍将显示为在nvidia smi中使用。你可以用
内存分配()和最大内存分配()来监视内存
被张量占用,并使用memory_cached()和max_memory_cached()
监视由缓存分配器管理的内存。使命感
empty_cache()从PyTorch中释放所有未使用的缓存内存,以便
这些可以被其他GPU应用程序使用。然而,被占用的GPU
张量产生的内存将不会被释放,因此无法增加数量
可用于PyTorch的GPU内存数量
我用粗体显示了一部分,其中提到了nvidia smi,据我所知,它是由GPUtil使用的。首先,使用nvidia smi
确认哪个进程正在使用GPU内存。在那里,进程idpid
可用于查找进程。如果没有显示任何进程,但GPU内存仍在使用,您可以尝试清除内存。Torch还可以为内部系统/管理器等分配内存。可能是它的分配器。关于空\u cache()
的句子呢?对我来说,这听起来很明显,它确实释放了内存,也就是说,它也是以“nvidia smi free”的方式释放的。的确,但不幸的是,它还声明,它只释放pytorch认为未使用的内存。。。这可能是挥之不去的5%,是的。一定也有@Tiphaine建议的内在因素。但这5%的运算量约为5千兆字节!然后,文档只知道“未使用的缓存内存”和“被张量占用的GPU内存”,这5%似乎都不属于它们。