为什么清除对象后GPU中的内存仍在使用?

问题描述

从零使用开始:

>>> 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_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:尝试全部删除torch(就好像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()从缓存中删除未使用的张量,但缓存本身仍使用一些内存)。

即使使用很小的1元素张量,在deltorch.cuda.empty_cache()之后,GPUtil.showUtilization(all=True)报告的GPU内存量与巨大张量使用的GPU内存量完全相同(并且torch.cuda.memory_cached()torch.cuda.memory_allocated()都返回零)。

相关文章