#!/usr/bin/env python3 """Run the corrected L3 seed/compiler/worker matrix with per-seed mesh coverage.""" import csv import re import subprocess import sys import time from pathlib import Path ROOT = Path.cwd() ROUND = ROOT / "Standalone/Research/WorldAssemblerM3/Linux3" SEEDS = ROOT / "Standalone/Research/WorldAssemblerM3/Linux2/seeds.txt" LOG_DIR = ROOT / "Saved/Linux" MEASURE = ROOT / "Standalone/Research/WorldAssemblerM3/Linux2/MeasureProcess.py" DATA = ROOT / "Standalone/data/owner_world.json" BINARIES = { "clang19-off": ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-clang19-l3-off", "clang19-on": ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-clang19-l3-on", "gcc14-default": ROOT / "Standalone/bin/linux/VoxelForgeCoreHeadless-gcc14-l3-default", } CAMERAS = { "surface-world": "0,-35,-487.94,0,-22", "floating-islands": "0,0,-32,0,-22", } HASH_RE = re.compile( r"\[PipelineWholeViewHash\] tiles=(\d+) density=0x([0-9a-f]+) " r"mesh=0x([0-9a-f]+) payload=0x([0-9a-f]+) topology=0x([0-9a-f]+)" ) MESH_RE = re.compile( r"\[PipelineMeshCoverage\] tiles=(\d+) nonempty_mesh_tiles=(\d+) indexed_triangles=(\d+)" ) PLACEMENT_RE = re.compile( r"\[SeedSurfacePlacement\].*camera_voxel=\(([-0-9.]+),([-0-9.]+),([-0-9.]+)\) status=PASS" ) READY_RE = re.compile(r"\[StreamPipeline\].*whole_view_ready=([0-9.]+)s") RESOURCE_RE = re.compile( r"\[ProcessResources\] exit_code=(-?\d+) wall_s=([0-9.]+) peak_rss_kib=(\d+)" ) def main() -> int: if len(sys.argv) > 2: raise SystemExit("usage: RunSeedSweep.py [budget-seconds; default 1800]") budget = int(sys.argv[1]) if len(sys.argv) == 2 else 1800 seeds = [int(line.strip()) for line in SEEDS.read_text().splitlines() if line.strip()] if len(seeds) != 48 or len(set(seeds)) != 48: raise SystemExit("expected the 48 unique signed int32 L2 seeds") missing = [str(path) for path in [MEASURE, DATA, *BINARIES.values()] if not path.is_file()] if missing: raise SystemExit("missing sweep input/build: " + ", ".join(missing)) LOG_DIR.mkdir(parents=True, exist_ok=True) output_path = ROUND / "seed_mesh_coverage.csv" fields = [ "seed", "recipe", "compiler_setting", "workers", "tiles", "nonempty_mesh_tiles", "indexed_triangles", "camera_x_vox", "camera_y_vox", "camera_z_vox", "density_hash", "mesh_hash", "payload_hash", "topology_hash", "whole_view_ready_s", "wall_s", "peak_rss_kib", "exit_code", "status", ] started = time.monotonic() total = len(seeds) * len(CAMERAS) * len(BINARIES) * 2 print(f"L3 sweep: {len(seeds)} seeds x 2 recipes x 3 builds x W1/W12 = {total}; budget={budget}s", flush=True) with output_path.open("w", newline="") as csv_file: writer = csv.DictWriter(csv_file, fieldnames=fields) writer.writeheader() completed = 0 for seed in seeds: for recipe, camera in CAMERAS.items(): for compiler, binary in BINARIES.items(): for workers in (1, 12): remaining = budget - (time.monotonic() - started) if remaining <= 0: print("L3 sweep exceeded its 30-minute budget; stopping.", file=sys.stderr, flush=True) return 124 stem = f"linux3-seed-{seed}-{recipe}-{compiler}-w{workers}" log_path = LOG_DIR / f"{stem}.log" args = [ str(binary), str(DATA), f"--seed={seed}", f"--recipe={recipe}", "--render-distance-chunks=0", f"--workers={workers}", "--world-assembler-prototype", "--stream-benchmark", "--stream-pipeline", "--stream-hash", "--mesh-coverage", "--auto-surface-camera", "--force-generate", "--clip-radius=1", "--max-clip-level=0", f"--camera={camera}", "--far-horizon-lod8-step=0", ] command = [ "taskset", "-c", "0-11", "prlimit", "--as=6442450944", "--", "python3", str(MEASURE), *args, ] with log_path.open("w") as log_file: log_file.write("[SweepCommand] " + " ".join(command) + "\n") log_file.flush() try: result = subprocess.run( command, cwd=ROOT, stdout=log_file, stderr=subprocess.STDOUT, timeout=min(900, max(1, remaining)), check=False, ) exit_code = result.returncode except subprocess.TimeoutExpired: exit_code = 124 log_file.write("\n[SweepTimeout] row reached its allotted limit\n") output = log_path.read_text(errors="replace") hashes = HASH_RE.search(output) mesh = MESH_RE.search(output) placement = PLACEMENT_RE.search(output) ready = READY_RE.search(output) resources = RESOURCE_RE.search(output) passed = bool( exit_code == 0 and hashes and mesh and placement and ready and resources and int(hashes.group(1)) == 27 and int(mesh.group(1)) == 27 and int(mesh.group(2)) > 0 and int(mesh.group(3)) > 0 and int(resources.group(1)) == 0 ) row = { "seed": seed, "recipe": recipe, "compiler_setting": compiler, "workers": workers, "tiles": mesh.group(1) if mesh else "", "nonempty_mesh_tiles": mesh.group(2) if mesh else "", "indexed_triangles": mesh.group(3) if mesh else "", "camera_x_vox": placement.group(1) if placement else "", "camera_y_vox": placement.group(2) if placement else "", "camera_z_vox": placement.group(3) if placement else "", "density_hash": "0x" + hashes.group(2) if hashes else "", "mesh_hash": "0x" + hashes.group(3) if hashes else "", "payload_hash": "0x" + hashes.group(4) if hashes else "", "topology_hash": "0x" + hashes.group(5) if hashes else "", "whole_view_ready_s": ready.group(1) if ready else "", "wall_s": resources.group(2) if resources else "", "peak_rss_kib": resources.group(3) if resources else "", "exit_code": exit_code, "status": "PASS" if passed else "FAIL", } writer.writerow(row) csv_file.flush() completed += 1 print( f"[{completed}/{total}] seed={seed} recipe={recipe} build={compiler} W{workers} " f"nonempty={row['nonempty_mesh_tiles']}/27 triangles={row['indexed_triangles']} " f"wall={row['wall_s']}s status={row['status']} elapsed={time.monotonic()-started:.1f}s", flush=True, ) if not passed: print(f"Failed row log: {log_path}", file=sys.stderr, flush=True) return exit_code or 1 rows = list(csv.DictReader(output_path.open(newline=""))) hash_columns = ("density_hash", "mesh_hash", "payload_hash", "topology_hash") compiler_checks = [] worker_checks = [] for seed in seeds: for recipe in CAMERAS: for workers in (1, 12): pair = [r for r in rows if int(r["seed"]) == seed and r["recipe"] == recipe and int(r["workers"]) == workers] compiler_checks.append(len(pair) == len(BINARIES) and all(all(row[key] == pair[0][key] for key in hash_columns) for row in pair)) for compiler in BINARIES: pair = [r for r in rows if int(r["seed"]) == seed and r["recipe"] == recipe and r["compiler_setting"] == compiler] worker_checks.append(len(pair) == 2 and all(all(row[key] == pair[0][key] for key in hash_columns) for row in pair)) elapsed = time.monotonic() - started maximum_rss = max(int(row["peak_rss_kib"]) for row in rows) empty_rows = sum(int(row["nonempty_mesh_tiles"]) == 0 or int(row["indexed_triangles"]) == 0 for row in rows) summary = ( f"runs={len(rows)} seeds={len(seeds)} recipes={len(CAMERAS)} builds={len(BINARIES)} workers=1,12 " f"cross_build_checks={len(compiler_checks)} cross_build_mismatches={sum(not x for x in compiler_checks)} " f"worker_checks={len(worker_checks)} worker_mismatches={sum(not x for x in worker_checks)} " f"empty_mesh_rows={empty_rows} max_peak_rss_kib={maximum_rss} elapsed_s={elapsed:.3f}\n" ) (ROUND / "seed_mesh_coverage_summary.txt").write_text(summary) print(summary, end="", flush=True) return 0 if all(compiler_checks) and all(worker_checks) and empty_rows == 0 and elapsed <= budget else 3 if __name__ == "__main__": raise SystemExit(main())