# sskj — 多平台大模型推理性能基准测试项目

> **更新（2026-07-21 14:12:30 +0800）**
> - RTX 6000D / DeepSeek-V4-Flash 的 SGLang 全量与 tiny 脚本切换到 `lmsysorg/sglang:nightly-dev-cu13-20260720-b3570a45`，MoE backend 保持 `auto`，由 nightly 自动选择可用的 FlashInfer MoE 实现；同时使用独立 nightly CUDA 13 cache，避免复用旧 SM120 修补镜像的编译缓存。

> **更新（2026-07-21 14:00:30 +0800）**
> - adaptive 并发搜索新增可配置的 `C=1 OOM` 配置级短路：同一 TP/DP 在最小并发仍 OOM 时，直接跳过该组更长输入，避免把已经确定不可部署的长度继续压测；6000D DSV4-Flash SGLang tiny 已启用，并支持从已有结果恢复时识别此前的该边界。

> **更新（2026-07-21 11:54:30 +0800）**
> - 新增 RTX 6000D / DeepSeek-V4-Flash tiny 自适应并发实验：输出固定 1K，输入遍历 1K、2K、4K、8K、16K、32K、64K、128K，并发采用 `C=16` 起、每次加 16、首点失败时按 `16 -> 8 -> 1` 回退。
> - vLLM 覆盖 TP2/DP4、TP4/DP2、TP8/DP1，部署固定为 128K context、128 活跃请求、0.9 显存比例；SGLang 覆盖 TP4/DP2、TP8/DP1，固定为 128K、64、0.9，TP2/DP4 因 SM120 Marlin 权重加载 OOM 明确排除。

> **更新（2026-07-20 17:55:20 +0800）**
> - H20 SGLang TPxDP matrix 默认传入 `--cuda-graph-max-bs-decode 128`，使高并发 decode 在 batch 不超过 128 时持续使用 CUDA Graph；Docker 与 native 启动入口均已覆盖。

> **更新（2026-07-20 17:25:40 +0800）**
> - RTX 6000D 的 SGLang DSV4-Flash 默认传入 `--cuda-graph-max-bs-decode 16`，避免 SM120 sparse MLA 在大 batch CUDA Graph 预捕获时 OOM。该参数仅限制预捕获图的 decode batch 上限，不限制服务的 `max-running-requests` 或 benchmark 并发；其他平台默认不受影响。
> - H20、RTX 6000D、P800 的配置不再硬编码 sskj 仓库绝对路径：仓库内的环境、数据集、缓存和 P800 patch 均通过共享的 `${ROOT_DIR}` 推导，仓库迁移后无需逐个修改路径。

> **更新（2026-07-20，PR 自动化测试）**
> - 仅用于验证 Gitee 受保护分支的自动 Pull Request 创建与评审流程；不修改实验代码、配置或结果口径。

> **更新（2026-07-20，`903084c`）**
> - RTX 6000D 的 SGLang DSV4-Flash 默认传入 `--cuda-graph-max-bs-decode 16`，避免 SM120 sparse MLA 在大 batch CUDA Graph 预捕获时 OOM。该参数仅限制预捕获图的 decode batch 上限，不限制服务的 `max-running-requests` 或 benchmark 并发；其他平台默认不受影响。
> - H20 / RTX 6000D 的 TPxDP matrix baseline 不再显式限制模型上下文或服务内并发：vLLM 使用默认 `max-model-len` / `max-num-seqs`，SGLang 使用默认 `context-length` / `max-running-requests`。
> - SGLang 固定使用 `--moe-runner-backend marlin`；vLLM 保持框架默认 MoE backend。
> - `run_adaptive_concurrency_add16.sh` 在首点 OOM 时会重启服务并按 `C=16 -> 8 -> 1` 回退；仅 H20 / RTX 6000D matrix 默认开启，H200 / P800 保持原行为。
> - RTX 6000D 旧 SGLang 结果使用 262K context cap，超过该范围或 C>32 的点不可与新 baseline 混用；请使用新的 `RUN_ID` 重跑受影响场景。

> **项目目的**：当新显卡（GPU/NPU）到货时，用最短时间完成大模型在该平台上的推理性能评估与部署配置选型。
> 当前模型：DeepSeek-V4-Flash（FP8 / INT8）；后续接入 GLM5.2，**完全复用**本项目的实验与报告流程。
> 新平台接入 SOP：[`docs/NEW_PLATFORM_GUIDE.md`](docs/NEW_PLATFORM_GUIDE.md)。

## 这个项目解决什么问题

