Files
agentic-pd-hybrid/docs/H200_DRIVER570_SETUP_ZH.md
tim 905d671135 feat(env): MC_TRANSFER_TIMEOUT=1800s default in setup_env + stack
Mooncake C++ batch_transfer_sync defaults to 30s timeout; on
saturated D scheduler threads doing LRU eviction, that fires as a
false positive and the SGLang hair-trigger in conn.py:1270
permanently blacklists the D's mooncake_session_id (E2 forensic in
docs/E1_E2_RESULTS_ZH.md §5c). Bump to 1800s in setup_env.sh and
mirror to subprocess env in stack.py so SGLang workers get it too.
30-min envelope still detects genuinely broken peers eventually.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 11:45:09 +08:00

14 KiB
Raw Blame History

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 @ 初始 commitsmoke test 已 RDMA 跑通 16 reqs / 0 error。


0. TL;DR5 行)

  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.13driver 570 拒绝运行 → cudaErrorInsufficientDriver
  3. 解法是本地装一份 cu12.8 toolkit 到 $HOME/cuda-12.8(不需要 root让 tvm_ffi 走 cu12.8 nvcc编译产物 NEEDED libcudart.so.12driver 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

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/<user>/cuda-12.8 (12.8, V12.8.93)
  libcudart.so.12 at .../.venv/lib/python3.12/site-packages/nvidia/cuda_runtime/lib
  MC_TRANSFER_TIMEOUT=1800s

MC_TRANSFER_TIMEOUT=1800 (30 min) 替代 mooncake 默认 30s——E2 forensic 发现 D 端 LRU eviction 会让 mooncake C++ control plane 被 starved 30+s触发 conn.py:1270 hair-trigger 永久 blacklist 整个 D 的 mooncake_session_id。1800s 给足缓冲30 分钟还没回应才是真正"D 死了"。详见 docs/E1_E2_RESULTS_ZH.md §5cstack.py 也对 worker subprocess 设了同名默认值。


2. Smoke test验证整条链路

把 16 个合成 request 喂给 1P3D 拓扑,启用真 RDMA跑通后才能动 E1/E2 实验。

# 假设已 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-15minmodel 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 <name> 只接单个设备名,给所有 worker 全局 override。Smoke test 默认填 mlx5_60P worker 在 cuda:0 上 NUMA-localD 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 块 HCAmlx5_22, _27, _42, _60, _88, _98, _126, _135NUMA 0/1/0/0/0/1/0/1 混杂)。


4. 踩过的坑(按时间线)

坑 1nvidia-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)。

坑 2vendor 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.tomlsglang==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。

坑 3cu13 切换是死路

发现 driver 570 不兼容时第一个想到的路径是「装 cu13 PyTorch」。试过

  1. pyproject.toml[[tool.uv.index]] 指向 https://download.pytorch.org/whl/cu130
  2. 同样改 vendor sglang 的 pyproject.tomlroot 项目的 sources 不会传递给 transitive editable dep
  3. uv sync 成功装上 torch==2.9.1+cu130nvidia-{nccl,nvjitlink,nvshmem,cusparselt,nvtx}-cu13
  4. 但 driver 570 不支持 cu13 runtime——torch.cuda.is_available()=FalseCUDA init 报 driver too old (12080)

→ cu13 路径需要 driver 580+。我们没有 root + 别人在用机器,所以放弃。本分支已 rollback 到 cu12 stackpyproject 干净)。

坑 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-scheduleevent loop 切到 event_loop_normal_disagg_prefill,但崩在另一个 kernel fused_inplace_qknorm,错误码完全相同(cudaErrorInsufficientDriver)。

→ 不是 overlap-specific整体 vendor sglang jit_kernel/ 模块和 driver 570 不兼容,任何 JIT kernel 都会崩在 runtime.cuh:21cudaOccupancyMaxActiveBlocksPerMultiprocessor 调用CUDA runtime 初始化时 driver feature 版本检查失败)。

