# Operating Point Lab

这个实验用一组**教材合成数据**演示四件事：

1. 先用质量、错误率和 P95 SLO 过滤不可行配置；
2. 用 qualified output tokens 计算 goodput 成本；
3. 在可行点中删除被支配配置；
4. 输出推荐点和 runner-up。

它不代表任何真实 GPU、模型、云价格或业务负载。请用自己的 `sweep.csv` 替换示例，才能形成作品集实测结论。

## 从网页下载并运行

网页读者先[下载完整实验 ZIP](../operating-point-lab.zip)，其中包含代码、输入材料、测试和 `expected/` 参考输出，无需获取整个仓库。需要 Python 3.10+，无需 GPU、API key 或第三方包。把 ZIP 保存到任意工作目录，在终端进入该目录后执行：

```bash
python3 -m zipfile -e operating-point-lab.zip .
cd operating-point-lab
python3 analyze.py sample-sweep.csv
python3 analyze.py sample-sweep.csv --constraints strict-ttft.json
python3 -m unittest -v
```

也可双击解压，再在解压出的 `operating-point-lab` 目录打开终端。预期 8 项测试通过；接下来所有命令都在这个目录运行。已持有完整站点的读者可直接进入 `labs/operating-point-lab`，跳过下载和解压。

这个 CSV 不是逐请求原始表，也不是尚未聚合的重复实验表；它要求<strong>每个 operating point 一行</strong>。你应先在独立 raw 目录保留每次 run，再用可审计脚本计算这一行。`config` 必须唯一，并包含足以区分模型、并行度、调度参数与负载点的身份；程序会拒绝重复值，防止字典覆盖悄悄丢掉一次 run。

CSV 字段：

- `config`：配置身份；
- `quality_score`：与固定 quality gate 对比；
- `error_rate`：包含 429、OOM、timeout 等；
- `p95_ttft_s`：对请求 TTFT 取 P95；
- `p95_itl_ms`：先收集所有成功完成、时间戳完整且至少输出两个 token 的请求中每一对相邻输出 token 的 gap，再对这些 gaps 取 P95；不可先删去 ITL 超标请求。若工具只给逐请求平均 TPOT，必须改字段名、阈值和报告，不能把 TPOT 填进 ITL 列；
- `qualified_output_tps`：通过成功、质量和 SLO 合同的输出 Token/s；
- `hourly_cost`：明确包含项与价格来源后的每小时成本；
- `headroom`：可解释的容量余量比例。

默认约束仅用于演示。真实项目应把它们写进 workload manifest；本程序支持用 <code>--constraints limits.json</code> 加载并打印本次约束。

## 从 Ch19 的 trace 走到配置选择（30 分钟）

先完成 scheduler lab 的 deadline30 反例：成功样本 P95 更好，可能只是慢请求超时了。本实验接下来问“在同一质量与负载下，哪些配置仍然可行”。它读取聚合 CSV，不会替你证明原始数据正确；模型、quality set、长度、到达模型、运行窗口和失败分母必须先冻结。

先预测：A、D、F 各会被哪个门淘汰？B 的成本较低，为什么不能说它支配了 C？写下预测后运行：

```bash
python3 analyze.py sample-sweep.csv
python3 -m unittest -v
```

实际程序输出见 [expected/default.txt](expected/default.txt)。A 被 error_rate、TTFT、headroom 淘汰；D 被 quality 淘汰；F 被 headroom 淘汰。B/C/E 都在 Pareto frontier，成本/百万合格输出分别约 0.823、1.113、1.141 个**合成货币单位**。按这次最低成本偏好推荐 B、runner-up 为 C。C 的延迟和错误率更低、headroom 更高，因此 B 没有支配 C。

手算 B：`11.50 / 3600 / 3880 × 1,000,000 ≈ 0.823`。这里只是复算聚合输入的决策，不能反向声称实测了每小时成本或 3,880 token/s。

### 只改合同，观察建议何时失效

先预测将 TTFT SLO 从 1.5 秒收紧到 1.0 秒后的推荐点，再运行：

```bash
python3 analyze.py sample-sweep.csv --constraints strict-ttft.json
```

程序会打印本次约束，实际输出见 [expected/strict-ttft.txt](expected/strict-ttft.txt)。这次 B 因 TTFT 被淘汰，C 成为推荐点，E 是 runner-up。CSV 没改，负载没改，是**决策合同**改变了。不能为了保住 B 再悄悄放宽阈值。自检：如果你把 max_error_rate 写成 5 表示 5%，程序应拒绝；正确值是 0.05。

### 聚合之前，先算对分母

设 10 秒窗口内共发出 4 个请求，质量门 0.90、单请求 TTFT 门 1.5 秒；下面只是手算数据，不是 sample-sweep 的来源。

| 请求 | 状态 | 输出 token | 质量 | TTFT | 其他请求级 SLO |
|---|---|---:|---:|---:|---|
| a | 成功 | 100 | 0.95 | 1.0s | 通过 |
| b | 超时 | 40（部分输出） | 未知 | 2.0s | 未完成 |
| c | 成功 | 200 | 0.80 | 1.0s | 通过 |
| d | 成功 | 50 | 0.95 | 2.0s | 通过 |

先自己计算，再对答案：错误率 `1/4=25%`；总已生成吞吐 `390/10=39 token/s`；合格吞吐只有 `100/10=10 token/s`。c 是质量失败，d 是 SLO 失败，都不是传输错误。不能把 `39×(1−25%)` 当 goodput；输出长度不同、质量/SLO 失败与系统错误也不是同一集合。实际 retry 需另外保留逻辑请求数与尝试数。

ITL 的输入必须有真实 token gap 或如实标注工具替代口径；不要把 Ch19 的 tick 填入这里的秒或毫秒列。所有请求超时或没有合格输出时，保留原始失败记录并判不可行，不填一个漂亮的零延迟；`qualified_output_tps=0` 会以 `no_goodput` 淘汰。CSV 的 NaN、负数和重复 config 会被拒绝，防止无效值漏过门槛。

### 换陌生工作负载后的交付

无 GPU 时，先用新的合成 workload 或获授权 trace 完成口径审计，明确 synthetic/trace-only。单 GPU 时，把固定请求、实际质量判断、超时/拒绝和 token 时间放到 raw；先生成每次运行结果，再聚合为一个 operating point。多 GPU 时保持总 GPU 数与同一 workload，单独比较 TP/replica 与故障域，不混入不同模型质量。

提交一页结论，包含默认推荐、收紧 SLO 后的推荐、上述四请求手算，以及自己的 workload 变化预测。验收：每个淘汰原因能回到字段与阈值；能够说明 B/C 的取舍；保留失败分母；在未取得真实模型、硬件和价格证据前，结论仍标记教材合成。
