【AWS】突如牙を剥く「NVIDIA-SMI has failed」の絶望を越えて:カーネルとドライバの深淵なる対立と共生

Python
NVIDIA-SMI has failed because it couldn't communicate with the NVIDIA driver. Make sure that the latest NVIDIA driver is installed and running.

昨日まで元気に数テラフロップスの計算を叩き出していたAWS EC2のGPUインスタンス(g4dn.xlargeやp3.2xlarge)が、突如としてただの「高価で電力消費の激しい暖房器具」へと成り下がる瞬間です。nvidia-smiを叩いても、ドライバがいないと門前払い。lsmod | grep nvidiaは何も返さない。この絶望感に、どれほどのAIエンジニアやSREが枕を濡らしてきたことでしょう。

本稿では、この「NVIDIA-SMI has failed」というエラーの裏側に潜む、Linuxカーネル、DKMS(Dynamic Kernel Module Support)、そしてNVIDIAドライバという「三権分立」ならぬ「三者対立」の構造を、コンピュータ・サイエンスの深淵まで潜って解剖します。なぜこのエラーは起きるのか?

1. アーキテクチャの断絶:ユーザー空間とカーネル空間の通信プロトコル

まず、なぜ nvidia-smi が失敗するのかを理解するために、現代のOSにおける「ドライバ」の立ち位置を復習しましょう。我々が叩く nvidia-smi は「ユーザー空間(User Space)」で動作するバイナリです。一方、GPUハードウェアを直接制御するのは「カーネル空間(Kernel Space)」で動作するカーネルモジュール(nvidia.koなど)です。

この両者の間には、ベルリンの壁よりも分厚い隔たりがあります。ユーザー空間のプロセスは、直接ハードウェアのメモリ(VRAM)やレジスタに触れることはできません。必ず「システムコール」や「ioctl(input/output control)」というゲートウェイを通じて、カーネルに依頼を出します。

ioctlの深淵

nvidia-smi が実行されると、まず /dev/nvidiactl/dev/nvidia0 といったデバイスファイルを開き、ioctl システムコールを発行します。これは「ドライバさん、今のGPUの温度とメモリ使用量を教えてください」というリクエストです。しかし、このときカーネル内に対応するドライバモジュールがロードされていない、あるいはロードされていてもバージョンが一致しない場合、カーネルは ENOTTYENOENT を返します。これが「Communication failed」の正体です。

2. なぜ「昨日まで動いていた」のに動かなくなるのか?

最も多い原因は、AWS(特にAmazon Linux 2やUbuntu)の「無人アップグレード(unattended-upgrade)」によるカーネルの更新です。これがこの「地獄」の入り口です。

ABI(Application Binary Interface)の非互換性

Linuxカーネルは、Windowsのドライバモデルとは異なり、ドライバに対して安定したABIを提供していません。カーネルのバージョンが 5.15.0-101-generic から 5.15.0-102-generic に上がっただけで、ドライバが依存していた関数シンボルのアドレスが変わったり、構造体のメンバレイアウトが変わったりします。

NVIDIAドライバは、その核心部分がクローズドソース(プロプライエタリなバイナリ・ブロブ)であるため、カーネルがアップデートされるたびに「現在のカーネルに合わせて再ビルド」する必要があります。この再ビルドを担うのが DKMS(Dynamic Kernel Module Support) です。

3. DKMS:救世主か、それとも時限爆弾か

DKMSは、新しいカーネルがインストールされた際に、フックを検知して自動的にカーネルモジュール(.koファイル)を再コンパイルする仕組みです。これがあるおかげで、我々はカーネルアップデートのたびに手動で NVIDIA-Linux-x86_64-xxx.run を叩かなくて済むはずでした。

しかし、DKMSによるビルドが失敗することが多々あります。その理由は主に3つです。

  • GCCバージョンの不一致: カーネルをコンパイルしたGCCのバージョンと、現在システムに入っているGCCのバージョンが異なると、モジュールのロード時に「Invalid module format」として蹴られます。
  • カーネルヘッダーの欠落: linux-headers-$(uname -r) がインストールされていない場合、DKMSはソースコードからバイナリを生成するための「設計図」を失い、ビルドに失敗します。
  • プロプライエタリなライセンスの壁: カーネルの一部の関数は EXPORT_SYMBOL_GPL とマークされており、GPL互換ライセンスを持たないNVIDIAドライバからは(建前上)アクセスできません。NVIDIAはこの制限を回避するために複雑なラッパーを介していますが、カーネルの変更によりこのラッパーが壊れることがあります。

4. AWS EC2 特有の事情:Nitroとインスタンス・ストア

