Files
aituner/docs/harness-ablation/no-llm-harness-mechanism-20260625.md

14 KiB
Raw Blame History

No-LLM Harness Mechanism - 2026-06-25

本文回答一个核心问题:如果不调用 LLMharness 为什么还能自动找到配置?

结论先说清楚no-LLM 模式下并不是“没有 planner”。当前 harness 本身就是一个 deterministic planner。LLM 在 AITuner 里只是一个可替换的 proposal backend当 harness 能从观测、瓶颈归因、候选 family 和 stop validator 中推出下一步时tuning loop 会直接使用 harness proposal而不会请求 LLM。

Tune loop 中 LLM 的位置

study tune 每轮的决策顺序是:

state + study spec + workload/probe results
        |
        v
build_harness_context(...)
        |
        +--> build_harness_stop_proposal(context)
        |       if true: write harness-stop and exit
        |
        +--> build_harness_guided_proposal(context)
        |       if true: run this deterministic proposal
        |
        +--> call_llm_for_proposal(...)
                only if no harness stop/proposal exists

因此在 study.llm.endpoint = null 的 no-LLM run 中,只要 harness 每轮都能给出 一个 deterministic proposal 或 deterministic stop整个实验就可以完全不调用 LLM。 如果 harness 既不能 propose 也不能 stop且没有 LLM endpointAITuner 会报错,而不是 偷偷退化成随机搜索。

当前 Qwen30B stopfix run 就是这种完整闭环:

.aituner/qwen30b-harness-only-medium-stopfix-dash1-20260624T144701Z/

它没有 LLM endpoint但仍完成了 9 个 measured trials并最终由 validator 写出 harness_stop

Harness 做的不是 prompt engineering

Harness 做的事情可以形式化成:

H = (O, B, G, S, V)

O: Observation schema
   将 workload、trial probes、SLO failure、launch failure、topology constraints
   转成结构化状态。

B: Bottleneck attribution
   将 SLO violation 归因到 serving regime例如 ttft_prefill、decode_tpot、
   admission_or_queueing、launch_or_memory。

G: Intervention grammar
   将 raw knobs 组织成有语义的 candidate families例如 topology、batching、
   sequence admission、KV memory headroom。

S: Scoring policy
   对候选 intervention 评分,选择最有信息量且最可能提升 SLO-constrained
   req/s/GPU 的下一步。

V: Validator / stop policy
   阻止非法、重复、已知失败或无意义的 proposal只有在剩余高价值候选被测完后
   才允许 stop。

LLM 可以读取这些结构化信息并生成 proposal但 no-LLM 时 H 自己就能生成 proposal。换句话说我们的核心是把

raw config vector search

转成:

mechanism-guided intervention search

这就是为什么没有 LLM 也能工作。

Agent loop 流程图

flowchart TD
  A[Baseline or latest measured trial] --> B[Load probe history and trial result]
  B --> C[Build workload L-C-A profile]
  B --> D[Build TrialProfile]
  C --> E[Rank bottleneck hypotheses]
  D --> E
  E --> F[Generate legal candidate actions]
  F --> G[Score candidates]
  G --> H{High-value candidate?}
  H -- yes --> I[Emit harness-proposal]
  I --> J[Run real vLLM trial over search range]
  J --> B
  H -- no --> K{Validator stop allowed?}
  K -- yes --> L[Emit harness-stop]
  K -- no --> M{LLM endpoint exists?}
  M -- yes --> N[Ask LLM backend]
  M -- no --> O[Fail loudly: no proposal source]

Observation: harness 看到什么

每一轮 harness 不看自然语言日志做猜测,而是读结构化状态:

  • StudySpec
    • hardware: GPU 数量、GPU 型号;
    • engine: base flags/envs、tunable flags/envs、topology constraints
    • trace: request mode、window id、输入长度过滤、输出长度 override
    • SLO: TTFT/TPOT rule、target pass rate
    • search: load range、tolerance、probe budget。
  • window_summary / WorkloadProfile
    • L: request length 分布、tail ratio
    • C: prefix/cache reuse
    • A: arrival rate、burstiness、interarrival variation。
  • 最近 trials
    • config patch
    • best feasible request rate
    • request_rate_per_gpu
    • pass rate
    • probe history
    • latency p50/p95/p99
    • SLO failure reason counts
    • launch/runtime failure stage。

这些数据会被压成 recent_trial_diagnosticstrial_profiles,后续步骤只使用这些结构化 字段。

Bottleneck classifier: 怎么判断方向

Harness 维护一组 ranked bottleneck hypotheses

ttft_prefill
decode_tpot
admission_or_queueing
launch_or_memory

