1. 编译带 NVTX 的 Mooncake
cmake -B build -DUSE_CUDA=ON -DPXN_ENABLE_NVTX=ON <你原来的参数>
cmake --build build -j
# configure 时应看到 "PXN NVTX ranges enabled"装到 sglang 用的 python 环境里(你的 mooncake-wheel 流程)。
2. 用 nsys 包住 prefill or decode服务
nsys profile \
-t cuda,nvtx,osrt \
-o /tmp/pxn_prefill \
--capture-range=cudaProfilerApi \
--capture-range-end=stop \
--cuda-memory-usage=false \
--force-overwrite=true \
python -m sglang.launch_server \
--disaggregation-mode prefill \
<你原来的所有参数>--capture-range=cudaProfilerApi 是核心 —— nsys 启动后不采集,一直等到进程里调 cudaProfilerStart() 才开始。这样跳过模型加载、warmup,只抓你圈定的窗口。
--capture-range-end=stop 表示收到 cudaProfilerStop() 就结束采集并落盘。
多进程注意:TP8 下 sglang 会 fork 出 8 个 scheduler 进程。nsys 默认跟踪子进程,会产出一个包含所有 rank 的 report。而
profiler_manager.py:260有个if self.ps.gpu_id == get_device().base_gpu_id的守卫 —— 只有 base GPU 那个 rank 会真正调cudaProfilerStart。所以采集窗口由 rank0 控制,但数据是全部 rank 的。文件会比较大,建议窗口卡短。
3. 等服务起来,然后圈窗口
# 确认 ready
curl http://localhost:30000/health
# 先跑几个请求 warmup(这时 nsys 还没开始采集)
python -m sglang.bench_serving --backend sglang \
--host localhost --port 30000 \
--num-prompts 20 --request-rate 4
# 开始采集
curl -X POST http://10.51.1.1:8000/start_profile \
-H "Content-Type: application/json" \
-d '{"activities": ["CUDA_PROFILER"]}'
# 跑真正要测的负载(并发要够,否则 coalescing 不触发)
python -m sglang.bench_serving --backend sglang \
--host localhost --port 30000 \
--num-prompts 200 --request-rate 16 \
--random-input-len 8192 --random-output-len 128
# 停止采集
curl -X POST http://10.51.1.1:8000/stop_profileactivities 只填 ["CUDA_PROFILER"] —— 别加 "GPU",那会同时开 torch profiler,两个 profiler 打架且开销巨大。
4. 拿 report
stop_profile 之后 nsys 会把 .nsys-rep 落盘。但要注意:
采集结束 ≠ 文件写完。 nsys 需要进程退出或采集正常结束才 finalize。做法是 stop_profile 后停掉服务:
# 优雅停(让 nsys 收尾)
kill -SIGINT <server_pid>
# 等它写完
ls -lh /tmp/pxn_prefill.nsys-rep
命令行先看一眼有没有东西:
```bash
nsys stats --report nvtx_sum /tmp/pxn_prefill.nsys-rep
应该能看到 pxn::sender::publish、pxn::relay::submit 这些名字。看不到就说明 PXN 没启用(还是那个 invalid PXN registry entry),或者没编 -DPXN_ENABLE_NVTX=ON。