sskj/experiments/pro6000/kimi3_pro6000_pd_rdma
shishi c69831f258 feat(pd): PD 长上下文 adaptive concurrency bench(SLO 方案 A,并发 +16)
- matrix.json: 3 个 shape(64k/128, 16k/1k, 1k/4k)
- run_adaptive_concurrency_pd.sh: PD 专用 adaptive 脚本
  - 复用 adaptive_bench_lib.sh(并发搜索/SLO 停止/OOM 检测/完整产物)
  - server 生命周期函数 no-op(PD 服务常驻,不启停)
  - 加 --flush-cache(配合 --disable-radix-cache 测纯净 TTFT/TPOT)
  - 离线环境变量 + 本地 tokenizer(避免 HF 在线下载)
- adaptive_config.env: SEARCH_ADDEND=16 +16 递增,上限 64,回退 8/1
- config.env: 新增 get_ttft_slo_ms 分层 SLO(1k->4s, 16k->15s, 64k->30s)
2026-08-11 14:45:36 +08:00
..

Kimi-K3 PD 分离部署MoonCake RDMA实验

RTX 6000Dsm_1208 节点 64 卡)上 Kimi-K3 的 Prefill/Decode 分离部署KV 传输使用 MoonCake RDMA(计算网 mlx5_0~34 链路 RoCE

背景与动机

PD 分离部署PD Disaggregation将 prefill预填充计算密集型与 decode逐 token 生成,访存密集型)拆分到不同节点组,是长上下文下提升吞吐/利用率的行业标准做法。本实验聚焦 KV 传输后端的选型验证与稳定部署。

为什么不用 NIXL

实测 NIXLUCX 后端)在 RTX 6000D无 GDR/GDAKIVRAM 单次传输上限约 20MB24/32/64MB 均报 Input/output errorNIXL_ERR_REMOTE_DISCONNECT),且 sglang NIXL 后端不做按字节分块(一次传输整个请求全部 KV连续负载下必断。根因UCX 依赖 GDAKIGPU Direct Async接口当前未启用NVreg_RegistryDwords="PeerMappingOverride=1;")。详见飞书 wiki「Kimi-K3 部署手册」PD 章节。

