Prepare remaining Qwen30 latency cases
This commit is contained in:
@@ -0,0 +1,136 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Compare one complete Qwen30 Frontier latency surface with real vLLM."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
from itertools import combinations
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
CONFIGS = tuple(f"tp{tp}_mns{mns}" for tp in (1, 2, 4) for mns in (8, 16, 32, 64))
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args() -> argparse.Namespace:
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--sim-root", type=Path, required=True)
|
||||||
|
parser.add_argument("--real-audit", type=Path, required=True)
|
||||||
|
parser.add_argument("--json-output", type=Path, required=True)
|
||||||
|
parser.add_argument("--markdown-output", type=Path, required=True)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def number(value: Any, field: str) -> float:
|
||||||
|
if not isinstance(value, (int, float)) or isinstance(value, bool):
|
||||||
|
raise ValueError(f"{field} is not numeric: {value!r}")
|
||||||
|
result = float(value)
|
||||||
|
if not math.isfinite(result) or result < 0:
|
||||||
|
raise ValueError(f"{field} is invalid: {value!r}")
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def parse_config(name: str) -> tuple[int, int]:
|
||||||
|
tp, mns = name.split("_", 1)
|
||||||
|
return int(tp.removeprefix("tp")), int(mns.removeprefix("mns"))
|
||||||
|
|
||||||
|
|
||||||
|
def rank(values: dict[str, float]) -> list[str]:
|
||||||
|
return [name for name, _ in sorted(values.items(), key=lambda item: (item[1], item[0]))]
|
||||||
|
|
||||||
|
|
||||||
|
def pairwise(sim: dict[str, float], real: dict[str, float]) -> dict[str, int | float | None]:
|
||||||
|
concordant = discordant = ties = 0
|
||||||
|
for left, right in combinations(CONFIGS, 2):
|
||||||
|
sim_delta = sim[left] - sim[right]
|
||||||
|
real_delta = real[left] - real[right]
|
||||||
|
if math.isclose(sim_delta, 0.0, abs_tol=1e-9) or math.isclose(real_delta, 0.0, abs_tol=1e-9):
|
||||||
|
ties += 1
|
||||||
|
elif (sim_delta > 0) == (real_delta > 0):
|
||||||
|
concordant += 1
|
||||||
|
else:
|
||||||
|
discordant += 1
|
||||||
|
informative = concordant + discordant
|
||||||
|
return {
|
||||||
|
"concordant_pairs": concordant,
|
||||||
|
"discordant_pairs": discordant,
|
||||||
|
"tied_pairs": ties,
|
||||||
|
"informative_pairs": informative,
|
||||||
|
"agreement": concordant / informative if informative else None,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
args = parse_args()
|
||||||
|
root = args.sim_root.resolve()
|
||||||
|
audit = json.loads(args.real_audit.read_text())
|
||||||
|
metrics = tuple(audit.get("applicable_metrics") or [])
|
||||||
|
if not metrics or set(audit.get("configs") or {}) != set(CONFIGS):
|
||||||
|
raise ValueError("real audit is incomplete")
|
||||||
|
expected_requests = int(audit["trace_manifests"]["tp1"]["requests"])
|
||||||
|
cells: dict[str, Any] = {}
|
||||||
|
for name in CONFIGS:
|
||||||
|
tp, mns = parse_config(name)
|
||||||
|
path = root / "runs" / name / f"tp{tp}" / "result.json"
|
||||||
|
result = json.loads(path.read_text())
|
||||||
|
if result.get("status") != "completed" or result.get("request_count") != expected_requests:
|
||||||
|
raise ValueError(f"incomplete simulator result: {path}")
|
||||||
|
if result.get("config") != {"tp": tp, "mns": mns, "name": name}:
|
||||||
|
raise ValueError(f"simulator config drift: {path}")
|
||||||
|
score = result.get("score")
|
||||||
|
if not isinstance(score, dict):
|
||||||
|
raise ValueError(f"simulator score missing: {path}")
|
||||||
|
values: dict[str, Any] = {}
|
||||||
|
for metric in metrics:
|
||||||
|
prefix = metric.removesuffix("_ms")
|
||||||
|
values[metric] = {
|
||||||
|
statistic: number(score.get(f"{prefix}_{statistic}_ms"), f"{path}:{metric}:{statistic}")
|
||||||
|
for statistic in ("mean", "p90")
|
||||||
|
}
|
||||||
|
cells[name] = {"path": str(path), "metrics": values}
|
||||||
|
selection: dict[str, Any] = {}
|
||||||
|
for metric in metrics:
|
||||||
|
for statistic in ("mean", "p90"):
|
||||||
|
sim_values = {name: cells[name]["metrics"][metric][statistic] for name in CONFIGS}
|
||||||
|
real_values = {
|
||||||
|
name: number(
|
||||||
|
audit["configs"][name]["metrics"][metric][f"pooled_{statistic}_ms"],
|
||||||
|
f"real:{name}:{metric}:{statistic}",
|
||||||
|
)
|
||||||
|
for name in CONFIGS
|
||||||
|
}
|
||||||
|
sim_ranking, real_ranking = rank(sim_values), rank(real_values)
|
||||||
|
sim_choice, real_best = sim_ranking[0], real_ranking[0]
|
||||||
|
selection[f"{metric}:{statistic}"] = {
|
||||||
|
"sim_winner": sim_choice,
|
||||||
|
"real_winner": real_best,
|
||||||
|
"winner_match": sim_choice == real_best,
|
||||||
|
"selected_config_real_regret": (real_values[sim_choice] - real_values[real_best]) / real_values[real_best],
|
||||||
|
"sim_ranking": sim_ranking,
|
||||||
|
"real_ranking": real_ranking,
|
||||||
|
**pairwise(sim_values, real_values),
|
||||||
|
}
|
||||||
|
payload = {
|
||||||
|
"schema": "qwen30-latency-case-frontier-real-comparison-v1",
|
||||||
|
"sim_root": str(root),
|
||||||
|
"real_audit": str(args.real_audit.resolve()),
|
||||||
|
"prefill_only": bool(audit["prefill_only"]),
|
||||||
|
"applicable_metrics": metrics,
|
||||||
|
"selection": selection,
|
||||||
|
"cells": cells,
|
||||||
|
}
|
||||||
|
lines = ["# Qwen30 Frontier vs real latency selection", "", "| Objective | Frontier | Real | Match | Regret | Pairwise |", "|---|---|---|---:|---:|---:|"]
|
||||||
|
for objective, row in selection.items():
|
||||||
|
agreement = "N/A" if row["agreement"] is None else f"{row['agreement']:.1%}"
|
||||||
|
lines.append(f"| {objective} | {row['sim_winner']} | {row['real_winner']} | {'yes' if row['winner_match'] else 'no'} | {row['selected_config_real_regret']:.1%} | {agreement} |")
|
||||||
|
args.json_output.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
args.markdown_output.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
args.json_output.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n")
|
||||||
|
args.markdown_output.write_text("\n".join(lines) + "\n")
|
||||||
|
print(json.dumps(selection, sort_keys=True))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
186
runs/frontier-fidelity-envelope-v1/audit_qwen30_latency_case.py
Normal file
186
runs/frontier-fidelity-envelope-v1/audit_qwen30_latency_case.py
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Audit one completed Qwen30 latency-selection real surface.
|
||||||
|
|
||||||
|
This reader intentionally treats a prefill-only case as a four-objective
|
||||||
|
surface: TTFT/E2E mean and p90. TPOT is omitted rather than coerced to zero.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
import statistics
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
CONFIGS = tuple(f"tp{tp}_mns{mns}" for tp in (1, 2, 4) for mns in (8, 16, 32, 64))
|
||||||
|
TRIALS = (1, 2, 3)
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args() -> argparse.Namespace:
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--case-root", type=Path, required=True)
|
||||||
|
parser.add_argument("--json-output", type=Path, required=True)
|
||||||
|
parser.add_argument("--markdown-output", type=Path, required=True)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def nearest_rank(values: list[float], fraction: float) -> float:
|
||||||
|
if not values:
|
||||||
|
raise ValueError("cannot calculate a percentile of an empty metric")
|
||||||
|
return sorted(values)[math.ceil(len(values) * fraction) - 1]
|
||||||
|
|
||||||
|
|
||||||
|
def finite(value: Any, field: str) -> float:
|
||||||
|
if not isinstance(value, (int, float)) or isinstance(value, bool):
|
||||||
|
raise ValueError(f"{field} is not numeric: {value!r}")
|
||||||
|
value = float(value)
|
||||||
|
if not math.isfinite(value) or value < 0:
|
||||||
|
raise ValueError(f"{field} is invalid: {value!r}")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def read_manifest(root: Path, tp: int) -> dict[str, Any]:
|
||||||
|
path = root / "traces" / f"tp{tp}" / "public" / "manifest.json"
|
||||||
|
manifest = json.loads(path.read_text())
|
||||||
|
if manifest.get("schema") != "qwen30-latency-case-v1":
|
||||||
|
raise ValueError(f"unexpected trace schema in {path}")
|
||||||
|
if manifest.get("tensor_parallel_size") != tp or int(manifest.get("requests", 0)) <= 0:
|
||||||
|
raise ValueError(f"invalid trace contract in {path}")
|
||||||
|
outputs = manifest.get("output_tokens")
|
||||||
|
if not isinstance(outputs, list) or len(outputs) != 1 or int(outputs[0]) <= 0:
|
||||||
|
raise ValueError(f"non-uniform output contract in {path}")
|
||||||
|
return manifest
|
||||||
|
|
||||||
|
|
||||||
|
def metric_stats(values: list[float]) -> dict[str, float]:
|
||||||
|
return {"samples": len(values), "mean_ms": statistics.fmean(values), "p90_ms": nearest_rank(values, 0.90)}
|
||||||
|
|
||||||
|
|
||||||
|
def validate_trial(path: Path, manifest: dict[str, Any]) -> tuple[dict[str, list[float]], dict[str, Any]]:
|
||||||
|
payload = json.loads(path.read_text())
|
||||||
|
if payload.get("schema") != "qwen30-exact-trace-anchor-v1":
|
||||||
|
raise ValueError(f"unexpected real result schema in {path}")
|
||||||
|
contract = payload.get("contract")
|
||||||
|
summary = payload.get("summary")
|
||||||
|
records = payload.get("requests")
|
||||||
|
if not isinstance(contract, dict) or not isinstance(summary, dict) or not isinstance(records, list):
|
||||||
|
raise ValueError(f"malformed result payload: {path}")
|
||||||
|
expected = int(manifest["requests"])
|
||||||
|
expected_contract = {
|
||||||
|
"requests": expected,
|
||||||
|
"requests_file_sha256": manifest["private_jsonl_sha256"],
|
||||||
|
"row_vector_sha256": manifest["row_vector_sha256"],
|
||||||
|
"first_arrival_s": manifest["first_arrival_s"],
|
||||||
|
"last_arrival_s": manifest["last_arrival_s"],
|
||||||
|
}
|
||||||
|
for name, wanted in expected_contract.items():
|
||||||
|
actual = contract.get(name)
|
||||||
|
if isinstance(wanted, float):
|
||||||
|
if not isinstance(actual, (int, float)) or not math.isclose(float(actual), wanted, abs_tol=1e-9):
|
||||||
|
raise ValueError(f"{path}: contract drift for {name}")
|
||||||
|
elif actual != wanted:
|
||||||
|
raise ValueError(f"{path}: contract drift for {name}")
|
||||||
|
if len(records) != expected or summary.get("completed") != expected or summary.get("failed") != 0:
|
||||||
|
raise ValueError(f"{path}: incomplete real replay")
|
||||||
|
|
||||||
|
metrics: dict[str, list[float]] = {"ttft_ms": [], "tpot_ms": [], "e2e_ms": []}
|
||||||
|
indices: set[int] = set()
|
||||||
|
expected_output = int(manifest["output_tokens"][0])
|
||||||
|
for record in records:
|
||||||
|
if record.get("success") is not True:
|
||||||
|
raise ValueError(f"{path}: failed request record")
|
||||||
|
index = record.get("source_index")
|
||||||
|
if not isinstance(index, int) or index in indices:
|
||||||
|
raise ValueError(f"{path}: duplicate/non-integer source index")
|
||||||
|
indices.add(index)
|
||||||
|
if record.get("actual_input_tokens") != record.get("input_tokens"):
|
||||||
|
raise ValueError(f"{path}: input usage drift")
|
||||||
|
if record.get("requested_output_tokens") != expected_output or record.get("actual_output_tokens") != expected_output:
|
||||||
|
raise ValueError(f"{path}: output usage drift")
|
||||||
|
for metric in ("ttft_ms", "e2e_ms"):
|
||||||
|
metrics[metric].append(finite(record.get(metric), metric))
|
||||||
|
tpot = record.get("tpot_ms")
|
||||||
|
if expected_output == 1:
|
||||||
|
if tpot is not None:
|
||||||
|
raise ValueError(f"{path}: OSL=1 must report TPOT=null")
|
||||||
|
else:
|
||||||
|
metrics["tpot_ms"].append(finite(tpot, "tpot_ms"))
|
||||||
|
if len(indices) != expected:
|
||||||
|
raise ValueError(f"{path}: missing source rows")
|
||||||
|
return metrics, {"result_path": str(path), "requests": expected}
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
args = parse_args()
|
||||||
|
root = args.case_root.resolve()
|
||||||
|
manifests = {tp: read_manifest(root, tp) for tp in (1, 2, 4)}
|
||||||
|
prefill_only = int(manifests[1]["output_tokens"][0]) == 1
|
||||||
|
if any((int(manifest["output_tokens"][0]) == 1) != prefill_only for manifest in manifests.values()):
|
||||||
|
raise ValueError("TP-specific output contracts differ")
|
||||||
|
applicable = ("ttft_ms", "e2e_ms") if prefill_only else ("ttft_ms", "tpot_ms", "e2e_ms")
|
||||||
|
configs: dict[str, Any] = {}
|
||||||
|
for name in CONFIGS:
|
||||||
|
tp = int(name.split("_", 1)[0].removeprefix("tp"))
|
||||||
|
trial_rows = []
|
||||||
|
pooled = {metric: [] for metric in applicable}
|
||||||
|
for trial in TRIALS:
|
||||||
|
path = root / "real" / name / f"trial{trial}" / "results" / "result.json"
|
||||||
|
values, provenance = validate_trial(path, manifests[tp])
|
||||||
|
trial_rows.append({
|
||||||
|
**provenance,
|
||||||
|
"trial": trial,
|
||||||
|
"metrics": {metric: metric_stats(values[metric]) for metric in applicable},
|
||||||
|
})
|
||||||
|
for metric in applicable:
|
||||||
|
pooled[metric].extend(values[metric])
|
||||||
|
configs[name] = {
|
||||||
|
"trials": trial_rows,
|
||||||
|
"metrics": {
|
||||||
|
metric: {
|
||||||
|
"pooled_samples": len(pooled[metric]),
|
||||||
|
"pooled_mean_ms": statistics.fmean(pooled[metric]),
|
||||||
|
"pooled_p90_ms": nearest_rank(pooled[metric], 0.90),
|
||||||
|
"trial_mean_of_means_ms": statistics.fmean(
|
||||||
|
row["metrics"][metric]["mean_ms"] for row in trial_rows
|
||||||
|
),
|
||||||
|
"trial_stddev_of_means_ms": statistics.stdev(
|
||||||
|
row["metrics"][metric]["mean_ms"] for row in trial_rows
|
||||||
|
),
|
||||||
|
}
|
||||||
|
for metric in applicable
|
||||||
|
},
|
||||||
|
}
|
||||||
|
winners: dict[str, Any] = {}
|
||||||
|
for metric in applicable:
|
||||||
|
for statistic in ("pooled_mean_ms", "pooled_p90_ms"):
|
||||||
|
ranked = sorted((row["metrics"][metric][statistic], name) for name, row in configs.items())
|
||||||
|
winners[f"{metric}:{statistic}"] = {
|
||||||
|
"winner": ranked[0][1],
|
||||||
|
"winner_value_ms": ranked[0][0],
|
||||||
|
"ranking": [name for _, name in ranked],
|
||||||
|
}
|
||||||
|
payload = {
|
||||||
|
"schema": "qwen30-latency-case-real-audit-v1",
|
||||||
|
"case_root": str(root),
|
||||||
|
"prefill_only": prefill_only,
|
||||||
|
"applicable_metrics": list(applicable),
|
||||||
|
"trace_manifests": {f"tp{tp}": manifests[tp] for tp in manifests},
|
||||||
|
"configs": configs,
|
||||||
|
"winners": winners,
|
||||||
|
}
|
||||||
|
lines = ["# Qwen30 real latency case audit", "", f"Prefill-only: `{prefill_only}`.", ""]
|
||||||
|
lines += ["| Objective | Real winner | Value (ms) |", "|---|---|---:|"]
|
||||||
|
for objective, winner in winners.items():
|
||||||
|
lines.append(f"| {objective} | {winner['winner']} | {winner['winner_value_ms']:.2f} |")
|
||||||
|
args.json_output.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
args.markdown_output.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
args.json_output.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n")
|
||||||
|
args.markdown_output.write_text("\n".join(lines) + "\n")
|
||||||
|
print(json.dumps(winners, sort_keys=True))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,245 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Materialize Qwen30 Fixed/Trace latency cases without changing their contract.
|
||||||
|
|
||||||
|
The private request file deliberately contains either an exact source prompt
|
||||||
|
(trace cases) or deterministic token IDs (fixed cases). The public Frontier
|
||||||
|
fixture contains only arrivals, shapes, sessions, and legal complete prefix
|
||||||
|
block identities.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import csv
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import math
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
|
||||||
|
FIELDS = (
|
||||||
|
"arrived_at",
|
||||||
|
"num_prefill_tokens",
|
||||||
|
"num_decode_tokens",
|
||||||
|
"session_id",
|
||||||
|
"block_hash_ids",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def sha256(path: Path) -> str:
|
||||||
|
digest = hashlib.sha256()
|
||||||
|
with path.open("rb") as source:
|
||||||
|
for chunk in iter(lambda: source.read(1 << 20), b""):
|
||||||
|
digest.update(chunk)
|
||||||
|
return digest.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def row_digest(rows: list[dict[str, Any]]) -> str:
|
||||||
|
digest = hashlib.sha256()
|
||||||
|
for row in rows:
|
||||||
|
digest.update(
|
||||||
|
json.dumps(
|
||||||
|
[
|
||||||
|
row["source_index"],
|
||||||
|
row["arrived_at"],
|
||||||
|
row["input_length"],
|
||||||
|
row["output_length"],
|
||||||
|
row["session_id"],
|
||||||
|
row["runtime_block_ids"],
|
||||||
|
],
|
||||||
|
separators=(",", ":"),
|
||||||
|
).encode()
|
||||||
|
)
|
||||||
|
digest.update(b"\n")
|
||||||
|
return digest.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args() -> argparse.Namespace:
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
sub = parser.add_subparsers(dest="kind", required=True)
|
||||||
|
|
||||||
|
trace = sub.add_parser("trace")
|
||||||
|
trace.add_argument("--base-public", type=Path, required=True)
|
||||||
|
trace.add_argument("--base-private", type=Path, required=True)
|
||||||
|
trace.add_argument("--output-tokens", type=int, required=True)
|
||||||
|
trace.add_argument("--tp", type=int, required=True)
|
||||||
|
trace.add_argument("--output-root", type=Path, required=True)
|
||||||
|
|
||||||
|
fixed = sub.add_parser("fixed")
|
||||||
|
fixed.add_argument("--model", type=Path, required=True)
|
||||||
|
fixed.add_argument("--input-tokens", type=int, required=True)
|
||||||
|
fixed.add_argument("--output-tokens", type=int, required=True)
|
||||||
|
fixed.add_argument("--requests", type=int, required=True)
|
||||||
|
fixed.add_argument("--per-gpu-rate", type=float, required=True)
|
||||||
|
fixed.add_argument("--tp", type=int, required=True)
|
||||||
|
fixed.add_argument("--output-root", type=Path, required=True)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def materialize_trace(args: argparse.Namespace) -> tuple[list[dict[str, Any]], bool, str, float]:
|
||||||
|
with args.base_public.open(newline="") as source:
|
||||||
|
public = list(csv.DictReader(source))
|
||||||
|
private = [json.loads(line) for line in args.base_private.open() if line.strip()]
|
||||||
|
if not public or len(public) != len(private):
|
||||||
|
raise ValueError("trace public/private request count mismatch")
|
||||||
|
rows: list[dict[str, Any]] = []
|
||||||
|
for public_row, private_row in zip(public, private, strict=True):
|
||||||
|
if int(public_row["num_prefill_tokens"]) != int(private_row["input_length"]):
|
||||||
|
raise ValueError("trace input-length drift")
|
||||||
|
if float(public_row["arrived_at"]) != float(private_row["arrived_at"]):
|
||||||
|
raise ValueError("trace arrival drift")
|
||||||
|
# The real vLLM request artifact retains its final partial prompt block
|
||||||
|
# for provenance, while the Frontier CSV deliberately projects only
|
||||||
|
# legal complete cache blocks. Use the latter as the shared
|
||||||
|
# simulator-facing identity vector; vLLM itself derives cache hashes
|
||||||
|
# from the exact private prompt text.
|
||||||
|
runtime_ids = [int(value) for value in public_row["block_hash_ids"].split("|") if value]
|
||||||
|
if len(runtime_ids) != int(private_row["input_length"]) // 16:
|
||||||
|
raise ValueError("public trace exposes an incomplete runtime prefix block")
|
||||||
|
if int(public_row["session_id"]) != int(private_row["session_id"]):
|
||||||
|
raise ValueError("trace session-id drift")
|
||||||
|
body = dict(private_row["body"])
|
||||||
|
body.update(
|
||||||
|
{
|
||||||
|
"min_tokens": args.output_tokens,
|
||||||
|
"max_tokens": args.output_tokens,
|
||||||
|
"ignore_eos": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
rows.append(
|
||||||
|
{
|
||||||
|
"source_index": int(private_row["source_index"]),
|
||||||
|
"arrived_at": float(private_row["arrived_at"]),
|
||||||
|
"input_length": int(private_row["input_length"]),
|
||||||
|
"output_length": args.output_tokens,
|
||||||
|
"session_id": int(private_row["session_id"]),
|
||||||
|
"runtime_block_ids": runtime_ids,
|
||||||
|
"body": body,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
rows,
|
||||||
|
True,
|
||||||
|
"trace-derived: exact input/arrival/session/prefix; output override only",
|
||||||
|
len(rows) / 600.0 * args.tp,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def materialize_fixed(args: argparse.Namespace) -> tuple[list[dict[str, Any]], bool, str, float]:
|
||||||
|
if min(args.input_tokens, args.output_tokens, args.requests, args.tp) <= 0:
|
||||||
|
raise ValueError("fixed dimensions must be positive")
|
||||||
|
if args.input_tokens + args.output_tokens > 40960:
|
||||||
|
raise ValueError("fixed shape exceeds max model length")
|
||||||
|
if not math.isfinite(args.per_gpu_rate) or args.per_gpu_rate <= 0:
|
||||||
|
raise ValueError("per-GPU rate must be positive")
|
||||||
|
from transformers import AutoTokenizer
|
||||||
|
|
||||||
|
tokenizer = AutoTokenizer.from_pretrained(args.model, trust_remote_code=True)
|
||||||
|
candidates = [
|
||||||
|
token for token in range(tokenizer.vocab_size) if token not in set(tokenizer.all_special_ids)
|
||||||
|
]
|
||||||
|
if len(candidates) < args.requests + 1:
|
||||||
|
raise ValueError("tokenizer does not provide enough non-special tokens")
|
||||||
|
rate = args.per_gpu_rate * args.tp
|
||||||
|
base = candidates[0]
|
||||||
|
rows = []
|
||||||
|
for index in range(args.requests):
|
||||||
|
rows.append(
|
||||||
|
{
|
||||||
|
"source_index": index,
|
||||||
|
"arrived_at": index / rate,
|
||||||
|
"input_length": args.input_tokens,
|
||||||
|
"output_length": args.output_tokens,
|
||||||
|
"session_id": index,
|
||||||
|
"runtime_block_ids": [],
|
||||||
|
"body": {
|
||||||
|
"prompt": [candidates[index + 1], *([base] * (args.input_tokens - 1))],
|
||||||
|
"min_tokens": args.output_tokens,
|
||||||
|
"max_tokens": args.output_tokens,
|
||||||
|
"ignore_eos": True,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return (
|
||||||
|
rows,
|
||||||
|
False,
|
||||||
|
"fixed-shape: deterministic token IDs, uniform TP-normalized QPS, no prefix reuse",
|
||||||
|
rate,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def write_case(
|
||||||
|
rows: list[dict[str, Any]],
|
||||||
|
*,
|
||||||
|
prefix_caching: bool,
|
||||||
|
description: str,
|
||||||
|
global_rate: float,
|
||||||
|
tp: int,
|
||||||
|
root: Path,
|
||||||
|
) -> None:
|
||||||
|
if not rows:
|
||||||
|
raise ValueError("empty case")
|
||||||
|
root = root.resolve()
|
||||||
|
public_root = root / "public"
|
||||||
|
private_root = root / "private"
|
||||||
|
public_root.mkdir(parents=True, exist_ok=True)
|
||||||
|
private_root.mkdir(parents=True, exist_ok=True)
|
||||||
|
public_path = public_root / "frontier.csv"
|
||||||
|
private_path = private_root / "real_requests.jsonl"
|
||||||
|
with public_path.open("w", newline="") as output:
|
||||||
|
writer = csv.DictWriter(output, fieldnames=FIELDS, lineterminator="\n")
|
||||||
|
writer.writeheader()
|
||||||
|
for row in rows:
|
||||||
|
writer.writerow(
|
||||||
|
{
|
||||||
|
"arrived_at": f"{row['arrived_at']:.12f}",
|
||||||
|
"num_prefill_tokens": row["input_length"],
|
||||||
|
"num_decode_tokens": row["output_length"],
|
||||||
|
"session_id": row["session_id"],
|
||||||
|
"block_hash_ids": "|".join(str(value) for value in row["runtime_block_ids"]),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
with private_path.open("w") as output:
|
||||||
|
for row in rows:
|
||||||
|
output.write(json.dumps(row, separators=(",", ":")) + "\n")
|
||||||
|
arrivals = [float(row["arrived_at"]) for row in rows]
|
||||||
|
manifest = {
|
||||||
|
"schema": "qwen30-latency-case-v1",
|
||||||
|
"description": description,
|
||||||
|
"tensor_parallel_size": tp,
|
||||||
|
"requests": len(rows),
|
||||||
|
"output_tokens": sorted({int(row["output_length"]) for row in rows}),
|
||||||
|
"prefix_caching": prefix_caching,
|
||||||
|
"public_csv": str(public_path),
|
||||||
|
"public_csv_sha256": sha256(public_path),
|
||||||
|
"private_jsonl": str(private_path),
|
||||||
|
"private_jsonl_sha256": sha256(private_path),
|
||||||
|
"row_vector_sha256": row_digest(rows),
|
||||||
|
"first_arrival_s": arrivals[0],
|
||||||
|
"last_arrival_s": arrivals[-1],
|
||||||
|
"global_offered_request_rate": global_rate,
|
||||||
|
"per_gpu_offered_request_rate": global_rate / tp,
|
||||||
|
}
|
||||||
|
(public_root / "manifest.json").write_text(json.dumps(manifest, indent=2, sort_keys=True) + "\n")
|
||||||
|
print(json.dumps(manifest, sort_keys=True))
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
args = parse_args()
|
||||||
|
if args.kind == "trace":
|
||||||
|
rows, prefix, description, global_rate = materialize_trace(args)
|
||||||
|
else:
|
||||||
|
rows, prefix, description, global_rate = materialize_fixed(args)
|
||||||
|
write_case(
|
||||||
|
rows,
|
||||||
|
prefix_caching=prefix,
|
||||||
|
description=description,
|
||||||
|
global_rate=global_rate,
|
||||||
|
tp=args.tp,
|
||||||
|
root=args.output_root,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
# EXP-SIMFID-Q30-LATENCY-EXPANSION: remaining Fixed/Trace × PD/P cases
|
||||||
|
|
||||||
|
> Status: prepared for runtime-alignment preflight (2026-07-18). The already
|
||||||
|
> completed Qwen3-30B-A3B Trace-PD surface is excluded from this card.
|
||||||
|
|
||||||
|
## Question and fixed boundary
|
||||||
|
|
||||||
|
Does the same graph-aligned Frontier configuration that selected the correct
|
||||||
|
winner on Trace-PD also select the real vLLM winner when either the arrival/
|
||||||
|
prefix state or the decode phase is removed? This is a selection test, not an
|
||||||
|
SLO/capacity evaluation.
|
||||||
|
|
||||||
|
| Case | Input / output | arrival and cache | Applicable objectives |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Fixed-PD | 2048 / 128 | 129 uniform requests; `t'=t/TP`; prefix cache off | mean/p90 TTFT, TPOT, E2E |
|
||||||
|
| Trace-P | exact held-out input, arrival, session and complete block-16 prefix relation / 1 | same TP-normalized 129-row trace; prefix cache on | mean/p90 TTFT, E2E; TPOT=N/A |
|
||||||
|
| Fixed-P | 2048 / 1 | 129 uniform requests; `t'=t/TP`; prefix cache off | mean/p90 TTFT, E2E; TPOT=N/A |
|
||||||
|
|
||||||
|
All cases use Qwen3-30B-A3B BF16, community vLLM 0.20.0, H20, `TP∈{1,2,4}`
|
||||||
|
and `MNS∈{8,16,32,64}`, MBT=8192, chunked prefill, three fresh-server trials
|
||||||
|
per cell. The fixed QPS is the Trace-PD base offered rate (`129/600` req/s per
|
||||||
|
GPU), hence the global arrival rate is multiplied by TP. It makes throughput
|
||||||
|
per GPU comparable without claiming that different TP values see identical
|
||||||
|
cluster-level load.
|
||||||
|
|
||||||
|
## Simulator and real contracts
|
||||||
|
|
||||||
|
- Frontier uses commit `deadc4a…`, `piecewise`, the frozen CUDA-event profile
|
||||||
|
for prefill/mixed batches and KERNEL_ONLY profile for captured pure decode.
|
||||||
|
- Trace-P reuses the already verified graph buckets/KV capacities because the
|
||||||
|
server CLI is unchanged from Trace-PD. The only workload change is `OSL→1`.
|
||||||
|
- Fixed-P/PD disables vLLM prefix caching on both sides. Before freezing their
|
||||||
|
simulator surfaces, a no-request server-start preflight records the actual
|
||||||
|
graph captures and KV-block capacities for every `(TP,MNS)`; no request
|
||||||
|
latency or winner is used as calibration.
|
||||||
|
- Each real result verifies every request's input/output usage and row-vector
|
||||||
|
digest. `OSL=1` produces JSON `null` TPOT samples and is never converted to
|
||||||
|
zero.
|
||||||
|
|
||||||
|
## Decision rule and cost
|
||||||
|
|
||||||
|
For every applicable objective, compare the complete 12-cell simulator and
|
||||||
|
pooled three-trial real surface: winner match, selected-config real regret,
|
||||||
|
and non-tied pair direction agreement. A simulator crash or missing request
|
||||||
|
metric is a coverage failure, not a high-latency cell.
|
||||||
|
|
||||||
|
The no-request Fixed runtime preflight is capped at 2 H20-GPUh. Each 36-run
|
||||||
|
real surface is estimated at 13 nominal / 41 worst-case H20-GPUh, plus CPU-only
|
||||||
|
Frontier replay. Launch logs record the resolved inputs, paths, and duration.
|
||||||
@@ -279,19 +279,23 @@ def score(path: Path, expected_shapes: list[tuple[int, int]]) -> dict[str, Any]:
|
|||||||
ttfts = [float(row["ttft_ms"]) for row in request_metrics]
|
ttfts = [float(row["ttft_ms"]) for row in request_metrics]
|
||||||
tpots = [float(row["tpot_ms"]) for row in request_metrics if row["tpot_ms"] is not None]
|
tpots = [float(row["tpot_ms"]) for row in request_metrics if row["tpot_ms"] is not None]
|
||||||
e2es = [float(row["e2e_ms"]) for row in request_metrics]
|
e2es = [float(row["e2e_ms"]) for row in request_metrics]
|
||||||
|
def summary(values: list[float]) -> dict[str, float | None]:
|
||||||
|
if not values:
|
||||||
|
return {"mean": None, "p50": None, "p90": None, "p95": None}
|
||||||
return {
|
return {
|
||||||
"ttft_mean_ms": sum(ttfts) / len(ttfts),
|
"mean": sum(values) / len(values),
|
||||||
"ttft_p50_ms": percentile(ttfts, 0.50),
|
"p50": percentile(values, 0.50),
|
||||||
"ttft_p90_ms": percentile(ttfts, 0.90),
|
"p90": percentile(values, 0.90),
|
||||||
"ttft_p95_ms": percentile(ttfts, 0.95),
|
"p95": percentile(values, 0.95),
|
||||||
"tpot_mean_ms": sum(tpots) / len(tpots),
|
}
|
||||||
"tpot_p50_ms": percentile(tpots, 0.50),
|
|
||||||
"tpot_p90_ms": percentile(tpots, 0.90),
|
ttft_summary = summary(ttfts)
|
||||||
"tpot_p95_ms": percentile(tpots, 0.95),
|
tpot_summary = summary(tpots)
|
||||||
"e2e_mean_ms": sum(e2es) / len(e2es),
|
e2e_summary = summary(e2es)
|
||||||
"e2e_p50_ms": percentile(e2es, 0.50),
|
return {
|
||||||
"e2e_p90_ms": percentile(e2es, 0.90),
|
**{f"ttft_{name}_ms": value for name, value in ttft_summary.items()},
|
||||||
"e2e_p95_ms": percentile(e2es, 0.95),
|
**{f"tpot_{name}_ms": value for name, value in tpot_summary.items()},
|
||||||
|
**{f"e2e_{name}_ms": value for name, value in e2e_summary.items()},
|
||||||
"slos": slos,
|
"slos": slos,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ TP="${TP:?TP is required}"
|
|||||||
MNS="${MNS:?MNS is required}"
|
MNS="${MNS:?MNS is required}"
|
||||||
TRACE_LABEL="${TRACE_LABEL:?TRACE_LABEL is required}"
|
TRACE_LABEL="${TRACE_LABEL:?TRACE_LABEL is required}"
|
||||||
SERVER_PORT="${SERVER_PORT:?SERVER_PORT is required}"
|
SERVER_PORT="${SERVER_PORT:?SERVER_PORT is required}"
|
||||||
|
PREFIX_CACHING="${PREFIX_CACHING:-true}"
|
||||||
VENV_ROOT="${VENV_ROOT:-/tmp/wjh/venvs/vllm-0.20.0-cu129-profiler-v1}"
|
VENV_ROOT="${VENV_ROOT:-/tmp/wjh/venvs/vllm-0.20.0-cu129-profiler-v1}"
|
||||||
MODEL_ROOT="${MODEL_ROOT:-/home/admin/cpfs/wjh/models/Qwen/Qwen3-30B-A3B}"
|
MODEL_ROOT="${MODEL_ROOT:-/home/admin/cpfs/wjh/models/Qwen/Qwen3-30B-A3B}"
|
||||||
FLASHINFER_WORKSPACE_BASE="${FLASHINFER_WORKSPACE_BASE:-/tmp/wjh/flashinfer-workspace-vllm020-profiler-v1}"
|
FLASHINFER_WORKSPACE_BASE="${FLASHINFER_WORKSPACE_BASE:-/tmp/wjh/flashinfer-workspace-vllm020-profiler-v1}"
|
||||||
SERVED_MODEL="qwen3-30b-exact-trace"
|
SERVED_MODEL="qwen3-30b-exact-trace"
|
||||||
|
EXACT_TRACE_CLIENT="${EXACT_TRACE_CLIENT:-qwen30_exact_trace_client.py}"
|
||||||
SERVER_PID=""
|
SERVER_PID=""
|
||||||
|
|
||||||
mkdir -p "${OUTPUT_ROOT}/logs" "${OUTPUT_ROOT}/provenance" "${OUTPUT_ROOT}/results" \
|
mkdir -p "${OUTPUT_ROOT}/logs" "${OUTPUT_ROOT}/provenance" "${OUTPUT_ROOT}/results" \
|
||||||
@@ -37,8 +39,21 @@ if [[ "${#GPU_IDS[@]}" -ne "${TP}" ]]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
case "${PREFIX_CACHING}" in
|
||||||
|
true)
|
||||||
|
PREFIX_CACHING_FLAG="--enable-prefix-caching"
|
||||||
|
;;
|
||||||
|
false)
|
||||||
|
PREFIX_CACHING_FLAG="--no-enable-prefix-caching"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "ERROR: PREFIX_CACHING must be true or false, got ${PREFIX_CACHING}" >&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
REQUEST_COUNT="$(wc -l < "${REQUESTS_FILE}")"
|
REQUEST_COUNT="$(wc -l < "${REQUESTS_FILE}")"
|
||||||
echo "QWEN30_EXACT_TRACE_REAL_LAUNCH_ECHO host=$(hostname) gpus=${CUDA_VISIBLE_DEVICES} model=${MODEL_ROOT} runtime=vLLM-0.20.0+cu129 dtype=BF16 config=TP${TP}_MNS${MNS}_MBT8192 trace=${TRACE_LABEL} requests=${REQUEST_COUNT} source=${REQUESTS_FILE} arrivals=original600s input_output_prompt=exact prefix=on block=16 tpot_slo=150ms flashinfer_workspace=${FLASHINFER_WORKSPACE_BASE} output=${OUTPUT_ROOT} expected_wall=12-35m hard_wall=3600s"
|
echo "QWEN30_EXACT_TRACE_REAL_LAUNCH_ECHO host=$(hostname) gpus=${CUDA_VISIBLE_DEVICES} model=${MODEL_ROOT} runtime=vLLM-0.20.0+cu129 dtype=BF16 config=TP${TP}_MNS${MNS}_MBT8192 trace=${TRACE_LABEL} requests=${REQUEST_COUNT} source=${REQUESTS_FILE} arrivals=manifest prefix=${PREFIX_CACHING} block=16 metrics=TTFT,TPOT-if-OSL-gt-1,E2E flashinfer_workspace=${FLASHINFER_WORKSPACE_BASE} output=${OUTPUT_ROOT} expected_wall=12-35m hard_wall=3600s"
|
||||||
date -u +"START_UTC=%Y-%m-%dT%H:%M:%SZ"
|
date -u +"START_UTC=%Y-%m-%dT%H:%M:%SZ"
|
||||||
sha256sum qwen30_exact_trace_client.py run_qwen30_exact_trace_real_anchor.sh \
|
sha256sum qwen30_exact_trace_client.py run_qwen30_exact_trace_real_anchor.sh \
|
||||||
../frontier-phase-factorial-v0/qwen30_prefill_client.py \
|
../frontier-phase-factorial-v0/qwen30_prefill_client.py \
|
||||||
@@ -60,7 +75,7 @@ setsid "${VENV_ROOT}/bin/vllm" serve "${MODEL_ROOT}" \
|
|||||||
--host 127.0.0.1 --port "${SERVER_PORT}" --served-model-name "${SERVED_MODEL}" \
|
--host 127.0.0.1 --port "${SERVER_PORT}" --served-model-name "${SERVED_MODEL}" \
|
||||||
--tensor-parallel-size "${TP}" --gpu-memory-utilization 0.92 \
|
--tensor-parallel-size "${TP}" --gpu-memory-utilization 0.92 \
|
||||||
--max-model-len 40960 --max-num-batched-tokens 8192 --max-num-seqs "${MNS}" \
|
--max-model-len 40960 --max-num-batched-tokens 8192 --max-num-seqs "${MNS}" \
|
||||||
--enable-prefix-caching --enable-chunked-prefill --no-enable-log-requests \
|
"${PREFIX_CACHING_FLAG}" --enable-chunked-prefill --no-enable-log-requests \
|
||||||
> "${OUTPUT_ROOT}/logs/server.log" 2>&1 &
|
> "${OUTPUT_ROOT}/logs/server.log" 2>&1 &
|
||||||
SERVER_PID=$!
|
SERVER_PID=$!
|
||||||
READY=0
|
READY=0
|
||||||
@@ -89,7 +104,7 @@ fi
|
|||||||
--model-path "${MODEL_ROOT}" --rate 1 --requests 4 --input-tokens 512 \
|
--model-path "${MODEL_ROOT}" --rate 1 --requests 4 --input-tokens 512 \
|
||||||
--output-tokens 1 --output "${OUTPUT_ROOT}/results/warmup.json"
|
--output-tokens 1 --output "${OUTPUT_ROOT}/results/warmup.json"
|
||||||
|
|
||||||
"${VENV_ROOT}/bin/python" qwen30_exact_trace_client.py \
|
"${VENV_ROOT}/bin/python" "${EXACT_TRACE_CLIENT}" \
|
||||||
--port "${SERVER_PORT}" --requests-file "${REQUESTS_FILE}" \
|
--port "${SERVER_PORT}" --requests-file "${REQUESTS_FILE}" \
|
||||||
--output "${OUTPUT_ROOT}/results/result.json" --tpot-slo-ms 150 \
|
--output "${OUTPUT_ROOT}/results/result.json" --tpot-slo-ms 150 \
|
||||||
--timeout-seconds 1800
|
--timeout-seconds 1800
|
||||||
|
|||||||
Reference in New Issue
Block a user