0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

CUDA Toolkitってなんだ?〜GPU開発の「工具箱」を完全理解する〜

0
Posted at

この記事の対象読者

  • Pythonの基本的な文法を理解している方
  • 「CUDA」という言葉を聞いたことがあるが、詳しくは知らない方
  • ローカルLLMやStable DiffusionなどGPUを使うツールに興味がある方
  • GPU開発の全体像を把握したいエンジニア

この記事で得られること

  • CUDA Toolkitの構成要素と各コンポーネントの役割の理解
  • nvcc(CUDAコンパイラ)の仕組みとコンパイルフローの把握
  • CUDA付属ライブラリ(cuBLAS, cuFFT等)の概要と使い分け
  • 開発ツール(Nsight Systems/Compute)によるプロファイリングの基礎
  • 環境構築から動作確認までの実践的な手順

この記事で扱わないこと

  • CUDAカーネルのゴリゴリな最適化テクニック
  • マルチGPUプログラミング
  • CUDA Cによる本格的なカスタムカーネル開発

1. CUDA Toolkitとの出会い

「PyTorchインストールしたのに、なんでCUDA Toolkitも入れなきゃいけないの?」

GPU環境を構築していて、こんな疑問を抱いたことはないだろうか。私は何度もあった。

最初は「とりあえずcondaで入れておけばいい」くらいの認識だった。しかし、ある日Stable Diffusionの推論速度を最適化しようとしたとき、壁にぶつかった。xformersのビルドに失敗し、エラーメッセージには「nvccが見つからない」の文字。

「nvccって何だ...?」

そこから調べ始めて、CUDA Toolkitが単なる「おまけ」ではなく、GPU開発の根幹を支える「工具箱」だと気づいた。

CUDA Toolkitは、NVIDIAが提供するGPU開発の総合パッケージだ。コンパイラ、ライブラリ、デバッグツール、プロファイラ...GPU開発に必要なものが全部入っている。いわば「GPU職人の道具一式」。

ここまでで、CUDA Toolkitがどんな立ち位置なのか、なんとなくイメージできただろうか。次は、この道具箱の中身を一つずつ見ていこう。


2. 前提知識の確認

本題に入る前に、この記事で使う用語を整理しておく。

2.1 CUDA(Compute Unified Device Architecture)とは

NVIDIAが開発した、GPUで汎用計算を行うためのプラットフォーム。2007年にリリースされ、今ではAI/ML分野のデファクトスタンダードになっている。

2.2 GPU(Graphics Processing Unit)とは

もともとは画像処理専用のプロセッサ。数千のコアを持ち、並列処理が得意。CPUが「少数精鋭の専門家チーム」なら、GPUは「大人数の作業員軍団」。

2.3 コンパイラとは

人間が書いたプログラムを、機械が実行できる形式に変換するソフトウェア。C言語ならgcc、Rustならrustc、そしてCUDAならnvcc。

2.4 ライブラリとは

よく使う機能をまとめた「部品集」。自分で一から書かなくても、ライブラリを呼び出すだけで高度な処理ができる。

これらの用語が押さえられたら、次に進もう。


3. CUDA Toolkitが生まれた背景

3.1 GPUプログラミングの黎明期

2000年代初頭、GPUで科学計算をしようとすると、OpenGLやDirectXといったグラフィックスAPIを「騙して」使う必要があった。計算結果をピクセルの色に変換したり、逆変換したり...正直、地獄だった。

3.2 NVIDIAの決断

2006年、NVIDIAは画期的な決断をした。「GPUを汎用計算に開放しよう」と。そして2007年、CUDA 1.0がリリースされた。これにより、GPUプログラミングは「グラフィックスの裏技」から「正式なプログラミングモデル」へと進化した。

3.3 現在の立ち位置

今やCUDAは、深層学習フレームワーク(PyTorch、TensorFlow)、科学計算、金融シミュレーション、医療画像処理など、あらゆる分野で使われている。CUDA Toolkitはその開発基盤として、年々進化を続けている。

