問題の概要:CUDAコードのコンパイルで遭遇する代表的なnvccエラー
CUDAを用いてGPU向けのプログラムを開発する際、nvccコンパイラによるコンパイルプロセスで様々なエラーに遭遇することがあります。特に環境構築時や複雑なコードを書いている際に、以下のようなエラーメッセージでコンパイルが失敗し、開発が停滞することが少なくありません。
nvcc fatal : Unsupported gpu architecture 'compute_90'
error: identifier "cudaMalloc" is undefined
CMake Error at /usr/lib/cmake/CUDA/CUDAConfig.cmake: (find_package):
Could not find a package configuration file provided by "CUDA"
これらのエラーは、CUDAツールキットのバージョン不一致、環境変数の設定漏れ、構文エラー、あるいはビルドシステム(MakeやCMake)との連携問題など、多岐にわたる原因によって引き起こされます。本記事では、AI開発者、特に深層学習フレームワークのカスタムカーネル開発や高性能計算に取り組む初心者から中級者を対象に、頻出するnvccコンパイルエラーの原因と、体系的な解決手順を解説します。
原因の解説:なぜnvccエラーは発生するのか?
nvccエラーの根本原因は、主に以下の4つのカテゴリに分類できます。
1. 環境設定の不整合
CUDAは、ホストコンパイラ(gccやclangなど)、ドライバー、ツールキットのバージョンが厳密に互換性を持つ必要があります。公式の互換性テーブルから外れた組み合わせを使用している場合、コンパイル自体が失敗したり、生成されたコードが実行時にエラーを起こしたりします。
2. コードの構文・セマンティクスエラー
CUDA C++は、標準C++を拡張した言語です。__global__や__device__などのキーワードの誤用、ホスト・デバイス間のメモリアクセスの誤り、サポートされていない機能の使用など、純粋なコード上の問題です。
3. ビルドシステムの設定ミス
CMakeやMakefileを使用する場合、CUDAのパス(CUDA_TOOLKIT_ROOT_DIR)やコンパイルフラグ(-arch=sm_xx)が正しく設定されていないと、コンパイラが見つからなかったり、ターゲットGPUアーキテクチャに対応したコードが生成されません。
4. GPUアーキテクチャの指定ミス
-archや-gencodeオプションで指定するアーキテクチャコード(例:sm_75 for Turing)が、インストールされているCUDAツールキットのバージョンでサポートされていない、または実在する物理GPUのアーキテクチャと一致しない場合にエラーが発生します。
解決方法:ステップバイステップで問題を切り分ける
以下に、発生したエラーに対して系統的にアプローチする解決ステップを紹介します。
ステップ1:基礎環境の確認
まず、CUDA環境が正しくインストールされ、認識されているかを確認します。
# CUDAドライバーのバージョン確認
nvidia-smi
# CUDAツールキットのバージョンとパス確認
nvcc --version
echo $CUDA_HOME
echo $PATH | tr ':' 'n' | grep cuda
nvidia-smiの上部に表示されるCUDA Versionはドライバーがサポートする最大バージョン、nvcc --versionは実際にインストールされているツールキットのバージョンです。後者が前者を超えていないか確認しましょう。
ステップ2:ホストコンパイラの互換性チェック
CUDAツールキットのバージョンに対応した、正しいバージョンのgccを利用しているか確認します。例えば、CUDA 11.x系ではgccのバージョンが制限されます。
gcc --version
互換性がない場合は、環境変数CCとCXXで使用するコンパイラを明示的に指定するか、適切なバージョンのgccをインストールします。
export CC=/usr/bin/gcc-9
export CXX=/usr/bin/g++-9
ステップ3:シンプルなテストコードでコンパイル
複雑なプロジェクトでエラーが起きている場合、問題がプロジェクト設定にあるのか、環境自体にあるのかを切り分けます。以下の最小限のCUDAコード(test.cu)を作成し、直接コンパイルを試みます。
#include <stdio.h>
__global__ void helloFromGPU() {
printf("Hello World from GPU!n");
}
int main() {
helloFromGPU<<<1, 1>>>();
cudaDeviceSynchronize();
return 0;
}
# 直接コンパイルを試す(アーキテクチャは自身のGPUに合わせて変更)
nvcc -arch=sm_75 test.cu -o test
これで成功すれば、環境そのものは正常であり、元のプロジェクトのビルド設定に問題がある可能性が高まります。
ステップ4:GPUアーキテクチャの正しい指定
「Unsupported gpu architecture」エラーは、指定したアーキテクチャがツールキットでサポートされていない場合に発生します。使用するCUDAバージョンとGPUモデルに応じた正しいアーキテクチャコードを指定します。
- NVIDIA公式ドキュメントで、CUDAバージョンとサポートする
compute_xx/sm_xxを確認。 - 自身のGPUアーキテクチャは、
nvidia-smi -q | grep "Compute Capability"や NVIDIA公式サイトで調べられます。
# 例:RTX 3080 (Compute Capability 8.6) + CUDA 11.x の場合
nvcc -arch=sm_86 test.cu -o test
# 複数アーキテクチャ向けにコンパイルする場合(互換性確保)
nvcc -gencode arch=compute_75,code=sm_75 -gencode arch=compute_86,code=sm_86 test.cu -o test
ステップ5:ヘッダーファイルとライブラリパスの確認
「undefined identifier」エラーは、CUDAのランタイムAPIやヘッダーが見つかっていない可能性があります。インクルードパスとリンクパスを明示的に指定します。
# 一般的なインクルードパスとライブラリパスを指定してコンパイル
nvcc -I$CUDA_HOME/include -L$CUDA_HOME/lib64 -lcudart -arch=sm_75 test.cu -o test
CUDA_HOMEが設定されていない場合は、/usr/local/cuda-11.6などの実際のインストールパスを指定してください。
ステップ6:CMakeを使用している場合の設定見直し
CMakeプロジェクトでは、CMakeLists.txtでCUDAを正しく有効化し、ターゲットアーキテクチャを設定する必要があります。
# CMakeLists.txt の例 (CMake 3.18以降推奨)
cmake_minimum_required(VERSION 3.18)
project(MyCudaProject LANGUAGES CXX CUDA) # CUDAを言語として明示
# CUDAの標準を設定
set(CMAKE_CUDA_STANDARD 17)
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
# ターゲットGPUアーキテクチャの設定(重要)
set(CMAKE_CUDA_ARCHITECTURES "75") # Compute Capability 7.5 (Turing) をターゲット
add_executable(my_target test.cu)
# CUDAライブラリは通常、ターゲットに自動リンクされる
古いCMakeでは、find_package(CUDA REQUIRED)とCUDA_ADD_EXECUTABLEを使用する方式もありますが、最新のCMake(3.8以降)では上記の「CUDA as a Language」アプローチが推奨されます。
ステップ7:詳細なログ出力によるデバッグ
エラーの原因がわからない場合は、nvccに詳細なログを出力させるフラグを追加します。
nvcc -v -arch=sm_75 test.cu -o test # -v フラグで詳細なコンパイルステップを表示
これにより、コンパイラが使用している内部コマンドやパスを確認でき、ホストコンパイラの呼び出し失敗やライブラリ検索パスの問題を発見しやすくなります。
コード例・コマンド例:よくあるエラーとその解決コマンド
例1:アーキテクチャ指定エラーの解決
エラーメッセージ: nvcc fatal : Unsupported gpu architecture 'compute_90'
原因と解決: CUDA 11.xではCompute Capability 9.x(Ada Lovelaceアーキテクチャ)をサポートしていません。CUDA 12.xにアップグレードするか、正しいアーキテクチャを指定します。
# 間違い(CUDA 11.xで)
nvcc -arch=compute_90 ...
# 正しい指定(RTX 4090を使用する場合、CUDA 12.xが必要)
nvcc -arch=sm_90 ...
# または、現在の環境でサポートされるアーキテクチャ(例:sm_86)を指定
nvcc -arch=sm_86 ...
例2:cudaMallocが未定義となるエラー
エラーメッセージ: error: identifier "cudaMalloc" is undefined
原因と解決: CUDAのヘッダーファイルをインクルードしていない、または名前空間の問題です。
// test.cu の先頭に必ずインクルードを追加
#include <cuda_runtime.h> // または <cuda.h>
// コード内では cudaMalloc を正しく使用
cudaMalloc((void**)&d_ptr, size);
# コンパイル時はcudartライブラリをリンク
nvcc -lcudart test.cu -o test
まとめ・補足情報
nvccコンパイルエラーは、一見すると難解ですが、その原因は「環境」「コード」「ビルド設定」「アーキテクチャ」のいずれかにほぼ集約されます。最初にnvidia-smiとnvcc --versionで環境を確認し、最小コードでのコンパイル試行によって問題を局所化するのが効率的なトラブルシューティングの第一歩です。
また、CUDAのバージョン管理にはconda環境を活用する方法も有効です。PyTorchやTensorFlowなどの深層学習フレームワークをcondaでインストールすると、互換性のあるCUDAツールキットが一緒にインストールされ、システム全体の環境を汚さずに管理できます。
conda create -n cuda_env python=3.9
conda activate cuda_env
conda install cuda -c nvidia # または pytorch, tensorflow-gpu など
常にCUDA Toolkit Release Notesやnvccドキュメントを参照し、使用しているソフトウェアスタックの互換性を意識することで、多くのコンパイルエラーを未然に防ぐことができるでしょう。