1. **新卡快速评估**：新平台到货后，按 SOP 复制实验目录、改少量配置，即可跑起与既有平台口径一致的 benchmark，横向可比。
2. **部署配置选型**：通过 TP×DP 并行矩阵 + 自适应并发搜索，回答"该平台上哪种并行配置在什么并发下满足 SLO、吞吐最高"。
3. **数据资产化**：每轮实验产出结构化结果（jsonl/csv/manifest），汇总成飞书性能报告并回填多维表格，形成可检索的历史数据库。

## 标准工作流（全流程）

```
① 跑实验        experiments/<platform>/<experiment>/run_adaptive_concurrency*.sh
                └─ 公共搜索逻辑: scripts/common/adaptive_bench_lib.sh
② 落盘          adaptive_results/<run_id>/
                └─ adaptive_points.jsonl / adaptive_shapes.jsonl / adaptive_summary.* / run_manifest.json
③ 分析          用 Python 从 jsonl 实算（禁止目测），SLO 口径见 docs/SLO_STANDARDS.md
④ 飞书报告      按飞书 wiki「性能报告编写指南（README）」写到「显卡性能报告/<平台>」节点下
⑤ 回填多维表格  飞书「模型推理适配 Bench 迭代跟踪」：每成功探测点一行
```

- SLO 口径（S2 层，DSV4-Flash / GLM5.2 均适用）：**TTFT P95 < 3s，TPOT P95 < 50ms**，严格小于。详见 [`docs/SLO_STANDARDS.md`](docs/SLO_STANDARDS.md)。
- 报告编写规范（章节骨架、分析口径、发布流程）以飞书 wiki「显卡性能报告 / 性能报告编写指南（README）」为准。
- 多维表格每行 = 一个成功探测点（config、Concurrency、Throughput、Input/Output TPS、TTFT/TPOT/E2E P95、SLO达标状态、开发文档链接）。

## 目录结构

```
platforms/                # 平台配置（每平台一个 .env）+ 平台补丁（patches/）
scripts/common/           # 跨实验复用的编排组件（见下）
experiments/              # 实验目录（三层结构）
├── TEMPLATE/             # 老式固定场景对比实验模板（sglang vs vllm）
├── h20/                  # NVIDIA H20 96GB
├── h200/                 # NVIDIA H200 143GB
├── p800/                 # Kunlun P800 XPU
└── pro6000/              # NVIDIA RTX 6000D
docs/                     # 规范与指南（SLO、实验规范、新卡接入）
envs/                     # 环境搭建文档（具体 venv 不提交，见 .gitignore）
datasets/                 # benchmark 数据集（不提交）
BENCHMARK_WORKFLOW.md     # 结果目录与命名规范、results.json schema
```

### scripts/common/ 组件

| 文件 | 职责 |
|---|---|
| `lib.sh` | 日志、health check、metadata JSON 生成 |
| `platform.sh` | 平台自动探测并加载 `platforms/<chip>.env` |
| `adaptive_bench_lib.sh` | **自适应并发搜索核心库**（引擎无关，靠 5 个 `engine_*` 回调注入平台逻辑） |
| `adaptive_concurrency.py` | 上者的 Python 助手（shapes 生成、结果解析、汇总） |
| `parse_backend.py` | 固定并发实验：raw jsonl → results.json + report.md |
| `compare.py` | SGLang vs vLLM 横向对比表（老式实验用） |
| `warmup.py` | 服务预热 |
| `server_docker.sh` / `bench_client_docker.sh` | P800 专用 Docker 服务端/客户端生命周期 |
| `adaptive_heartbeat.sh` | 长跑实验的心跳监控（手动独立运行） |

## 实验索引

### TP/DP matrix + 自适应并发（当前主流形态）

| 实验 | 说明 |
|---|---|
| `experiments/h20/dsv4_h20_vllm_tp_dp_matrix/` | H20 + vLLM，TP2/DP4、TP4/DP2、TP8/DP1 |
| `experiments/h20/dsv4_h20_sglang_tp_dp_matrix/` | H20 + SGLang，同上 |
| `experiments/h200/dsv4_h200_vllm_tp_dp_matrix/` | H200 + vLLM |
| `experiments/h200/dsv4_h200_sglang_tp_dp_matrix/` | H200 + SGLang |
| `experiments/p800/dsv4_p800_sglang_tp_dp_matrix/` | P800 + SGLang（INT8；TP2/DP4 启动 OOM 无数据，见 config.env 注释） |
| `experiments/pro6000/dsv4_pro6000_vllm_tp_dp_matrix/` | RTX 6000D + vLLM |
| `experiments/pro6000/dsv4_pro6000_sglang_tp_dp_matrix/` | RTX 6000D + SGLang |