背景がわかったところで、抽象的な概念から順に、具体的なコンポーネントを見ていこう。


4. CUDA Toolkitの全体像

CUDA Toolkitは大きく4つのカテゴリに分類できる。

カテゴリ 主なコンポーネント 役割
コンパイラ nvcc, nvrtc CUDAコードを実行可能形式に変換
ライブラリ cuBLAS, cuFFT, cuDNN等 高性能な数学関数を提供
ランタイム CUDA Runtime API, Driver API GPUとの通信を抽象化
開発ツール Nsight Systems/Compute, cuda-gdb デバッグとプロファイリング

これを「GPU開発の工具箱」に例えると、こうなる。

CUDA Toolkit(工具箱)
├── nvcc(ドライバー)       → コードを組み立てる道具
├── cuBLAS/cuFFT(電動工具) → 重い作業を自動化
├── Runtime API(説明書)    → GPUの使い方ガイド
└── Nsight(測定器)         → 性能を計測・診断

基本概念が理解できたところで、これらの抽象的な概念を具体的なコンポーネントの解説に落とし込んでいこう。


5. nvcc: CUDAコンパイラの仕組み

5.1 nvccとは何か

nvcc(NVIDIA CUDA Compiler)は、CUDAコードをコンパイルするためのドライバプログラム。実際には複数のツールを内部で呼び出し、複雑なコンパイル処理を一手に引き受けてくれる。

5.2 コンパイルの流れ

CUDAプログラムのコンパイルは、以下の流れで進む。

ソースコード (.cu)
    ↓
[前処理] デバイスコードとホストコードを分離
    ↓
[デバイスコンパイル] → PTX(中間表現)→ cubin(バイナリ)
    ↓
[ホストコンパイル] → g++/clang で通常のC++としてコンパイル
    ↓
[リンク] デバイスコードをfatbinaryとしてホストコードに埋め込み
    ↓
実行可能ファイル

5.3 PTX, cubin, fatbinaryって何?

この3つの用語は、CUDAコンパイルを理解する上で重要だ。

形式 説明 例えるなら
PTX 仮想的な中間表現。GPUアーキテクチャに依存しない 設計図
cubin 特定のGPUアーキテクチャ向けのバイナリ 完成品
fatbinary 複数のPTX/cubinをまとめたコンテナ 詰め合わせセット

PTXの利点は「前方互換性」。古いCUDA Toolkitでコンパイルしたコードでも、新しいGPUで実行するときにJIT(Just-In-Time)コンパイルされる。

5.4 アーキテクチャ指定の重要性

nvccでは-archオプションでターゲットアーキテクチャを指定する。

# 仮想アーキテクチャ(PTX生成)
nvcc -arch=compute_89 sample.cu -o sample

# 実アーキテクチャ(cubin生成)
nvcc -arch=sm_89 sample.cu -o sample

# 複数ターゲット(推奨)
nvcc -gencode arch=compute_80,code=sm_80 \
     -gencode arch=compute_89,code=sm_89 \
     -gencode arch=compute_89,code=compute_89 \
     sample.cu -o sample

最後の例では、sm_80とsm_89向けのcubinと、将来のGPU向けのPTXを同時に生成している。

nvccの仕組みがわかったところで、次はCUDA Toolkitに含まれるライブラリ群を見ていこう。


6. CUDAライブラリ: 高性能計算の「電動工具」

CUDA Toolkitには、GPU最適化された数学ライブラリが多数含まれている。これらを使えば、自分でカーネルを書かなくても高性能な処理が可能になる。

6.1 主要ライブラリ一覧

