跳到主要内容
TileLang 系统教程

tilelang-tutorial.huandu.me

第 12 章 调试与性能分析

/code/12-debugging-and-profiling/

05-print-and-assert/README.md2062 字节
# 示例 5:运行期打印与断言(NVIDIA / CUDA 侧)

## 目的

编译期工具回答「IR 对不对」,运行期工具回答「数值对不对」。本示例把 `T.print` 的四种
用法与 `T.device_assert` 放在一起,并重点标注**单线程门控语义**——这是最容易踩的坑。

门控规则(`_vendor/tilelang-v0.1.15/tilelang/cuda/language/print.py:155-194`):

| buffer scope | 门控条件 | 含义 |
| --- | --- | --- |
| `local` | `True` | 所有线程都打印 |
| `local.fragment` | `tx == main_lane and ty == 0 and tz == 0` | 先 `copy` 到 shared,再只由一个线程打印 |
| `shared` / `shared.dyn` | 同上 | 只由一个线程打印 |
| `global` | `True` | 所有线程都打印,输出会被重复 N 次 |

`main_lane` 由 `warp_group_id * 128 + warp_id * 32` 算出(`print.py:149-151`)。
打印标量表达式时,`T.print` 不做任何门控,必须自己加 `if tx == 0` 之类的条件。

## 运行前提

* `--static-only`:任意机器。
* 实际运行:NVIDIA GPU + CUDA toolkit + torch(CUDA) + TileLang v0.1.15。

## 运行命令

```bash
python3 debug_print_demo.py --static-only    # 任何机器
python3 debug_print_demo.py                  # 需要 NVIDIA GPU
```

## 期望输出

`--static-only`(写作机实际输出,退出码 0):

```
py_compile: ok
需要与锁定版本核对的入口(逐个在 _vendor/tilelang-v0.1.15/ 下确认):
  T.print(CUDA 方言,含门控)                   tilelang/cuda/language/print.py:128-207
  T.device_assert(CUDA 方言)               tilelang/cuda/debug.py:23
  device 侧 printf 模板                     src/tl_templates/cuda/debug.h:11-55
  单线程门控常量(warp_group_size=128)           tilelang/cuda/language/print.py:149-151
(本机没有 GPU:这里只核对语法与入口存在性,未运行任何 kernel。)
```

在有 GPU 的机器上运行时,device 端输出形如(格式来自官方 debug 文档与
`src/tl_templates/cuda/debug.h` 的模板,**具体数值取决于实际调度**):

```
msg='shared_buf' BlockIdx=(0, 0, 0), ThreadIdx=(0, 0, 0): buffer=shared_buf, index=0, dtype=half value=...
msg='block_sum' BlockIdx=(0, 0, 0), ThreadIdx=(0, 0, 0): dtype=int value=0
msg='hello from debug_print_demo' BlockIdx=(...), ThreadIdx=(...): dtype=unknown value=...
```

**判据**:kernel 正常结束(没有 device assert 失败),stdout 里能看到上面的消息。

## 代价与限制

* device 侧 `printf` 走受限的片上缓冲,会串行化并且**显著改变耗时**;它只应出现在调试
  版本里,调完必须移除。
* `T.print(global_buf)` 默认每个线程各打印一遍,输出会被放大 `threads` 倍,很容易把
  缓冲区打满。
* `T.device_assert` 的消息会带调用栈(除非 `no_stack_info=True`),非空消息会轻微拖慢
  kernel(源码里有对应告警)。

## 作者实际做到的验证级别

**仅静态核对**:`py_compile` 通过,4 个入口逐个核对;**本机没有 GPU,未运行任何 kernel**。

← 浏览本章全部代码