773 lines
24 KiB
Markdown
773 lines
24 KiB
Markdown
# 6000D 双机 DeepSeek-V4-Pro 推理优化计划
|
||
|
||
> 适用环境:`174.1.51.5 + 174.1.51.7`,每台 8 张 RTX PRO 6000 Blackwell Server Edition
|
||
> 当前部署:DeepSeek-V4-Pro,16 张 GPU 组成一个完整实例
|
||
> 当前约束:模型暂时只能使用全部 16 张 GPU,无法额外复制一套模型进行 PD 分离
|
||
> 计划版本:2026-07-31 12:26:00 CST
|
||
|
||
## 阶段档案与实验命令规范
|
||
|
||
每个 Phase HTML 的正文只保留最终成功实验、有效结果和结论;失败尝试压缩到
|
||
末尾的经验教训。阶段完成时删除“暂不能下结论”等过渡内容。
|
||
|
||
每个 Phase HTML 必须包含“实验复现命令”,并明确区分:
|
||
|
||
| 标签 | 含义 | 必须记录的内容 |
|
||
|---|---|---|
|
||
| 实际执行命令 | 该次有效 Run 真正运行过 | 执行节点、工作目录、tmux/入口、完整 Docker 服务命令、Benchmark/Profile/监控命令、停止清理命令、Run ID 与命令证据路径 |
|
||
| 复现命令 | 根据实际 Run 整理,可重新执行 | 与实际参数等价;允许为可读性换行,但不得省略影响结果的参数 |
|
||
| 计划或示例命令 | 尚未在当前阶段运行 | 必须显式标注“未执行”,真机完成后替换为实际命令,不能作为结果证据 |
|
||
|
||
长命令必须同时原样保存到结果目录的 `*_cmd.txt` 或 Manifest。HTML 负责教学、
|
||
解释和索引,落盘命令文件负责精确审计。
|
||
|
||
## 0. 双机通信前置知识与当前修正
|
||
|
||
完整术语、设备映射、日志判读和 2026-07-30 网络事故复盘见:
|
||
|
||
- [6000D 双机通信与 NCCL 术语入门](./6000D双机通信与NCCL术语入门.html)
|
||
|
||
本项目部署时只使用两条节点间计算网:
|
||
|
||
| 物理端口 | Linux netdev/IP 入口 | RDMA Verbs/HCA 入口 | 交换路径 |
|
||
|---|---|---|---|
|
||
| 400G Rail 1 | `eth0` | `mlx5_0` | switch 1 |
|
||
| 400G Rail 2 | `eth3` | `mlx5_3` | switch 2 |
|
||
|
||
`eth0` 与 `mlx5_0` 不是同一个软件设备。它们是同一条 400G 物理 Ethernet
|
||
端口的两种入口:前者服务 IP/TCP Socket,后者服务 RoCE/RDMA Verbs。
|
||
400G 指物理链路的标称线速,不专属于 TCP 或 RDMA;400 Gbit/s 约等于
|
||
50 GB/s 单向理论上限,不能直接当作 NCCL 或模型端到端可达到的吞吐。
|
||
|
||
当前唯一启动入口只允许 `eth0/eth3` 与 `mlx5_0/mlx5_3`,在两端预检并
|
||
透传 `rdma_cm/uverbs0/uverbs3`,并要求 NCCL INFO 证明两条 HCA 的
|
||
`NET/IB + GDRDMA` 已启用,否则不开始 benchmark。修正后的 Phase 1
|
||
正式矩阵 12/12、长 Decode 补测 2/2 均成功。
|
||
|
||
## 1. 目标与原则
|
||
|
||
### 1.1 最终目标
|
||
|
||
在不做 PD 分离的前提下,定位 DeepSeek-V4-Pro 在双机 6000D 上的端到端瓶颈,并提高:
|
||
|
||
- 满足 TTFT、TPOT 等 SLO 时的最大吞吐。
|
||
- 长上下文 Prefill 性能。
|
||
- Decode 输出吞吐和单请求 TPOT。
|
||
- 混合流量下的稳定性与 P95/P99 时延。
|
||
- 16 张 GPU、PCIe 和双 Rail 计算网的有效利用率。
|
||
|
||
### 1.2 核心原则
|
||
|
||
1. 先找关键路径,再调参数。
|
||
2. 先用端到端指标确认问题,再用 Timeline 找到阶段,最后才用 Kernel Profiler。
|
||
3. Prefill、Decode 和混合干扰必须分别测试。
|
||
4. 一次只改变一个变量,每项优化都要保留可复现的 A/B 结果。
|
||
5. 单算子更快不代表服务吞吐更高,最终结论必须回到真实请求和 SLO。
|
||
6. Profiling Run 只用于定位,不能与无 Profiler 的正式性能结果直接比较。
|
||
|
||
## 2. 当前最值得验证的瓶颈假设
|
||
|
||
| 编号 | 假设 | 为什么值得优先检查 |
|
||
|---|---|---|
|
||
| H1 | TP16 每层跨机通信暴露过多 | 两台机器没有跨机 NVLink,TP Collective 需要经过 RoCE |
|
||
| H2 | NSA Indexer 或 Sparse Attention Kernel 效率不足 | DSV4-Pro 的稀疏注意力路径复杂,Indexer 可能抵消稀疏收益 |
|
||
| H3 | MoE Grouped GEMM 或路由负载不均 | Decode 小 Batch 容易 Memory-bound,热门专家可能制造慢 Rank |
|
||
| H4 | 长 Prefill 干扰在线 Decode | 统一实例中 Prefill 与 Decode 竞争计算、显存带宽和调度预算 |
|
||
| H5 | CPU Scheduler、Metadata 或 Kernel Launch 产生 GPU 空洞 | 小 Batch Decode 对 CPU 和 Launch 开销特别敏感 |
|
||
| H6 | KV Cache 容量、碎片或 Preemption 限制并发 | 大模型权重占用高,剩余 HBM 决定上下文与并发容量 |
|
||
| H7 | 当前并行拓扑并非最优 | 使用 16 张卡不等于只能采用单一 TP16 拓扑 |
|
||
|
||
## 3. Profiling 总体流程
|
||
|
||
```text
|
||
端到端性能地图
|
||
↓
|
||
服务内部指标与硬件计数器
|
||
↓
|
||
Nsight Systems 时间线
|
||
↓
|
||
确定 1-3 个主要瓶颈
|
||
↓
|
||
Nsight Compute 或专项 Microbenchmark
|
||
↓
|
||
提出优化并做单变量 A/B
|
||
↓
|
||
回到完整 Benchmark 和 SLO 验证
|
||
```
|
||
|
||
不要直接对完整服务运行长时间 Nsight Compute。它的开销很高,也会生成巨大的报告。应先用 Nsight Systems 找到占关键路径的 Kernel,再构造小型复现。
|
||
|
||
## 4. Phase 0:冻结可复现环境
|
||
|
||
正式测试前,每个 Run 必须保存以下信息:
|
||
|
||
- 两台机器的 GPU、Driver、CUDA、NCCL 版本。
|
||
- vLLM 或 SGLang 的镜像名、镜像 ID、Git Commit 和 Python 包版本。
|
||
- 模型目录、权重文件校验信息和模型配置。
|
||
- 完整 Docker Run 与服务启动命令。
|
||
- 完整 Benchmark 命令。
|
||
- TP、DP、PP、EP 拓扑。
|
||
- Attention、NSA、Indexer、MoE、GEMM 和通信 Backend。
|
||
- `NCCL_SOCKET_IFNAME`、`NCCL_IB_HCA`、`NCCL_CROSS_NIC` 等通信变量。
|
||
- GPU Memory Fraction、Context Limit、Active Request Limit、KV Cache Dtype。
|
||
- CUDA Graph、Chunked Prefill、Prefix Cache 和投机解码状态。
|
||
- 运行前后的 `nvidia-smi`、容器列表和网络状态。
|
||
|
||
建议每次运行生成:
|
||
|
||
```text
|
||
results/<RUN_ID>/
|
||
run_manifest.txt
|
||
server_cmd.txt
|
||
bench_cmd.txt
|
||
summary.csv
|
||
requests.jsonl
|
||
server/
|
||
hardware/
|
||
profiles/
|
||
notes.md
|
||
```
|
||
|
||
### 基线约束
|
||
|
||
- 初始基线不启用 MTP、EAGLE、DSpark 等投机解码。
|
||
- 初始基线使用唯一随机 Prompt,避免 Prefix Cache 影响。
|
||
- 服务启动完成后做固定 Warm-up。
|
||
- 每个测试点至少重复 3 次。
|
||
- 正式结果使用无 Profiler 运行。
|
||
- Profiling 只捕获预热后的少量 Engine Step。
|
||
|
||
## 5. Phase 1:建立阶段化性能地图
|
||
|
||
详细结果见 [Phase 1 实验档案](./phase1_exp.html),实现说明见
|
||
[Phase 1 代码详解](./phase1_code.html)。
|
||
|
||
### 5.1 第一轮最小矩阵
|
||
|
||
| 场景 | ISL | OSL | 并发 | 主要目标 |
|
||
|---|---:|---:|---:|---|
|
||
| P1 短 Prefill 延迟底线 | 1K | 1 | 1 | 固定开销与最小 TTFT |
|
||
| P2 中长 Prefill | 32K | 1 | 1 | NSA、Indexer、Attention |
|
||
| P3 长 Prefill | 128K | 1 | 1 | 长上下文计算和显存压力 |
|
||
| P4 Prefill 吞吐 | 32K | 1 | 逐步加并发 | Chunked Prefill 与输入 TPS |
|
||
| D1 Decode 延迟底线 | 1K | 1K | 1 | 单请求 TPOT |
|
||
| D2 Decode 吞吐 | 1K | 1K | 16/32/64 | MoE、Batch 与通信 |
|
||
| M1 混合负载 | Decode C=32 时注入 128K Prefill | | | Prefill 对在线 Decode 的干扰 |
|
||
|
||
长度应以当前已验证的服务容量为上限。如果 128K 不可用,先降到 64K,但必须在 Manifest 中记录原因。
|
||
|
||
### 5.2 并发搜索
|
||
|
||
沿用 Add-16 加退化回退策略:
|
||
|
||
```text
|
||
C = 1(延迟基线)
|
||
C = 16, 32, 48, 64, ...
|
||
```
|
||
|
||
停止条件需要区分:
|
||
|
||
- `OOM`
|
||
- `ENGINE_CRASH`
|
||
- `TTFT_SLO_EXCEEDED`
|
||
- `TPOT_SLO_EXCEEDED`
|
||
- `TPS_SATURATED`
|
||
- `TPS_REGRESSION`
|
||
- `MAX_CONCURRENCY_REACHED`
|
||
|
||
不能把“最大成功并发”“最高 TPS 并发”和“满足 SLO 的最大并发”混为同一个值。
|
||
|
||
### 5.3 每个 Case 必须记录
|
||
|
||
#### 请求层
|
||
|
||
- 实际成功、失败和超时请求数。
|
||
- 实际输入、输出和总 token 数。
|
||
- Request Throughput。
|
||
- Input、Output 和 Total TPS。
|
||
- P50/P95/P99 TTFT。
|
||
- P50/P95/P99 TPOT。
|
||
- P50/P95/P99 ITL。
|
||
- P50/P95/P99 E2E。
|
||
- Queue Time 与 Service Time,若框架支持。
|
||
|
||
#### Scheduler 层
|
||
|
||
- Running、Waiting Request 数。
|
||
- 每轮 Batch Sequence 数。
|
||
- 每轮 Prefill、Decode Token 数。
|
||
- Chunked Prefill 次数和 Chunk 大小。
|
||
- Forward Step 时间。
|
||
- Scheduler/Metadata 准备时间。
|
||
- Preemption、Recompute、Retract 次数。
|
||
- Prefix Cache Hit Tokens。
|
||
|
||
#### 显存层
|
||
|
||
- 权重占用。
|
||
- KV Cache 总量、已用量和峰值。
|
||
- CUDA Graph 占用。
|
||
- Workspace 与临时 Tensor 峰值。
|
||
- Reserved/Allocated 差异与碎片。
|
||
|
||
## 6. Phase 2:同步采集硬件指标
|
||
|
||
Phase 2 已有正式阶段结果,详见 [Phase 2 实验档案](./phase2_exp.html) 和
|
||
[Phase 2 代码详解](./phase2_code.html)。
|
||
最终 Run `dsv4pro-phase2-20260731-163620` 在 28 分 44 秒内完成 8/8
|
||
benchmark,正式测量窗口 8/8 精确,18/18 个采集器正常启停。两节点
|
||
DCGM、CPU、NUMA、双 Rail RDMA 和通信微基准数据均有效,实验后容器、
|
||
端口与 16 张 GPU 已清理。
|
||
|
||
最终归因:
|
||
|
||
- 混合 Prefill/Decode 令 Output TPS 下降 23.96%、TPOT P95 增加 66.75%。
|
||
- GPU 未降频、整机 CPU 未饱和,双 Rail 最高约 83.5 Gbit/s/rail 且零错误。
|
||
- PCIe 跨 NUMA P2P 损失约 2.3%,16-GPU AllReduce busbw 约 39.3-39.7 GB/s。
|
||
- `NCCL_CROSS_NIC=0/1/2` 差异小于 1%,不再作为主要调优方向。
|
||
- Phase 3 只需捕获混合 Control/Treatment 的短 Timeline,定位 Kernel、
|
||
Collective、Scheduler gap 与慢 Rank 同步。
|
||
|
||
Phase 2 只提供一个用户入口:
|
||
|
||
```bash
|
||
cd /data/hzy/sskj/experiments/pro6000/dsv4pro_pro6000d_2node_sglang_hardware_contention_attribution
|
||
RUN_ID=dsv4pro-phase2-$(date +%Y%m%d-%H%M%S)
|
||
tmux new-session -d -s dsv4pro-phase2 \
|
||
"RUN_ID=${RUN_ID} bash run_hardware_contention_attribution.sh all \
|
||
2>&1 | tee /data/hzy/${RUN_ID}.log"
|
||
```
|
||
|
||
`all` 会内部完成 TP16 服务启停、两节点采集、五个固定 Case、混合 A/B、
|
||
结果汇总和异常清理。不要手工并行执行 Phase 1 的 `start/stop`。
|
||
|
||
### 6.1 GPU
|
||
|
||
测试期间持续记录:
|
||
|
||
```bash
|
||
nvidia-smi \
|
||
--query-gpu=index,timestamp,utilization.gpu,utilization.memory,\
|
||
memory.used,memory.total,power.draw,temperature.gpu,clocks.sm,clocks.mem,pstate \
|
||
--format=csv,noheader,nounits
|
||
```
|
||
|
||
重点观察:
|
||
|
||
- SM Utilization。
|
||
- HBM Utilization。
|
||
- 显存占用。
|
||
- GPU Clock、Memory Clock。
|
||
- Power 与温度降频。
|
||
- PCIe RX/TX。
|
||
|
||
如果有 DCGM,增加:
|
||
|
||
- Tensor Core Active。
|
||
- DRAM Active。
|
||
- SM Active。
|
||
- PCIe Throughput。
|
||
- GPU Stall 与 XID。
|
||
|
||
### 6.2 CPU
|
||
|
||
记录服务主进程与 Worker 线程:
|
||
|
||
```bash
|
||
pidstat -t -p <PID> 1
|
||
mpstat -P ALL 1
|
||
numastat -p <PID>
|
||
```
|
||
|
||
需要发现:
|
||
|
||
- 单个 Scheduler Thread 是否满核。
|
||
- Tokenizer、HTTP Frontend 或 Python 线程是否阻塞。
|
||
- Worker 是否跨 NUMA 访问。
|
||
- CPU 空洞是否对应 GPU 空洞。
|
||
|
||
### 6.3 网络
|
||
|
||
Phase 1 正式 Run 已确认容器内可见 RDMA 设备,NCCL 同时识别
|
||
`mlx5_0/mlx5_3`,跨节点 Channel 使用 `NET/IB + GDRDMA`。Phase 2
|
||
保留相同 fail-closed 门禁,并同步采集两条 Rail 的流量和错误计数。
|
||
|
||
当前拓扑中需要分别观察两条 Compute Rail,确认:
|
||
|
||
- 两条 Rail 是否同时有流量。
|
||
- 带宽是否均衡。
|
||
- 是否有丢包、重传、PFC Pause 或错误计数。
|
||
- 慢 Rank 是否固定绑定某个 NIC 或 NUMA 节点。
|
||
|
||
基础监控可以使用:
|
||
|
||
```bash
|
||
sar -n DEV 1
|
||
ethtool -S eth0
|
||
ethtool -S eth3
|
||
```
|
||
|
||
通信调试 Run 可以临时开启:
|
||
|
||
```bash
|
||
NCCL_DEBUG=INFO
|
||
NCCL_DEBUG_SUBSYS=INIT,NET,GRAPH,TUNING
|
||
```
|
||
|
||
该日志开销较高,不应在正式性能结果中长期启用。
|
||
|
||
## 7. Phase 3:Nsight Systems 时间线
|
||
|
||
### 7.1 捕获策略
|
||
|
||
- 只捕获预热后的 10 到 32 个 Engine Step;混合场景窗口略长,用于覆盖 Prefill 注入前后。
|
||
- Prefill、Decode 和混合干扰分别生成报告。
|
||
- 两台机器分别保存原始报告。
|
||
- 优先保留所有 Rank;文件过大时至少保留代表 Rank 和跨机通信相关 Rank。
|
||
- 报告必须和对应 Benchmark Case ID 绑定。
|
||
|
||
### 7.2 vLLM
|
||
|
||
当前版本支持时,使用 CUDA Profiler 动态 Capture:
|
||
|
||
```bash
|
||
export VLLM_WORKER_MULTIPROC_METHOD=spawn
|
||
|
||
nsys profile \
|
||
--trace=cuda,nvtx,nccl \
|
||
--trace-fork-before-exec=true \
|
||
--cuda-graph-trace=node \
|
||
--capture-range=cudaProfilerApi \
|
||
--capture-range-end=repeat \
|
||
-o /data/profile/dsv4_tp16 \
|
||
vllm serve ... \
|
||
--profiler-config.profiler cuda
|
||
```
|
||
|
||
压测端使用支持 Profile Trigger 的 Bench:
|
||
|
||
```bash
|
||
vllm bench serve ... --profile
|
||
```
|
||
|
||
### 7.3 SGLang
|
||
|
||
服务启动前设置:
|
||
|
||
```bash
|
||
export SGLANG_TORCH_PROFILER_DIR=/data/profile/sglang
|
||
```
|
||
|
||
Profiling 专用 Run 可增加:
|
||
|
||
```text
|
||
--enable-layerwise-nvtx-marker
|
||
```
|
||
|
||
捕获预热后的 10 个 Step:
|
||
|
||
```bash
|
||
curl -X POST http://127.0.0.1:30000/start_profile \
|
||
-H 'Content-Type: application/json' \
|
||
-d '{
|
||
"output_dir": "/data/profile/sglang",
|
||
"start_step": 5,
|
||
"num_steps": 10,
|
||
"activities": ["CPU", "GPU"]
|
||
}'
|
||
```
|
||
|
||
多机 Trace 自动合并要求两台机器能访问同一个共享输出目录。没有共享目录时分别保存,再在本地汇总。
|
||
|
||
当前实现位于:
|
||
|
||
```text
|
||
experiments/pro6000/dsv4pro_pro6000d_2node_sglang_timeline_profiling
|
||
```
|
||
|
||
正式场景为:
|
||
|
||
- Decode Control:`1K -> 1K, C=32`,确认 Decode 活跃后跳过 2 Step,捕获 16 Step。
|
||
- Mixed Treatment:`1K -> 1K, C=32` 背景先捕获 2 个纯 Decode Step,再注入 `128K -> 1`,总计捕获 32 Step。
|
||
- Long Prefill:`128K -> 1, C=1`,从首个 Chunk 开始捕获 16 Step。
|
||
|
||
双节点 PyTorch/Nsight smoke 已通过。正式 Run 尚未执行,因此暂不生成 Phase 3 的 `exp/code` HTML。正式命令只在 Head 执行:
|
||
|
||
```bash
|
||
cd /data/hzy/sskj/experiments/pro6000/dsv4pro_pro6000d_2node_sglang_timeline_profiling
|
||
RUN_ID=dsv4pro-phase3-$(date +%Y%m%d-%H%M%S)
|
||
tmux new-session -d -s dsv4pro-phase3 \
|
||
"RUN_ID=${RUN_ID} bash run_timeline_profiling.sh all \
|
||
2>&1 | tee /data/hzy/${RUN_ID}.log"
|
||
tmux attach -t dsv4pro-phase3
|
||
```
|
||
|
||
三段范围复用一次模型加载,因此 Nsight 使用 `--capture-range-end=repeat:3:defer`,而不是单段示例中的 `stop`。
|
||
|
||
### 7.4 时间线必须回答的问题
|
||
|
||
1. Prefill 和 Decode 各自的 Top Kernel 是什么?
|
||
2. NCCL 在关键路径上的暴露时间是多少?
|
||
3. 通信与计算重叠了多少?
|
||
4. 每层之间是否存在 CPU 或同步空洞?
|
||
5. CUDA Graph 是否覆盖常见 Decode Batch?
|
||
6. 16 个 Rank 是否同时结束?
|
||
7. 是否存在固定慢 Rank?
|
||
8. MoE Expert Token 是否严重不均衡?
|
||
9. NSA Indexer 的成本占 Sparse Attention 总成本多少?
|
||
10. 长 Prefill 到来时,Decode Kernel 为什么被延迟?
|
||
|
||
### 7.5 报告分析
|
||
|
||
```bash
|
||
nsys stats <REPORT>.nsys-rep
|
||
```
|
||
|
||
重点查看:
|
||
|
||
- CUDA GPU Kernel Summary。
|
||
- NCCL Summary。
|
||
- NCCL GPU Time Utilization。
|
||
- Communication/Compute Overlap。
|
||
- NCCL Straggler。
|
||
- CUDA API Summary。
|
||
- OS Runtime 和 CPU Thread Timeline。
|
||
|
||
## 8. 证据到优化方向的映射
|
||
|
||
| 观察到的证据 | 更可能的根因 | 下一项 A/B |
|
||
|---|---|---|
|
||
| Decode 中 NCCL 占比高,且通信未被计算覆盖 | TP16 通信受限 | TP8+PP2、NCCL 拓扑与算法 |
|
||
| C=1 很慢,并发增加后 TPS 明显改善 | MoE/权重读取 Memory-bound | Batch、MoE Backend、MTP |
|
||
| GPU 利用率呈锯齿,Kernel 间有明显空洞 | CPU Scheduler 或 Launch 开销 | CUDA Graph、异步调度 |
|
||
| 一个或少数 Rank 长期最慢 | Expert、NIC 或 NUMA 不均衡 | EPLB、Affinity、Rank Mapping |
|
||
| NSA Indexer 时间接近或超过 Attention | 稀疏索引收益不足 | Indexer Backend、Top-K、融合 |
|
||
| 长 ISL 的 Attention 时间异常增长 | Prefill Kernel 或 Chunking 问题 | Prefill Backend、Chunk Size |
|
||
| KV Cache 长期接近满并发生重算 | HBM 容量不足 | FP8 KV、并发和 Context 上限 |
|
||
| 注入长 Prefill 后 Decode TPOT 暴涨 | Prefill/Decode 相互干扰 | Chunked Prefill 与 Scheduler |
|
||
| GPU 利用率低但 CPU 单核满载 | Host 端瓶颈 | Frontend、Tokenizer、Scheduler |
|
||
| 两条 Rail 流量明显不均 | NIC Mapping 或 NCCL 拓扑 | HCA、CROSS_NIC、NUMA Affinity |
|
||
|
||
## 9. Phase 4:优先级最高的拓扑实验
|
||
|
||
### 9.1 A:TP16 基线
|
||
|
||
当前方案用于建立所有后续实验的对照。
|
||
|
||
风险是每层 TP Collective 都可能跨越两台机器,Decode 小消息通信尤其容易被延迟支配。
|
||
|
||
### 9.2 B:TP8 + PP2
|
||
|
||
逻辑上:
|
||
|
||
```text
|
||
Node 5: Pipeline Stage 0, TP8
|
||
Node 7: Pipeline Stage 1, TP8
|
||
```
|
||
|
||
理想情况下,每卡权重占用与 TP16 接近:
|
||
|
||
```text
|
||
TP16:
|
||
每卡权重约为 W / 16
|
||
|
||
TP8 + PP2:
|
||
每个 Stage 保存 W / 2
|
||
Stage 内由 8 卡切分
|
||
每卡权重约为 (W / 2) / 8 = W / 16
|
||
```
|
||
|
||
潜在收益:
|
||
|
||
- 每层 TP Collective 留在单机。
|
||
- 跨机主要传输 Pipeline Stage 边界激活。
|
||
- 避免每层都进行跨机 AllReduce。
|
||
|
||
潜在代价:
|
||
|
||
- Pipeline Bubble。
|
||
- 低并发延迟可能变差。
|
||
- KV Cache、Hybrid Cache 和 DSV4-Pro 模型实现可能暂不支持 PP。
|
||
- 两个 Stage 的计算量可能不均衡。
|
||
|
||
测试顺序:
|
||
|
||
1. 先做加载与单请求 Smoke Test。
|
||
2. 对比 C=1 Decode 延迟。
|
||
3. 对比 C=16/32/64 吞吐。
|
||
4. 观察跨机网络流量是否显著下降。
|
||
5. 观察两个 Pipeline Stage 是否负载均衡。
|
||
|
||
### 9.3 C:Attention TP8/DP2 + MoE EP16
|
||
|
||
目标是:
|
||
|
||
- Attention 在节点内使用 TP8。
|
||
- 两个 Attention DP Group 并行处理请求。
|
||
- MoE Expert 在 16 张卡上分布。
|
||
|
||
这接近“Attention DP + MoE EP”的思路。Expert 权重通常占模型大头,因此即使 Attention 权重复制两份,也有机会放入显存。
|
||
|
||
必须先验证:
|
||
|
||
- 当前 vLLM/SGLang 版本是否支持 DSV4-Pro 的该拓扑。
|
||
- Expert 权重、非 Expert 权重和 KV Cache 的实际显存占用。
|
||
- All-to-All 是否比当前 TP16 AllReduce 更划算。
|
||
- Expert 负载是否均衡。
|
||
|
||
## 10. Phase 5:通信专项
|
||
|
||
### 10.1 不只测 1 GiB 大消息
|
||
|
||
之前的 1 GiB `all_reduce_perf` 主要说明大消息带宽。Decode 中的 Collective 往往更小,可能由延迟主导。
|
||
|
||
需要覆盖真实消息尺度:
|
||
|
||
```bash
|
||
all_reduce_perf -b 8K -e 64M -f 2 -g 8
|
||
all_gather_perf -b 8K -e 64M -f 2 -g 8
|
||
reduce_scatter_perf -b 8K -e 64M -f 2 -g 8
|
||
```
|
||
|
||
若启用 EP,还要测试 All-to-All。
|
||
|
||
### 10.2 通信优化顺序
|
||
|
||
1. 确认两条 Rail 都在工作。
|
||
2. 确认 Rank、GPU、NIC 和 NUMA Affinity。
|
||
3. 对照实际模型消息大小。
|
||
4. 查看 NCCL 自动选择的 Algorithm、Protocol 和 Channel。
|
||
5. 只有自动选择明显不合理时,才 A/B `Ring/Tree`、`Simple/LL128` 等设置。
|
||
6. 观察模型端到端结果,而不只看 nccl-tests 峰值。
|
||
|
||
## 11. Phase 6:Kernel 专项
|
||
|
||
从 Nsight Systems 中选累计占关键路径最高的 1 到 3 个 Kernel,再使用 Nsight Compute。
|
||
|
||
DSV4-Pro 的优先怀疑对象:
|
||
|
||
- NSA Indexer/Top-K。
|
||
- Sparse MLA/Attention Prefill。
|
||
- Sparse MLA/Attention Decode。
|
||
- MoE Gate、Dispatch、Grouped GEMM、Combine。
|
||
- FP8 Quant/Dequant 与 Scale Packing。
|
||
- RMSNorm、Rope、KV Cache Store 等碎片化小算子。
|
||
- NCCL Collective Kernel。
|
||
|
||
需要分析:
|
||
|
||
- SM 和 Tensor Core 利用率。
|
||
- DRAM 吞吐与 L2 Hit Rate。
|
||
- Occupancy。
|
||
- Register 与 Shared Memory 压力。
|
||
- Warp Stall 原因。
|
||
- Kernel Shape 与 Batch/Token 数。
|
||
- 小 Kernel Launch 次数。
|
||
|
||
优化优先顺序:
|
||
|
||
1. 切换已有高性能 Backend。
|
||
2. 调整 Backend 的 Shape/Workspace/Tile 配置。
|
||
3. 消除无用 Copy、Cast 和临时 Tensor。
|
||
4. 融合相邻的 Memory-bound 小算子。
|
||
5. 现有 Backend 不覆盖关键 Shape 时,再开发新 Kernel 或提交 PR。
|
||
|
||
## 12. Phase 7:Scheduler 与统一实例干扰
|
||
|
||
### 12.1 混合干扰实验
|
||
|
||
先建立稳定 Decode 背景流量:
|
||
|
||
```text
|
||
ISL=1K
|
||
OSL=1K
|
||
C=32
|
||
```
|
||
|
||
运行稳定后,周期性注入一个长 Prefill:
|
||
|
||
```text
|
||
ISL=128K
|
||
OSL=1
|
||
C=1
|
||
```
|
||
|
||
比较注入前后:
|
||
|
||
- Decode P50/P95/P99 TPOT。
|
||
- Decode Output TPS。
|
||
- 长请求 TTFT。
|
||
- 每轮 Prefill Chunk。
|
||
- Scheduler Queue。
|
||
- GPU Timeline。
|
||
|
||
### 12.2 可调方向
|
||
|
||
- Chunked Prefill Size。
|
||
- Max Prefill Tokens。
|
||
- Max Batched Tokens。
|
||
- Max Running Requests/Max Num Seqs。
|
||
- Prefill 与 Decode 调度优先级。
|
||
- CUDA Graph Batch Coverage。
|
||
- 双 Batch Overlap 或框架已有的通算重叠能力。
|
||
|
||
调优目标不是单独最大化 Prefill TPS,而是减少长 Prefill 对 Decode SLO 的破坏。
|
||
|
||
## 13. Phase 8:显存与缓存
|
||
|
||
当前初始值应保持固定,只在发现明确证据后调整:
|
||
|
||
- GPU Memory Fraction。
|
||
- Max Context Length。
|
||
- Active Request Limit。
|
||
- KV Cache Dtype。
|
||
- Page/Block Size。
|
||
- CUDA Graph Capture Size。
|
||
|
||
若 KV Cache 是瓶颈,优先顺序:
|
||
|
||
1. 确认权重和 Workspace 的真实占用。
|
||
2. 检查 Allocated/Reserved 差值与碎片。
|
||
3. 使用 FP8 KV Cache,前提是当前 Kernel 支持且精度可接受。
|
||
4. 根据业务上限设置 Context Length,不为不会出现的极端长度预留容量。
|
||
5. 设置合理的 Active Request Limit,避免运行时 OOM。
|
||
6. 再考虑 CPU/L3 KV Offload。
|
||
|
||
Prefix Cache 单独做第二阶段测试:
|
||
|
||
| 命中率 | 用途 |
|
||
|---:|---|
|
||
| 0% | 纯计算基线 |
|
||
| 20% | 低复用业务 |
|
||
| 50% | 中等公共前缀 |
|
||
| 80% | Agent/Coding 高复用 |
|
||
|
||
Mooncake 或三级缓存只有在 Prefix 可复用时才有明显价值。随机独立 Prompt 不适合评价它。
|
||
|
||
## 14. Phase 9:MTP 与模型级优化
|
||
|
||
当 TP16 Baseline、并行拓扑、通信、Backend 和 Scheduler 已稳定后,再测试:
|
||
|
||
- 原生 MTP。
|
||
- DSpark。
|
||
- EAGLE。
|
||
- KV Cache 量化。
|
||
- 更低比特权重量化。
|
||
- Sparse Attention 算法或 Indexer 优化。
|
||
|
||
投机解码至少记录:
|
||
|
||
- Accept Rate。
|
||
- Mean Accept Length。
|
||
- Target Forward TPS。
|
||
- Draft/MTP 开销。
|
||
- CPU 调度气泡。
|
||
- 不同并发下的净收益。
|
||
|
||
不能只看 Accept Length,也不能只看 C=1。
|
||
|
||
## 15. 里程碑与交付物
|
||
|
||
### M1:可信 Baseline
|
||
|
||
完成条件:
|
||
|
||
- 七组最小矩阵均有 3 次重复。
|
||
- 同一 Case 的关键 TPS 变异系数尽量不超过 3%。
|
||
- 所有环境、命令和日志可追溯。
|
||
|
||
交付:
|
||
|
||
- Baseline Summary。
|
||
- SLO Frontier。
|
||
- GPU/CPU/Network Timeline。
|
||
|
||
### M2:瓶颈报告
|
||
|
||
完成条件:
|
||
|
||
- Prefill、Decode、混合三类 Profile 完成。
|
||
- 找出累计贡献最高的 1 到 3 个瓶颈。
|
||
- 每个判断都有 Trace、计数器或日志证据。
|
||
|
||
交付:
|
||
|
||
- `.nsys-rep` 或 Torch Trace。
|
||
- Kernel/NCCL Summary。
|
||
- Bottleneck Evidence Table。
|
||
|
||
### M3:并行拓扑 A/B
|
||
|
||
完成条件:
|
||
|
||
- TP16 保留基线。
|
||
- TP8+PP2 完成可行性与性能验证。
|
||
- Attention DP + MoE EP 完成支持性和显存评估。
|
||
|
||
交付:
|
||
|
||
- 每种拓扑的显存、通信、TTFT、TPOT 和 TPS 对比。
|
||
- 推荐拓扑与不推荐拓扑的证据。
|
||
|
||
### M4:首轮优化闭环
|
||
|
||
完成条件:
|
||
|
||
- 至少一项优化通过完整 Benchmark。
|
||
- 结果在无 Profiler 环境下可复现。
|
||
- 正确性无回归。
|
||
- 满足 SLO 的吞吐有明确改善。
|
||
|
||
期望目标:
|
||
|
||
- 首轮争取获得至少 10% 的 SLO 内吞吐提升,或显著降低 P95/P99 长尾。
|
||
- 若无法提升,也必须形成排除结论,说明瓶颈为什么不在该方向。
|
||
|
||
## 16. 实验纪律
|
||
|
||
每次实验都必须回答:
|
||
|
||
1. 改了什么?
|
||
2. 为什么认为它会影响当前瓶颈?
|
||
3. 除该变量外,还有什么发生了变化?
|
||
4. 端到端指标如何变化?
|
||
5. Profile 证据如何变化?
|
||
6. 是否引入精度、稳定性或显存风险?
|
||
7. 是否值得保留?
|
||
|
||
禁止以下做法:
|
||
|
||
- 同时修改多个参数后只报告最终 TPS。
|
||
- 用 Profiling Run 和普通 Run 直接比较性能。
|
||
- 只看平均值,不看 P95/P99。
|
||
- 用配置 ISL/OSL 估算 TPS,而不核对实际 token 数。
|
||
- 用 1 GiB NCCL 带宽代表 Decode 小消息性能。
|
||
- 因单个 Kernel 更快就宣称端到端优化成功。
|
||
- OOM 后不重启服务继续测试。
|
||
|
||
## 17. 首轮执行建议
|
||
|
||
建议直接按以下顺序推进:
|
||
|
||
1. 固化当前 TP16 服务命令和 Manifest。
|
||
2. 跑 P1、P2、P3、D1、D2、M1。
|
||
3. 同步采集 GPU、CPU 和双 Rail 数据。
|
||
4. 对 P3、D2、M1 各捕获 5 到 10 个 Engine Step。
|
||
5. 输出 NCCL、NSA/Attention、MoE、CPU Gap 四项时间占比。
|
||
6. 根据最大暴露时间选择第一个优化方向。
|
||
7. 优先做 TP16 与 TP8+PP2 的可行性和性能对比。
|
||
8. 回到完整 Benchmark 验证 SLO 内吞吐。
|
||
|
||
最重要的判定标准是:
|
||
|
||
> 优化暴露在关键路径上的时间,而不是只优化看起来最慢的单个算子。
|
||
|
||
## 18. 参考资料
|
||
|
||
- [vLLM Profiling](https://docs.vllm.ai/en/stable/contributing/profiling/)
|
||
- [SGLang Benchmark and Profiling](https://github.com/sgl-project/sglang/blob/main/docs/developer_guide/benchmark_and_profiling.md)
|
||
- [SGLang Server Arguments](https://github.com/sgl-project/sglang/blob/main/docs/advanced_features/server_arguments.md)
|
||
- [NVIDIA Nsight Systems User Guide](https://docs.nvidia.com/nsight-systems/UserGuide/index.html)
|
||
- [NVIDIA Nsight Systems Analysis Guide](https://docs.nvidia.com/nsight-systems/AnalysisGuide/index.html)
|
||
- [腾讯混元 Hy3 Preview AI Infra 精读笔记](../hy3_infra_article/Hy3_Preview_AI_Infra_精读笔记.md)
|