# CUDA Events - eBPF-based CUDA API Tracing
[eunomia-bpf](https://eunomia.dev) の eBPF チュートリアル「CUDA Events」は、CUDA アプリケーションが GPU とやり取りする CUDA API 呼び出しを、eBPF の uprobe を使ってリアルタイムにトレースする方法を実装例とともに解説する。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
## 目的と位置づけ
GPU 上での処理は非同期かつ独自のメモリ空間を持つため、従来のデバッグ・プロファイリングツールでは内部状態へのアクセスが困難だった。本チュートリアルは、CUDA ランタイムライブラリ `libcudart.so` への uprobe で API 呼び出しを傍受し、メモリ割当サイズ、転送方向と量、カーネル起動パラメータ、API 戻り値、タイミング情報を収集する。これによりアプリケーションコードの改変やプロプライエタリツールに依存せず、GPU 利用のマクロ視図を得る。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
ただし、CPU 側トレースには限界がある。`cudaLaunchKernel` は GPU への作業投入に過ぎず、カーネル内部のスレッド動作やメモリアクセスパターンは見えない。このデバイス内観測には、本チュートリアルが参照する [eGPU](https://dl.acm.org/doi/10.1145/3723851.3726984) や [bpftime GPU examples](https://github.com/bpftime/bpftime) のような PTX 注入型アプローチが必要である。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
## トレース対象となる CUDA 関数
本チュートリアルで計測対象とした CUDA ランタイム API は以下の通り。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
### メモリ管理
- `cudaMalloc` — デバイスメモリ割当。要求サイズと成否を記録。
- `cudaFree` — デバイスメモリ解放。メモリリークや二重解放の検出に役立つ。
### データ転送
- `cudaMemcpy` — ホスト・デバイス間またはデバイス内のコピー。`kind` パラメータで `cudaMemcpyHostToDevice`(1)、`cudaMemcpyDeviceToHost`(2)、`cudaMemcpyDeviceToDevice`(3) を区別する。
### カーネル実行
- `cudaLaunchKernel` — GPU カーネルの起動。gridDim/blockDim/共有メモリ量/ストリームを捕捉する。
### ストリームと同期
- `cudaStreamCreate` — 非同期実行用ストリームの生成。
- `cudaStreamSynchronize` — ストリーム内の処理完了待ち。ボトルネック特定の同期点。
### イベント
- `cudaEventCreate` / `cudaEventRecord` / `cudaEventSynchronize` — タイミング計測と同期用イベント。
### デバイス管理
- `cudaGetDevice` / `cudaSetDevice` — 現在または指定の GPU デバイス。
## アーキテクチャ
トレーサは 3 ファイルで構成される。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
1. **`cuda_events.h`** — カーネル空間とユーザ空間の通信用 `struct event` と `enum cuda_event_type` を定義。
2. **`cuda_events.bpf.c`** — eBPF プログラム。各 CUDA API の enter/return に uprobe/uretprobe を設定。
3. **`cuda_events.c`** — libbpf で eBPF をロードし、ring buffer からイベントを読み出して表示するユーザ空間アプリケーション。
`struct event` は PID、プロセス名、イベント種別、union によるイベント固有データ、`is_return` フラグ、戻り値、詳細文字列を持つ。union を使うことで、同時に必要なデータは 1 種類のみであることを利用して省スペース化している。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
## 実装の要点
### ring buffer
```c
struct {
__uint(type, BPF_MAP_TYPE_RINGBUF);
__uint(max_entries, 256 * 1024);
} rb SEC(".maps");
```
eBPF プログラムは 256 KiB の ring buffer にイベントを投入する。これによりイベントのバーストでもデータ欠落を抑えられる。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
### uprobe/uretprobe
`cudaMalloc` の例:
```c
SEC("uprobe")
int BPF_KPROBE(cuda_malloc_enter, void **ptr, size_t size) {
return submit_malloc_event(size, false, 0);
}
SEC("uretprobe")
int BPF_KRETPROBE(cuda_malloc_exit, int ret) {
return submit_malloc_event(0, true, ret);
}
```
enter プローブで要求サイズ、return プローブでエラーコードを取得する。このパターンを各 CUDA API について繰り返す。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
### ユーザ空間の表示
`handle_event` は ring buffer からイベントを受け取り、時刻・プロセス名・PID・イベント種別・enter/exit・詳細を整形して出力する。`cuda_error_str` 関数で 100 以上ある CUDA エラーコードを人間可読な文字列に変換する。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
## 実行例とベンチマーク
```bash
make
sudo ./cuda_events -p ./basic02
```
典型的な出力は「メモリ割当 → ホストからデバイスへ転送(kind=1) → カーネル起動 → デバイスからホストへ転送(kind=2) → メモリ解放」という CUDA アプリケーションのライフサイクルを反映する。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
ベンチマークでは 1,048,576 バイト(1,024 KiB)、10,000 イテレーションで、トレーサなしと有りの平均レイテンシを比較した。
| 操作 | トレーサなし | トレーサ有り |
|---|---|---|
| cudaMalloc | 113.14 µs | 119.81 µs |
| cudaMemcpyH2D | 365.85 µs | 367.16 µs |
| cudaLaunchKernel | 7.82 µs | 8.77 µs |
| cudaMemcpyD2H | 393.55 µs | 383.66 µs |
本チュートリアルは「トレーサが CUDA API 呼び出しあたり約 2 µs のオーバーヘッドを追加する」と結論づけている。これは多くの用途で無視できるレベルである。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
## コマンドラインオプション
- `-v`: 冗長出力
- `-t`: タイムスタンプ非表示
- `-r`: 関数出口のみ非表示(入口だけ表示)
- `-p PATH`: CUDA ランタイムライブラリまたは対象アプリケーションのパス
- `-d PID`: 特定プロセスのみトレース
## 次のステップ
本チュートリアルは、GPU ドライバ拡張の [gpu_ext](https://github.com/eunomia-bpf/gpu_ext) や [bpftime](https://github.com/bpftime/bpftime) を使ったデバイス内計装へ発展させることができる。さらに他の CUDA API、OpenCL、ROCm への拡張も示唆している。(Source: [[.raw/articles/cuda-events-2026-07-04.md]])
## 関連
- 概念: [[CUDA API トレース]] / [[CUDA]] / [[uprobe]] / [[eBPF]] / [[GPU観測性]] / [[動的計装]]
- エンティティ: [[eunomia-bpf]] / [[bpftime]] / [[libbpf]] / [[NVIDIA]] / [[yunwei37]]
- ソース: [[@2025__HCDS__eGPU - Extending eBPF Programmability and Observability to GPUs]] / [[@2025__eBPF__eInfer - Unlocking Fine-Grained Tracing for Distributed LLM Inference with eBPF]] / [[@2026__arXiv__ProfInfer - An eBPF-based Fine-Grained LLM Inference Profiler]] / [[@2021__yuuk.io__Linux eBPF Tracing Technology]]