Repository navigation
feat(asap-tools): run the e2e planner through the rqe-optimizer MILP (planner.use_optimizer) - #831
Conversation
…(planner.use_optimizer) planner.use_optimizer (default true) makes experiment_run_e2e start asap-planner with --planner milp, reading planner.saturation_dir (atomic costs at optimizer_cost/rqe_atomic_costs.json inside it) and planner.workload_facts on the remote, plus optional w_cpu/w_mem. The containerized planner mounts both read-only. Settings the MILP can't honor fail fast: punting, auto_discover_labels, windowing, and the scripts that only run the legacy planner (ClickHouse, grafana demo, ingest path). aggregate_cleanup and sketch_parameters are left out of the planner input since the MILP picks both. Closes #830 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
milindsrivastava1997
left a comment
There was a problem hiding this comment.
Core wiring looks right: the CLI flags match asap-planner-rs/src/main.rs, the compose mounts are correct, and generate_controller_client_configs already handles None for cleanup and sketch params. Inline comments cover the rest. Two points that touch lines outside the diff:
- The Grafana demo and ingest-path scripts silently run the legacy planner when
use_optimizer=true.experiment_run_grafana_demo.pyandexperiment_only_ingest_path.pyread the same config and callcontroller_service.start(...)withoutmilp. ClickHouse got a guard, so this is inconsistent, and it breaks fail-loud: a user who setsuse_optimizer=truefor a Grafana demo gets a legacy plan with no warning. Either addrequire_legacy_plannerthere too (this only works if the default becomesfalse), or wiremilpthrough. - Tests: the negative paths are covered well. Nothing covers the default-config interaction, though: a test that loads the real
config.yamldefaults and runs the ClickHouse guard would have caught the regression flagged onexperiment_run_clickhouse.py. - Nit (predates this PR):
Args.cleanup_policy(config.py:612) is set but never read anywhere, and it's now misleading under MILP. Drop it if you're nearby.
| + config.required_cloudlab_params(cfg), | ||
| script_name="experiment_run_clickhouse", | ||
| ) | ||
| config.require_legacy_planner(cfg, "experiment_run_clickhouse") |
There was a problem hiding this comment.
experiment_run_clickhouse now fails by default. config.yaml defaults planner.use_optimizer: true, and this guard runs first, so every ClickHouse run now needs planner.use_optimizer=false. The PR notes cover the e2e break but not this one. Options: default use_optimizer: false (this also avoids breaking e2e runs until the saturation and facts inputs are routinely available), have ClickHouse ignore the key, or keep the guard and document the required override.
| "--enable-punting"{% endif %}{% if saturation_dir %}, | ||
| "--planner", "milp", | ||
| "--workload-facts", "/app/input/workload_facts.yaml", | ||
| "--atomic-costs", "/app/saturation/optimizer_cost/rqe_atomic_costs.json", |
There was a problem hiding this comment.
The cost-table path is written in two places: here and as COST_TABLE in experiment_utils/services/misc.py. Pass it into the template (e.g. /app/saturation/{{ cost_table }}) so there is one source of truth.
| "--workload-facts", "/app/input/workload_facts.yaml", | ||
| "--atomic-costs", "/app/saturation/optimizer_cost/rqe_atomic_costs.json", | ||
| "--saturation-dir", "/app/saturation"{% endif %}{% if w_cpu is not none %}, | ||
| "--w-cpu", "{{ w_cpu }}"{% endif %}{% if w_mem is not none %}, |
There was a problem hiding this comment.
Nit: --w-cpu/--w-mem sit outside {% if saturation_dir %}, and generate_controller_compose.py only checks that saturation-dir and facts are set together. Weights without a saturation dir would render flags the planner rejects (main.rs:125). That fails loudly, so it's harmless, but nesting the weights inside the block or adding them to the generator's parser.error check would be tidier.
| Fails on settings --planner milp can't honor rather than dropping them. | ||
| """ | ||
| planner = cfg.get("planner") | ||
| if planner is None or not planner.get("use_optimizer", False): |
There was a problem hiding this comment.
The use_optimizer default is set in two places: config.yaml says true, but this .get(..., False) falls back to False (same at L778 in require_legacy_planner). Since config.yaml always defines planner, read cfg.planner.use_optimizer directly.
| cfg.aggregate_cleanup, | ||
| cfg.get("sketch_parameters", None), | ||
| # The MILP rejects both; it chooses sketch parameters and cleanup itself. | ||
| None if milp else cfg.aggregate_cleanup, |
There was a problem hiding this comment.
Nit: with the optimizer on, aggregate_cleanup and sketch_parameters are dropped without a message. That's unavoidable since config.yaml sets defaults for both, but an explicit CLI override (e.g. sketch_parameters.CountMinSketch.width=4096) vanishes quietly. Consider a one-line log when the optimizer is on.
Closes #830.
experiment_run_e2enow startsasap-planner --planner milp(sketch-bench's rqe-optimizer) when the new Hydra optionplanner.use_optimizeris on (defaulttrue).Config (
config/config.yaml):Changes
MilpPlanner(experiment_utils/services/misc.py):ControllerService.start(milp=...)adds--planner milp --workload-facts --atomic-costs --saturation-dir [--w-cpu] [--w-mem]on bare metal. In the containerized path it passes the inputs togenerate_controller_compose.py.asap-planner-rs/docker-compose.yml.j2: mounts the saturation dir and the facts file read-only (/app/saturation,/app/input/workload_facts.yaml) and points the MILP flags at them.config.milp_planner(cfg)fails fast on settings the MILP can't honor:saturation_dirorworkload_factsunsetcontroller.punting=truecontroller.auto_discover_labels=truewindowingsetexperiment_run_e2eleavesaggregate_cleanupandsketch_parametersout of the planner input when the optimizer is on: the MILP rejects both and chooses them itself.experiment_run_clickhousefails fast whenuse_optimizer=true, because MILP doesn't support SQL. The grafana demo and ingest-path scripts are unchanged.Notes
truemeans e2e runs must now setplanner.saturation_dirandplanner.workload_facts, or passplanner.use_optimizer=false.sketchdb-controllerimage must be rebuilt so it includes--planner milp.NoCleanupuntil planner: MILP plan → InferenceConfig should use ReadBased cleanup instead of NoCleanup #800 lands.Testing
pytest asap-tools/experiments/tests: 61 passed. New tests are intests/test_planner_config.pyandtests/test_controller_service.py.🤖 Generated with Claude Code