ライブラリ 正式名称 用途 CPU版の相当品
cuBLAS CUDA Basic Linear Algebra Subroutines 行列演算(GEMM等) OpenBLAS, MKL
cuFFT CUDA Fast Fourier Transform 高速フーリエ変換 FFTW
cuSPARSE CUDA Sparse Matrix 疎行列演算 MKL Sparse
cuSOLVER CUDA Solver 連立方程式、固有値計算 LAPACK
cuRAND CUDA Random Number Generation 乱数生成 -
NPP NVIDIA Performance Primitives 画像・信号処理 Intel IPP
cuDNN CUDA Deep Neural Network 深層学習の基本演算 -

6.2 cuBLAS: 行列演算の主役

深層学習の計算の大部分は行列演算。cuBLASはその心臓部を担う。

# PyTorchでの行列積(内部でcuBLASが呼ばれる)
import torch

a = torch.randn(1024, 1024, device='cuda')
b = torch.randn(1024, 1024, device='cuda')
c = torch.mm(a, b)  # cuBLASのSGEMM/DGEMMが動く

6.3 cuFFT: 信号処理の定番

音声処理や画像処理でおなじみのFFT。cuFFTを使えばGPUで高速に実行できる。

import torch.fft

signal = torch.randn(1024, device='cuda')
spectrum = torch.fft.fft(signal)  # cuFFTが動く

6.4 cuDNN: 深層学習の縁の下の力持ち

畳み込み、正規化、活性化関数など、深層学習に必要な演算を高度に最適化。PyTorchやTensorFlowは内部でcuDNNを呼び出している。

# cuDNNのベンチマークモード(最適なアルゴリズムを自動選択)
torch.backends.cudnn.benchmark = True

ライブラリの概要が把握できたところで、次はRuntime APIとDriver APIの違いを見ていこう。


7. Runtime API vs Driver API

CUDAには2つのAPIレベルが存在する。これが初心者を混乱させる原因の一つ。

7.1 二つのAPIの違い

項目 Runtime API Driver API
ヘッダ cuda_runtime.h cuda.h
ライブラリ libcudart.so libcuda.so
提供元 CUDA Toolkit NVIDIAドライバ
抽象度 高い(使いやすい) 低い(細かい制御可能)
初期化 暗黙的 明示的
用途 一般的なCUDAアプリ ランタイム開発、JITコンパイル

7.2 どちらを使うべきか

結論から言うと、99%の開発者はRuntime APIで十分

// Runtime API(簡潔)
cudaMalloc(&d_ptr, size);
cudaMemcpy(d_ptr, h_ptr, size, cudaMemcpyHostToDevice);
myKernel<<<grid, block>>>(d_ptr);

// Driver API(冗長だが細かい制御可能)
cuMemAlloc(&d_ptr, size);
cuMemcpyHtoD(d_ptr, h_ptr, size);
cuLaunchKernel(kernel, gridX, gridY, gridZ, blockX, blockY, blockZ, ...);

Driver APIが必要なケースは、以下のような特殊な状況に限られる。

  • カスタムランタイムの開発
  • 動的なカーネルロード/アンロード
  • 複数のCUDAコンテキストの細かい制御

7.3 PyTorchユーザーは気にしなくていい

PyTorchやTensorFlowを使う場合、これらのAPIは完全に隠蔽されている。フレームワークが適切なAPIを選択してくれるので、意識する必要はない。

APIの違いが理解できたところで、次は開発ツールによるデバッグとプロファイリングを見ていこう。


8. 開発ツール: Nsightファミリー

8.1 Nsight Systemsとは

システム全体のパフォーマンスを可視化するプロファイラ。CPU/GPU間のデータ転送、カーネル実行のタイムライン、メモリ使用量などを一目で把握できる。

# プロファイル実行
nsys profile --stats=true python train.py

# 出力例
Time (%)  Total Time (ns)  Instances  Avg (ns)   Operation
--------  ---------------  ---------  ---------  --------------------------
   45.2       1,234,567          100    12,345  CUDA Kernel: forward_pass
   30.1         823,456           50    16,469  CUDA memcpy HtoD
   24.7         675,432           50    13,508  CUDA memcpy DtoH

8.2 Nsight Computeとは

