关于 cuda-debugging
面向 CUDA 开发者的调试技能,涵盖内核交互式检查、内存与竞态检测、核心转储分析、设备端 printf 和运行时错误排查。
主要功能
- 01使用 cuda-gdb 单步调试内核
- 02检测内存错误与竞态
- 03分析 GPU 核心转储
- 04使用设备端 printf 调试
- 05排查 CUDA 错误码
适用场景
- 01诊断 GPU 非法内存访问
- 02调查间歇性竞态故障
- 03逐步检查内核执行
- 04排查内核挂起与超时
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ mohitmishra786/ low-level-dev-skills --skill cuda-debugging安装后在 Claude Code 中输入/cuda-debugging确认已加载。
详细介绍
CUDA 调试
目的
指导 Agent 使用 cuda-gdb 交互式检查 GPU 线程、使用 NVIDIA Compute Sanitizer 自动检测内存错误和竞态、分析 GPU 核心转储、使用设备端 printf,以及排查常见的 CUDA 运行时错误代码。
适用场景
- 出现
cudaErrorIllegalAddress(700)或设备端段错误 - 多线程 GPU 代码间歇性出现正确性问题
- 调试 warp 之间或主机与设备之间的竞态条件
- 使用 cuda-gdb 逐行执行内核代码
- 使用 initcheck 验证未初始化内存读取
- 内核挂起或出现
cudaErrorLaunchTimeout(702)
工作流
1. 为调试构建
# Debug build — disables optimizations, enables device debug
nvcc -G -g -O0 -arch=sm_80 -o app_debug main.cu
# Sanitizer-friendly build (lineinfo helps reports)
nvcc -lineinfo -g -O2 -arch=sm_80 -o app_san main.cu
cuda-gdb 要进行源码级单步调试,必须使用 -G。Sanitizer 可用于优化构建,但 -G 能提供更清晰的行号。
2. Compute Sanitizer — 自动检查
# Memory errors (OOB, misaligned, leak)
compute-sanitizer --tool memcheck ./app_san
# Shared memory and global memory races
compute-sanitizer --tool racecheck ./app_san
# Uninitialized memory reads
compute-sanitizer --tool initcheck ./app_san
# Synchronization errors (missing __syncthreads)
compute-sanitizer --tool synccheck ./app_san
# Verbose with source correlation
compute-sanitizer --tool memcheck --show-reachable=yes --log-file san.log ./app_san
典型的 memcheck 输出:
======== Invalid __global__ write of size 4
======== at 0x1a0 in vector_add(vector_add.cu:12)
======== by thread (0,0,0) in block (0,0,0)
======== Address 0x7f... is out of bounds
3. cuda-gdb 交互式会话
# Launch under cuda-gdb
cuda-gdb ./app_debug
# Or attach to running process
cuda-gdb -p <pid>
常用命令:
# Break at kernel entry
(cuda-gdb) break vector_add
(cuda-gdb) run
# Focus on GPU threads
(cuda-gdb) info cuda kernels
(cuda-gdb) cuda kernel 0
(cuda-gdb) cuda thread (0,0,0) # block (x,y,z), thread (x,y,z)
# Inspect device memory
(cuda-gdb) print data[i]
(cuda-gdb) x/10f d_ptr
# Step in kernel
(cuda-gdb) cuda step
(cuda-gdb) cuda next
# All threads in block
(cuda-gdb) info cuda threads
(cuda-gdb) cuda thread (0,0,5)
4. 设备端 printf
__global__ void debug_kernel(float *data, int n) {
int i = blockIdx.x * blockDim.x + threadIdx.x;
if (i < n) {
if (i < 5) // limit output
printf("thread %d: data[%d] = %f\n", i, i, data[i]);
data[i] *= 2.0f;
}
}
# Buffer size for printf (default may truncate)
cuda-gdb) set cuda printf_buffer_size 16777216
检查输出前,使用 cudaDeviceSynchronize() 刷新缓冲区。所有线程过量调用 printf 会导致缓冲区不堪重负。
5. 错误代码排查
| 代码 | 名称 | 常见原因 |
|---|---|---|
| 700 | cudaErrorIllegalAddress | 越界访问、释放后使用、指针错误 |
| 701 | cudaErrorLaunchOutOfResources | 每个 block 的共享内存或寄存器用量过大 |
| 702 | cudaErrorLaunchTimeout | 无限循环、TDR 看门狗(Windows/默认 Linux) |
| 719 | cudaErrorLaunchFailure | 内核中的断言、栈溢出 |
// Always check after launch
kernel<<<grid, block>>>(args);
cudaError_t err = cudaGetLastError();
if (err != cudaSuccess)
fprintf(stderr, "launch: %s\n", cudaGetErrorString(err));
cudaDeviceSynchronize();
err = cudaGetLastError();
if (err != cudaSuccess)
fprintf(stderr, "exec: %s\n", cudaGetErrorString(err));
6. GPU 核心转储
# Enable coredump (driver 450+)
export CUDA_ENABLE_COREDUMP_ON_EXCEPTION=1
export CUDA_COREDUMP_FILE=/tmp/cuda_coredump_%h.%p
./app_san # crash generates dump
# Analyze with cuda-gdb
cuda-gdb ./app_san /tmp/cuda_coredump_hostname.pid
(cuda-gdb) cuda coredump load /tmp/cuda_coredump_hostname.pid
(cuda-gdb) bt
(cuda-gdb) info cuda kernels
7. 调试决策树
Crash or wrong results?
├── Consistent wrong values → logic bug; use printf or cuda-gdb
├── Intermittent / depends on size → OOB or race
│ ├── compute-sanitizer --tool memcheck
│ └── compute-sanitizer --tool racecheck
├── Hang / timeout 702 → infinite loop or barrier mismatch
│ └── synccheck; audit __syncthreads paths
└── Works in debug (-G), fails in release → uninitialized mem or race
└── initcheck + racecheck on release build
8. 多 GPU 和 MIG 说明
# Isolate GPU
CUDA_VISIBLE_DEVICES=0 compute-sanitizer --tool memcheck ./app
# MIG instances appear as separate devices
nvidia-smi -L
常见问题
| 现象 | 原因 | 解决方法 |
|---|---|---|
| cuda-gdb 无法在内核中设置断点 | 构建时未使用 -G | 使用 nvcc -G -g -O0 重新构建 |
| Sanitizer 未报告错误,但崩溃仍然存在 | 异步错误延迟出现 | 在内核后添加 cudaDeviceSynchronize() |
printf 没有任何输出 | 缓冲区已满或未同步 | 限制打印量;增大缓冲区;执行同步 |
| racecheck 对原子操作误报 | 使用了非原子的读-改-写操作 | 使用 atomicAdd/atomicCAS |
| 附加失败 | 进程尚未进入 CUDA 上下文 | 在首次调用 cudaMalloc 后设置断点 |
| Windows 上发生 TDR 超时 | 内核运行时间过长 | 拆分内核;使用 cudaDeviceSetLimit 或 regedit 调整 TDR |
相关技能
skills/gpu/cuda— 内核模式、内存层次结构、启动配置skills/gpu/cuda-profiling— 验证正确性后进行性能分析skills/gpu/gpu-memory-model— 理解竞态和合并访问skills/debuggers/gdb— 与 cuda-gdb 共用的主机端 GDB 命令skills/runtimes/sanitizers— 主机代码的 ASan/TSan 概念skills/kernel/kernel-debugging— 针对驱动程序级问题的 kgdb/kprobes
评论
支持 Markdown