web-dev-qa-db-ja.com

オブジェクトをクリアした後、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% |
_

Attempt 2:変数を削除する

いいえ、これも機能しません

_>>> del x
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
|  0 |  0% | 26% |
|  1 |  0% |  0% |
|  2 |  0% |  0% |
|  3 |  0% |  0% |
_

Attempt 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% |
_

Attempt 4:ガベージコレクターをクリアします。

いいえ、5%はまだ消費されています

_>>> gc.collect()
0
>>> GPUtil.showUtilization()
| ID | GPU | MEM |
------------------
|  0 |  0% |  5% |
|  1 |  0% |  0% |
|  2 |  0% |  0% |
|  3 |  0% |  0% |
_

Attempt 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の要素がたくさんあるようです...

キャッシュをクリアした後も、なぜメモリがまだ使用されているのでしょうか?

10
alvas

テンソルがない場合でも、PyTorchのキャッシングアロケーターが一定量のメモリを予約しているように見え、この割り当ては最初のCUDAメモリアクセスによってトリガーされます(torch.cuda.empty_cache()は未使用のテンソルをキャッシュから削除しますが、キャッシュ自体はまだです一部のメモリを使用します)。

小さな1要素のテンソルを使用しても、deltorch.cuda.empty_cache()の後に、GPUtil.showUtilization(all=True)は、巨大なテンソル(および両方のtorch.cuda.memory_cached()およびtorch.cuda.memory_allocated()はゼロを返します)。

5

PyTorchのドキュメントには、かなり関連性があるように見える部分があります。
https://pytorch.org/docs/stable/notes/cuda.html#memory-management

メモリ管理

PyTorchは、キャッシュメモリアロケーターを使用してメモリ割り当てを高速化します。これにより、デバイスを同期せずに高速でメモリの割り当てを解除できます。ただし、アロケータが管理する未使用のメモリは、nvidia-smiで使用されているかのように表示されます。 memory_allocated()およびmax_memory_allocated()を使用して、テンソルによって占有されているメモリを監視し、memory_cached()およびmax_memory_cached()を使用して、キャッシングアロケータによって管理されているメモリを監視できます。 empty_cache()を呼び出すと、すべての未使用のキャッシュメモリがPyTorchから解放され、他のGPUアプリケーションで使用できるようになります。ただし、テンソルによって占有されているGPUメモリは解放されないため、PyTorchで使用できるGPUメモリの量を増やすことはできません。

nvidia-smiについて言及している部分を太字にしました。私の知る限り、これはGPUtilで使用されています。

3
Stanowczo