問題の概要:CUDAバージョン競合によるエラー
AI開発、特に深層学習のモデル訓練を行う際、異なるフレームワークやプロジェクトが要求するCUDAバージョンが異なることがよくあります。例えば、PyTorch 1.x系はCUDA 10.2を、TensorFlow 2.5はCUDA 11.2を要求するといったケースです。このような状況で、単一のCUDAバージョンしかシステムにインストールしていないと、以下のような典型的なエラーに遭遇します。
ImportError: libcudart.so.11.0: cannot open shared object file: No such file or directory
あるいは、nvcc --versionで確認されるコンパイラバージョンと、プログラムが実行時に参照するランタイムライブラリのバージョンが一致せず、動作が不安定になることもあります。システムのデフォルトCUDAを頻繁に再インストールするのは非現実的であり、時間の浪費です。本記事では、Debian/Ubuntu系のLinuxディストリビューションで広く使われるupdate-alternativesコマンドを活用し、複数のCUDAバージョンを安全かつ柔軟に管理する方法を解説します。
原因の解説:シンボリックリンクとパスの管理
根本的な原因は、CUDAツールキットがインストールされるパス(通常は/usr/local/cuda)が、実際には特定のバージョン(例: /usr/local/cuda-11.8)を指すシンボリックリンクであることにあります。nvccやlibcudart.soなどの重要な実行ファイルやライブラリは、この/usr/local/cudaリンクを介して参照されます。
従来の方法では、このシンボリックリンクを直接書き換えていました。
sudo rm /usr/local/cuda
sudo ln -s /usr/local/cuda-11.8 /usr/local/cuda
しかし、この方法では「どのバージョンが現在有効か」の記録が残らず、手動での切り替えはミスを招きやすくなります。update-alternativesは、このシンボリックリンク群を一元的に管理するシステムを提供します。複数の候補(今回は異なるCUDAバージョンのパス)を登録しておき、優先度に基づいてシステム全体で使用するバージョンを簡単に切り替えられるようにするのです。
解決方法:update-alternativesによるCUDAバージョン管理
ここからは、CUDA 11.8とCUDA 12.1がそれぞれ/usr/local/cuda-11.8と/usr/local/cuda-12.1にインストールされていることを前提に、手順を説明します。
ステップ1: 既存の手動シンボリックリンクを削除
まず、既に/usr/local/cudaが手動で作成されたシンボリックリンクであれば、削除します。
sudo rm -f /usr/local/cuda
ステップ2: update-alternatives グループの作成と候補の登録
cudaという名前の管理グループを作成し、各CUDAバージョンのインストールパスを候補として登録します。優先度は数字で指定し、通常はバージョン番号が新しいほど高い値(例えば、バージョン番号*10)に設定します。
# CUDA 11.8を登録 (優先度: 118)
sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-11.8 118
# CUDA 12.1を登録 (優先度: 121)
sudo update-alternatives --install /usr/local/cuda cuda /usr/local/cuda-12.1 121
--installオプションの構成は以下の通りです。
<リンクパス> <グループ名> <候補の実パス> <優先度>
ステップ3: 使用するCUDAバージョンの切り替え
登録が完了したら、以下のコマンドでインタラクティブにバージョンを選択できます。表示されるメニューから、該当する番号を入力します。
sudo update-alternatives --config cuda
実行例:
There are 2 choices for the alternative cuda (providing /usr/local/cuda).
Selection Path Priority Status
------------------------------------------------------------
* 0 /usr/local/cuda-12.1 121 auto mode
1 /usr/local/cuda-11.8 118 manual mode
2 /usr/local/cuda-12.1 121 manual mode
Press <enter> to keep the current choice[*], or type selection number: 1
ここで1を入力してEnterを押すと、システムのデフォルトCUDAが11.8に切り替わります。
ステップ4: 切り替えの確認
切り替えが正しく行われたか、以下のコマンドで確認します。
# シンボリックリンクの確認
ls -l /usr/local/cuda
# 期待する出力: /usr/local/cuda -> /usr/local/cuda-11.8
# nvccコンパイラのバージョン確認
nvcc --version
# 出力の一部に「release 11.8」と表示されるはず
# ランタイムライブラリの確認
ldconfig -p | grep cudart
# libcudart.so.11.8 が表示される
コード例・コマンド例:よく使う操作とトラブルシューティング
現在の設定状態を確認する
# 登録されている全候補と現在の選択状態を表示
sudo update-alternatives --display cuda
現在の選択を「自動モード」に戻す
最高優先度の候補が自動的に選択されるモードです。
sudo update-alternatives --auto cuda
特定の候補を削除する(CUDAをアンインストールした場合など)
sudo update-alternatives --remove cuda /usr/local/cuda-10.2
環境変数PATHの設定
update-alternativesで/usr/local/cudaのリンク先を切り替えても、シェルのPATH環境変数に/usr/local/cuda/binが含まれていなければツールは見つかりません。~/.bashrcまたは~/.zshrcに以下の設定を追加してください。
export PATH=/usr/local/cuda/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
設定を反映させます。
source ~/.bashrc # または source ~/.zshrc
仮想環境ごとの固定
システム全体のCUDAを切り替えたくない場合は、仮想環境内で環境変数を直接設定することで、特定のCUDAバージョンを強制できます。例えば、conda環境でCUDA 11.8を専用に使いたい場合:
# conda activate your_env の後で実行
export CUDA_HOME=/usr/local/cuda-11.8
export PATH=$CUDA_HOME/bin:$PATH
export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH
まとめ・補足情報
update-alternativesを用いることで、複数のCUDAバージョンをシステムに共存させ、プロジェクトやフレームワークの要求に応じてクリーンに切り替えることが可能になります。これにより、「ライブラリが見つからない」エラーに悩まされる時間を大幅に削減できます。
重要な注意点:
- この方法は主に
nvccやCUDAランタイムライブラリなどの開発・実行環境を管理します。NVIDIAドライバ自体のバージョンとは独立しています(ドライバは新しいバージョンのCUDAに下位互換性があります)。 - PyTorchやTensorFlowなどのフレームワークをpip/condaでインストールする際は、そのパッケージが内部に持つCUDAランタイム(例:
cudatoolkit)のバージョンも重要です。システムCUDAとフレームワーク内CUDAの両方が互換性のあるバージョンであることを確認しましょう。 - CUDAのメジャーバージョンが異なると(例: CUDA 11.x と 12.x)、互換性が保証されない変更があるため、切り替え後にプログラムの再コンパイルが必要な場合があります。
最終的に、システムCUDAのバージョン管理を確立することは、効率的で再現性の高いAI開発環境を構築するための基礎的なステップとなります。update-alternativesはその強力な味方です。