diff --git a/docs/aituner-roadmap.md b/docs/aituner-roadmap.md new file mode 100644 index 0000000..8935581 --- /dev/null +++ b/docs/aituner-roadmap.md @@ -0,0 +1,81 @@ +# AITuner roadmap + +本文只维护最小 roadmap:我们想 claim 什么、已有证据在哪里、下一步缺哪块证据。 +详细实验过程放到对应专题文档里,不在这里堆流水账。 + +## Paper frame + +AITuner 的核心不是“用 LLM 调参”,而是一个 SLO-aware tuning agent workflow: + +```text +measurement -> observation -> bottleneck classifier -> candidate family + -> SLO-constrained scoring -> validator -> proposal / stop +``` + +LLM 的角色是 planner,不是唯一贡献。Harness 给 planner 提供 domain-specific +system knowledge 和决策边界,使 tuning 从开放式 knob guessing 变成受测量约束的 +优化过程。 + +## Scope decision + +当前 paper 主线先聚焦 vLLM serving engine,把 workflow/harness 机制论证完整: + +```text +vLLM cases first: workflow/harness effectiveness, mechanism, robustness, near-optimum evidence +multi-engine later: engine adapter abstraction, low adaptation cost, one SGLang-style validation case +``` + +因此主 claim 不写成“已经完整验证所有 serving engines”。更稳妥的表述是: + +- AITuner 的 control loop 使用 engine adapter 抽象:launch recipe、healthcheck、 + OpenAI-compatible request API、engine-specific flag/env mapping、topology constraints。 +- 当前实验集中在 vLLM 上,因为 vLLM case 足以完整证明 harness workflow 是否有效。 +- 不同 serving engine 的兼容性作为 architecture portability 论证;只有补充 + SGLang 等 engine 的 adapter 和至少一个验证 case 后,才升级为 evaluated claim。 + +## 设计点 + +| 设计点 | 作用 | 需要证明的性质 | +| --- | --- | --- | +| Observation | 把 config、probe history、SLO failure、latency profile、incumbent、failed signatures 结构化 | LLM 看到的是可计算状态,不只是自然语言日志 | +| Bottleneck classifier | 把 TTFT/prefill、decode TPOT、admission/queueing、memory/launch failure 分开 | proposal 方向和测量瓶颈一致 | +| Candidate family | 将 bottleneck 映射到 topology/runtime/cache/admission knob family | 搜索空间被压缩,但不写死单个 case | +| SLO-constrained scoring | 用 `max feasible req/s/GPU` 评价 candidate | 优化目标和生产 SLO 一致,不追 raw throughput | +| Validator / stop | 阻止非法、重复、失败 family;在 search high saturated 或无有效候选时停止 | 减少 GPU burn,同时避免过早停止 | + +## Claim roadmap + +| Claim | 当前状态 | 证据文档 | 缺口 | +| --- | --- | --- | --- | +| Harness 比 naive 收敛更快、上限更高 | 已有强证据 | [Qwen27B 2x2](harness-ablation/qwen27b-tight-2x2-model-ablation-20260623.md), [Qwen30B SLO robustness](harness-ablation/qwen30b-slo-robustness-20260624.md) | 补齐 Qwen235B decode 2x2 aggregate | +| Harness 不是强模型本身带来的收益 | 已有一个完整 2x2;第二个正在跑 | [Qwen27B 2x2](harness-ablation/qwen27b-tight-2x2-model-ablation-20260623.md), [Qwen235B prefill progress](harness-ablation/qwen235b-prefill-2x2-progress-20260623.md) | 完成 Qwen235B decode 2x2;更新 prefill final doc | +| Harness 对 SLO 变化 robust | Qwen30B 已完成 | [Qwen30B SLO robustness](harness-ablation/qwen30b-slo-robustness-20260624.md) | 选择一个第二 case 做 SLO sweep,而不是立即铺很多 case | +| Harness 找到的是合理/near-optimum config | 部分解释已有,严格证据不足 | [Qwen30B SLO robustness](harness-ablation/qwen30b-slo-robustness-20260624.md), [AITuner summary](aituner-harness-summary.md) | 对 1-2 个 case 做局部 grid 或专家配置对照 | +| Harness 的每个组件都有贡献 | 设计解释已有,组件 ablation 不足 | [AITuner summary](aituner-harness-summary.md) | 做 no-classifier / no-family / no-validator / no-stop ablation | +| Workflow 可通过 engine adapter 迁移到其他 serving engine | 设计上可行,暂不作为主实验 claim | 当前 `EngineLaunchSpec` / launch recipe 抽象 | vLLM 主线完成后,再做 SGLang adapter 和一个低成本验证 case | + +## 当前最高优先级 + +1. 完成并整理 Qwen235B decode 2x2。 + 目标:回答 `weak model + harness` 是否能超过 `strong model + naive`。 + +2. 更新 Qwen235B prefill 2x2 final 文档。 + 目标:避免 roadmap 指向过期 progress 文档。 + +3. 选定一个 near-optimum 证明 case。 + 目标:用小规模 grid 或专家配置对照证明 harness 找到的是合理最优区间,而不是 + prompt coincidence。 + +4. 决定第二个 SLO robustness case。 + 目标:证明 Qwen30B 以外也成立,但先不要盲目铺实验。 + +5. 设计 engine adapter 迁移实验,但暂缓执行。 + 目标:在 vLLM 证据链完整后,用一个 SGLang-style case 证明适配成本低,而不是提前分散主线。 + +## 暂不做 + +- 暂不同时开启大量 SLO sweep;先对齐 paper frame 和最高价值 claim。 +- 暂不把所有旧文档重写成中文;只对新证据文档和 roadmap 使用中文,旧文档按需要逐步迁移。 +- 暂不 claim 全局最优;没有 grid/expert baseline 前,只 claim near-optimum evidence pending。 +- 暂不把 multi-engine support 放进主 claim;先写成 adapter-based design,等 vLLM + 机制证据完整后再补 SGLang validation。 diff --git a/docs/harness-ablation/qwen30b-slo-robustness-20260624.md b/docs/harness-ablation/qwen30b-slo-robustness-20260624.md new file mode 100644 index 0000000..68fef49 --- /dev/null +++ b/docs/harness-ablation/qwen30b-slo-robustness-20260624.md @@ -0,0 +1,164 @@ +# Qwen30B SLO robustness - 2026-06-24 + +本文整理 Qwen30B-A3B community vLLM 0.20 case 在三档 SLO 下的 harness/naive +对比,并解释不同 SLO 为什么没有导致完全不同的最终 topology,却改变了可承载负载边界 +和 bottleneck 判断。 + +原始报告位于远端共享 checkout: + +```text +.aituner-reports/qwen30b-slo-robust-gpt55-dash1-20260623T163521Z-strict/report.md +.aituner-reports/qwen30b-slo-robust-gpt55-dash1-20260623T163521Z-medium/report.md +.aituner-reports/qwen30b-slo-robust-gpt55-dash1-20260623T163521Z-loose/report.md +``` + +## 实验设计 + +Case: `qwen30b-a3b-slo-{strict,medium,loose}-gpt55`。 + +共同设置: + +- Served model: Qwen30B-A3B community vLLM 0.20。 +- Hardware: H20,允许 1/2/4/8 GPU topology。 +- Trace: chat 0-8k,输出长度 128。 +- Search: `sampling_u in [0, 1.0]`,tolerance 0.001,max 6 probes。 +- Objective: 在 pass rate >= 0.95 下最大化 `request_rate / used_gpu_count`。 +- Tuner model: `gpt-5.5`。 + +三档 SLO: + +| SLO | TTFT step rule | TPOT | +| --- | --- | ---: | +| strict | <=4k: 1s, <=32k: 2s, else: 3s | 40 ms | +| medium | <=4k: 2s, <=32k: 4s, else: 6s | 50 ms | +| loose | <=4k: 4s, <=32k: 8s, else: 12s | 70 ms | + +## 结果摘要 + +| SLO | Harness final req/s/GPU | Naive final req/s/GPU | Final speedup | AUC speedup | Harness TTT | +| --- | ---: | ---: | ---: | ---: | ---: | +| strict | 2.2083 | 0.8000 | 2.7604x | 2.7886x | 1 | +| medium | 3.2583 | 0.8000 | 4.0729x | 4.0729x | 1 | +| loose | 3.2583 | 1.0458 | 3.1155x | 4.4622x | 1 | + +三个 SLO 下 harness 都在第一个 trial 到达该 SLO 下的 reference best。naive 在 8 个 +trials 内没有达到 95% reference target。 + +## 最终 tune 出来的配置 + +三档 SLO 的最终 best topology 都是: + +```text +tensor-parallel-size = 2 +data-parallel-size = 1 +enable-expert-parallel = false +``` + +但这不表示 SLO 没有影响。SLO 改变的是同一个 topology 的可行负载上限: + +| SLO | Best config | Best sampling_u | Total req/s | req/s/GPU | Pass rate | +| --- | --- | ---: | ---: | ---: | ---: | +| strict | `TP=2, DP=1` | 0.484375 | 4.4167 | 2.2083 | 1.0000 | +| medium | `TP=2, DP=1` | 0.750000 | 6.5167 | 3.2583 | 1.0000 | +| loose | `TP=2, DP=1` | 0.750000 | 6.5167 | 3.2583 | 1.0000 | + +strict 到 medium/loose 的主要变化是 feasible frontier 右移:同一个 `TP=2, DP=1` +配置在 strict 下只能稳定承载 `sampling_u=0.484375`,在 medium/loose 下可以承载 +`sampling_u=0.75`。 + +## 为什么 `TP=2, DP=1` 稳定胜出 + +AITuner 的 scoring 不是 raw throughput,而是 SLO-constrained per-GPU throughput: + +```text +J(c, SLO) = max_u request_rate(c, u) / used_gpu_count(c) +subject to pass_rate(c, u, SLO) >= 0.95 +``` + +这解释了为什么 `TP=4` 没有赢。`TP=4` 的单请求 latency 更低、总吞吐可以更高, +但它使用两倍 GPU,per-GPU objective 反而下降: + +| SLO | Config | Total req/s | Used GPUs | req/s/GPU | 解释 | +| --- | --- | ---: | ---: | ---: | --- | +| strict | `TP=2, DP=1` | 4.4167 | 2 | 2.2083 | strict best | +| strict | `TP=4, DP=1` | 4.4167 | 4 | 1.1042 | latency 更低,但 GPU efficiency 更差 | +| medium/loose | `TP=2, DP=1` | 6.5167 | 2 | 3.2583 | medium/loose best | +| medium/loose | `TP=4, DP=1` | 8.3667 | 4 | 2.0917 | raw throughput 更高,但 per-GPU 不划算 | + +因此 harness 学到的不是“越多 GPU 越好”,而是更具体的机制: + +```text +TP=1: 单请求 prefill/decode latency 偏高,SLO-constrained load frontier 低。 +TP=2: 足够缓解 latency,同时 GPU 数量仍低,per-GPU objective 最优。 +TP=4: 继续降低 latency,但通信和 GPU 数量成本超过收益。 +``` + +## SLO 改变 bottleneck 的方式 + +strict 下,`TP=2, DP=1` 在 `sampling_u=0.484375` 可行,但下一档 +`sampling_u=0.5` 直接进入 queueing collapse: + +| Point | Pass rate | 主要失败原因 | +| --- | ---: | --- | +| strict, `u=0.484375` | 1.0000 | 无 | +| strict, `u=0.5` | 0.0290 | `tpot_ms>40`, `ttft_ms>1000/2000`, `slo_pass_rate_unrecoverable` | + +medium/loose 下,TTFT 阈值放宽后,同一 topology 能承载更高 arrival intensity。 +但是在 `u=0.765625` 仍会进入不可恢复的排队区: + +| SLO | Feasible point | Next infeasible point | 主要失败原因 | +| --- | --- | --- | --- | +| medium | `u=0.75`, pass 1.0000 | `u=0.765625`, pass 0.6900 | `tpot_ms>50`, `slo_pass_rate_unrecoverable` | +| loose | `u=0.75`, pass 1.0000 | `u=0.765625`, pass 0.2900 | `tpot_ms>70`, `slo_pass_rate_unrecoverable` | + +这说明 SLO 放宽不是无限提高吞吐。服务系统还有 queueing stability frontier; +超过 frontier 后,即使单个请求的 steady-state latency 看起来可控,排队也会让 pass rate +迅速崩掉。 + +## 其他候选配置的信号 + +`TP=1, DP=1` 对 SLO 更敏感: + +| SLO | `TP=1, DP=1` req/s/GPU | 解释 | +| --- | ---: | --- | +| strict | 2.2000 | 接近 strict best,但略低于 `TP=2` | +| medium | 2.2000 | 仍低于 `TP=2` | +| loose | 2.8500 | 宽松 SLO 下受益明显,但仍低于 `TP=2` | + +`gpu-memory-utilization=0.92` 在 medium/loose 中与 `TP=2` 打平: + +| SLO | Config | req/s/GPU | +| --- | --- | ---: | +| medium | `TP=2, gpu-memory-utilization=0.92` | 3.2583 | +| loose | `TP=2, gpu-memory-utilization=0.92` | 3.2583 | + +这说明该 workload 的主瓶颈不是 KV memory headroom,而是 topology 和 queueing +frontier。 + +EP family 在该环境下不稳定: + +```text +TP=4, EP=2/4, enable-expert-parallel=true -> engine_launch exit_code=2 +``` + +这些失败 trial 没有进入 best candidate,但它们说明当前 failure memory 还可以继续加强: +同一类 EP launch failure 出现后,后续 proposal 应更积极地屏蔽该 family。 + +## 对 paper claim 的含义 + +这组实验支持的 claim 是: + +1. Harness 对 SLO 变化有稳定收益:strict/medium/loose 三档均显著优于 naive。 +2. Harness 不是固定写死某个 knob。它通过 SLO-constrained probing 找到 feasible + frontier;在本 case 中最终 topology 相同,但可承载负载边界随 SLO 改变。 +3. Harness 的 value 来自 topology-first candidate family、per-GPU scoring 和 + validator 对 failed family 的处理,而不是自然语言 prompt 的偶然表达。 + +这组实验尚不能单独 claim: + +- 所有模型和 workload 上都 robust。 +- `TP=2, DP=1` 是全局最优。 +- EP family 已经被最优处理。 + +对应的后续证据应放在 roadmap 中跟踪:局部 grid/near-optimum、跨模型 2x2、跨 workload +SLO robustness,以及 failure-memory ablation。 diff --git a/infra/gpu_fleet/config/fleet.example.toml b/infra/gpu_fleet/config/fleet.example.toml index ad41108..03bce71 100644 --- a/infra/gpu_fleet/config/fleet.example.toml +++ b/infra/gpu_fleet/config/fleet.example.toml @@ -51,6 +51,13 @@ enabled = true sync_remote_path = "~/aituner" fleet_root = "~/.aituner_gpu_fleet" +[[hosts]] +name = "dash4" +ssh_alias = "dash4" +enabled = true +sync_remote_path = "~/workspace/aituner" +fleet_root = "~/.aituner_gpu_fleet" + [[hosts]] name = "dash5" ssh_alias = "dash5" diff --git a/infra/gpu_fleet/config/ssh_aliases.example.txt b/infra/gpu_fleet/config/ssh_aliases.example.txt index 9c851ad..681f2f2 100644 --- a/infra/gpu_fleet/config/ssh_aliases.example.txt +++ b/infra/gpu_fleet/config/ssh_aliases.example.txt @@ -4,5 +4,5 @@ dash0 dash1 dash2 dash3 +dash4 dash5 -