Files
aituner/runs/opprof-phase3/provenance/opprof_phase3_matrix.py
Gahow Wang d5b276180d Add OpProf campaign: protocols, results, patches, run evidence (P0-P6)
Workload-conditioned operator profiling on patched vLLM 0.24.0 +
Qwen3-30B-A3B/H20. H1b PASS (irregular patterns carry +23-45pp R64
raggedness, 8-45% token-efficiency loss vs rectangular controls);
mechanism decomposition kills the padding narrative and finds the
arrival-uniformization artifact (-12.9%); cross-version churn surface
shows TP2/MNS64 -29.4% across vLLM 0.20->0.24 while the argmax held.
Raw Layer-1 JSONL streams (507 MB) stay on disk, git-ignored; footer
sidecars and metrics are tracked.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 11:06:10 +08:00

1253 lines
43 KiB
Python

#!/usr/bin/env python3
"""Detached, resumable four-GPU controller for the Phase-3 matrix."""
from __future__ import annotations
import argparse
import gzip
import hashlib
import json
import math
import os
import re
import shlex
import shutil
import signal
import subprocess
import time
import urllib.request
from dataclasses import dataclass
from pathlib import Path
from typing import Any
import opprof_phase3_controller as common
SCHEMA = 1
WORKDIR = Path("/home/admin/cpfs/wjh/opprof-phase3-dash0-20260712")
RUN_ROOT = WORKDIR / "runs/phase3"
PRIVATE = Path("/home/admin/cpfs/wjh/opprof-phase3-private/manifests")
MODEL = Path("/home/admin/cpfs/wjh/models/Qwen/Qwen3-30B-A3B")
SOURCE = Path(
"/home/admin/cpfs/wjh/opprof-phase2-dash0-20260711/vllm-v0.24.0"
)
VENV = Path("/tmp/wjh-opprof-phase2-dash0-20260711/.venv")
CLIENT = WORKDIR / "scripts/opprof_phase3_client.py"
STATE = RUN_ROOT / "controller-state.json"
GPU_LIMIT = 4
GPU_HOUR_LIMIT = 16.0
PRIOR_GPU_HOURS = 3.964 + 427.43714332580566 / 3600
CPU_MAP = common.CPU_MAP
PROFILE_CONFIG = {
"profiler": "torch",
"torch_profiler_with_stack": True,
"torch_profiler_record_shapes": True,
"torch_profiler_use_gzip": True,
"ignore_frontend": True,
"wait_iterations": 0,
"warmup_iterations": 2,
"active_iterations": 8,
}
CONFIGS = {
"C00": {"tp": 1, "mns": 1024, "mbt": 8192, "flags": []},
"C10": {
"tp": 1,
"mns": 64,
"mbt": 8192,
"flags": ["--max-num-seqs", "64"],
},
"C01": {
"tp": 1,
"mns": 1024,
"mbt": 2048,
"flags": ["--max-num-batched-tokens", "2048"],
},
"C11": {
"tp": 1,
"mns": 64,
"mbt": 2048,
"flags": [
"--max-num-seqs",
"64",
"--max-num-batched-tokens",
"2048",
],
},
"C00-TP2": {"tp": 2, "mns": 1024, "mbt": 8192, "flags": []},
}
LONG_BURST = {"P04", "P06", "P07", "P08", "P11"}
SENTINELS = ("P01", "P03", "P06", "P10")
PATTERNS = tuple(f"P{index:02d}" for index in range(1, 12))
@dataclass(frozen=True)
class Cell:
pattern: str
config: str
@property
def cell_id(self) -> str:
return f"{self.pattern}-{self.config}"
@property
def width(self) -> int:
return int(CONFIGS[self.config]["tp"])
@dataclass(frozen=True)
class Assignment:
cell: Cell
gpus: tuple[int, ...]
def drain_budget(pattern: str) -> int:
if pattern == "P10":
return 600
if pattern in LONG_BURST:
return 240
return 120
def sha256_file(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 atomic_json(path: Path, value: Any) -> None:
common.atomic_json(path, value)
def run_text(command: list[str], check: bool = True) -> str:
return common.run_text(command, check=check)
def numeric_sanity(values: list[float | int]) -> dict[str, Any]:
finite = [float(value) for value in values if math.isfinite(float(value))]
return {
"n": len(values),
"finite_n": len(finite),
"missing_n": len(values) - len(finite),
"min": min(finite) if finite else None,
"max": max(finite) if finite else None,
"distinct_n": len(set(finite)),
}
def cells() -> list[Cell]:
result = [Cell(pattern, "C00") for pattern in PATTERNS]
for pattern in SENTINELS:
result.extend(Cell(pattern, config) for config in ("C10", "C01", "C11"))
result.append(Cell("P10", "C00-TP2"))
return sorted(
result,
key=lambda cell: hashlib.sha256(
f"20260713:{cell.pattern}:{cell.config}".encode()
).hexdigest(),
)
def pack_cells(items: list[Cell]) -> list[list[Assignment]]:
waves: list[list[Assignment]] = []
current: list[Assignment] = []
slot = 0
for cell in items:
if slot + cell.width > GPU_LIMIT:
waves.append(current)
current = []
slot = 0
current.append(Assignment(cell, tuple(range(slot, slot + cell.width))))
slot += cell.width
if current:
waves.append(current)
assert sum(len(wave) for wave in waves) == len(items)
assert all(sum(item.cell.width for item in wave) <= GPU_LIMIT for wave in waves)
return waves
def load_state(resume: bool) -> dict[str, Any]:
if STATE.exists():
if not resume:
raise RuntimeError("controller state exists; use --resume")
return json.loads(STATE.read_text())
return {
"schema": SCHEMA,
"status": "created",
"created_at": time.time(),
"controller_pid": os.getpid(),
"gpu_hours_total": PRIOR_GPU_HOURS,
"gpu_hours_this_stage": 0.0,
"completed_measured_runs": 0,
"completed_burnins": 0,
"drain_quarantined_runs": 0,
"clean_window_failures": 0,
"missing_trace_files": 0,
"stages": {},
"fingerprint": {},
}
def save_state(state: dict[str, Any]) -> None:
state["controller_pid"] = os.getpid()
state["updated_at"] = time.time()
atomic_json(STATE, state)
def manifest_fingerprint() -> dict[str, Any]:
result = {}
for pattern in PATTERNS:
path = PRIVATE / f"{pattern}.jsonl"
summary_path = path.with_suffix(path.suffix + ".summary.json")
if not path.exists() or not summary_path.exists():
raise RuntimeError(f"manifest missing: {path}")
summary = json.loads(summary_path.read_text())
expected_rows = 4011 if pattern == "P10" else 32768
if summary["rows"] != expected_rows or summary["sha256"] != sha256_file(path):
raise RuntimeError(f"manifest verification failed: {pattern}")
result[pattern] = {
"path": str(path),
"rows": summary["rows"],
"sha256": summary["sha256"],
}
return result
def fingerprint() -> dict[str, Any]:
return {
"source_commit": run_text(
["git", "-C", str(SOURCE), "rev-parse", "HEAD"]
).strip(),
"source_tree": run_text(
["git", "-C", str(SOURCE), "rev-parse", "HEAD^{tree}"]
).strip(),
"client_sha256": sha256_file(CLIENT),
"controller_sha256": sha256_file(Path(__file__)),
"common_controller_sha256": sha256_file(
Path(common.__file__).resolve()
),
"model": str(MODEL),
"cpu_map": {str(key): value for key, value in CPU_MAP.items()},
"manifests": manifest_fingerprint(),
"cells": [cell.cell_id for cell in cells()],
}
def ensure_provenance() -> None:
destination = RUN_ROOT / "provenance"
destination.mkdir(parents=True, exist_ok=True)
sources = [CLIENT, Path(__file__).resolve(), Path(common.__file__).resolve()]
checksums = {}
for source in sources:
target = destination / source.name
digest = sha256_file(source)
if target.exists() and sha256_file(target) != digest:
target = destination / f"{source.stem}.{digest[:12]}{source.suffix}"
if target.exists() and sha256_file(target) != digest:
raise RuntimeError(f"content-addressed provenance mismatch: {target}")
if not target.exists():
shutil.copy2(source, target)
checksums[target.name] = digest
patch_dir = WORKDIR / "provenance/patches-vllm-0.24.0-opprof"
checksums["patches"] = {
path.name: sha256_file(path) for path in sorted(patch_dir.glob("0*.patch"))
}
atomic_json(destination / "sha256.json", checksums)
def preflight(stage_dir: Path, gpus: list[int]) -> None:
stage_dir.mkdir(parents=True, exist_ok=True)
common.preflight(gpus, stage_dir)
free_kb = shutil.disk_usage(RUN_ROOT.parent).free
if free_kb < 100 * (1 << 30):
raise RuntimeError("CPFS free space below 100 GiB")
def cpu_mask(gpus: tuple[int, ...]) -> str:
ranges = [CPU_MAP[gpu] for gpu in gpus]
return ",".join(ranges)
def server_command(
assignment: Assignment, port: int, trace_dir: Path
) -> list[str]:
config = {
**PROFILE_CONFIG,
"torch_profiler_dir": str(trace_dir),
}
details = CONFIGS[assignment.cell.config]
return [
"taskset",
"-c",
cpu_mask(assignment.gpus),
str(VENV / "bin/vllm"),
"serve",
str(MODEL),
"--host",
"127.0.0.1",
"--port",
str(port),
"--tensor-parallel-size",
str(details["tp"]),
"--enable-chunked-prefill",
"--enable-prefix-caching",
"--shutdown-timeout",
"120",
"--profiler-config",
json.dumps(config, separators=(",", ":")),
*details["flags"],
]
def client_command(
assignment: Assignment,
port: int,
run_dir: Path,
load_point: str,
profile: bool,
burnin: bool,
saturation_result: Path | None,
) -> list[str]:
if burnin:
warmup, segment, segments = 0, 20, 3
else:
warmup, segment, segments = 60, 80, 3
drain = drain_budget(assignment.cell.pattern)
command = [
"taskset",
"-c",
cpu_mask(assignment.gpus),
str(VENV / "bin/python"),
str(CLIENT),
"run",
"--manifest",
str(PRIVATE / f"{assignment.cell.pattern}.jsonl"),
"--base-url",
f"http://127.0.0.1:{port}",
"--model",
str(MODEL),
"--load-point",
load_point,
"--max-concurrency",
"256",
"--ignore-eos",
"--temperature",
"0",
"--warmup-seconds",
str(warmup),
"--clean-segment-seconds",
str(segment),
"--num-clean-segments",
str(segments),
"--recovery-seconds",
"30",
"--drain-timeout-seconds",
str(drain),
"--workload-seed",
"20260712",
"--server-seed",
"20260712",
"--result-dir",
str(run_dir / "client"),
]
if load_point == "saturation":
command.extend(("--request-rate", "inf"))
else:
if saturation_result is None:
raise RuntimeError("moderate run lacks saturation result")
command.extend(
(
"--saturation-result",
str(saturation_result),
"--rate-fraction",
"0.60",
)
)
if profile:
command.extend(
(
"--profile-after-clean",
"--num-profile-windows",
"2",
"--profile-warmup-iterations",
"2",
"--profile-active-iterations",
"8",
"--profile-trace-dir",
str(run_dir / "trace-tmp"),
"--profile-timeout-seconds",
"120",
)
)
return command
def wait_ready(entries: list[dict[str, Any]]) -> None:
pending = {entry["port"]: entry for entry in entries}
deadline = time.monotonic() + 300
while pending and time.monotonic() < deadline:
for port, entry in list(pending.items()):
if entry["server"].poll() is not None:
raise RuntimeError(f"server exited before ready: {entry['run_id']}")
try:
with urllib.request.urlopen(
f"http://127.0.0.1:{port}/health", timeout=1
) as response:
if response.status == 200:
del pending[port]
except Exception:
pass
time.sleep(1)
if pending:
raise TimeoutError(f"server readiness timeout: {sorted(pending)}")
def stop_servers(entries: list[dict[str, Any]]) -> None:
live = [entry for entry in entries if entry["server"].poll() is None]
for entry in live:
try:
os.kill(entry["server"].pid, signal.SIGINT)
except ProcessLookupError:
pass
deadline = time.monotonic() + 150
while time.monotonic() < deadline and any(
entry["server"].poll() is None for entry in live
):
time.sleep(1)
remaining = [entry for entry in live if entry["server"].poll() is None]
for signum in (signal.SIGTERM, signal.SIGKILL):
if not remaining:
break
for entry in remaining:
try:
os.killpg(entry["server"].pid, signum)
except ProcessLookupError:
pass
time.sleep(5)
remaining = [entry for entry in remaining if entry["server"].poll() is None]
if remaining:
raise RuntimeError("server process groups survived SIGKILL")
def trace_summary(path: Path) -> dict[str, Any]:
opener = gzip.open if path.suffix == ".gz" else open
with opener(path, "rt", encoding="utf-8") as source:
payload = json.load(source)
durations: dict[str, float] = {}
kernel_count = 0
steps = set()
executes = 0
for event in payload.get("traceEvents", []):
name = str(event.get("name", ""))
if event.get("cat") == "user_annotation":
match = re.fullmatch(r"ProfilerStep#(\d+)", name)
if match:
steps.add(int(match.group(1)))
if name.startswith("execute_"):
executes += 1
if event.get("cat") == "kernel":
duration = float(event.get("dur", 0))
if duration < 0:
raise RuntimeError(f"negative kernel duration in {path}")
family = common.classify_kernel(name)
durations[family] = durations.get(family, 0.0) + duration
kernel_count += 1
total = sum(durations.values())
shares = {
family: duration / total for family, duration in sorted(durations.items())
}
classifiable = 1.0 - shares.get("other", 0.0)
valid = (
kernel_count > 0
and steps == set(range(2, 10))
and executes == 8
and classifiable >= 0.70
)
return {
"path": str(path),
"sha256": sha256_file(path),
"bytes": path.stat().st_size,
"kernel_count": kernel_count,
"profiler_steps": sorted(steps),
"execute_annotations": executes,
"duration_us": durations,
"shares": shares,
"classifiable_fraction": classifiable,
"valid": valid,
}
def validate_layer1(run_dir: Path) -> dict[str, Any]:
streams = sorted((run_dir / "opprof").glob("*.jsonl"))
sidecars = sorted((run_dir / "opprof").glob("*.jsonl.footer.json"))
if len(streams) != 1 or len(sidecars) != 1:
raise RuntimeError(
f"{run_dir}: expected one Layer-1 stream/sidecar, "
f"got {len(streams)}/{len(sidecars)}"
)
raw = streams[0].read_bytes()
if not raw.endswith(b"\n"):
raise RuntimeError(f"partial Layer-1 line: {streams[0]}")
decoded = [json.loads(line) for line in raw.splitlines()]
if not decoded or decoded[-1].get("record_type") != "footer":
raise RuntimeError(f"clean-close footer missing: {streams[0]}")
records, footer = decoded[:-1], decoded[-1]
sidecar = json.loads(sidecars[0].read_text())
indices = [int(record["step_index"]) for record in records]
invariants = {
"schema_1": all(item.get("schema") == 1 for item in decoded)
and sidecar.get("schema") == 1,
"steps_unique_contiguous": sorted(indices) == list(range(len(indices))),
"footer_written_matches": footer["written_records"] == len(records),
"footer_balanced": footer["encoded_records"]
== footer["written_records"] + footer["dropped_records"],
"zero_drops": footer["dropped_records"] == 0
and all(record["dropped_records_before"] == 0 for record in records),
"sidecar_final": sidecar.get("final") is True,
"sidecar_agrees": all(
sidecar[counter] == footer[counter]
for counter in ("encoded_records", "written_records", "dropped_records")
),
"token_composition": all(
record["prefill_tokens"] + record["decode_tokens"]
>= 0
for record in records
),
"cudagraph_identity": all(
record["cudagraph"]["bucket_tokens"]
== record["cudagraph"]["unpadded_tokens"]
+ record["cudagraph"]["padding_tokens"]
for record in records
),
}
if not all(invariants.values()):
raise RuntimeError(f"Layer-1 invariant failure: {run_dir}: {invariants}")
return {
"stream": str(streams[0]),
"stream_sha256": sha256_file(streams[0]),
"sidecar": str(sidecars[0]),
"records": len(records),
"last_step_index": max(indices),
"footer": footer,
"invariants": invariants,
"numeric": {
"prefill_tokens": numeric_sanity(
[record["prefill_tokens"] for record in records]
),
"decode_tokens": numeric_sanity(
[record["decode_tokens"] for record in records]
),
"scheduled_requests": numeric_sanity(
[record["scheduled_requests"] for record in records]
),
"padding_tokens": numeric_sanity(
[record["cudagraph"]["padding_tokens"] for record in records]
),
},
}
def summarize_request_failures(
requests: list[dict[str, Any]], clean_start: float, clean_end: float
) -> dict[str, Any]:
failed = [request for request in requests if not request["success"]]
clean_failed = [
request
for request in failed
if clean_start <= float(request["completed_s"]) < clean_end
]
excluded_kinds: dict[str, int] = {}
for request in failed:
if clean_start <= float(request["completed_s"]) < clean_end:
continue
key = str(request.get("error_kind") or "unknown")
excluded_kinds[key] = excluded_kinds.get(key, 0) + 1
return {
"failed": len(failed),
"clean_failed": len(clean_failed),
"excluded": len(failed) - len(clean_failed),
"excluded_kinds": excluded_kinds,
}
def p10_warmup_stability(run_dir: Path, t0_mono_ns: int) -> dict[str, Any]:
streams = sorted((run_dir / "opprof").glob("*.jsonl"))
if len(streams) != 1:
return {
"passed": False,
"reason": f"expected one Layer-1 stream, found {len(streams)}",
"step_counts": [0, 0, 0],
"scheduled_token_throughput": [None, None, None],
"mean_scheduled_token_throughput": None,
"slope_tokens_per_second_squared": None,
"normalized_drift": None,
}
records = []
try:
for line in streams[0].read_text().splitlines():
item = json.loads(line)
if "step_index" in item:
records.append(item)
except (OSError, ValueError) as error:
return {
"passed": False,
"reason": f"Layer-1 decode failed: {error}",
"step_counts": [0, 0, 0],
"scheduled_token_throughput": [None, None, None],
"mean_scheduled_token_throughput": None,
"slope_tokens_per_second_squared": None,
"normalized_drift": None,
}
indices = [int(item["step_index"]) for item in records]
continuous = indices == list(range(len(indices)))
step_counts = [0, 0, 0]
token_counts = [0, 0, 0]
for item in records:
if not item.get("model_executed"):
continue
relative_s = (int(item["submit_mono_ns"]) - t0_mono_ns) / 1e9
if not 45 <= relative_s < 60:
continue
bin_index = min(2, int((relative_s - 45) // 5))
step_counts[bin_index] += 1
token_counts[bin_index] += int(item["prefill_tokens"]) + int(
item["decode_tokens"]
)
rates = [tokens / 5.0 for tokens in token_counts]
mean_rate = sum(rates) / len(rates)
midpoints = [47.5, 52.5, 57.5]
mean_midpoint = sum(midpoints) / len(midpoints)
slope = sum(
(point - mean_midpoint) * (rate - mean_rate)
for point, rate in zip(midpoints, rates, strict=True)
) / sum((point - mean_midpoint) ** 2 for point in midpoints)
normalized_drift = (
abs(slope) * 15.0 / mean_rate if mean_rate > 0 else math.inf
)
finite_positive = all(math.isfinite(rate) and rate > 0 for rate in rates)
passed = (
continuous
and all(count >= 16 for count in step_counts)
and finite_positive
and math.isfinite(normalized_drift)
and normalized_drift <= 0.10
)
return {
"passed": passed,
"reason": None if passed else "A-P3-6 stabilization criterion not met",
"window_seconds": [45.0, 60.0],
"bin_seconds": 5.0,
"step_counts": step_counts,
"scheduled_tokens": token_counts,
"scheduled_token_throughput": rates,
"mean_scheduled_token_throughput": mean_rate,
"slope_tokens_per_second_squared": slope,
"normalized_drift": normalized_drift,
"normalized_drift_limit": 0.10,
"step_indices_continuous": continuous,
}
def validate_client(
run_dir: Path, pattern: str, profile: bool, burnin: bool
) -> dict[str, Any]:
result = json.loads((run_dir / "client/result.json").read_text())
sanity = json.loads((run_dir / "client/sanity.json").read_text())
failed = [
key
for key, value in sanity["invariants"].items()
if not value and key != "drain_within_timeout"
]
quarantined = float(result["drain_seconds"]) > drain_budget(pattern)
expected_duration = 60 if burnin else 240
warmup_completions = 0
requests = []
for line in (run_dir / "client/requests.jsonl").read_text().splitlines():
request = json.loads(line)
requests.append(request)
if 0 <= request["completed_s"] < result["warmup_seconds"] and request["success"]:
warmup_completions += 1
clean_start = float(result["clean"]["start_s"])
clean_end = float(result["clean"]["end_s"])
failure_summary = summarize_request_failures(requests, clean_start, clean_end)
request_rate = result["request_rate"]
warmup_required = 32
if pattern != "P10" and request_rate != "inf":
warmup_required = min(
32,
max(1, math.floor(float(request_rate) * result["warmup_seconds"])),
)
warmup_stability = (
p10_warmup_stability(run_dir, int(result["t0_mono_ns"]))
if pattern == "P10" and not burnin
else None
)
if burnin:
warmup_passed = True
warmup_gate_branch = "burnin"
elif pattern == "P10" and warmup_completions >= 32:
warmup_passed = True
warmup_gate_branch = "count"
elif (
pattern == "P10"
and warmup_completions >= 16
and warmup_stability is not None
and warmup_stability["passed"]
):
warmup_passed = True
warmup_gate_branch = "telemetry"
else:
warmup_passed = warmup_completions >= warmup_required
warmup_gate_branch = "count" if warmup_passed else "failed"
invariants = {
"client_sanity": not failed,
"clean_duration": math.isclose(
float(result["clean"]["duration_s"]), expected_duration
),
"clean_failures_zero": result["clean"]["failed"] == 0
and failure_summary["clean_failed"] == 0,
"failed_records_accounted": result["failed_records"]
== failure_summary["failed"],
"manifest_no_wrap": not result["manifest_wrapped"]
and not result["manifest_exhausted"],
"warmup_completions": warmup_passed,
"profile_count": len(result["profiles"]) == (2 if profile else 0),
"profile_after_clean": all(
item["start_call_s"] >= result["warmup_seconds"] + expected_duration
for item in result["profiles"]
),
"drain_re_adjudicated": not quarantined,
}
non_drain_invariants = {
key: value for key, value in invariants.items() if key != "drain_re_adjudicated"
}
if not all(non_drain_invariants.values()):
raise RuntimeError(
f"client invariant failure: {run_dir}: {invariants}; failed={failed}; "
f"warmup_completions={warmup_completions}; "
f"warmup_gate_branch={warmup_gate_branch}; "
f"warmup_stability={warmup_stability}"
)
return {
"result": result,
"sanity": sanity,
"request_count": len(requests),
"warmup_completions": warmup_completions,
"warmup_required": warmup_required,
"warmup_gate_branch": warmup_gate_branch,
"warmup_stability": warmup_stability,
"drain_budget_seconds": drain_budget(pattern),
"drain_quarantined": quarantined,
"excluded_window_failures": failure_summary["excluded"],
"excluded_window_failure_kinds": failure_summary["excluded_kinds"],
"invariants": invariants,
}
def validate_run(
entry: dict[str, Any],
profile: bool,
burnin: bool,
allow_missing_traces: bool = False,
) -> dict[str, Any]:
run_dir = entry["run_dir"]
client = validate_client(
run_dir, entry["assignment"].cell.pattern, profile, burnin
)
layer1 = validate_layer1(run_dir)
log = (run_dir / "server.log").read_text(errors="replace")
details = CONFIGS[entry["assignment"].cell.config]
server_invariants = {
"triton_moe": "Using TRITON Unquantized MoE backend" in log,
"chunked_mbt": (
(
details["mbt"] == 8192
and "Chunked prefill is enabled with max_num_batched_tokens=8192"
in log
)
or (
details["mbt"] == 2048
and "'max_num_batched_tokens': 2048" in log
and "'enable_chunked_prefill': True" in log
)
),
"tp_effective": f"tensor_parallel_size={details['tp']}" in log,
"drain_shutdown": "mode=drain timeout=120s" in log,
"mns_effective": details["mns"] == 1024
or "'max_num_seqs': 64" in log,
}
if not all(server_invariants.values()):
raise RuntimeError(
f"server config/backend failure: {run_dir}: {server_invariants}"
)
trace_summaries: list[dict[str, Any]] = []
if profile:
trace_dir = run_dir / "traces"
traces = sorted(trace_dir.glob("*.pt.trace.json*"))
expected = 2 * int(details["tp"])
if len(traces) != expected and not allow_missing_traces:
raise RuntimeError(
f"trace count mismatch: {run_dir}: {len(traces)} != {expected}"
)
if traces:
trace_summaries = [trace_summary(path) for path in traces]
if not all(summary["valid"] for summary in trace_summaries):
raise RuntimeError(f"invalid Layer-2 trace: {run_dir}")
for rank in range(int(details["tp"])):
if sum(f"rank{rank}" in path.name for path in traces) != 2:
raise RuntimeError(f"rank trace mismatch: {run_dir}: rank{rank}")
forbidden = re.compile(r'"(?:prompt|messages|content|text)"\s*:')
for path in (
run_dir / "client/requests.jsonl",
run_dir / "client/result.json",
Path(layer1["stream"]),
):
if forbidden.search(path.read_text(errors="replace")):
raise RuntimeError(f"private/generated text field leaked: {path}")
summary = {
"schema": SCHEMA,
"run_id": entry["run_id"],
"pattern": entry["assignment"].cell.pattern,
"config": entry["assignment"].cell.config,
"gpus": entry["assignment"].gpus,
"client": client,
"layer1": layer1,
"traces": trace_summaries,
"missing_trace_files": (
2 * int(details["tp"]) - len(trace_summaries) if profile else 0
),
"layer2_missing_after_controller_cleanup": bool(
profile and not trace_summaries and allow_missing_traces
),
"drain_quarantined": client["drain_quarantined"],
"server_invariants": server_invariants,
}
atomic_json(run_dir / "run-complete.json", summary)
return summary
def run_stage(
state: dict[str, Any],
stage_name: str,
assignments: list[Assignment],
load_point: str,
*,
profile: bool,
burnin: bool = False,
confirmation: bool = False,
) -> None:
stage_dir = RUN_ROOT / "stages" / stage_name
existing = state["stages"].get(stage_name)
if existing and existing.get("status") == "complete":
if not (stage_dir / "stage-complete.json").exists():
raise RuntimeError(f"complete stage marker missing: {stage_name}")
print(f"RESUME skip {stage_name}", flush=True)
return
if stage_dir.exists():
os.replace(stage_dir, stage_dir.with_name(f"{stage_dir.name}.interrupted-{int(time.time())}"))
stage_dir.mkdir(parents=True)
physical_gpus = sorted({gpu for item in assignments for gpu in item.gpus})
reserve = sum(item.cell.width for item in assignments) * 1200 / 3600
if state["gpu_hours_total"] + reserve > GPU_HOUR_LIMIT:
raise RuntimeError(
f"GPU budget reservation exceeds {GPU_HOUR_LIMIT}: "
f"used={state['gpu_hours_total']:.6f} reserve={reserve:.6f}"
)
state["stages"][stage_name] = {
"status": "preflight",
"started_at": time.time(),
"load_point": load_point,
"profile": profile,
"burnin": burnin,
"confirmation": confirmation,
"assignments": [
{"cell": item.cell.cell_id, "gpus": item.gpus} for item in assignments
],
}
save_state(state)
preflight(stage_dir, physical_gpus)
entries: list[dict[str, Any]] = []
handles: list[Any] = []
owned_pgids: set[int] = set()
monitor: common.Monitor | None = None
failure: Exception | None = None
stage_gpu_seconds = 0.0
try:
for assignment in assignments:
suffix = "burnin" if burnin else ("confirmation" if confirmation else load_point)
run_id = f"{assignment.cell.cell_id}-{suffix}"
if burnin:
run_dir = RUN_ROOT / "burnins" / assignment.cell.config
elif confirmation:
run_dir = RUN_ROOT / "confirmations" / assignment.cell.pattern
else:
run_dir = RUN_ROOT / "primary" / assignment.cell.cell_id / load_point
if run_dir.exists():
os.replace(
run_dir,
run_dir.with_name(f"{run_dir.name}.interrupted-{int(time.time())}"),
)
run_dir.mkdir(parents=True)
trace_tmp = Path(f"/tmp/wjh-opprof-phase3-matrix/{run_id}")
if trace_tmp.exists():
shutil.rmtree(trace_tmp)
trace_tmp.mkdir(parents=True)
(run_dir / "trace-tmp").symlink_to(trace_tmp, target_is_directory=True)
port = 8100 + assignment.gpus[0]
command = server_command(assignment, port, trace_tmp)
with (run_dir / "commands.log").open("w", encoding="utf-8") as output:
output.write(
f"GPU_COMMAND {run_id} server: {shlex.join(command)}; "
"expected=startup 60-180s + fixed load 300-600s\n"
)
environment = os.environ.copy()
environment.update(
{
"CUDA_VISIBLE_DEVICES": ",".join(map(str, assignment.gpus)),
"VLLM_OPPROF_DIR": str(run_dir / "opprof"),
"HF_HUB_OFFLINE": "1",
"TRANSFORMERS_OFFLINE": "1",
"PYTHONUNBUFFERED": "1",
}
)
handle = (run_dir / "server.log").open("ab", buffering=0)
handles.append(handle)
spawned_at = time.time()
server = subprocess.Popen(
command,
cwd=SOURCE,
env=environment,
stdout=handle,
stderr=subprocess.STDOUT,
start_new_session=True,
)
owned_pgids.add(server.pid)
entries.append(
{
"assignment": assignment,
"run_id": run_id,
"run_dir": run_dir,
"trace_tmp": trace_tmp,
"port": port,
"server": server,
"spawned_at": spawned_at,
}
)
state["stages"][stage_name]["status"] = "starting_servers"
state["stages"][stage_name]["servers"] = {
entry["run_id"]: {
"pid": entry["server"].pid,
"pgid": entry["server"].pid,
"gpus": entry["assignment"].gpus,
}
for entry in entries
}
save_state(state)
wait_ready(entries)
monitor = common.Monitor(stage_dir / "monitor.jsonl", owned_pgids)
monitor.start()
for entry in entries:
assignment = entry["assignment"]
saturation_result = None
if load_point == "moderate":
saturation_result = (
RUN_ROOT
/ "primary"
/ assignment.cell.cell_id
/ "saturation/client/result.json"
)
command = client_command(
assignment,
entry["port"],
entry["run_dir"],
load_point,
profile,
burnin,
saturation_result,
)
with (entry["run_dir"] / "commands.log").open("a", encoding="utf-8") as output:
output.write(
f"GPU_COMMAND {entry['run_id']} client: {shlex.join(command)}; "
"expected=fixed protocol timeline\n"
)
handle = (entry["run_dir"] / "client.log").open("ab", buffering=0)
handles.append(handle)
client = subprocess.Popen(
command,
cwd=WORKDIR,
stdout=handle,
stderr=subprocess.STDOUT,
start_new_session=True,
)
entry["client"] = client
owned_pgids.add(client.pid)
state["stages"][stage_name]["status"] = "running_clients"
state["stages"][stage_name]["clients"] = {
entry["run_id"]: {"pid": entry["client"].pid, "pgid": entry["client"].pid}
for entry in entries
}
save_state(state)
deadline = time.monotonic() + 1200
while time.monotonic() < deadline and any(
entry["client"].poll() is None for entry in entries
):
if any(entry["server"].poll() is not None for entry in entries):
raise RuntimeError("server exited while a client was active")
if monitor.other_apps:
raise RuntimeError(f"other GPU process appeared: {monitor.other_apps}")
live_hours = sum(
(time.time() - entry["spawned_at"]) * entry["assignment"].cell.width
for entry in entries
) / 3600
if state["gpu_hours_total"] + live_hours >= GPU_HOUR_LIMIT:
raise RuntimeError("cumulative GPU-hour hard stop reached")
time.sleep(2)
if any(entry["client"].poll() is None for entry in entries):
raise TimeoutError(f"stage exceeded 1200 seconds: {stage_name}")
bad = {}
for entry in entries:
if entry["client"].returncode == 0:
continue
sanity_path = entry["run_dir"] / "client/sanity.json"
if not sanity_path.exists():
bad[entry["run_id"]] = entry["client"].returncode
continue
client_sanity = json.loads(sanity_path.read_text())["invariants"]
failed = [key for key, value in client_sanity.items() if not value]
if failed != ["drain_within_timeout"]:
bad[entry["run_id"]] = {
"returncode": entry["client"].returncode,
"failed_invariants": failed,
}
if bad:
raise RuntimeError(f"client failures: {bad}")
for entry in entries:
if profile:
destination = entry["run_dir"] / "traces"
destination.mkdir()
for path in sorted(entry["trace_tmp"].glob("*.pt.trace.json*")):
shutil.copy2(path, destination / path.name)
state["stages"][stage_name]["status"] = "clients_complete"
save_state(state)
except Exception as error:
failure = error
finally:
for entry in entries:
client = entry.get("client")
if client is not None and client.poll() is None:
try:
os.killpg(client.pid, signal.SIGKILL)
except ProcessLookupError:
pass
try:
stop_servers(entries)
except Exception as error:
failure = failure or error
ended_at = time.time()
stage_gpu_seconds = sum(
(ended_at - entry["spawned_at"]) * entry["assignment"].cell.width
for entry in entries
)
if monitor is not None:
monitor.stop()
atomic_json(stage_dir / "other-gpu-processes.json", monitor.other_apps)
if monitor.other_apps:
failure = failure or RuntimeError(
f"other GPU process appeared: {monitor.other_apps}"
)
for entry in entries:
trace_link = entry["run_dir"] / "trace-tmp"
if trace_link.is_symlink():
trace_link.unlink()
if entry["trace_tmp"].exists():
shutil.rmtree(entry["trace_tmp"])
for handle in handles:
handle.close()
(stage_dir / "clocks-after.txt").write_text(
run_text(["nvidia-smi", "-q", "-d", "CLOCK"], check=False)
)
(stage_dir / "loadavg-after.txt").write_text(
" ".join(str(value) for value in os.getloadavg()) + "\n"
)
try:
common.verify_idle(physical_gpus, stage_dir)
except Exception as error:
failure = failure or error
state["gpu_hours_total"] += stage_gpu_seconds / 3600
state["gpu_hours_this_stage"] = stage_gpu_seconds / 3600
if failure is None:
try:
summaries = [validate_run(entry, profile, burnin) for entry in entries]
except Exception as error:
failure = error
if failure is not None:
state["stages"][stage_name]["status"] = "failed"
state["stages"][stage_name]["failure"] = repr(failure)
state["stages"][stage_name]["gpu_hours"] = stage_gpu_seconds / 3600
state["status"] = "failed"
save_state(state)
raise failure
marker = {
"schema": SCHEMA,
"stage": stage_name,
"completed_at": time.time(),
"gpu_hours": stage_gpu_seconds / 3600,
"runs": [summary["run_id"] for summary in summaries],
}
atomic_json(stage_dir / "stage-complete.json", marker)
state["stages"][stage_name].update(
{
"status": "complete",
"completed_at": marker["completed_at"],
"gpu_hours": marker["gpu_hours"],
"servers": {},
"clients": {},
}
)
if burnin:
state["completed_burnins"] += len(assignments)
else:
state["completed_measured_runs"] += len(assignments)
state.setdefault("drain_quarantined_runs", 0)
state["drain_quarantined_runs"] += sum(
summary["drain_quarantined"] for summary in summaries
)
if (
state["completed_measured_runs"] > 0
and state["drain_quarantined_runs"]
/ state["completed_measured_runs"]
> 0.20
):
state["status"] = "failed"
save_state(state)
raise RuntimeError("drain-quarantine rate exceeded 20%")
save_state(state)
def cleanup_recorded(state: dict[str, Any]) -> None:
for stage in state.get("stages", {}).values():
if stage.get("status") == "complete":
continue
for group in ("clients", "servers"):
for item in stage.get(group, {}).values():
pgid = item.get("pgid")
if pgid:
try:
os.killpg(int(pgid), signal.SIGKILL)
except ProcessLookupError:
pass
time.sleep(2)
def execute(resume: bool) -> None:
RUN_ROOT.mkdir(parents=True, exist_ok=True)
state = load_state(resume)
if resume:
cleanup_recorded(state)
current = fingerprint()
if state["fingerprint"] and state["fingerprint"] != current:
raise RuntimeError("resume fingerprint differs from frozen matrix")
state["fingerprint"] = current
state["status"] = "running"
save_state(state)
ensure_provenance()
burnin_cells = [Cell("P06", config) for config in CONFIGS]
for index, wave in enumerate(pack_cells(burnin_cells), 1):
run_stage(
state,
f"burnin-{index:02d}",
wave,
"saturation",
profile=False,
burnin=True,
)
matrix_waves = pack_cells(cells())
for index, wave in enumerate(matrix_waves, 1):
run_stage(
state,
f"primary-{index:02d}-saturation",
wave,
"saturation",
profile=True,
)
run_stage(
state,
f"primary-{index:02d}-moderate",
wave,
"moderate",
profile=True,
)
confirmations = [
Assignment(Cell(pattern, "C00"), (gpu,))
for gpu, pattern in enumerate(("P10", "P06", "P03", "P01"))
]
run_stage(
state,
"confirmations",
confirmations,
"moderate",
profile=False,
confirmation=True,
)
if state["completed_measured_runs"] != 52 or state["completed_burnins"] != 5:
raise RuntimeError(
f"completion count mismatch: measured={state['completed_measured_runs']} "
f"burnins={state['completed_burnins']}"
)
trace_count = len(list((RUN_ROOT / "primary").glob("*/*/traces/*.pt.trace.json*")))
expected_trace_count = 100 - state.get("missing_trace_files", 0)
if trace_count != expected_trace_count:
raise RuntimeError(
f"trace aggregate mismatch: {trace_count} != {expected_trace_count}"
)
state["trace_files"] = trace_count
state["status"] = "complete"
state["completed_at"] = time.time()
save_state(state)
print(json.dumps(state, sort_keys=True), flush=True)
def plan() -> dict[str, Any]:
matrix_waves = pack_cells(cells())
return {
"schema": SCHEMA,
"placement": "4-way GPU0-3",
"cells": len(cells()),
"primary_runs": 48,
"confirmation_runs": 4,
"burnins": 5,
"matrix_waves": [
[
{"cell": item.cell.cell_id, "gpus": item.gpus}
for item in wave
]
for wave in matrix_waves
],
"expected_trace_files": 100,
"prior_gpu_hours": PRIOR_GPU_HOURS,
"gpu_hour_limit": GPU_HOUR_LIMIT,
}
def main() -> None:
parser = argparse.ArgumentParser()
subparsers = parser.add_subparsers(dest="command", required=True)
run = subparsers.add_parser("run")
run.add_argument("--resume", action="store_true")
subparsers.add_parser("status")
subparsers.add_parser("plan")
args = parser.parse_args()
if args.command == "run":
execute(args.resume)
elif args.command == "status":
print(STATE.read_text() if STATE.exists() else '{"status":"absent"}')
else:
print(json.dumps(plan(), sort_keys=True, indent=2))
if __name__ == "__main__":
main()