它的输入不是单一阈值,而是多类证据:

  • workload default长 prompt tail 更偏向 ttft_prefill
  • request modedecode-only 且有 TPOT SLO 时更偏向 decode_tpot
  • probe sequence最近 trial 的 active bottleneck 权重大于旧 trial
  • failed reason counts
    • ttft_ms>... 支持 ttft_prefill
    • tpot_ms>... 支持 decode_tpot
    • arrival_lag_s> / probe_elapsed_s> 支持 admission_or_queueing
  • launch failure / OOM支持 launch_or_memory

代码里这不是一个硬编码单标签,而是带 confidence 的 ranked list。例如最近 probe 明确出现 TPOT failure会提高 decode_tpot 分数;如果同时 workload 有长 prompt tail ttft_prefill 仍会保留为次级 hypothesis。

Candidate family: raw knobs 如何变成 intervention

Harness 不直接在所有 tunable flags 上盲采样。它先把 knobs 分成有系统含义的 intervention family

Family 代表 knobs 机制含义
topology tensor-parallel-size, data-parallel-size, EP knobs 改变每请求并行度、replica 数量、通信/效率 tradeoff
batching max-num-batched-tokens, enable-chunked-prefill 改变 prefill/decode batching 与 HoL blocking
admission max-num-seqs 改变并发 admission 与 TPOT/TTFT tail
KV memory gpu-memory-utilization 改变 KV cache blocks 和可承载并发
failure memory failed signatures 阻止重复已知 launch/runtime 失败方向

关键点是candidate 来自当前 StudySpec 的 tunable schema 和 topology constraints。 例如 topology candidate 只枚举合法 TP/DP/EP 组合;如果 EP 没有直接证据generic topology search 不会主动引入 EP。

Scoring: 为什么会先走 topology再走 gmu

Candidate action 的评分大致是:

score = expected_bottleneck_relief * bottleneck_confidence
      + information_gain
      + launch_safety
      - regression_risk

然后 experiment_plan.next_action 选择最高分候选。分数超过阈值时harness 直接生成 proposal否则进入 stop validator 或 LLM fallback。

这套 scoring 体现了几个系统原则:

  1. Topology 是 serving 的一阶决策。 当 TP frontier 还没测完,gpu-memory-utilizationmax-num-seqs 这类 runtime 微调不会抢在 topology 前面。

  2. Topology 不是“越大越好”。 评分和最终 winner 都看 request_rate_per_gpu,不是 raw request rate。TP4 可能总吞吐 更高,但如果使用更多 GPU 后 per-GPU 效率下降,就不会成为 incumbent。

  3. Runtime tuning 必须 anchored on incumbent topology。 当 topology 已经验证过runtime proposal 会 preserve 当前 best topology只在其上 调 gpu-memory-utilizationmax-num-seqsmax-num-batched-tokens

  4. Measurement 决定最终答案。 Candidate 只是一个 hypothesis是否接受由真实 trial 的 SLO-constrained request_rate_per_gpu 决定。

Validator stop: 为什么不会过早停止

Harness stop 不是“找到一个不错配置就停”。当前 stop validator 包含几个条件:

  • search_high_saturated_by_incumbent
    • incumbent 的最高 feasible probe 已经贴近 configured search high
    • 说明当前测量范围已被打满。
  • topology_frontier_requires_probe
    • 如果 active bottleneck 仍要求更高 TP frontier 且未测,禁止 stop。
  • experiment_plan_has_high_value_candidate
    • 如果还有高分候选,禁止 stop。
  • post_incumbent_validation_exhausted
    • strong incumbent 后至少要有 post-incumbent validation
    • validation 覆盖 topology/runtime family 或达到足够数量;
    • 没有任何 validation trial 超过 incumbent
    • 才允许 clean stop。

所以 validator 的作用是 fail-safe

wrong proposal 最多浪费一个 trial
wrong stop 会终止搜索,所以必须由 deterministic validator 授权。

Qwen30B no-LLM run 中具体发生了什么

Run:

qwen30b-harness-only-medium-stopfix-dash1-20260624T144701Z

设置:

  • Model: Qwen/Qwen3-30B-A3B
  • Engine: community vLLM 0.20
  • Hardware: 8x H20, 允许 TP/DP/EP frontier
  • Trace: chat 0-8k, output 128, replay time scale 0.1
  • SLO: target pass rate 0.95, TTFT step rule, TPOT 50ms
  • LLM endpoint: null

真实 trial path:

