From b55371fe697a34924f1dbae57fee04f87ae2c97d Mon Sep 17 00:00:00 2001 From: tim Date: Tue, 12 May 2026 00:10:14 +0800 Subject: [PATCH] docs: H200 + driver 570 setup guide + 11 lessons learned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Captures the full debugging journey of getting vendored SGLang 0.5.10 + mooncake RDMA running on a 4×H200 node with the older driver 570.86.15. Driver 570's actual API is cu12.8 — nvidia-smi's "CUDA Version: 13.0" header is a forward-compat ceiling, not the driver's own version — and that single misreading drove most of the detours. Lessons cover: pip vs vendor sglang divergence, why cu13 switching was a dead end (mooncake is cu12-only by wheel, driver 570 can't run cu13 anyway), why --disable-overlap-schedule alone isn't enough, why pip nvidia-cuda-nvcc-cu12 doesn't ship the nvcc binary, and how tvm_ffi's ninja-driven nvcc invocation makes CUDA_HOME the single hook point that fixes everything. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/H200_DRIVER570_SETUP_ZH.md | 267 ++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 docs/H200_DRIVER570_SETUP_ZH.md diff --git a/docs/H200_DRIVER570_SETUP_ZH.md b/docs/H200_DRIVER570_SETUP_ZH.md new file mode 100644 index 0000000..35c812f --- /dev/null +++ b/docs/H200_DRIVER570_SETUP_ZH.md @@ -0,0 +1,267 @@ +# H200 + Driver 570 上跑通本仓库的环境配置(含踩坑记录) + +**适用范围**:4× H200 节点 + NVIDIA driver `570.86.15` + 本仓库 `kvc-debug-journey-v1-to-v4` 或后续分支。 +**目标读者**:拿到一台新 H200 机器、需要快速跑通 sglang 0.5.10 vendor + mooncake RDMA + agentic-pd-hybrid 的下一个 SWE/research agent。 +**作者状态**:本文档定稿于 `h200-cu130 @ 初始 commit`,smoke test 已 RDMA 跑通 16 reqs / 0 error。 + +--- + +## 0. TL;DR(5 行) + +1. **`nvidia-smi` 的 "CUDA Version: 13.0" 是个陷阱**——它是 driver 能 forward-compat 跑的 runtime 上限,不是 driver 自己 API 版本。driver `570.86.15` 提供的 driver API 是 **cu12.8**。 +2. vendor sglang 0.5.10 的 `jit_kernel/` 用 `tvm_ffi` + ninja + nvcc binary 在首次调用每个 kernel 时编译。系统唯一 nvcc 在 `/usr/local/cuda-13.0/bin/`,cu13 编译出的 .so 会 NEEDED `libcudart.so.13`,driver 570 拒绝运行 → `cudaErrorInsufficientDriver`。 +3. 解法是**本地装一份 cu12.8 toolkit 到 `$HOME/cuda-12.8`**(不需要 root),让 tvm_ffi 走 cu12.8 nvcc,编译产物 NEEDED `libcudart.so.12`,driver 570 完美支持。 +4. mooncake wheel (`mooncake-transfer-engine 0.3.10.post2`) 也是 cu12 build,需要 `libcudart.so.12`——已经由 `nvidia-cuda-runtime-cu12` 包提供,在 venv 里。 +5. 每个 shell **必须 `source scripts/setup_env.sh`** 才能跑 SGLang。已封装好。 + +--- + +## 1. 一次性 setup(约 25min) + +```bash +cd /path/to/agentic-pd-hybrid + +# (1) Python 环境 (~3min) +uv sync + +# (2) cu12.8 toolkit 本地装(~5GB 下载 + 5min 解压 = ~15-20min) +mkdir -p /tmp/cuda_dl && cd /tmp/cuda_dl +wget https://developer.download.nvidia.com/compute/cuda/12.8.1/local_installers/cuda_12.8.1_570.124.06_linux.run +sh cuda_12.8.1_570.124.06_linux.run \ + --silent --toolkit --override \ + --installpath=$HOME/cuda-12.8 \ + --tmpdir=$HOME/tmp \ + --no-drm --no-man-page + +# (3) 验证 +$HOME/cuda-12.8/bin/nvcc --version # 应该看到 release 12.8, V12.8.93 + +# (4) 回到 repo 根目录,首次 source(每个 shell 都要做) +cd /path/to/agentic-pd-hybrid +source scripts/setup_env.sh +``` + +`source scripts/setup_env.sh` 输出应是: +``` +agentic-pd-hybrid env ready: + CUDA_HOME=/home//cuda-12.8 (12.8, V12.8.93) + libcudart.so.12 at .../.venv/lib/python3.12/site-packages/nvidia/cuda_runtime/lib +``` + +--- + +## 2. Smoke test(验证整条链路) + +把 16 个合成 request 喂给 1P3D 拓扑,启用真 RDMA,跑通后才能动 E1/E2 实验。 + +```bash +# 假设已 source scripts/setup_env.sh +mkdir -p outputs/smoke_rdma + +uv run --no-sync python -m agentic_pd_hybrid.cli make-small-append-trace \ + --output outputs/smoke_rdma/mini_trace.jsonl \ + --session-count 4 --turns-per-session 4 \ + --initial-input-length 1024 --append-input-length 200 --output-length 50 \ + --inter-turn-gap-s 2 --session-stagger-s 1 + +uv run --no-sync python -m agentic_pd_hybrid.cli benchmark-live \ + --trace outputs/smoke_rdma/mini_trace.jsonl \ + --output-root outputs/smoke_rdma \ + --mechanism pd-disaggregation --policy default \ + --model-path /mnt/models/Qwen/Qwen3-30B-A3B-Instruct-2507 \ + --prefill-workers 1 --decode-workers 3 \ + --prefill-tp-size 1 --decode-tp-size 1 \ + --prefill-gpu-ids 0 --decode-gpu-ids 1,2,3 \ + --transfer-backend mooncake \ + --force-rdma --ib-device mlx5_60 \ + --gpu-budget 4 --time-scale 1 \ + --concurrency-limit 4 --timeout-s 1800 --request-timeout-s 300 \ + --session-sample-rate 1.0 --min-turns 1 --target-duration-s 600 +``` + +**首次跑会慢 8-15min**(model load 196s + 5-10 个 JIT kernel 各编译 ~10-30s + warmup)。后续跑只 ~3-5min。 + +**期望结果**:`request_count=16, error=0, abort=0, failure=0, execution_modes={'pd-disaggregation-router': 16}`。 + +每个 worker 的日志应有 `installTransport, type=rdma`,表示 mooncake 真的走 RDMA 而不是 TCP loopback。 + +--- + +## 3. GPU ↔ RDMA HCA 映射(本机实测) + +8 块 ConnectX HCA,全部 ACTIVE / 400 Gb/s NDR / RoCE v2 (link_layer=Ethernet, GID Index 3)。Mooncake 按 NUMA / PCIe affinity 自动选 preferred: + +| GPU | preferred HCA | NUMA | +|---|---|---| +| cuda:0 | mlx5_60 | 0 | +| cuda:1 | mlx5_88 | 0 | +| cuda:2 | mlx5_98 | 1 | +| cuda:3 | mlx5_42 | 1 | + +CLI 的 `--ib-device ` 只接单个设备名,给所有 worker 全局 override。Smoke test 默认填 `mlx5_60`(P worker 在 cuda:0 上 NUMA-local;D worker 在其它 GPU 上是 cross-NUMA 但能跑)。E1/E2 实验如果想最优,可以分 P/D worker 独立设环境变量,但目前 stack.py 不支持 per-worker `MOONCAKE_DEVICE`,要么所有 worker 同一个,要么走 mooncake auto(需把 `MC_MS_AUTO_DISC=0` 改回 1)。 + +完整 8 块 HCA:`mlx5_22, _27, _42, _60, _88, _98, _126, _135`(NUMA 0/1/0/0/0/1/0/1 混杂)。 + +--- + +## 4. 踩过的坑(按时间线) + +### 坑 1:`nvidia-smi` 的 "CUDA Version: 13.0" 是误导 + +`nvidia-smi` header 显示 `Driver Version: 570.86.15 / CUDA Version: 13.0` 让人以为机器支持 cu13。**这是 driver 能 forward-compat 跑的 CUDA runtime 上限**,不是 driver 自己 API 的版本。driver 570 的 driver API 上限是 cu12.8(参见 NVIDIA "CUDA Compatibility" 矩阵)。 + +**正确判断方法**:跑 `torch.cuda.is_available()`,如果装了 cu13 build 的 torch 会报 `The NVIDIA driver on your system is too old (found version 12080)`。返回 `12080` 才是 driver 自己 API 版本(cu12.8)。 + +### 坑 2:vendor sglang vs pip sglang 的 patch 差异 + +仓库的 `third_party/sglang/python/` 是带项目自有 patches 的 SGLang 0.5.10 fork。**pip 上的 `sglang==0.5.10` 不包含核心 patches**——具体差异: + +| 文件 | pip 版 | vendor 版 | +|---|---|---| +| `srt/managers/scheduler.py` | 3621 行 | 3938 行 | +| `admit_direct_append` 出现次数 | 2 | **11** | +| `DirectAppendAdmissionReqInput/Output` | 没有 | **有**(核心 RPC) | +| `_should_allow_local_prefill_on_decode` | 没有 | 有 | +| `maybe_trim_decode_session_cache` | 没有 | 有 | +| `decode_direct_waiting_queue` | 没有 | 有 | + +→ **必须用 vendor 版**。本分支已把 `pyproject.toml` 的 `sglang==0.5.10` 改成 `sglang` + `[tool.uv.sources] sglang = { path = "third_party/sglang/python", editable = true }`,`uv sync` 后会自动 editable 安装 vendor 版。 + +历史上有些 sweep 脚本用 `PYTHONPATH=src:third_party/sglang/python` 在运行时切换,但用 `uv.sources` 把它装进 venv 更彻底,不会被 pip 的 sglang 偷偷 shadow。 + +### 坑 3:cu13 切换是死路 + +发现 driver 570 不兼容时第一个想到的路径是「装 cu13 PyTorch」。试过: + +1. 改 `pyproject.toml` 加 `[[tool.uv.index]]` 指向 `https://download.pytorch.org/whl/cu130` +2. 同样改 vendor sglang 的 `pyproject.toml`(root 项目的 sources 不会传递给 transitive editable dep) +3. `uv sync` 成功装上 `torch==2.9.1+cu130` 和 `nvidia-{nccl,nvjitlink,nvshmem,cusparselt,nvtx}-cu13` +4. **但 driver 570 不支持 cu13 runtime**——`torch.cuda.is_available()=False`,CUDA init 报 `driver too old (12080)` + +→ cu13 路径需要 **driver 580+**。我们没有 root + 别人在用机器,所以放弃。本分支已 rollback 到 cu12 stack(pyproject 干净)。 + +### 坑 4:`--disable-overlap-schedule` 不够 + +第一次 smoke 崩在 `resolve_future_token_ids.cuh:49`,路径是 `event_loop_overlap_disagg_prefill`,怀疑是 overlap 模式特定 JIT kernel 问题。 + +cli.py 给 PD worker 加了 `--disable-overlap-schedule` 后,event loop 切到 `event_loop_normal_disagg_prefill`,但**崩在另一个 kernel `fused_inplace_qknorm`**,错误码完全相同(`cudaErrorInsufficientDriver`)。 + +→ 不是 overlap-specific,是 **整体 vendor sglang `jit_kernel/` 模块和 driver 570 不兼容**,任何 JIT kernel 都会崩在 `runtime.cuh:21` 的 `cudaOccupancyMaxActiveBlocksPerMultiprocessor` 调用(CUDA runtime 初始化时 driver feature 版本检查失败)。 + +但 `--disable-overlap-schedule` 留着不会造成伤害,且能避免之后类似 overlap-path 特定问题。本分支保留它在 `cli.py:_topology_from_args`。 + +### 坑 5:pip sgl_kernel vs vendor sglang/jit_kernel/ 是两套系统 + +`pip install sglang-kernel` 提供 `.venv/lib/.../sgl_kernel/{flash_ops,flashmla_ops,spatial_ops}.abi3.so`——这是 AOT 预编译产物。 + +`third_party/sglang/python/sglang/jit_kernel/` 是 vendor SGLang 0.5.10 内置的 **另一套 JIT 模块**,运行时用 tvm_ffi 编译。Smoke 崩在 vendor 的 jit_kernel,**降级 pip sgl_kernel 没用**(实测 0.4.0 / 0.4.1 同样崩)。 + +### 坑 6:`nvidia-cuda-nvcc-cu12` PyPI 包没装 nvcc binary + +发现 cu13 nvcc 是 root cause 后,第一反应是 PyPI 装 cu12 nvcc 包: + +```bash +uv pip install nvidia-cuda-nvcc-cu12==12.8.93 +``` + +装上以后 `find .venv -name nvcc` **返回空**——这个 PyPI 包只装 `ptxas` 和 `nvvm/`,**没有 nvcc binary**(NVIDIA 出于分发限制不把 nvcc 放 PyPI)。 + +→ 完整 nvcc 必须从 NVIDIA 官方 `.run` installer 或 apt 装。`.run` installer 可以装到 user-writable 路径不需要 root,本仓库选这条路。 + +### 坑 7:tvm_ffi 通过 ninja 调用 nvcc + +vendor sglang 的 `jit_kernel/` 用 `tvm_ffi.cpp.extension`,源码在 `~/.local/lib/python3.12/site-packages/tvm_ffi/cpp/extension.py`。关键路径: + +```python +def _find_cuda_home() -> str: + cuda_home = os.environ.get("CUDA_HOME") or os.environ.get("CUDA_PATH") + if cuda_home is None: + nvcc_path = shutil.which("nvcc") + if nvcc_path is not None: + cuda_home = str(Path(nvcc_path).parent.parent) + ... +``` + +然后构造 ninja file: +``` +nvcc = {_find_cuda_home()}/bin/nvcc +``` + +→ **设 `CUDA_HOME=$HOME/cuda-12.8` 就能 hook 整条编译链**。`scripts/setup_env.sh` 已经设好。 + +JIT 编译产物缓存在 `~/.cache/tvm-ffi/sgl_kernel_jit_*/*.so`。如果之前用 cu13 nvcc 编过,要先 `rm -rf ~/.cache/tvm-ffi/sgl_kernel_jit_*` 再用 cu12.8 重编。 + +### 坑 8:mooncake import path 与 onboarding 文档不一致 + +`docs/ONBOARDING_NEXT_AGENT_ZH.md` §3.3 的环境验证写: +```python +from mooncake_transfer_engine import TransferEngine +``` + +但实际 PyPI `mooncake-transfer-engine 0.3.10.post2` wheel 的 import path 是: +```python +from mooncake.engine import TransferEngine +``` + +第一次 `from mooncake_transfer_engine` 会 `ModuleNotFoundError`。**ONBOARDING 文档应该更新**(本分支不动 onboarding,留给主 agent 决定)。 + +### 坑 9:mooncake.engine import 必须有 libcudart.so.12 + +`from mooncake.engine import TransferEngine` 在 fresh shell(未 source setup_env.sh)下报: +``` +ImportError: libcudart.so.12: cannot open shared object file: No such file or directory +``` + +mooncake 的 `engine.so` 是 cu12 build,dynamic link `libcudart.so.12`。venv 里有但需要 LD_LIBRARY_PATH 暴露。`scripts/setup_env.sh` 已加。 + +### 坑 10:Inferact 数据集 schema 与 agentic-pd-hybrid 期望不匹配 + +`huggingface.co/datasets/Inferact/codex_swebenchpro_traces` 是 ShareGPT 格式(`{"from": "human/gpt", "value": ""}`),不含 token 计数 / hash_ids / 时间戳。 + +`agentic-pd-hybrid` 期望 JSONL:`chat_id, parent_chat_id, timestamp, input_length, output_length, type, turn, hash_ids[]`。 + +→ 已写 `scripts/convert_inferact_to_trace.py`:tokenize(用 model 自带 tokenizer)+ 滚动 hash 切 24-token block + 伪造 timestamp。610 trials × 33 turns 处理约 37min,跑出 20,230 reqs(与 Inferact README 的 "20,230 total LLM calls" 完全一致)。 + +输出 `outputs/inferact_codex_swebenchpro.jsonl`(1.3GB,被 `.gitignore` 排除不进仓库)。 + +### 坑 11:sampling 默认 `--session-sample-rate 0.01` + +`benchmark-live` 跑的时候内部会先做 sampling。默认 1%,意味着 50 sessions 才抽 1 个。Mini smoke trace 4 sessions × 1% = 0 → `ValueError: Sampling produced no requests`。 + +→ smoke test 命令显式加 `--session-sample-rate 1.0 --target-duration-s 600`。 + +--- + +## 5. 后续给下个 agent + +跑 E1 / E2 sweep 之前**每个 shell 第一件事**: + +```bash +cd /path/to/agentic-pd-hybrid +source scripts/setup_env.sh +``` + +然后用 ONBOARDING §3 的 sweep 脚本(参考 `scripts/sweep_ts1_migration_v2.sh` 作为底版)。注意几处针对本机的修改: + +1. **MODEL 路径**改成 `/mnt/models/Qwen/Qwen3-30B-A3B-Instruct-2507`(onboarding 写的 `/mnt/kzlin/workflow/pd-hybrid/simm-swe-bench/models/...` 不存在)。 +2. **TRACE 路径**:`outputs/qwen35-swebench-50sess.jsonl` 不存在;用 `outputs/inferact_codex_swebenchpro.jsonl` (converter 跑完后产生)。 +3. **`--ib-device`** 选 `mlx5_60`(cuda:0 NUMA-local)或视实验需要自选;onboarding 写的 `mlx5_0` 在本机不存在。 +4. **保留 cli.py 的 `--disable-overlap-schedule`** 不要删——理论上 cu12.8 toolchain 应该让 overlap 也能跑,但目前未验证 overlap path 没有别的潜在问题,留着是 zero-cost 保险。 + +--- + +## 附录 A:本分支的代码改动 + +- `pyproject.toml`:sglang dep 改用 `[tool.uv.sources]` path source 走 `third_party/sglang/python`(editable)。 +- `src/agentic_pd_hybrid/cli.py:_topology_from_args`:给 prefill/decode worker 自动加 `--disable-overlap-schedule`。 +- `scripts/setup_env.sh`:env wrapper,每个 shell `source` 一次。 +- `scripts/convert_inferact_to_trace.py`:Inferact ShareGPT → agentic-pd-hybrid JSONL schema converter。 +- `docs/H200_DRIVER570_SETUP_ZH.md`:本文档。 + +## 附录 B:被 `.gitignore` 排除的产物 + +- `outputs/inferact_codex_swebenchpro.jsonl`(1.3GB)——converter 输出,用 `scripts/convert_inferact_to_trace.py` 重新生成 +- `outputs/smoke_rdma/`(含 mini trace + smoke run artifacts) +- `third_party/codex_swebenchpro_traces/`(209MB,HF dataset 下载)—— `hf download Inferact/codex_swebenchpro_traces --repo-type dataset --local-dir third_party/codex_swebenchpro_traces` 重下 +- `~/cuda-12.8/`——cu12.8 toolkit,用 §1 步骤 (2) 重装 +- `.venv/`——`uv sync` 重建