個々のCUDAカーネルを詳細に分析するプロファイラ。占有率、メモリスループット、演算スループットなど、カーネルレベルの最適化に必要な情報を提供。

# 特定のカーネルをプロファイル
ncu --set full python inference.py

# roofline analysisを実行
ncu --set roofline python inference.py

8.3 使い分けの指針

パフォーマンス問題の調査フロー:

1. まずNsight Systemsで全体像を把握
   ↓ ボトルネックのカーネルを特定
2. Nsight Computeで詳細分析
   ↓ 最適化ポイントを発見
3. 改善 → 再度Nsight Systemsで効果確認

8.4 cuda-gdb: GPUデバッガ

GDBの拡張版。ブレークポイント設定、変数検査、スレッド状態確認など、CPUデバッグと同じ感覚でGPUコードをデバッグできる。

cuda-gdb ./my_cuda_app
(cuda-gdb) break myKernel
(cuda-gdb) run
(cuda-gdb) cuda thread  # 現在のGPUスレッド情報
(cuda-gdb) info cuda kernels  # 実行中のカーネル一覧

開発ツールの概要を押さえたところで、実際にCUDA Toolkitをインストールして動かしてみよう。


9. 実際に使ってみよう

9.1 環境構築

インストール方法の選択

方法 メリット デメリット
公式インストーラ 完全なToolkit システム汚染のリスク
conda 環境分離可能 バージョンが古い場合あり
Docker 完全な分離 オーバーヘッド

9.2 設定ファイルの準備

以下の3種類の環境設定を用意した。用途に応じて選択してほしい。

開発環境用(cuda_env_dev.sh)

#!/bin/bash
# cuda_env_dev.sh - 開発環境用(このままコピーして使える)

# CUDA Toolkit のパス設定
export CUDA_HOME=/usr/local/cuda
export PATH=$CUDA_HOME/bin:$PATH
export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH

# デバッグ用設定
export CUDA_LAUNCH_BLOCKING=1  # 同期実行(デバッグしやすい)
export CUDA_VISIBLE_DEVICES=0  # 使用するGPUを限定

# コンパイラ設定
export NVCC_GENCODE="-gencode arch=compute_89,code=sm_89"

echo "CUDA開発環境を設定しました"
echo "CUDA Version: $(nvcc --version | grep release)"

本番環境用(cuda_env_prod.sh)

#!/bin/bash
# cuda_env_prod.sh - 本番環境用(このままコピーして使える)

# CUDA Toolkit のパス設定
export CUDA_HOME=/usr/local/cuda
export PATH=$CUDA_HOME/bin:$PATH
export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH

# パフォーマンス最適化設定
export CUDA_LAUNCH_BLOCKING=0  # 非同期実行(高速)
export CUDA_AUTO_BOOST=1       # クロック自動ブースト有効

# cuDNN最適化
export CUDNN_BENCHMARK=1       # ベンチマークモード有効

# マルチGPU設定(必要に応じて変更)
# export CUDA_VISIBLE_DEVICES=0,1,2,3

echo "CUDA本番環境を設定しました"

CI/テスト環境用(cuda_env_test.sh)

#!/bin/bash
# cuda_env_test.sh - CI/テスト環境用(このままコピーして使える)

# CUDA Toolkit のパス設定
export CUDA_HOME=/usr/local/cuda
export PATH=$CUDA_HOME/bin:$PATH
export LD_LIBRARY_PATH=$CUDA_HOME/lib64:$LD_LIBRARY_PATH

# 再現性重視の設定
export CUDA_LAUNCH_BLOCKING=1
export CUBLAS_WORKSPACE_CONFIG=:4096:8  # 決定論的動作
export CUDNN_DETERMINISTIC=1            # cuDNN決定論的モード

# テスト用に最小リソース
export CUDA_VISIBLE_DEVICES=0

echo "CUDAテスト環境を設定しました(決定論的モード)"

9.3 動作確認コード

"""
cuda_check.py - CUDA Toolkit動作確認スクリプト
使い方: python cuda_check.py
"""
import subprocess
import sys