Trial Source Config patch req/s/GPU pass rate Harness 解释
0001 baseline {} 2.2000 1.0000 建立 baseline 和 probe evidence
0002 harness TP=2 3.2583 1.0000 latency/SLO pressure 下先测 adjacent TP
0003 harness TP=4 2.0917 1.0000 验证更高 TP frontierraw 总吞吐高但 per-GPU 低
0004 harness TP=2, gmu=0.92 3.2583 1.0000 topology 已 settle开始 incumbent topology 上的 KV headroom climb
0005 harness TP=2, gmu=0.94 3.2583 1.0000 继续小步 hill-climb未改善但未失败
0006 harness TP=2, gmu=0.96 3.3333 1.0000 KV headroom 带来更高 feasible frontier
0007 harness TP=2, gmu=0.97 3.4333 1.0000 达到 safe ceiling成为 incumbent
0008 harness TP=4, DP=2 1.0458 1.0000 post-incumbent topology validation没有超过 incumbent
0009 harness TP=8 1.0458 1.0000 继续 frontier validation没有超过 incumbent
0010 harness stop stop - - validator: post_incumbent_validation_exhausted

这个过程里没有外部 LLM 决策。每一步 proposal 都来自 harness

  1. baseline 观测到当前 engine 在 SLO 下的可行 frontier
  2. bottleneck/机制模型认为 topology 是一阶干预;
  3. 测 TP2接受因为 per-GPU 从 2.2 提到 3.2583
  4. 测 TP4拒绝为 incumbent因为 per-GPU 降到 2.0917
  5. topology frontier settle 后,在 TP2 上小步提升 gpu-memory-utilization
  6. gmu=0.97 达到 3.4333
  7. 再测 nearby topology确认没有更好
  8. validator 授权 stop。

为什么这不是写死 Qwen30B

这条路径看起来像“harness 知道答案是 TP2+gmu0.97”,但代码机制不是这样写的。

没有写死的部分:

  • 没有写死 model name
  • 没有写死 Qwen30B
  • 没有写死 TP=2 是最终答案;
  • 没有写死 gmu=0.97 一定最好;
  • 没有跳过真实测量;
  • 没有把 TP4/TP8 直接判负,而是实际运行并比较。

真正写入 harness 的 domain knowledge 是:

  • TP/DP/EP 是 topology family必须满足 topology constraints
  • topology 通常是一阶 serving intervention要先于 runtime 微调被验证;
  • raw throughput 不等于目标,跨 topology 比较要用 request_rate_per_gpu
  • gpu-memory-utilization 是 KV memory headroom 微调,只应在 incumbent topology 上小步 hill-climb
  • launch failure 和 tested signatures 是 hard negative evidence
  • stop 必须由 validator 授权,不能由 proposer 自己说停就停。

这是一种系统机制约束,不是 case-specific prompt。

它和 BO / raw heuristic 的区别

普通 BO 或 raw heuristic 的搜索空间通常是:

config = {tp, dp, ep, gmu, max_num_seqs, max_num_batched_tokens, ...}
score = measured req/s/GPU

这会产生几个问题:

  • 它不知道哪些 knobs 是 topology family哪些是 runtime family
  • 它可能在没测 TP frontier 前浪费大量 trial 调 runtime
  • 它可能重复已知 launch failure
  • 它可能把 raw throughput 高但 GPU efficiency 差的配置误当方向;
  • 它很难解释“这个 trial 试图证伪哪个瓶颈 hypothesis”。

Harness-shaped search space 是:

state -> bottleneck hypothesis -> legal intervention family -> measured verdict

因此 BO、bandit、LLM、deterministic heuristic 都可以接在 harness 后面。它们优化的不是 raw knob vector而是有 serving 语义的 intervention graph。

这也是我们新 framing 的核心:

black-box optimization
  -> grey-box / mechanism-guided experimental optimization

当前还需要补的证据

No-LLM Qwen30B run 证明了 deterministic harness 可以完整闭环,但 paper 还需要继续补:

  1. Planner-agnostic ablation

    • raw BO vs harness-guided BO
    • raw heuristic vs harness deterministic policy
    • 证明收益来自 harness substrate而不是某个 LLM。
  2. Mechanism ablation

    • no attribution
    • shuffled attribution
    • no topology-first
    • no intervention grammar
    • no validator/failure memory。
  3. Near-optimum evidence

    • 在 1-2 个 case 做局部 grid
    • 证明 harness path 找到的是 near-optimal region不只是一个可行 config。
  4. Cross-case robustness

    • 再选 decode-heavy 或 long-prefill case
    • 验证不同 workload/SLO 下 candidate family 会发生合理切换。

一句话总结

No-LLM harness 能自动找到配置,是因为它已经实现了一个面向 serving 机制的实验 planner 先把 trial 观测归因成 bottleneck再把 bottleneck 映射成合法 intervention family按 SLO-constrained req/s/GPU 真实测量更新 incumbent最后由 validator 判断是否停止。 LLM 只是这个 planner 的一个可替换 proposal backend而不是 AITuner 的必要核心。