問題の概要:CUDAコードのコンパイルで直面する典型的なnvccエラー
CUDAを用いてGPU向けのカーネルを記述し、nvccコマンドでコンパイルを試みると、様々なエラーメッセージに遭遇することがあります。特に環境構築直後や、異なるマシンへのコード移行時には、コンパイルが通らずに開発が停滞する原因となります。代表的なエラーメッセージには以下のようなものがあります。
nvcc fatal : Unsupported gpu architecture 'compute_XX'
nvcc fatal : Cannot find compiler 'cl.exe' in PATH
error: identifier "xxxx" is undefined
error: function "xxxx" has already been defined
ptxas fatal : Unresolved extern function 'cudaMalloc'
これらのエラーは、CUDA ToolkitのバージョンとGPUアーキテクチャの不一致、開発環境のパス設定不備、コードの文法問題、リンク時のライブラリ不足など、多岐にわたる原因から発生します。本記事では、これらの頻出エラーを体系的に理解し、確実に解決するための手順を解説します。
原因の解説:なぜnvccエラーは起こるのか?
nvccはCUDAコードをコンパイルするためのドライバコンパイラであり、ホストコード(CPU側)のコンパイルとデバイスコード(GPU側)のコンパイルを調整します。このプロセスは複雑で、以下のような複数の要素が絡み合っています。
1. 環境設定の不整合
最も多い原因は、CUDA Toolkit、GPUドライバ、グラフィックスカードのアーキテクチャ、そしてホストコンパイラ(WindowsならVisual Studioのcl.exe、Linuxならgcc)の間の互換性問題です。CUDA Toolkitは特定のバージョンのGPUドライバとホストコンパイラを要求します。
2. アーキテクチャ指定の誤り
-arch=compute_XXや-code=sm_XXといったコンパイルオプションで指定する仮想アーキテクチャ(compute)と実アーキテクチャ(sm)の番号は、使用するGPUの世代(例:Turing, Ampere)に合わせる必要があります。古いバージョンのnvccで新しいGPUのアーキテクチャを指定するとエラーになります。
3. コードとライブラリの依存関係
CUDA Runtime APIやcuBLASなどのライブラリ関数をコード内で使用している場合、コンパイル時(-lcudart)やリンク時に適切なライブラリを指定しなければ「undefined reference」エラーが発生します。
解決方法:ステップバイステップでのトラブルシューティング
ステップ1:環境情報の確認
まず、現在の環境を以下のコマンドで確認します。これが全ての解決策の基礎となります。
# GPUとドライバ情報の確認
nvidia-smi
# CUDA Toolkitバージョンの確認
nvcc --version
# ホストコンパイラの確認 (Linux例)
gcc --version
# Windows (Visual Studio Developer Command Prompt内で)
cl
nvidia-smiの右上に表示される「CUDA Version」はドライバがサポートする最大のCUDAバージョンであり、インストールされているCUDA Toolkitのバージョンとは異なる場合がある点に注意してください。
ステップ2:パスと環境変数の設定確認
特にWindows環境でcl.exeが見つからないエラーが頻発します。
Windowsの場合: Visual Studioの「x64 Native Tools Command Prompt」または「Developer Command Prompt」を起動してからnvccを実行します。これにより、cl.exeへのパスが自動で設定されます。常にこの方法でコンパイルするか、環境変数PATH、INCLUDE、LIBを手動で設定します。
Linux/Macの場合: .bashrcや.zshrcに以下のようなパス設定がされているか確認します。
export PATH=/usr/local/cuda-11.8/bin${PATH:+:${PATH}}
export LD_LIBRARY_PATH=/usr/local/cuda-11.8/lib64${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}
ステップ3:適切なコンパイルオプションの設定
GPUのアーキテクチャに合ったオプションを指定します。NVIDIAの公式ドキュメントでアーキテクチャ番号を確認してください(例:RTX 30シリーズはAmpereアーキテクチャでsm_86など)。
# よくあるコンパイルコマンド例(Linux)
# 単一アーキテクチャ向け
nvcc -arch=sm_86 -o my_program my_program.cu
# 複数アーキテクチャ向けのFatbinary(互換性向上)
nvcc -arch=compute_86 -code=sm_86,compute_86 -o my_program my_program.cu
# デバッグ情報付き、最適化オフ
nvcc -G -g -arch=sm_86 -o my_program_debug my_program.cu
「Unsupported gpu architecture」エラーが出る場合は、使用しているnvccのバージョンがそのアーキテクチャをサポートしているか確認し、必要に応じてCUDA Toolkitをアップデートまたはダウングレードします。
ステップ4:コードとリンクの問題の解決
「undefined identifier」エラーは、関数や変数のスペルミス、必要なヘッダーファイルのインクルード漏れが原因です。CUDA関数を使うには#include <cuda_runtime.h>が必須です。
「Unresolved extern function」や「undefined reference to」エラーは、リンクするライブラリが不足しています。以下のように-lcudartなどのオプションを追加します。
# CUDA Runtime APIを使用する場合のリンクオプション
nvcc -arch=sm_86 -o my_program my_program.cu -lcudart
# cuBLASなどのライブラリを使用する場合
nvcc -arch=sm_86 -o my_blas_program my_blas_program.cu -lcudart -lcublas
ステップ5:CMakeLists.txtを使用した体系的な管理(中級者向け)
プロジェクトが大きくなると、手動でnvccコマンドを打つのは非現実的です。CMakeを使用することで、環境の差異を吸収し、ビルドを安定化させることができます。
# CMakeLists.txt の最小例
cmake_minimum_required(VERSION 3.10)
project(MyCUDAProject)
find_package(CUDA REQUIRED)
# CUDAのコンパイルオプションを設定
set(CUDA_NVCC_FLAGS "${CUDA_NVCC_FLAGS} -arch=sm_86 -O2")
# 実行ファイルの追加
cuda_add_executable(my_program my_program.cu)
# ライブラリをリンク
target_link_libraries(my_program ${CUDA_LIBRARIES})
コード例・コマンド例:実際のトラブルシューティングフロー
RTX 4060 (Ada Lovelaceアーキテクチャ, sm_89) で、CUDA 12.1をインストールした環境を想定します。
# エラーが発生するコマンド(古いアーキテクチャ指定)
nvcc -arch=sm_75 -o test test.cu
# 出力: nvcc fatal : Unsupported gpu architecture 'sm_75'
# 解決策1: 正しいアーキテクチャを指定
nvcc -arch=sm_89 -o test test.cu
# 解決策2: より汎用的な指定(複数世代対応)
nvcc -arch=compute_89 -code=sm_89,compute_89 -o test test.cu
# エラー: undefined reference to `cudaMalloc`
# 原因: -lcudart のリンク忘れ
nvcc -arch=sm_89 -o test test.cu -lcudart # これで解決
まとめ・補足情報
nvccコンパイルエラーの解決は、以下のチェックリストに沿って行うことで、ほとんどの場合に対処できます。
- 環境確認:
nvidia-smi,nvcc --version, ホストコンパイラの確認。 - パス確認: 特にWindowsでは適切なコマンドプロンプトを使用する。
- アーキテクチャ指定: 自分のGPUに合った
-archオプションを調べて使用する。 - コード確認: ヘッダーファイルのインクルード、関数名のスペルを確認する。
- リンク確認: 使用しているライブラリ(cudart, cublas, cusparse等)を
-lオプションで指定する。
最後に、CUDA Toolkit、ドライバ、GPUの3点セットの互換性が最も重要です。新しいGPUを購入した場合は、それに対応した新しいCUDA Toolkitのインストールがほぼ必須となります。また、エラーメッセージをそのままインターネットで検索すると、NVIDIA Developer ForumやStack Overflowに多くの解決例が掲載されています。エラーメッセージのキーワードと自分の環境(OS, CUDAバージョン)を組み合わせて検索することで、より具体的な解決策にたどり着けるでしょう。