每个目录内：`run_bench.sh` 跑固定并发矩阵；`run_adaptive_concurrency.sh` 从 C=1 指数倍增搜饱和点；`run_adaptive_concurrency_add16.sh` 从 C=16 线性 +16 步进、带 TTFT SLO 停止与回退（当前主力用法，见 `experiments/ADAPTIVE_CONCURRENCY_USAGE.md`）。

### 其他实验（H200 老形态 & 专项）

| 实验 | 说明 |
|---|---|
| `experiments/h200/dsv4_h200_sglang/` `…/dsv4_h200_vllm/` | H200 单引擎 baseline |
| `experiments/h200/dsv4_h200_sglang_vs_vllm/` | H200 引擎控制变量对比 |
| `experiments/h200/dsv4_h200_dspark/` `…/dsv4_h200_vllm_dspark_vs_default/` | DSpark 投机解码相关 |
| `experiments/h200/dsv4_h200_vllm_mtp_vs_default/` | vLLM MTP 对比 |
| `experiments/h200/dsv4_h200_vllm_tp{2,4,8}_custom_bench/` | 自定义压测客户端（多服务负载均衡） |
| `experiments/h200/dsv4_h200_max_context_length/` `…/dsv4_h200_long_context_matrix/` `…/dsv4_h200_256k_4k_probe/` `…/dsv4_h200_64k_sglang_vs_vllm/` | 长上下文专项 |
| `experiments/p800/dsv4_p800_sglang/` `…/dsv4_p800_max_context_length/` `…/dsv4_p800_long_context_matrix/` `…/dsv4_p800_256k_4k_probe/` | P800 baseline 与长上下文专项 |
| `experiments/TEMPLATE/` | 老式固定场景实验模板 |

## 快速复现

以 H20 vLLM 自适应并发搜索为例（其他平台同理，换目录即可）：

```bash
# 1. dry-run：只打印搜索计划，不加载模型
cd experiments/h20/dsv4_h20_vllm_tp_dp_matrix
DRY_RUN=1 bash run_adaptive_concurrency_add16.sh

# 2. 单组合冒烟：只测 TP=8、1K/128，并发上限 8
RUN_ID=smoke-$(date +%Y%m%d-%H%M%S) \
TP_LIST="8" ISL_LIST="1024" OSL_LIST="128" GRID_LIMIT=1 SEARCH_MAX_CONCURRENCY=8 \
bash run_adaptive_concurrency_add16.sh

# 3. 正式跑（放 tmux）
tmux new-session -d -s h20-vllm-adaptive \
  "cd $(pwd) && bash run_adaptive_concurrency_add16.sh"
```

更多用法（断点续跑 RESUME_RUN_ID、常用覆盖参数）见 `experiments/ADAPTIVE_CONCURRENCY_USAGE.md`。

## 新平台 / 新模型接入

- **新显卡**：按 [`docs/NEW_PLATFORM_GUIDE.md`](docs/NEW_PLATFORM_GUIDE.md) 执行，核心动作是复制 `experiments/h20/dsv4_h20_<engine>_tp_dp_matrix`、改 `config.env` / `adaptive_config.env` / `matrix.json` 三件套，再加 `platforms/<chip>.env`。
- **新模型（GLM5.2）**：复用同一实验目录结构，新增 `experiments/<platform>/glm52_<platform>_<engine>_tp_dp_matrix/`，改模型路径、量化与引擎启动参数即可；SLO 口径、报告流程、多维表格结构不变。

## 环境要求

- 公共：bash、Python 3、`sglang.bench_serving` 压测客户端（Docker 或 venv）；绘图分析用 `envs/charts/`（matplotlib）。
- 各平台的镜像 / venv / 模型路径见对应实验目录的 `config.env` 与 `platforms/<chip>.env`；**模型与数据集路径是机器相关的**，换机器时按实际路径调整。
- 环境搭建规范见 `envs/README.md` 与 `envs/UV_ENV_SETUP.md`。

## 注意事项

- 提交内容：实验代码 + 最终产物（results.json / report.md / adaptive 的 jsonl 与 summary）；日志、raw_outputs、gpu_logs 不入库（`.gitignore` 已排除）。
- 仓库会clone到多台机器，实验脚本内引用公共组件一律用 `${SCRIPT_DIR}/../../../scripts/common`（TEMPLATE 为 `../../`），不要写绝对路径。
