facebookexperimental/CUTracer
GitHub: facebookexperimental/CUTracer
基于 NVBit 构建的 CUDA 动态二进制插桩工具,专注于内核指令追踪、死锁检测与数据竞争发现。
Stars: 67 | Forks: 9
# CUTracer
CUTracer 是一个基于 [NVBit](https://github.com/NVlabs/NVBit) 构建的 CUDA 二进制插桩工具。它将轻量级的数据收集(插桩)与主机端处理(分析)清晰地分离开来。典型的工作流包括每个 warp 的指令直方图(由 GPU 时钟读取分隔)以及 kernel 挂死检测。
## 功能特性
- 基于 NVBit,通过 `CUDA_INJECTION64_PATH` 进行运行时附加(无需重新构建应用程序)
- 多种插桩模式:仅操作码 (opcode-only)、寄存器追踪 (register trace)、内存追踪 (memory trace)、随机延迟 (random delay)
- 内置分析功能:
- 指令直方图(用于 Proton/Triton 工作流)
- 死锁/挂死检测
- 数据竞争检测
- 兼容 CUDA Graph 和流捕获的工作流
- 确定性的 kernel 日志文件命名与 CSV 输出
## 环境要求
所有环境要求均与 NVBit 保持一致。
特殊要求:
- **libzstd**:用于 trace 压缩
## 安装说明
1. 克隆代码仓库:
```
cd ~
git clone git@github.com:facebookexperimental/CUTracer.git
cd CUTracer
```
2. 安装系统依赖(用于独立构建的 libzstd 静态库):
```
# Ubuntu/Debian
# 在大多数 Ubuntu/Debian 系统上,libzstd-dev 会同时提供动态库和静态库 (libzstd.a)。
# 您可以使用以下命令进行验证:dpkg -L libzstd-dev | grep 'libzstd.a'
# 如果您的发行版在 libzstd-dev 中未提供静态库,您可能需要
# 从源码编译 zstd 或安装特定于发行版的静态 libzstd 包。
sudo apt-get install libzstd-dev
# CentOS/RHEL/Fedora (用于可移植构建的静态库)
sudo dnf install libzstd-static
# 如果静态库不可用,构建将回退到动态链接
# 并显示警告。生成的二进制文件将不是自包含的。
```
3. 下载第三方依赖:
```
./install_third_party.sh
```
这将下载:
- NVBit (NVIDIA 二进制插桩工具)
- nlohmann/json (用于 C++ 的 JSON 库)
4. 构建工具:
```
make -j$(nproc)
```
## 快速入门
### 1. 安装 Python CLI
```
cd ~/CUTracer/python
pip install .
```
### 2. 使用 CUTracer 运行您的 CUDA 应用程序
```
# 选项 A:设置 CUTRACER_LIB_PATH 一次(推荐)
export CUTRACER_LIB_PATH=~/CUTracer/lib
cutracer trace -i tma_trace -- ./your_app
# 选项 B:显式指定 cutracer.so
cutracer trace -i tma_trace --cutracer-so ~/CUTracer/lib/cutracer.so -- ./your_app
# 选项 C:从 CUTracer 项目根目录运行(自动发现 ./lib/cutracer.so)
cd ~/CUTracer
cutracer trace -i tma_trace -- ./your_app
# 选项 D:仅记录 Kernel 启动日志(无插桩,无 trace 文件)
cutracer trace -- ./your_app
```
### 3. 分析输出结果
```
cutracer analyze warp-summary output.ndjson
cutracer query output.ndjson --filter "warp=24"
cutracer validate output.ndjson
```
## 配置 (环境变量)
- `CUTRACER_INSTRUMENT`:以逗号分隔的模式:`opcode_only`、`reg_trace`、`mem_trace`、`random_delay`
- `CUTRACER_ANALYSIS`:以逗号分隔的分析项:`proton_instr_histogram`、`deadlock_detection`、`random_delay`
- 启用 `proton_instr_histogram` 会自动启用 `opcode_only`
- 启用 `deadlock_detection` 会自动启用 `reg_trace`
- 启用 `random_delay` 会自动启用 `random_delay` 插桩;同时需要设置 `CUTRACER_DELAY_NS`
- `KERNEL_FILTERS`:用于匹配未重整或重整后的 kernel 名称的逗号分隔子字符串
- `INSTR_BEGIN`, `INSTR_END`:插桩期间的静态指令索引控制门
- `TOOL_VERBOSE`:0/1/2
- `CUTRACER_TRACE_FORMAT`:trace 输出格式。接受字符串名称或数值(取代了旧版 `TRACE_FORMAT_NDJSON` 环境变量,为了向后兼容仍支持该旧版变量)
- **ndjson** 或 2 (默认):NDJSON 未压缩(`.ndjson`)
- text (或 0):纯文本(`.log`,旧格式,内容详细)
- zstd (或 1):NDJSON+Zstd 压缩(`.ndjson.zst`,约 12 倍压缩率,节省 92% 空间)
- clp (或 3):CLP 归档(`.clp`)
- `CUTRACER_ZSTD_LEVEL`:Zstd 压缩级别 (1-22,默认为 9)
- 较低的值 (1-3):压缩速度较快,输出文件稍大
- 较高的值 (19-22):最大压缩率,速度较慢但输出文件最小
- 默认值 9 提供了均衡的压缩速度和压缩率
- `CUTRACER_DELAY_NS`:用于 `random_delay` 分析的最大延迟值(以纳秒为单位)(启用 `random_delay` 时为必填项)
- `CUTRACER_DELAY_MIN_NS`:最小延迟(以纳秒为单位)—— 随机模式的下限(默认值:0)。必须 ≤ `CUTRACER_DELAY_NS`
- `CUTRACER_DELAY_MODE`:延迟模式:`random`(每个线程的随机延迟在 `[min, max]` 范围内,默认)或 `fixed`(所有线程延迟相同,通常会掩盖数据竞争)
- `CUTRACER_DELAY_DUMP_PATH`:延迟配置 JSON 文件的输出路径(用于记录插桩模式)
- `CUTRACER_DELAY_LOAD_PATH`:延迟配置 JSON 文件的输入路径(用于回放模式 - 确定性重现)
- `CUTRACER_OUTPUT_DIR`:所有 CUTracer 文件(trace 文件和日志文件)的输出目录。默认为当前目录。该目录必须存在且具有写入权限。
- `CUTRACER_CPU_CALLSTACK`:每次 kernel 启动时的 CPU 调用栈捕获模式(默认:`auto`)
- `auto` (默认):优先使用 PyTorch CapturedTraceback 捕获 Python 帧信息,如果 Python/PyTorch 不可用,则回退到 C++ backtrace
- `pytorch`:强制仅使用 PyTorch CapturedTraceback(如果不可用则返回空)
- `backtrace`:强制仅使用 C++ backtrace(原始行为)
- `1`:与 `auto` 相同(向后兼容)
- `0`:禁用调用栈捕获
- 当启用时,`kernel_metadata` trace 事件将包含一个 `cpu_callstack` 数组和一个指示所用捕获方法的 `cpu_callstack_source` 字段(`"pytorch"` 或 `"backtrace"`)
- `CUTRACER_KERNEL_TIMEOUT_S`:Kernel 执行时间限制(以秒为单位)(默认值:0 = 禁用)
- 当 kernel 运行时间超过此值时,使用 SIGTERM 终止进程
- 作为通用安全阀,独立于死锁检测(不需要 `-a deadlock_detection`)
- `CUTRACER_NO_DATA_TIMEOUT_S`:无数据挂起检测超时时间(以秒为单位)(默认值:15)
- 当在此时长内未收到任何 trace 数据时,使用 SIGTERM 终止进程
- 作为通用安全阀,独立于死锁检测(不需要 `-a deadlock_detection`)
- 可捕获所有 warp 都阻塞在同步原语上且 trace 输出为零时的“静默”挂起
- 无论 kernel 在产生一些数据后变为静默,还是从未产生过任何数据,均能正常工作
- 当同时激活 `-a deadlock_detection` 时,将在终止前打印详细的 warp 状态摘要
- 设置为 0 以禁用
- `CUTRACER_TRACE_SIZE_LIMIT_MB`:trace 文件的最大大小(以 MB 为单位)(默认值:0 = 禁用)
- 当任何 trace 文件超过此限制时,将停止对该 kernel 的追踪;kernel 执行将继续正常运行
- 可用于防止失控的 trace 文件填满磁盘(例如,在发生死锁的 kernel 期间)
**注意:**
- 该工具设置 `CUDA_MANAGED_FORCE_DEVICE_ALLOC=1` 以简化通道内存处理。
- 多个分析项可以组合使用(例如,`CUTRACER_ANALYSIS=proton_instr_histogram,deadlock_detection`)。每个分析项会自动启用其所需的插桩模式。
## 分析模块
### 指令直方图 (proton_instr_histogram)
- 统计由时钟读取界定的区域内(启动/停止模型;不支持嵌套区域)每个 warp 的 SASS 指令助记符数量
- 输出:每次 kernel 启动生成一个 CSV 文件,包含 `warp_id,region_id,instruction,count` 列
示例 (Triton/Proton + IPC):
```
cd ~/CUTracer/tests/proton_tests
# 1) 使用 CUTracer 收集直方图
CUDA_INJECTION64_PATH=~/CUTracer/lib/cutracer.so \
CUTRACER_ANALYSIS=proton_instr_histogram \
KERNEL_FILTERS=add_kernel \
python ./vector-add-instrumented.py
# 2) 在不使用 CUTracer 的情况下运行,以生成纯净的 Chrome trace
python ./vector-add-instrumented.py
# 3) 合并并计算 IPC
python ~/CUTracer/scripts/parse_instr_hist_trace.py \
--chrome-trace ./vector.chrome_trace \
--cutracer-trace ./kernel_*_add_kernel_hist.csv \
--cutracer-log ./cutracer_main_*.log \
--output vectoradd_ipc.csv
```
### 死锁 / 挂死检测 (deadlock_detection)
- 通过识别卡在稳定 PC 循环中的 warp 来检测持续性挂死;如果状态持续不变则记录日志并发出 SIGTERM→SIGKILL 信号
- 需要 `reg_trace`(自动启用)
示例 (故意制造的循环):
```
cd ~/CUTracer/tests/hang_test
CUDA_INJECTION64_PATH=~/CUTracer/lib/cutracer.so \
CUTRACER_ANALYSIS=deadlock_detection \
python ./test_hang.py
```
### 数据竞争检测 (random_delay)
- 数据竞争依赖于线程调度和时机——有缺陷的代码可能碰巧表现正常。
此分析通过在**与同步相关的 SASS 指令**(例如 `BAR`、`MEMBAR`、`ATOM`、`RED`)之前注入随机延迟,破坏正常时序,从而迫使潜在的竞争表现为可观察到的故障,以此暴露隐藏的竞争。
- 每个插桩点随机启用/禁用(50% 概率)
- 两种延迟模式:
- **`random`(默认):** 每个线程使用以 `threadIdx/blockIdx/clock` 为种子的 GPU 端 xorshift32 PRNG,获得 `[0, CUTRACER_DELAY_NS]` 范围内的随机延迟。产生逐线程的时序偏差,从而放大数据竞争。**推荐使用。**
- **`fixed`:** 所有线程获得相同的延迟。保留了线程间的相对时序,通常会使竞争被*掩盖*而不是暴露。不推荐用于竞争检测。
- 需要设置 `CUTRACER_DELAY_NS`。`random_delay` 插桩模式将被自动启用。
示例:
```
CUTRACER_DELAY_NS=100000 \
CUTRACER_ANALYSIS=random_delay \
CUDA_INJECTION64_PATH=~/CUTracer/lib/cutracer.so \
python3 your_kernel.py
```
#### 延迟转储与回放
CUTracer 支持将延迟配置转储为 JSON,以便确定性地重现数据竞争:
- **转储模式**:设置 `CUTRACER_DELAY_DUMP_PATH` 可将随机插桩模式保存到 JSON 文件中
- **回放模式**:设置 `CUTRACER_DELAY_LOAD_PATH` 可加载已保存的配置并重现完全相同的延迟模式
**注意**:不能同时使用这两种模式。
**工作流**:
1. 运行时使用 `CUTRACER_DELAY_DUMP_PATH=/tmp/config.json` 来记录延迟模式
2. 当发生故障时,保存该配置文件
3. 使用 `CUTRACER_DELAY_LOAD_PATH=/tmp/config.json` 进行回放,以确定性地重现问题
4. 使用 `cutracer reduce` 进行精简,以找到最小的延迟点集合(见下文)
#### 精简 (Delta Debugging)
`reduce` 子命令用于寻找触发数据竞争的最小延迟注入点集合。两种策略:
- **`linear`**:逐个测试每个点。O(N) 次测试运行。简单但速度慢。
- **`bisect`**:ddmin 风格的二分法。将点集分成两半并递归缩小范围。通常需要 O(log N) 次迭代。**推荐用于大型配置。**
当竞争具有概率性时,使用 `--confidence-runs N`(奇数)进行多数投票。
```
# 二分缩减(快速)
cutracer reduce -c config.json -t ./test_race.sh --strategy bisect --confidence-runs 3
```
测试脚本约定遵循 `llvm-reduce`:退出码 0 = 有趣(发生竞争),退出码 1 及以上 = 无趣(未发生竞争)。
## 示例
[`examples/`](examples/) 目录包含常见工作流的参考 trace 输出:
- **[Proton Trace](examples/proton_trace/)** -- 指令直方图 CSV 示例、CUTracer 日志,以及解释 Triton vector-add kernel 端到端 proton 插桩工作流的 README
## 故障排除
- 没有 CSV/日志输出:检查 `CUDA_INJECTION64_PATH`、`KERNEL_FILTERS` 以及写入权限
- 直方图为空:确保 kernel 发出时钟指令(例如,Triton `pl.scope`)
- 开销过高:优先选择 opcode-only 模式;缩小过滤器范围;使用 `INSTR_BEGIN/INSTR_END`
- CUDA Graph/stream 捕获:数据在 `cuGraphLaunch` 退出时刷新;确保 stream 同步
- IPC 合并问题:使用解析器标志解决 warp 不匹配和 kernel 哈希歧义
## 许可证
本代码仓库包含基于 MIT 许可证 和 BSD-3-Clause 许可证 (NVIDIA) 的代码。详情请参见 [LICENSE](LICENSE) 和 [LICENSE-BSD](LICENSE-BSD)。
## 📚 文档
完整的项目文档位于 [`docs/`](docs/) 目录中,并在每次推送到 `main` 分支时通过
[`.github/workflows/sync-wiki.yml`](.github/workflows/sync-wiki.yml)
自动同步至 [GitHub Wiki](https://github.com/facebookexperimental/CUTracer/wiki)。
**请编辑 `docs/*.md`,而不是直接编辑 wiki** —— 直接编辑 wiki 的内容将在下一次同步时被覆盖。
关键主题:[快速入门](docs/Quickstart.md)、[概念](docs/Concepts.md)、
[配置](docs/Configuration.md)、
[插桩模式](docs/Instrumentation-Modes.md)、
[输出与文件格式](docs/Outputs-and-File-Formats.md)、
[API 与数据结构](docs/API-and-Data-Structures.md)、
[分析模块](docs/Analyses.md)、
[后处理:IPC 合并](docs/Post-processing-IPC-Merge.md)、
[Triton/Proton 集成](docs/Triton_Proton-Integration.md)、
[系统架构](docs/Architecture.md)、
[开发者指南]( )、
[构建、测试与 CI](docs/Build-Test-and-CI.md)、
[故障排除](docs/Troubleshooting.md)、[常见问题](docs/FAQ.md)。
标签:C++, CUDA, CUDA Graph, GPGPU, GPU, NVBit, Python, Vectored Exception Handling, Zstandard压缩, 云资产清单, 代码分析, 内存追踪, 内核指令, 凭证管理, 动态二进制插桩, 威胁情报, 寄存器追踪, 并行计算, 开发者工具, 性能优化, 性能分析, 指令直方图, 数据擦除, 数据竞争, 无后门, 检测绕过, 死锁检测, 计算机体系结构, 逆向工具, 逆向工程, 高性能计算