🙈

"Failed to initialize NVML" を再起動せずに解決する方法

2023/10/01に公開

よく忘れるので備忘録代わりに書いておきます.誰かの役に立てれば幸いです.
書いたこと自体を忘れがちなのは触れてはいけない

はじめに

忙しい人のための3行クッキングです.これで解決します.

$ sudo modprobe -r nvidia_drm
$ sudo modprobe -r nvidia_uvm
$ sudo modprobe nvidia

デスクトップ環境の方は注意点もご覧ください.

これはなに

意図しないタイミングでCUDAドライバのアップデートが発生して

Failed to initialize NVML: Driver/library version mismatch

に頭を抱えてしまうことは,誰しも一度は通る道だと思います.
このエラーに遭遇したらマシンを再起動するのが通常の解決方法ですが,どうしても再起動したくないタイミングってありますよね?
この記事ではそんな場合に重宝する,再起動せずにCUDAドライバのバージョンミスマッチを解決する方法を紹介します.
といっても作業自体は冒頭のコマンド3行打つだけです.

原因

CUDAドライバのアップデート時,NVIDIAのGPU用カーネルモジュールは自動的にリロードされません.
このためカーネルモジュールのバージョンが古いまま動き続け,更新されたCUDAドライバに付属するライブラリのバージョンとの整合性が取れなくなってエラーが発生します.
実際にエラーが起きた状態で

$ modinfo nvidia --field=version

を実行すると,この不整合が発生していることが確認できます.
マシンを再起動すると,すべてのカーネルモジュールが確実にリロードされるのでエラーを解決できるというわけです.

そこで今回は,原因となっているカーネルモジュールを特定し,それをリロードすることでマシンを再起動させることなくエラーを解決します.

解決方法

まず,GPUドライバに関連してそうなカーネルモジュールを見つけてきます.

$ lspci -k -d 10de::0300
81:00.0 VGA compatible controller: NVIDIA Corporation TU102GL [Quadro RTX 6000/8000] (rev a1)
        Subsystem: NVIDIA Corporation Quadro RTX 6000
        Kernel driver in use: nvidia
        Kernel modules: nvidiafb, nouveau, nvidia_drm, nvidia

ここで,デバイスとして10de::0300を指定していますが,それぞれ

  • 10de: NVIDIA Corporation のvendor ID
  • 0300: VGA compatible controller のclass code

で対象を絞り込んでいます.

これでNVIDIAのGPU関連のカーネルモジュールはnvidia*と命名されていそうだとわかったので,次にlsmodで依存関係を確認します.

$ lsmod | grep -ie '^module' -e nvidia
Module                  Size  Used by
nvidia_uvm           1216512  0
nvidia_drm             61440  0
nvidia_modeset       1241088  1 nvidia_drm
nvidia              56291328  2 nvidia_uvm,nvidia_modeset
drm_kms_helper        184320  4 ast,nvidia_drm
drm                   495616  7 drm_kms_helper,drm_vram_helper,ast,nvidia,nvidia_drm,ttm
i2c_nvidia_gpu         16384  0

これで

nvidia
├── nvidia_uvm
└── nvidia_modeset
    └── nvidia_drm

というような依存関係があることがわかりました.
あとはこの依存関係に沿ってカーネルモジュールをアンロード・ロードするだけです.

このとき,依存関係の上位にあるモジュールは,下位のモジュールがすべてアンロードされると自動的にアンロードされます.
逆に,上位のモジュールをロードすると自動的に下位のモジュールから先にロードされます.

$ sudo modprobe -r nvidia_drm
# nvidia_drmにのみ依存していたnvidia_modesetも自動的にアンロード
$ sudo modprobe -r nvidia_uvm
# nvidia_uvm,nvidia_modesetがアンロードされたので,これらに依存していたnvidiaも自動的にアンロード
$ sudo modprobe nvidia
# これでnvidiaとその依存関係にあるカーネルモジュールがロードされる

これでnvidia-smiを実行すると,問題なくGPUの情報が表示されるはずです.
このときmodinfo nvidia --field=versionを実行すると,インストールされているCUDAドライバと同じバージョンが表示されます.

注意点

筆者の場合はデスクトップ環境を利用していないのでわかりませんが,デスクトップ環境の方は追加で作業が必要になるかもしれません.
また,おそらくですがカーネルモジュールをアンロードする際は一時的にGUIからCUIに切り替えたほうが良いと思います.

Discussion