AWSのEC2、特にNitro System上で動くG4dnやP4dインスタンスでは、ハイパーバイザがGPUをPCI Pass-through(正確にはSR-IOVなど)で直接見せています。この「物理的に直結されている感」が、ソフトウェア側の些細な不整合によるエラーをより深刻にします。

また、AMI(Amazon Machine Image)から起動した際、OS側が「よし、アップデートがあるから適用しよう」と親切心(お節介)を出してカーネルを上げ、再起動後にドライバとのリンクが切れる。これが「AMIから立ち上げ直した瞬間に死ぬ」現象の正体です。

5. 現場で使える「外科手術」的解決策

さて、理論はここまでにして、実際にこの地獄に陥った際の脱出フローを、シニアエンジニアの視点で解説します。

ステップ1:現状の死因特定(dmesgの確認)

まずは dmesg を確認しましょう。ここにはカーネルの叫びが記録されています。

dmesg | grep -E "NVIDIA|nv"

API mismatch という文言があれば、ユーザー空間のライブラリ(libnvidia-ml.so)とカーネルモジュールのバージョンがズレています。Unknown symbol があれば、DKMSの再ビルド失敗です。

ステップ2:DKMSの状態を確認

dkms status

もし Error!Added(Installedになっていない)状態であれば、手動でリビルドを命じます。この際、カーネルヘッダーを忘れずにインストールします。

sudo apt-get install linux-headers-$(uname -r)
sudo dkms install -m nvidia -v [VERSION]

ステップ3:奥の手、ドライバのクリーン再インストール

DKMSが修復不能なほど壊れている場合、一度すべてを「無」に帰すのが最速です。中途半端にファイルを残すと、共有ライブラリのリンクが壊れたままになります。

sudo apt-get purge nvidia*
sudo apt-get autoremove
sudo apt-get autoclean
# その後、公式リポジトリまたはRUNファイルから再インストール

6. 予防医学:二度とこのエラーを見ないためのベストプラクティス

プロのエンジニアは、火を消すよりも「火を起こさない」ことに心血を注ぎます。

A. カーネルバージョンの固定(Apt-mark / Yum versionlock)

OSに勝手にカーネルを上げさせない。これが鉄則です。

# Ubuntuの場合
sudo apt-mark hold linux-image-generic linux-headers-generic

B. Container Toolkit (NVIDIA Docker) の活用

ホストOSには最低限のドライバだけを入れ、CUDAライブラリやcuDNN、コンパイラ群はすべてDockerコンテナ内に閉じ込めます。これにより、ドライバとCUDAバージョンの依存関係(CUDA互換性)の悩みを大幅に軽減できます。ただし、ホストのカーネルとドライバモジュールの不一致だけはコンテナでも防げないため、やはりカーネル固定は必須です。

C. Golden Image (AMI) の運用

起動時に apt upgrade を走らせるようなUser Dataを書くのは言語道断です。完全に動作確認が取れた「カーネル + ドライバ + ライブラリ」のセットをAMIとして固め、オートスケーリングではそのAMIを使い回す。アップデートが必要な場合は、新しいAMIを「焼く」というイミュータブル・インフラストラクチャの考え方を導入しましょう。

7. まとめ:ドライバエラーはOSとの対話である

「NVIDIA-SMI has failed」は、一見するとただの不具合ですが、その実態は「動的なオープンソースカーネル」と「静的なプロプライエタリドライバ」の間に生じる、宿命的な摩擦の火花です。コンピュータ・サイエンスの視点で見れば、メモリ管理、シンボル解決、ABIの維持という、OSの最もエキサイティングで困難な課題がここに凝縮されています。

次にこのエラーに出会ったとき、あなたは単にコマンドをコピペするのではなく、背後で起きているカーネルの再構築や、デバイスファイルを通じた通信の断絶を想像できるはずです。それこそが、単なる「作業者」ではない「エンジニア」としての格の違いを生むのです。

GPUという強力な牙を、カーネルという檻の中で飼い慣らす。このスリル満点の運用を楽しめるようになってこそ、真のAIインフラエンジニアと言えるでしょう。

さて、環境構築が無事に終わったら、次は本番のディープラーニング実装です。効率的なモデル構築と訓練のノウハウを学ぶために、以下の書籍を手に取ってみることをお勧めします。

GPUの真価を引き出し、複雑なニューラルネットワークを自在に実装するための実践的なテクニックが凝縮されています。インフラの苦労を乗り越えた先に待つ、創造的な開発フェーズへの最良のガイドブックとなるでしょう。

コメント

タイトルとURLをコピーしました