为什么 MoonCake RDMA 可行

  • MoonCake 走 libibverbs 直连(传统 GDR + dmabuf 注册),不依赖 UCX/GDAKI
  • 实测跨节点 GPU 显存传输 1GB 无压力,连续 10×64MB 全部成功
  • 必须用 0.3.12.post1(含 dmabuf 注册修复 #2035镜像自带的 0.3.11.post1 无修复)

关键坑(务必遵守)

  1. 不能设 PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True expandable_segments 分配的 GPU 段mooncake RDMA 注册报 Bad address [14]GitHub kvcache-ai/Mooncake #2511)。移除后 KV 注册 2376 条失败 → 0 失败。
  2. P 组先启动D 组后启动prefill 需先注册 bootstrap
  3. 容器内必须升级 mooncake 到 0.3.12.post1wheel 在 /data/flashkda_deploy/wheels/profile 的 BOOTSTRAP 里已含 pip install
  4. NCCL/GLOO 走计算网(bond1 + NCCL_IB_HCA=mlx5_0..3),不要走管理网 bond0。

架构

                    ┌───────────────────┐
  client ──31000──▶ │  router (MiniLB)  │ 174.1.60.5
                    └───────┬───────────┘
                    ┌───────▼───────────┐
  P 组 (prefill)   │  174.1.60.1~4      │  TP32×EP324 节点 32 卡
  └── prefill 计算  │  计算完产出 KV      │
                    └───────┬───────────┘
                    ┌───────▼───────────┐
      MoonCake RDMA│  mlx5_0~3 (RoCE)  │  4 链路并行
                    └───────┬───────────┘
                    ┌───────▼───────────┐
  D 组 (decode)    │  174.1.60.5~8      │  TP32×EP324 节点 32 卡
  └── decode 生成   │  接收 KV 逐 token  │
                    └───────────────────┘

  mc-master (174.1.60.1:50051)  MoonCake 元数据服务

运维一键部署(从干净环境到跑通)

以下是运维同学按顺序执行即可完成整套 PD 部署的完整步骤。前 4 步是"一次性准备"(新机器/新环境才需要;已部署过的集群可跳过,直接看第 5 步)。

步骤 1准备 8 节点环境(一次性)

前置8 台节点174.1.60.1~8已安装 NVIDIA 驱动 + CUDA + DockerGPU 空闲(nvidia-smi 全 0 MiB

# 在任意一台(建议 .5)确认能免密 ssh 到全部 8 节点
for i in 1 2 3 4 5 6 7 8; do ssh 174.1.60.$i hostname; done
# 若某台需密码,先配免密(把公钥分发过去)
ssh-copy-id root@174.1.60.$i   # 对每台执行

步骤 2分发部署文件到 8 节点(一次性)

每台节点需要 3 个文件patch 脚本 + flashkda wheel + mooncake wheel放到指定路径

# 在 .5 上执行(假设文件已存在于 .5 的对应位置;若没有,先从模型团队获取)
FILES="/tmp/patch_k3_sm120.py
/tmp/flash_kda-0.0.1-cp312-cp312-linux_x86_64.whl
/data/flashkda_deploy/wheels/mooncake_transfer_engine_cuda13-0.3.12.post1-cp312-cp312-manylinux_2_28_x86_64.whl"

for h in 1 2 3 4 5 6 7 8; do
  ssh 174.1.60.$h "mkdir -p /tmp /data/flashkda_deploy/wheels"  # 确保父目录存在
  for f in $FILES; do
    scp -q $f 174.1.60.$h:/$f
  done
  echo "  .$h 文件就位"
done

# 验证:每台应显示 3/3
for h in 1 2 3 4 5 6 7 8; do
  echo -n "  .$h: "
  ssh 174.1.60.$h "ls /tmp/patch_k3_sm120.py /tmp/flash_kda-0.0.1-cp312-cp312-linux_x86_64.whl /data/flashkda_deploy/wheels/*.whl 2>/dev/null | wc -l"
done

步骤 3部署 sskj 仓库到 .5 和 .1(一次性)

deploy_pd.sh 依赖 sskj 仓库:.5 上用于编排,.1 上用于执行 P 组 deploy 层命令。

# .5 上已有仓库则跳过;没有则 clone在 .5 上执行)
git clone https://git.meta-stone.net/qqtang/sskj.git /data/yy/sskj

# .1 上也必须 clonedeploy_pd.sh 会在 .1 执行 python -m sskj.deploy
ssh 174.1.60.1 "mkdir -p /data/yy && git clone https://git.meta-stone.net/qqtang/sskj.git /data/yy/sskj"

# 保持两边同步最新
cd /data/yy/sskj && git pull origin main
ssh 174.1.60.1 "cd /data/yy/sskj && git pull origin main"

步骤 4拉取镜像一次性

for h in 1 2 3 4 5 6 7 8; do
  ssh 174.1.60.$h "docker pull lmsysorg/sglang:kimi-k3" &
done; wait

步骤 5一键启动每次部署执行

cd /data/yy/sskj/experiments/pro6000/kimi3_pro6000_pd_rdma
bash deploy_pd.sh start
# 预计 12~18 分钟(模型加载 + CUDA graph + PD warmup

步骤 6验证

# 看状态
bash deploy_pd.sh status

# 端到端推理(应有正常文本返回)
curl -s http://174.1.60.5:31000/generate -H "Content-Type: application/json"   -d '{"text":"Hello","sampling_params":{"max_new_tokens":16}}'

停止 / 重启

bash deploy_pd.sh stop      # router → D 组 → P 组 → mc-master
bash deploy_pd.sh restart

部署文件来源

  • patch_k3_sm120.pyflash_kda-0.0.1-*.whl:模型团队产物(见 docs/KIMI_K3_DEPLOY.md 附录 A
  • mooncake_transfer_engine_cuda13-0.3.12.post1-*.whl/data/flashkda_deploy/wheels/
  • 若文件缺失,找模型团队提供或重新构建/下载

使用

# 一键启动mc-master → P 组 → D 组 → router
bash deploy_pd.sh start

# 查看状态
bash deploy_pd.sh status

# 停止 / 重启
bash deploy_pd.sh stop
bash deploy_pd.sh restart

# 端到端验证router 入口,自动双发 P/D
curl -s http://174.1.60.5:31000/generate -H "Content-Type: application/json" \
  -d '{"text":"Hello","sampling_params":{"max_new_tokens":16}}'

实测验证2026-08-11

测试 输入 tokens 输出 tokens 结果
warmup 6 16 200 OK
中等 1680 512 e2e 31.4s
长输入 5280 256 e2e 13.0s
  • P 组 prefill throughput ~112 tok/s5280 token 输入D 组 decode ~26 tok/s
  • 两端 GPU 同步工作,PD 分离链路完整跑通
  • 对比 NIXLMoonCake RDMA 处理长 KV 传输稳定,无 20MB 上限问题

文件

文件 说明
deploy_pd.sh PD 编排脚本mc-master + P + D + router 全生命周期)
config.env 实验配置
deploy/profiles/pro6000/kimi3_pro6000_pd_prefill.env P 组prefill部署 profile
deploy/profiles/pro6000/kimi3_pro6000_pd_decode.env D 组decode部署 profile

参考

  • 飞书 wiki「Kimi-K3 部署手册」PD 分离章节(七~十一章)
  • GitHub kvcache-ai/Mooncake: #2511expandable_segments 注册失败)、#2035dmabuf 修复)、#351Bad address