def check_nvcc():
    """nvccのバージョン確認"""
    try:
        result = subprocess.run(
            ['nvcc', '--version'],
            capture_output=True,
            text=True
        )
        print("=== nvcc (CUDAコンパイラ) ===")
        print(result.stdout)
        return True
    except FileNotFoundError:
        print("ERROR: nvccが見つかりません")
        print("CUDA Toolkitがインストールされているか確認してください")
        return False

def check_pytorch_cuda():
    """PyTorchからのCUDA確認"""
    try:
        import torch
        print("=== PyTorch CUDA情報 ===")
        print(f"PyTorch Version: {torch.__version__}")
        print(f"CUDA Available: {torch.cuda.is_available()}")
        
        if torch.cuda.is_available():
            print(f"CUDA Version: {torch.version.cuda}")
            print(f"cuDNN Version: {torch.backends.cudnn.version()}")
            print(f"GPU Count: {torch.cuda.device_count()}")
            
            for i in range(torch.cuda.device_count()):
                props = torch.cuda.get_device_properties(i)
                print(f"\nGPU {i}: {props.name}")
                print(f"  Compute Capability: {props.major}.{props.minor}")
                print(f"  Total Memory: {props.total_memory / 1024**3:.1f} GB")
                print(f"  SM Count: {props.multi_processor_count}")
        return True
    except ImportError:
        print("PyTorchがインストールされていません")
        return False

def check_cuda_libraries():
    """CUDAライブラリの確認"""
    try:
        import torch
        if not torch.cuda.is_available():
            return False
            
        print("\n=== CUDAライブラリ動作確認 ===")
        
        # cuBLAS確認(行列積)
        a = torch.randn(100, 100, device='cuda')
        b = torch.randn(100, 100, device='cuda')
        c = torch.mm(a, b)
        print("cuBLAS (GEMM): OK")
        
        # cuFFT確認
        signal = torch.randn(1024, device='cuda')
        spectrum = torch.fft.fft(signal)
        print("cuFFT (FFT): OK")
        
        # cuDNN確認(畳み込み)
        conv = torch.nn.Conv2d(3, 64, 3, device='cuda')
        x = torch.randn(1, 3, 224, 224, device='cuda')
        y = conv(x)
        print("cuDNN (Conv2d): OK")
        
        # cuRAND確認
        rand = torch.rand(1000, device='cuda')
        print("cuRAND (Random): OK")
        
        return True
    except Exception as e:
        print(f"ERROR: {e}")
        return False

def main():
    print("=" * 50)
    print("CUDA Toolkit 動作確認")
    print("=" * 50)
    
    results = []
    results.append(("nvcc", check_nvcc()))
    results.append(("PyTorch CUDA", check_pytorch_cuda()))
    results.append(("CUDA Libraries", check_cuda_libraries()))
    
    print("\n" + "=" * 50)
    print("確認結果サマリー")
    print("=" * 50)
    for name, status in results:
        mark = "OK" if status else "NG"
        print(f"  {name}: {mark}")
    
    all_ok = all(status for _, status in results)
    sys.exit(0 if all_ok else 1)

if __name__ == "__main__":
    main()

9.4 実行結果

上記のコードを実行すると、以下のような出力が得られる。

==================================================
CUDA Toolkit 動作確認
==================================================
=== nvcc (CUDAコンパイラ) ===
nvcc: NVIDIA (R) Cuda compiler driver
Copyright (c) 2005-2024 NVIDIA Corporation
Built on ...
Cuda compilation tools, release 12.4, V12.4.131

=== PyTorch CUDA情報 ===
PyTorch Version: 2.2.0
CUDA Available: True
CUDA Version: 12.1
cuDNN Version: 8902
GPU Count: 1

GPU 0: NVIDIA GeForce RTX 4090
  Compute Capability: 8.9
  Total Memory: 24.0 GB
  SM Count: 128