--disable-overlap-schedule 留着不会造成伤害,且能避免之后类似 overlap-path 特定问题。本分支保留它在 cli.py:_topology_from_args

坑 5pip 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 同样崩)。

坑 6nvidia-cuda-nvcc-cu12 PyPI 包没装 nvcc binary

发现 cu13 nvcc 是 root cause 后,第一反应是 PyPI 装 cu12 nvcc 包:

uv pip install nvidia-cuda-nvcc-cu12==12.8.93

装上以后 find .venv -name nvcc 返回空——这个 PyPI 包只装 ptxasnvvm/没有 nvcc binaryNVIDIA 出于分发限制不把 nvcc 放 PyPI

→ 完整 nvcc 必须从 NVIDIA 官方 .run installer 或 apt 装。.run installer 可以装到 user-writable 路径不需要 root本仓库选这条路。

坑 7tvm_ffi 通过 ninja 调用 nvcc

vendor sglang 的 jit_kernel/tvm_ffi.cpp.extension,源码在 ~/.local/lib/python3.12/site-packages/tvm_ffi/cpp/extension.py。关键路径:

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 重编。

坑 8mooncake import path 与 onboarding 文档不一致

docs/ONBOARDING_NEXT_AGENT_ZH.md §3.3 的环境验证写:

from mooncake_transfer_engine import TransferEngine

但实际 PyPI mooncake-transfer-engine 0.3.10.post2 wheel 的 import path 是:

from mooncake.engine import TransferEngine

第一次 from mooncake_transfer_engineModuleNotFoundErrorONBOARDING 文档应该更新(本分支不动 onboarding留给主 agent 决定)。

坑 9mooncake.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 builddynamic link libcudart.so.12。venv 里有但需要 LD_LIBRARY_PATH 暴露。scripts/setup_env.sh 已加。

坑 10Inferact 数据集 schema 与 agentic-pd-hybrid 期望不匹配

huggingface.co/datasets/Inferact/codex_swebenchpro_traces 是 ShareGPT 格式({"from": "human/gpt", "value": "<text>"}),不含 token 计数 / hash_ids / 时间戳。

agentic-pd-hybrid 期望 JSONLchat_id, parent_chat_id, timestamp, input_length, output_length, type, turn, hash_ids[]

→ 已写 scripts/convert_inferact_to_trace.pytokenize用 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.jsonl1.3GB,被 .gitignore 排除不进仓库)。

坑 11sampling 默认 --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 第一件事

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-2507onboarding 写的 /mnt/kzlin/workflow/pd-hybrid/simm-swe-bench/models/... 不存在)。
  2. TRACE 路径outputs/qwen35-swebench-50sess.jsonl 不存在;用 outputs/inferact_codex_swebenchpro.jsonl converter 跑完后产生)。
  3. --ib-devicemlx5_60cuda:0 NUMA-local或视实验需要自选onboarding 写的 mlx5_0 在本机不存在。
  4. 保留 cli.py 的 --disable-overlap-schedule 不要删——理论上 cu12.8 toolchain 应该让 overlap 也能跑,但目前未验证 overlap path 没有别的潜在问题,留着是 zero-cost 保险。

附录 A本分支的代码改动

  • pyproject.tomlsglang dep 改用 [tool.uv.sources] path source 走 third_party/sglang/pythoneditable
  • src/agentic_pd_hybrid/cli.py:_topology_from_args:给 prefill/decode worker 自动加 --disable-overlap-schedule
  • scripts/setup_env.shenv wrapper每个 shell source 一次。
  • scripts/convert_inferact_to_trace.pyInferact ShareGPT → agentic-pd-hybrid JSONL schema converter。
  • docs/H200_DRIVER570_SETUP_ZH.md:本文档。

附录 B.gitignore 排除的产物

  • outputs/inferact_codex_swebenchpro.jsonl1.3GB——converter 输出,用 scripts/convert_inferact_to_trace.py 重新生成
  • outputs/smoke_rdma/(含 mini trace + smoke run artifacts
  • third_party/codex_swebenchpro_traces/209MBHF 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 重建