あれ!?プロセス全部killしたのにGPUが0にならないぞ?!
深層学習初心者の僕は毎度毎度jupyter notebookなどで実験をしているとGPUメモリを解放したくて以下のコマンドをよく実行して
$ # nvidia関連のプロセスを全部kill
$ kill -9 $(lsof -t /dev/nvidia*)
僕「よし、GPU解放したぞ!nvidia-smiで早速確認〜」
$ nvidia-smi
Tue Jan 11 08:58:05 2022
+-----------------------------------------------------------------------------+
| NVIDIA-SMI 460.91.03 Driver Version: 460.91.03 CUDA Version: 11.2 |
|-------------------------------+----------------------+----------------------+
| GPU Name Persistence-M| Bus-Id Disp.A | Volatile Uncorr. ECC |
| Fan Temp Perf Pwr:Usage/Cap| Memory-Usage | GPU-Util Compute M. |
| | | MIG M. |
|===============================+======================+======================|
| 0 Tesla V100-SXM2... On | 00000000:00:04.0 Off | 0 |
| N/A 37C P0 39W / 300W | 2631MiB / 16160MiB | 0% Default |
| | | N/A |
+-------------------------------+----------------------+----------------------+
+-----------------------------------------------------------------------------+
| Processes: |
| GPU GI CI PID Type Process name GPU Memory |
| ID ID Usage |
|=============================================================================|
| 0 N/A N/A 3721 C ...nvs/codeparrot/bin/python 2629MiB |
+-----------------------------------------------------------------------------+
僕「ん、約2GBも解放されてない?なんでだ?」
と、ずっと疑問でしたが先日hugging faceのドキュメント読んでたら解決しました。
原因:カーネルがGPUに乗るだけで結構メモリが食われる
結論としては
pythonカーネルがGPUに乗ってるだけで1〜2GBメモリ食われるよ
とのことでした。以下、元ページの翻訳になりますがnvidia-ml-py3
ライブラリからGPUの占有状況を調べてみると
>>> from pynvml import *
>>> def print_gpu_utilization():
nvmlInit()
handle = nvmlDeviceGetHandleByIndex(0)
info = nvmlDeviceGetMemoryInfo(handle)
print(f"GPU memory occupied: {info.used//1024**2} MB")
>>> print_gpu_utilization()
GPU memory occupied: 0 MB
pythonを起動しただけではGPUは占有されていないことがわかりますが、torch.Tensorオブジェクト一つでもGPUに送ると...
>>> import torch
>>> torch.ones((1,1)).to("cuda")
>>> print_gpu_utilization()
GPU memory occupied: 1343 MB
のように1GBもメモリは喰われてしまうようです!
モデル単体はどれくらい食うの?
当然、利用するモデルにはよりますがBERTのlarge-uncasedもおよそ1.3GB取るみたいです。
>>> from transformers import AutoModelForSequenceClassification
>>> model = AutoModelForSequenceClassification.from_pretrained("bert-large-uncased").to("cuda")
>>> print_gpu_utilization()
GPU memory occupied: 2631 MB.
従って、プロセスをキルしたとしても2GBくらいはメモリがしようされているものと考えて良さそうです!