Files
vllm-omni/benchmarks/tts/edge_results/summarize.py
T
tzhouamandClaude Fable 5.1 580a201631 [Edge][WP4] Windowed Code2Wav decoder export (torch.export / ExecuTorch) + client backend; results summarizer
vllm_omni/edge/decoder_export.py exports a stateless windowed decoder (context
72 frames + chunk, one program per ramp chunk size) via torch.export (.pt2,
verified here on CPU for chunks 2 and 25 with the real 0.6B decoder: exact
match vs eager, 460 MB fp32 per program) or ExecuTorch XNNPACK (.pte; written
against the executorch 1.x API, not executed: package not installed, install
is permission gated; QNN partitioner export-only/unverified). The WP5 client
gains --decoder-backend executorch --pte-manifest for phone/NPU targets.
benchmarks/tts/edge_results/summarize.py renders all committed JSON as tables.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-09 15:02:19 +08:00

183 lines
5.8 KiB
Python

#!/usr/bin/env python3
"""Render the committed edge results (stream_latency / init_profile / hw_emulation / cpu_sweep /
codec_stream) as markdown tables.
python benchmarks/tts/edge_results/summarize.py [--root benchmarks/tts/edge_results] [--out summary.md]
"""
from __future__ import annotations
import argparse
import json
from pathlib import Path
from typing import Any
HERE = Path(__file__).resolve().parent
GiB = 1 << 30
def _load(p: Path) -> dict[str, Any] | None:
try:
return json.loads(p.read_text())
except (OSError, ValueError):
return None
def _f(v: Any, nd: int = 1) -> str:
if v is None:
return ""
if isinstance(v, float):
return f"{v:.{nd}f}"
return str(v)
def stream_latency_rows(root: Path) -> list[dict[str, Any]]:
rows = []
for f in sorted((root / "stream_latency").glob("*/*/*.json")):
d = _load(f)
if not d or "summary" not in d:
continue
s = d["summary"]
meta = d.get("meta", {})
res = d.get("resources", {}) or {}
tag = f.stem.split("_", 1)[1] if "_" in f.stem else ""
st = d.get("step_stats") or {}
rows.append(
{
"model": f.parents[1].name.replace("Qwen3-TTS-12Hz-", "").replace("-CustomVoice", ""),
"deploy": f.parent.name,
"tag": tag,
"run": f.stem.split("_", 1)[0],
"n": s.get("n_requests"),
"init_s": d.get("init", {}).get("init_s"),
"ttfa_p50": s["ttfa_ms"]["p50"],
"ttfa_p90": s["ttfa_ms"]["p90"],
"playback_p50": s["playback_start_ms"]["p50"],
"stall_p50": s["stall_at_ttfa_ms"]["p50"],
"rtf_stream_p50": s["rtf_streamed"]["p50"],
"rtf_total_p50": s["rtf_total"]["p50"],
"rss_gib": (res.get("peak_rss_bytes") or 0) / GiB,
"gpu_mib": res.get("peak_gpu_mem_mib"),
"sha": (meta.get("git_sha") or "")[:8],
"step_stats": st.get("attribution", [])[:6] if st else None,
"path": str(f.relative_to(root)),
}
)
return rows
def table(rows: list[dict[str, Any]], cols: list[str], nd: int = 1) -> str:
out = ["| " + " | ".join(cols) + " |", "|" + "---|" * len(cols)]
for r in rows:
out.append("| " + " | ".join(_f(r.get(c), nd) for c in cols) + " |")
return "\n".join(out)
def render(root: Path) -> str:
parts = ["# Edge results summary\n"]
rows = stream_latency_rows(root)
parts.append("## Streaming latency (stream_latency_bench.py)\n")
parts.append(
table(
rows,
[
"model",
"deploy",
"tag",
"run",
"n",
"init_s",
"ttfa_p50",
"ttfa_p90",
"playback_p50",
"stall_p50",
"rtf_stream_p50",
"rtf_total_p50",
"rss_gib",
"gpu_mib",
"sha",
],
)
)
for r in rows:
if r.get("step_stats"):
parts.append(f"\n### Step attribution: {r['model']} {r['deploy']} {r['tag']} ({r['run']})\n")
parts.append(
table(r["step_stats"], ["role", "counter", "count", "mean_ms", "p95_ms", "share_of_frame"], nd=3)
)
for name, cols in (
("init_profile", ["config", "init_s", "ttfa_ms", "gpu_mib"]),
(
"hw_emulation",
[
"case",
"hardware_class",
"returncode",
"init_s",
"ttfa_p50",
"playback_start_p50",
"stall_p50",
"rtf_total_p50",
"peak_rss_gib",
"peak_gpu_mib",
],
),
(
"cpu_sweep",
[
"case",
"threads",
"inductor",
"returncode",
"init_s",
"ttfa_p50",
"playback_start_p50",
"rtf_total_p50",
"peak_rss_gib",
],
),
):
for f in sorted((root / name).glob("*/summary.json")):
d = _load(f)
if not d:
continue
parts.append(f"\n## {name} {f.parent.name}\n")
rows_n = d.get("rows") or d.get("configs") or []
if name == "init_profile" and isinstance(rows_n, dict):
rows_n = [{"config": k, **v} for k, v in rows_n.items()]
parts.append(table(rows_n, cols))
if name == "cpu_sweep":
for r in rows_n:
if r.get("step_stats"):
parts.append(f"\n### Step attribution: {r['case']}\n")
parts.append(
table(
r["step_stats"],
["role", "counter", "count", "mean_ms", "p95_ms", "share_of_frame"],
nd=3,
)
)
for f in sorted((root / "codec_stream").glob("**/*.json")):
d = _load(f)
if d and ("snr_db" in d or "parity" in d):
parts.append(f"\n## codec_stream {f.relative_to(root)}\n")
parts.append("```json\n" + json.dumps(d, indent=1)[:3000] + "\n```")
return "\n".join(parts) + "\n"
def main(argv: list[str] | None = None) -> int:
p = argparse.ArgumentParser(description=__doc__)
p.add_argument("--root", default=str(HERE))
p.add_argument("--out", default=None)
args = p.parse_args(argv)
text = render(Path(args.root))
if args.out:
Path(args.out).write_text(text)
else:
print(text)
return 0
if __name__ == "__main__":
raise SystemExit(main())