#!/usr/bin/env python3 """Serialized controller for the crossed-constraint action-aware pilot.""" from __future__ import annotations import argparse import json import os import shlex import signal import subprocess import sys import time from pathlib import Path from typing import Any, Mapping HERE = Path(__file__).resolve().parent PHASE6 = HERE.parent / "opprof-phase6" sys.path.insert(0, str(PHASE6)) import opprof_phase6_controller as base # noqa: E402 SCHEMA = "action-aware-constraint-pilot-state-v0" def atomic_json(path: Path, payload: Any) -> None: base.atomic_json(path, payload) def wait_all_idle(timeout_s: float = 30.0) -> None: deadline = time.monotonic() + timeout_s last_error: Exception | None = None while time.monotonic() < deadline: try: base.assert_all_idle() return except RuntimeError as error: last_error = error time.sleep(1.0) raise last_error or RuntimeError("GPU idle timeout") def configure(args: argparse.Namespace, manifest: Mapping[str, Any]) -> None: base.WORKDIR = args.run_root.parent base.RUN_ROOT = args.run_root base.STATE = args.run_root / "controller-state.json" base.SOURCE = args.vllm_source base.VENV = args.venv base.AITUNER = args.aituner_root base.MODEL = args.model base.CLIENT = args.client base.GPU_LIMIT = float(manifest["budget"]["hard_cap_h20_hours"]) base.MARKER = "action-aware-constraint-pilot-v0" def validate_inputs(args: argparse.Namespace, manifest: Mapping[str, Any]) -> None: if manifest.get("schema") not in { "action-aware-constraint-pilot-manifest-v0", "action-aware-constraint-pilot-manifest-v1", }: raise RuntimeError("unexpected action-aware manifest schema") if manifest.get("status") != "PASS": raise RuntimeError("action-aware manifest did not pass preflight") red_flags = manifest.get("sanity", {}).get("red_flags", []) if red_flags: raise RuntimeError(f"manifest red flags: {red_flags}") required = { "manifest": args.manifest, "aituner_root": args.aituner_root, "vllm_source": args.vllm_source, "venv_python": args.venv / "bin/python", "venv_vllm": args.venv / "bin/vllm", "model": args.model, "client": args.client, "burnin_study": Path(manifest["burnin"]["study"]), } for repetition, item in manifest["repetitions"].items(): required[f"rep{repetition}_study"] = Path(item["study"]) required[f"rep{repetition}_trace"] = Path(item["merged_trace"]["path"]) missing = {name: str(path) for name, path in required.items() if not path.exists()} if missing: raise RuntimeError(f"action-aware input paths missing: {missing}") def config_map(manifest: Mapping[str, Any]) -> dict[str, dict[str, Any]]: return {str(item["id"]): dict(item) for item in manifest["configs"]} def server_command( config: Mapping[str, Any], *, gpus: tuple[int, ...], port: int ) -> list[str]: return [ "taskset", "-c", base.cpu_mask(gpus), str(base.VENV / "bin/vllm"), "serve", str(base.MODEL), "--host", "127.0.0.1", "--port", str(port), "--served-model-name", "qwen3-30b-a3b-community", "--max-num-batched-tokens", str(config["mbbt"]), "--max-num-seqs", str(config["mns"]), "--tensor-parallel-size", "4", "--shutdown-timeout", "120", ] def client_command( entry: Mapping[str, Any], config: Mapping[str, Any], *, study: str, anchor: float, output: Path, warmup: bool, ) -> list[str]: command = [ "taskset", "-c", base.cpu_mask(entry["gpus"]), str(base.VENV / "bin/python"), str(base.CLIENT), "warmup" if warmup else "run-anchor", "--study", study, "--cell", str(config["id"]), "--anchor", str(anchor), "--tp", "4", "--mns", str(config["mns"]), "--mbbt", str(config["mbbt"]), "--base-url", f"http://127.0.0.1:{entry['port']}", "--result-dir", str(output), "--disable-slo-early-stop", ] return command def remaining_projection( manifest: Mapping[str, Any], *, completed_sessions: int ) -> float: remaining = len(manifest["configs"]) - completed_sessions return ( remaining * float(manifest["budget"]["session_estimate_h20_hours"]) + float(manifest["budget"]["safety_h20_hours"]) ) def dry_run_plan( args: argparse.Namespace, manifest: Mapping[str, Any] ) -> dict[str, Any]: sessions = [] for index, config in enumerate(manifest["configs"]): entry = {"gpus": (0, 1, 2, 3), "port": 9050 + index} session_root = args.run_root / "sessions" / str(config["id"]) first_repetition = str(config["repetition_order"][0]) first = manifest["repetitions"][first_repetition] commands = { "server": server_command(config, gpus=entry["gpus"], port=entry["port"]), "warmup": client_command( entry, config, study=first["study"], anchor=float(first["selection"]["anchor"]), output=session_root / "warmup", warmup=True, ), "burnin": client_command( entry, config, study=manifest["burnin"]["study"], anchor=float(manifest["burnin"]["anchor"]), output=session_root / "burnin", warmup=False, ), } for repetition in config["repetition_order"]: item = manifest["repetitions"][str(repetition)] commands[f"rep{repetition}"] = client_command( entry, config, study=item["study"], anchor=float(item["selection"]["anchor"]), output=session_root / f"rep{repetition}", warmup=False, ) sessions.append( { "config": config["id"], "mns": config["mns"], "mbbt": config["mbbt"], "port": entry["port"], "repetition_order": config["repetition_order"], "commands": { role: shlex.join(command) for role, command in commands.items() }, } ) return { "schema": "action-aware-constraint-pilot-dry-run-v0", "status": "PASS", "manifest": str(args.manifest), "run_root": str(args.run_root), "projected_h20_hours": remaining_projection( manifest, completed_sessions=0 ), "hard_cap_h20_hours": manifest["budget"]["hard_cap_h20_hours"], "sessions": sessions, } def load_state(path: Path, hard_cap: float) -> dict[str, Any]: if path.exists(): return json.loads(path.read_text(encoding="utf-8")) return { "schema": SCHEMA, "status": "initialized", "hard_cap_h20_hours": hard_cap, "gpu_hours_total": 0.0, "completed_sessions": 0, "sessions": {}, "failures": [], "started_at": time.time(), } def append_echo(run_root: Path, line: str) -> None: run_root.mkdir(parents=True, exist_ok=True) with (run_root / "launch-echo.log").open("a", encoding="utf-8") as target: target.write(line + "\n") print(line, flush=True) def start_server( *, args: argparse.Namespace, config: Mapping[str, Any], index: int, ) -> dict[str, Any]: gpus = (0, 1, 2, 3) session_root = args.run_root / "sessions" / str(config["id"]) session_root.mkdir(parents=True, exist_ok=True) port = 9050 + index command = server_command(config, gpus=gpus, port=port) with (session_root / "commands.log").open("a", encoding="utf-8") as log: log.write(f"SERVER {shlex.join(command)}\n") server_log = (session_root / "server.log").open("ab", buffering=0) environment = os.environ.copy() environment.update( { "CUDA_VISIBLE_DEVICES": "0,1,2,3", "VLLM_OPPROF_DIR": str(session_root / "opprof"), "OPPROF_PHASE6_MARKER": base.MARKER, "AITUNER_ROOT": str(base.AITUNER), "HF_HUB_OFFLINE": "1", "TRANSFORMERS_OFFLINE": "1", "PYTHONUNBUFFERED": "1", } ) server = subprocess.Popen( command, cwd=base.SOURCE, env=environment, stdout=server_log, stderr=subprocess.STDOUT, start_new_session=True, ) base.OWNED_PGIDS.add(server.pid) return { "cell": str(config["id"]), "gpus": gpus, "port": port, "dir": session_root, "server": server, "server_handle": server_log, "spawned_at": time.time(), "results": [], } def validate_result( result: Mapping[str, Any], *, config: Mapping[str, Any], selection: Mapping[str, Any], role: str, warmup: bool, ) -> None: if result.get("schema") != "action-aware-pilot-result-v0": raise RuntimeError(f"unexpected result schema: {role}") if result.get("config_id") != config["id"]: raise RuntimeError(f"config id mismatch: {role}") if int(result["tp"]) != 4: raise RuntimeError(f"TP mismatch: {role}") if int(result["mns"]) != int(config["mns"]): raise RuntimeError(f"MNS mismatch: {role}") if int(result["mbbt"]) != int(config["mbbt"]): raise RuntimeError(f"MBBT mismatch: {role}") if result.get("slo_early_stop_disabled") is not True: raise RuntimeError(f"SLO early stop was not disabled: {role}") if warmup: if result["kind"] != "warmup" or int(result["selection"]["count"]) != 16: raise RuntimeError(f"invalid warmup: {role}") return if bool(result["early_stopped"]): raise RuntimeError(f"uncensored run early-stopped: {role}") if int(result["selection"]["count"]) != int(selection["selected_count"]): raise RuntimeError(f"selection count mismatch: {role}") if int(result["observed_count"]) != int(selection["selected_count"]): raise RuntimeError(f"request accounting mismatch: {role}") for result_key, selection_key in ( ("request_id_order_sha256", "request_id_order_sha256"), ("arrival_order_sha256", "arrival_order_sha256"), ("raw_length_order_sha256", "input_length_order_sha256"), ): if result["selection"][result_key] != selection[selection_key]: raise RuntimeError(f"selection hash mismatch {result_key}: {role}") def burnin_gate( result: Mapping[str, Any], *, expected_count: int, maximum_elapsed_s: float, ) -> dict[str, Any]: if result.get("kind") != "anchor": raise RuntimeError("burnin gate received a non-anchor result") if int(result["selection"]["count"]) != expected_count: raise RuntimeError("burnin gate received the wrong request set") elapsed_s = float(result["interval"]["elapsed_s"]) summary = { "elapsed_s": elapsed_s, "pass_rate": float(result["pass_rate"]), "feasible": bool(result["feasible"]), } if elapsed_s > maximum_elapsed_s: raise RuntimeError( f"burnin throughput gate failed: {elapsed_s:.3f}s > " f"{maximum_elapsed_s:.3f}s" ) return summary def run_client( *, entry: dict[str, Any], config: Mapping[str, Any], role: str, study: str, selection: Mapping[str, Any], output: Path, state: Mapping[str, Any], timeout_s: float, warmup: bool = False, ) -> dict[str, Any]: command = client_command( entry, config, study=study, anchor=float(selection["anchor"]), output=output, warmup=warmup, ) with (entry["dir"] / "commands.log").open("a", encoding="utf-8") as log: log.write(f"CLIENT role={role} {shlex.join(command)}\n") handle = (output.parent / f"{output.name}.log").open("ab", buffering=0) environment = os.environ.copy() environment.update({"AITUNER_ROOT": str(base.AITUNER), "PYTHONUNBUFFERED": "1"}) process = subprocess.Popen( command, cwd=base.WORKDIR, env=environment, stdout=handle, stderr=subprocess.STDOUT, start_new_session=True, ) deadline = time.monotonic() + timeout_s try: while process.poll() is None: if time.monotonic() > deadline: raise TimeoutError(f"client timeout: {config['id']} {role}") if entry["server"].poll() is not None: raise RuntimeError(f"server exited during {config['id']} {role}") base.assert_no_other_compute() if state["gpu_hours_total"] + base.live_gpu_hours([entry]) >= base.GPU_LIMIT: raise RuntimeError("action-aware pilot H20-hour hard cap reached") time.sleep(1.0) except Exception: try: os.killpg(process.pid, signal.SIGTERM) except ProcessLookupError: pass try: process.wait(timeout=10.0) except subprocess.TimeoutExpired: try: os.killpg(process.pid, signal.SIGKILL) except ProcessLookupError: pass process.wait(timeout=10.0) raise finally: handle.close() if process.returncode: raise RuntimeError( f"client failed: config={config['id']} role={role} rc={process.returncode}" ) result = json.loads((output / "result.json").read_text(encoding="utf-8")) validate_result( result, config=config, selection=selection, role=role, warmup=warmup, ) entry["results"].append( {"anchor": float(selection["anchor"]), "dir": str(output), "kind": result["kind"]} ) return result def execute_session( *, args: argparse.Namespace, manifest: Mapping[str, Any], config: Mapping[str, Any], index: int, state: dict[str, Any], state_path: Path, ) -> None: name = str(config["id"]) if state["sessions"].get(name, {}).get("status") == "complete": return projection = remaining_projection( manifest, completed_sessions=int(state["completed_sessions"]) ) if float(state["gpu_hours_total"]) + projection > base.GPU_LIMIT: raise RuntimeError(f"projected cost exceeds cap before {name}") load_values = { float(item["selection"]["offered_req_s_per_gpu"]) for item in manifest["repetitions"].values() } load_text = ( f"{next(iter(load_values)):.6g}" if len(load_values) == 1 else ",".join(f"{value:.6g}" for value in sorted(load_values)) ) echo = ( f"ACTION_AWARE_SESSION_ECHO host=dash0 config={name} tp=4 " f"mns={config['mns']} mbbt={config['mbbt']} gpus=0-3 " f"workload={manifest['source']['window_id']} load_per_gpu={load_text} " f"duration_s={manifest['engine']['duration_s']} " f"repetitions={','.join(map(str, config['repetition_order']))} " f"source={args.manifest} output={args.run_root / 'sessions' / name} " f"spent_h20h={state['gpu_hours_total']:.6f} " f"remaining_projection_h20h={projection:.3f} cap_h20h={base.GPU_LIMIT:.1f}" ) append_echo(args.run_root, echo) wait_all_idle() session_state = { "status": "starting", "mns": int(config["mns"]), "mbbt": int(config["mbbt"]), "repetition_order": list(config["repetition_order"]), "started_at": time.time(), "runs": [], } state["status"] = "running" state["sessions"][name] = session_state atomic_json(state_path, state) entry = start_server(args=args, config=config, index=index) failure: Exception | None = None try: base.wait_ready(entry) first = manifest["repetitions"][str(config["repetition_order"][0])] session_state["status"] = "warmup" atomic_json(state_path, state) run_client( entry=entry, config=config, role="warmup", study=first["study"], selection=first["selection"], output=entry["dir"] / "warmup", state=state, timeout_s=180.0, warmup=True, ) session_state["status"] = "burnin" atomic_json(state_path, state) burnin = manifest["burnin"] burnin_result = run_client( entry=entry, config=config, role="burnin", study=burnin["study"], selection=burnin, output=entry["dir"] / "burnin", state=state, timeout_s=float(manifest["engine"]["client_timeout_s"]), ) session_state["burnin"] = burnin_gate( burnin_result, expected_count=int(burnin["selected_count"]), maximum_elapsed_s=float(manifest["engine"]["burnin_max_elapsed_s"]), ) atomic_json(state_path, state) session_state["status"] = "measured" atomic_json(state_path, state) for repetition in config["repetition_order"]: item = manifest["repetitions"][str(repetition)] role = f"rep{repetition}" result = run_client( entry=entry, config=config, role=role, study=item["study"], selection=item["selection"], output=entry["dir"] / role, state=state, timeout_s=float(manifest["engine"]["client_timeout_s"]), ) session_state["runs"].append( { "repetition": int(repetition), "pass_rate": result["pass_rate"], "feasible": result["feasible"], "slo_pass_count": result["slo_pass_count"], "elapsed_s": result["interval"]["elapsed_s"], } ) atomic_json(state_path, state) session_state["status"] = "stopping" atomic_json(state_path, state) except Exception as error: # noqa: BLE001 failure = error finally: try: base.stop_entry(entry) except Exception as error: # noqa: BLE001 failure = failure or error time.sleep(2.0) try: wait_all_idle() except Exception as error: # noqa: BLE001 failure = failure or error session_hours = base.live_gpu_hours([entry]) state["gpu_hours_total"] += session_hours session_state["gpu_hours"] = session_hours if failure is not None: session_state["status"] = "failed" session_state["failure"] = repr(failure) state["status"] = "failed" state["failures"].append({"session": name, "failure": repr(failure)}) atomic_json(state_path, state) raise failure validation = base.validate_cell(entry) session_state["validation"] = validation session_state["status"] = "complete" session_state["completed_at"] = time.time() state["completed_sessions"] += 1 atomic_json(state_path, state) def parser() -> argparse.ArgumentParser: result = argparse.ArgumentParser() result.add_argument("--manifest", type=Path, required=True) result.add_argument("--run-root", type=Path, required=True) result.add_argument("--aituner-root", type=Path, required=True) result.add_argument("--vllm-source", type=Path, required=True) result.add_argument("--venv", type=Path, required=True) result.add_argument("--model", type=Path, required=True) result.add_argument("--client", type=Path, required=True) result.add_argument("--dry-run", action="store_true") return result def main() -> None: args = parser().parse_args() manifest = json.loads(args.manifest.read_text(encoding="utf-8")) validate_inputs(args, manifest) configure(args, manifest) if args.dry_run: print(json.dumps(dry_run_plan(args, manifest), indent=2, sort_keys=True)) return args.run_root.mkdir(parents=True, exist_ok=True) copied_manifest = args.run_root / "pilot-manifest.json" if not copied_manifest.exists(): atomic_json(copied_manifest, manifest) state_path = args.run_root / "controller-state.json" state = load_state(state_path, base.GPU_LIMIT) state["status"] = "running" atomic_json(state_path, state) for index, config in enumerate(manifest["configs"]): execute_session( args=args, manifest=manifest, config=config, index=index, state=state, state_path=state_path, ) state["status"] = "complete" state["completed_at"] = time.time() atomic_json(state_path, state) wait_all_idle() print( json.dumps( { "status": state["status"], "completed_sessions": state["completed_sessions"], "gpu_hours_total": state["gpu_hours_total"], }, sort_keys=True, ) ) if __name__ == "__main__": main()