=== CUDAライブラリ動作確認 ===
cuBLAS (GEMM): OK
cuFFT (FFT): OK
cuDNN (Conv2d): OK
cuRAND (Random): OK

==================================================
確認結果サマリー
==================================================
  nvcc: OK
  PyTorch CUDA: OK
  CUDA Libraries: OK

9.5 よくあるエラーと対処法

エラー 原因 対処法
nvcc: command not found PATHが通っていない export PATH=/usr/local/cuda/bin:$PATH
libcudart.so: cannot open LD_LIBRARY_PATHの問題 export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH
CUDA driver version is insufficient ドライバが古い NVIDIAドライバを更新
no kernel image is available アーキテクチャ不一致 正しい-archオプションでリビルド
CUDA out of memory VRAM不足 バッチサイズ削減、torch.cuda.empty_cache()

基本的な使い方をマスターしたので、次はユースケース別のガイドを見ていこう。


10. ユースケース別ガイド

10.1 ユースケース1: PyTorchでの深層学習

想定読者: 深層学習エンジニア、データサイエンティスト

推奨構成: conda環境 + PyTorch公式バイナリ

サンプルコード:

"""
pytorch_cuda_example.py - PyTorchでのCUDA活用例
"""
import torch
import torch.nn as nn
import time

def benchmark_cuda():
    """CPU vs GPU の性能比較"""
    # モデル定義
    model = nn.Sequential(
        nn.Linear(1024, 2048),
        nn.ReLU(),
        nn.Linear(2048, 2048),
        nn.ReLU(),
        nn.Linear(2048, 1024)
    )
    
    x = torch.randn(256, 1024)
    
    # CPU実行
    model_cpu = model.to('cpu')
    x_cpu = x.to('cpu')
    
    start = time.time()
    for _ in range(100):
        _ = model_cpu(x_cpu)
    cpu_time = time.time() - start
    
    # GPU実行
    if torch.cuda.is_available():
        model_gpu = model.to('cuda')
        x_gpu = x.to('cuda')
        
        # ウォームアップ
        _ = model_gpu(x_gpu)
        torch.cuda.synchronize()
        
        start = time.time()
        for _ in range(100):
            _ = model_gpu(x_gpu)
        torch.cuda.synchronize()
        gpu_time = time.time() - start
        
        print(f"CPU Time: {cpu_time:.3f}s")
        print(f"GPU Time: {gpu_time:.3f}s")
        print(f"Speedup: {cpu_time/gpu_time:.1f}x")
    else:
        print("CUDA is not available")

if __name__ == "__main__":
    benchmark_cuda()

10.2 ユースケース2: カスタムCUDAカーネルのビルド

想定読者: パフォーマンス最適化エンジニア、ライブラリ開発者

推奨構成: 公式CUDA Toolkitフルインストール

サンプルコード:

"""
custom_kernel_build.py - PyTorchでカスタムCUDA拡張をビルド
"""
import torch
from torch.utils.cpp_extension import load_inline

# CUDAカーネルのソースコード
cuda_source = """
__global__ void vector_add_kernel(
    const float* a, const float* b, float* c, int n
) {
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if (idx < n) {
        c[idx] = a[idx] + b[idx];
    }
}

torch::Tensor vector_add_cuda(torch::Tensor a, torch::Tensor b) {
    auto c = torch::empty_like(a);
    int n = a.numel();
    
    int threads = 256;
    int blocks = (n + threads - 1) / threads;
    
    vector_add_kernel<<<blocks, threads>>>(
        a.data_ptr<float>(),
        b.data_ptr<float>(),
        c.data_ptr<float>(),
        n
    );
    
    return c;
}
"""

cpp_source = """
torch::Tensor vector_add_cuda(torch::Tensor a, torch::Tensor b);
"""

