起動中のDockerコンテナでGPUが使えてたのにしばらくすると使えなくなる（Failed to initialize NVML: Unknown Errorになる）


Dockerコンテナを立ち上げてでGPUが使えてたのに，しばらくするといつの間にかGPUが使えなくなる（Failed to initialize NVML: Unknown Errorになる，torch.cuda.is_available()がfalseになる）という現象に1ヶ月以上困っていたのですが，その解決方法が見つかったので書いておきます．

# 症状

- Ubuntu22.04LTS
- docker
- 各種GPU

長らくUbuntu20.04LTSを使ってたのですが，22.04にアップグレードしました．それ以前はなんの問題もなく使っていたのに，アップグレード後は上記問題が発生しました．

- 毎回発生する訳ではない．1週間ぐらい問題ないときもあれば，1日に複数回発生するときもある．およそ2−3日に1回程度は発生するが運次第．
- マシン依存ではない．複数台のサーバでGPUも構成もバラバラなのに，発生する．
- スクリプトをループ実行していつ頃発生するのかをモニターしたところ，どうやら発生した時刻の前後数秒で，daily cronのようなものが定期実行している様子．aptなどが悪さをしていると推測．
  - ちなみにnvidia driverがaptで自動アップデートされてしまうと起動中のコンテナからGPUが見えなくなるので，nvidia周りだけ自動アップデートはoffにしてある．（のになぜ？　まあそれなら`Failed to initialize NVML: Unknown Error`ではなくて`Failed to initialize NVML: Driver/library version mismatch`となるから違うはず）
  - ちなみにnvidia-runtimeの[debug log](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/user-guide.html#generating-debugging-logs)を取ってみても，問題発生時刻には何も出てこない．

# 情報

探しても「ホストでGPUが使えるのにコンテナから使えない」という情報なら見つかるのですが，

https://qiita.com/k_ikasumipowder/items/5e71208b7c7ae3e4fe7c

「起動中のコンテナでGPUが使えていたのに，しばらくすると使えない」というのは，日本語では探しても情報が見つからず．githubのissueでいくつか見つけました．

- [GPU becomes unavailable after some time in Docker container NVIDIA/nvidia-docker#1469](https://github.com/NVIDIA/nvidia-docker/issues/1469)
- ["Failed to initialize NVML: Unknown Error" after random amount of time NVIDIA/nvidia-docker#1671](https://github.com/NVIDIA/nvidia-docker/issues/1671)
- [GPU in Docker container becomes unavailable if not used for sometime coder/coder#4038](https://github.com/coder/coder/discussions/4038)
- [nvidia-smi command in container returns "Failed to initialize NVML: Unknown Error" after couple of times NVIDIA/nvidia-docker#1678](https://github.com/NVIDIA/nvidia-docker/issues/1678)
- [Failed to initialize NVML: Unknown Error after callingsystemctl daemon-reload  NVIDIA/nvidia-docker#1650
](https://github.com/NVIDIA/nvidia-docker/issues/1650)

この中で有力なのは，`systemctl daemon-reload`が実行されるとこの症状が発生する，というもの．

- https://github.com/NVIDIA/nvidia-docker/issues/1671#issuecomment-1235955979

たしかにsyslogを見ると問題発生時刻にreloadされてる．手動でreloadしても現象が再現できた．

```text
May 23 23:21:20 MYMACHINE systemd[1]: Reloading.
```

# 対処＆問題解決

Nvidiaの中の人が対応策を3つ示していました．

https://github.com/NVIDIA/nvidia-docker/issues/1671#issuecomment-1419720602

1. 問題は`/dev/char`がなぜか無くなってしまうことらしいので，`ncidia-ctk`で作成する．（でもこれだけではダメでdocker起動時にdevice指定のオプションをつける必要があるので面倒くさい）
1. cgroupを`systemd`が管理するのがダメなので，それをdisableにする．これが簡単．
1. `docker`をダウングレードする．イマイチな方法．

ということで2を実行．`"exec-opts"`の部分がそれです．

```json:/etc/docker/daemon.json
{
    "default-runtime": "nvidia",
    "runtimes": {
        "nvidia": {
            "args": [],
            "path": "nvidia-container-runtime"
        }
    },
    "exec-opts": ["native.cgroupdriver=cgroupfs"]
}
```

これでdockerを再起動したところ，問題が発生しなくなりました．これで解決．


# その後

このnvidiaの人によると，

- そもそもdockerがCDIをサポートすればよいのに
https://github.com/NVIDIA/nvidia-docker/issues/1671#issuecomment-1422631765
- dockerがcgroupを最近突然にcgroupfsからsystemdに変えたのがそもそもの原因
https://github.com/NVIDIA/nvidia-docker/issues/1671#issuecomment-1420855027

ということでこの人dockerにCDIサポートしろというissueも出してる．
- https://github.com/docker/cli/issues/3864