quantize_dit_int8wo.py builds the offline W8A16 artifact (per-channel symmetric int8, pack-quantized via compressed-tensors' own packer, per-component config wrapper so encoder/VAE stay BF16, digest manifest); serve.sh/probe.py/gate.py/psnr.py adapt the issue-2 kit for the structure-gated capacity matrix (1-4 refs x seeds 2301-2304).
95 lines
3.3 KiB
Python
95 lines
3.3 KiB
Python
#!/usr/bin/env python
|
|
"""Issue 5 structure gate + capacity summarizer.
|
|
|
|
Applies the gate rule from issue 1's FP8 misread to every recorded request
|
|
and folds a run directory into the capacity matrix row: per reference
|
|
count, wall time, peak VRAM, and the server-reported peak.
|
|
|
|
Gate rule (a run only counts when structurally sound):
|
|
opaque_fraction >= 0.99 AND mean(rgb_std) >= 10
|
|
|
|
Broken FP8 output measured opaque 0.008-0.035 with flat grey RGB (std of a
|
|
few); the BF16 path is 100% opaque with healthy channel spread.
|
|
|
|
Usage: gate.py RUN_DIR [RUN_DIR ...] # reads matrix.json / matrix-*.json
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import pathlib
|
|
import re
|
|
|
|
|
|
def peak_vram_mb(vram_log: pathlib.Path) -> int | None:
|
|
if not vram_log.exists():
|
|
return None
|
|
peak = 0
|
|
for line in vram_log.read_text().splitlines():
|
|
match = re.match(r"\s*(\d+)\s+MiB\s*,", line) or re.match(r"\s*(\d+),", line)
|
|
if match:
|
|
peak = max(peak, int(match.group(1)))
|
|
return peak or None
|
|
|
|
|
|
def server_peak_mb(serve_log: pathlib.Path) -> int | None:
|
|
if not serve_log.exists():
|
|
return None
|
|
peaks = [int(m) for m in re.findall(r"peak.*?(\d[\d,]+)\s*MB", serve_log.read_text())]
|
|
if not peaks:
|
|
return None
|
|
return max(peaks)
|
|
|
|
|
|
def gate(structure: dict) -> bool:
|
|
return (
|
|
structure["opaque_fraction"] >= 0.99
|
|
and sum(structure["rgb_std"]) / len(structure["rgb_std"]) >= 10
|
|
)
|
|
|
|
|
|
def main() -> int:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument("runs", nargs="+", type=pathlib.Path)
|
|
args = parser.parse_args()
|
|
|
|
for run_dir in args.runs:
|
|
records: list[dict] = []
|
|
for candidate in sorted(run_dir.glob("matrix*.json")):
|
|
records.extend(json.loads(candidate.read_text()))
|
|
by_refs: dict[int, list[dict]] = {}
|
|
for rec in records:
|
|
by_refs.setdefault(rec.get("n_references", 0), []).append(rec)
|
|
|
|
print(f"== {run_dir.name} ==")
|
|
all_pass = bool(records)
|
|
for n_refs in sorted(by_refs):
|
|
rows = by_refs[n_refs]
|
|
walls = [r["wall_s"] for r in rows if "wall_s" in r]
|
|
gates = [gate(r["structure"]) for r in rows if "structure" in r]
|
|
row_pass = bool(rows) and all(gates) and len(gates) == len(rows)
|
|
all_pass = all_pass and row_pass
|
|
print(
|
|
f" {n_refs}-ref: n={len(rows)} gate={'PASS' if row_pass else 'FAIL'} "
|
|
f"wall {min(walls):.1f}-{max(walls):.1f}s"
|
|
+ (f" (mean {sum(walls) / len(walls):.1f}s)" if walls else "")
|
|
)
|
|
for rec in rows:
|
|
s = rec.get("structure")
|
|
tag = "" if s is None else (" ok" if gate(s) else " BROKEN")
|
|
err = f" error={rec['error'][:80]}" if rec.get("error") else ""
|
|
print(
|
|
f" {rec.get('fixture_id')} s{rec.get('seed')}: "
|
|
f"{rec.get('wall_s')}s {json.dumps(s) if s else 'no-image'}{tag}{err}"
|
|
)
|
|
peak = peak_vram_mb(run_dir / "vram.log")
|
|
server_peak = server_peak_mb(run_dir / "serve.log")
|
|
print(f" nvidia-smi peak: {peak} MiB; server peak: {server_peak} MB")
|
|
print(f" STRUCTURE GATE: {'PASS' if all_pass else 'FAIL'}")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|