def build_and_test():
    """カスタムカーネルをビルドしてテスト"""
    # JITコンパイル
    custom_ops = load_inline(
        name='custom_vector_add',
        cpp_sources=cpp_source,
        cuda_sources=cuda_source,
        functions=['vector_add_cuda'],
        verbose=True
    )
    
    # テスト
    a = torch.randn(10000, device='cuda')
    b = torch.randn(10000, device='cuda')
    
    # カスタムカーネルで実行
    c_custom = custom_ops.vector_add_cuda(a, b)
    
    # PyTorch標準で実行(検証用)
    c_pytorch = a + b
    
    # 結果確認
    assert torch.allclose(c_custom, c_pytorch)
    print("Custom CUDA kernel works correctly!")

if __name__ == "__main__":
    build_and_test()

10.3 ユースケース3: プロファイリングによる最適化

想定読者: パフォーマンスチューニングを行うエンジニア

推奨構成: Nsight Systems + Nsight Compute

サンプルコード:

"""
profiling_example.py - Nsightでプロファイリングする例
実行: nsys profile python profiling_example.py
"""
import torch
import torch.nn as nn
import torch.cuda.nvtx as nvtx  # NVIDIAプロファイラ用マーカー

class ProfiledModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.conv1 = nn.Conv2d(3, 64, 3, padding=1)
        self.conv2 = nn.Conv2d(64, 128, 3, padding=1)
        self.fc = nn.Linear(128 * 56 * 56, 1000)
        
    def forward(self, x):
        # NVTXマーカーで各レイヤーを識別
        with nvtx.range("conv1"):
            x = torch.relu(self.conv1(x))
            x = torch.max_pool2d(x, 2)
        
        with nvtx.range("conv2"):
            x = torch.relu(self.conv2(x))
            x = torch.max_pool2d(x, 2)
        
        with nvtx.range("fc"):
            x = x.view(x.size(0), -1)
            x = self.fc(x)
        
        return x

def main():
    model = ProfiledModel().cuda()
    x = torch.randn(32, 3, 224, 224, device='cuda')
    
    # ウォームアップ
    for _ in range(10):
        _ = model(x)
    torch.cuda.synchronize()
    
    # プロファイリング対象の実行
    with nvtx.range("inference_batch"):
        for i in range(100):
            with nvtx.range(f"iteration_{i}"):
                output = model(x)
    
    torch.cuda.synchronize()
    print("Profiling complete. Check the .nsys-rep file.")

if __name__ == "__main__":
    main()

ユースケースが把握できたところで、この記事を読んだ後の学習パスを確認しよう。


11. 学習ロードマップ

この記事を読んだ後、次のステップとして以下をおすすめする。

初級者向け(まずはここから)

  1. CUDA公式チュートリアルを試す
  2. サンプルプロジェクトを動かす

中級者向け(実践に進む)

  1. Nsightツールでプロファイリングを習得
  2. cuBLAS/cuDNNの直接利用を学ぶ

上級者向け(さらに深く)

  1. CUDAプログラミングガイドを精読
  2. カスタムカーネル最適化に挑戦

12. まとめ

この記事では、CUDA Toolkitについて以下を解説した。

  1. 全体像: コンパイラ、ライブラリ、ランタイム、開発ツールの4カテゴリ
  2. nvcc: CUDAコードをPTX/cubinにコンパイルする仕組み
  3. ライブラリ群: cuBLAS、cuFFT、cuDNNなどの役割と使い分け
  4. API: Runtime APIとDriver APIの違い
  5. 開発ツール: Nsight Systems/Computeによるプロファイリング

私の所感

正直なところ、CUDA Toolkitを「完全に理解した」と言えるエンジニアは少ないと思う。コンポーネントが多すぎて、全部を使いこなすのは不可能に近い。

でも、それでいい。

大事なのは「どこに何があるか」を把握しておくこと。PyTorchが遅いと感じたらNsightで調べる。カスタムカーネルが必要になったらnvccの使い方を調べる。そういう「地図」があれば、必要なときに深掘りできる。

この記事が、あなたのGPU開発の「地図」になれば幸いだ。


参考文献

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?