15import argparse, copy, json, os, subprocess, sys, time
46def _one(cfg_path, max_it, restarts, seed):
51 L1._get_num_workers =
lambda cfg: 1
52 base = load_config(str(cfg_path)); cfg = copy.deepcopy(base)
53 req = cfg.design_requirements.model_dump()
54 pcfg = {
"mode":
"optimizer_controlled",
55 "max_lox_pressure_psi": float(req[
"max_lox_tank_pressure_psi"]),
56 "max_fuel_pressure_psi": float(req[
"max_fuel_tank_pressure_psi"])}
61 req[
"layer1_random_seed"] = int(seed)
62 np.random.seed(seed); t0 = time.perf_counter()
63 L1.run_layer1_optimization(cfg, PintleEngineRunner(copy.deepcopy(base)), req,
64 target_burn_time=float(req.get(
"target_burn_time", 6.0)),
65 tolerances={
"thrust": 0.10,
"apogee": 0.15}, pressure_config=pcfg,
66 layer1_smoke=
True, layer1_max_iterations=int(max_it), layer1_cma_restarts=int(restarts))
67 return time.perf_counter() - t0
71 os.environ[
"ED_ACCEL"] =
"off" if mode ==
"python" else "numba"
72 os.environ[
"ED_LAYER1_NATIVE_EVAL"] =
"0" if mode ==
"python" else "1"
74 _one(cfg_path, 1, 1, seed)
76 wall =
_one(cfg_path, max_it, restarts, seed)
77 cands = C.native_calls
if C.native_calls
else C.runner_calls
78 out = {
"mode": mode,
"wall_s": wall,
"candidates": cands,
79 "native_calls": C.native_calls,
"native_fallbacks": C.native_none,
80 "runner_calls": C.runner_calls,
81 "us_per_candidate": (wall / cands * 1e6)
if cands
else None}
82 print(
"BENCH_JSON " + json.dumps(out))
113 ap = argparse.ArgumentParser()
114 ap.add_argument(
"--config", default=
"configs/impinging_lox_ch4_8000N.yaml")
115 ap.add_argument(
"--max-iterations", type=int, default=8)
116 ap.add_argument(
"--cma-restarts", type=int, default=1)
117 ap.add_argument(
"--seed", type=int, default=0)
118 ap.add_argument(
"--reps", type=int, default=3,
119 help=
"timed repetitions per accelerated mode (noise control)")
120 ap.add_argument(
"--python-reps", type=int, default=1,
121 help=
"reps for the Python baseline (~10x slower, 1 is usually enough)")
122 ap.add_argument(
"--mode", choices=[
"python",
"numba"], default=
None)
124 cfg_path = (ROOT / a.config)
if not os.path.isabs(a.config)
else Path(a.config)
126 _run_condition(a.mode, cfg_path, a.max_iterations, a.cma_restarts, a.seed);
return
127 print(f
"config: {cfg_path}\nbudget: max_iterations={a.max_iterations} restarts={a.cma_restarts} "
128 f
"seed={a.seed} reps={a.reps} (serial, warmup discarded)")
130 for mode
in (
"python",
"numba"):
132 for _
in range(a.python_reps
if mode ==
"python" else a.reps):
133 cmd = [sys.executable, str(Path(__file__).resolve()),
"--config", a.config,
134 "--max-iterations", str(a.max_iterations),
"--cma-restarts", str(a.cma_restarts),
135 "--seed", str(a.seed),
"--mode", mode]
136 p = subprocess.run(cmd, cwd=str(ROOT), capture_output=
True, text=
True)
137 line = next((l
for l
in p.stdout.splitlines()
if l.startswith(
"BENCH_JSON ")),
None)
139 print(f
"!! {mode} produced no result. stderr tail:\n"
140 +
"\n".join(p.stderr.splitlines()[-20:]));
return
141 runs.append(json.loads(line[len(
"BENCH_JSON "):]))
142 agg[mode] =
_pc(mode, runs)
143 py, nb = agg[
"python"], agg[
"numba"]
144 print(
"\n" +
"=" * 68)
145 for stat
in (
"min",
"median"):
146 print(f
" [{stat:6s}] per-candidate us: python={py[stat]:.0f} numba={nb[stat]:.0f}"
147 f
" speedup={py[stat]/nb[stat]:.1f}x")