Skip to content

perf(ep): EP factor searches skip per-search visuals by default (#1642, PR 2 of 3) - #1644

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/ep-factor-search-overhead-p2
Sep 24, 2026
Merged

Jammy2211 merged 1 commit into
mainfrom
feature/ep-factor-search-overhead-p2

Conversation

@Jammy2211

Copy link
Copy Markdown
Collaborator

Summary

PR 2 of 3 under #1642, stacked on #1643 (base = feature/ep-factor-search-overhead). Retarget to main after #1643 merges. PR 3 (mapper fast path) follows.

EP re-enters the same factor search once per EP step. At small per-factor fits the per-search plotting dominated the wall time, and the images were overwritten on every step anyway. This PR switches it off by default:

  • New config key general.yaml -> output -> visualize_ep_factor_searches: false. It is read with .get(..., False), so user configs that predate the key keep working.
  • NonLinearSearch._visualize_fit / _visualize_before_fit are class attributes (default True). optimise (the EP entry point) sets them around self.fit(...) and resets both to True in a finally.
  • pre_fit_output gates analysis.visualize_before_fit on _visualize_before_fit, so only the first search of each factor (number == 0) draws before-fit visuals.
  • SearchUpdater(visualization_enabled=True): when False, visualize returns immediately (no analysis.visualize / visualize_combined / plot_results, no samples loaded for plotting). The cached _updater re-applies self._visualize_fit on every access.

Samples, summaries and the EP optimiser's own graph.info / graph.png / graph_factors.png / mean_field_evolution.png / ep_history.csv are unchanged.

Harness: n5_profile, repeat 0, max_steps 3, nlive 100, seeded. The machine was shared with another profiling job (load average ~6), so the PR 1 head was re-run interleaved as a load-matched control.

PR 1 (1678905) PR 2 (1cd4a5b)
run_nested calls (15 factor searches) 15 15
per-search wall, quiet machine 1.575 s not measured (target ≤ 1.5 s)
per-search wall, loaded, interleaved pairs 3.52 / 4.12 / 2.01 s 2.61 / 2.77 / 1.54 s (26–37 % lower per pair)
centre moments max abs diff vs PR 1 – 0.0 (5 runs, bit-identical)
ep_history flags S26 / NC15 / F0 / BP10 / E0 identical
PNGs under dataset_*/optimization_* per-search corner / fit images only optimization_0/image/data.png per factor

Full evidence: #1642 (comment).

API Changes

No public signature is removed or changed incompatibly. One behaviour change and two additions:

  • EP factor searches no longer write per-search visuals (corner plots, model-fit images) and no longer redraw before-fit visuals after the first search of each factor. Set output.visualize_ep_factor_searches: true in general.yaml to restore the previous behaviour. The NSS live-visual path is untouched, and ordinary search.fit (outside EP) is unchanged.
  • New config key output.visualize_ep_factor_searches (default false).
  • New keyword SearchUpdater(..., visualization_enabled: bool = True) and attribute SearchUpdater.visualization_enabled.

See full details below.

Test Plan

  • New test_autofit/graphical/test_ep_factor_search_visuals.py (3 tests, all red on PR 1 source):
    • default key: a two-factor EP run with a named DynestyStatic makes 0 visualize and 0 plot_results calls and one visualize_before_fit per factor; graph.info, graph.png, ep_history.csv present;
    • key true: every factor search draws per-search visuals;
    • the visual switches are back to True after optimise.
  • test_updater.py::test__visualize__disabled_skips_all.
  • Full suite, run serially (pytest test_autofit -p no:xdist): 2885 passed, 2 skipped.
  • EP harness: moments bit-identical to PR 1, per-search wall 26–37 % lower in load-matched pairs.
  • Downstream impact (iii) none: visualize_ep_factor_searches, visualization_enabled, _visualize_fit, _visualize_before_fit have no hits in autofit_workspace*, HowToFit, PyAutoArray, PyAutoGalaxy or PyAutoLens.
Full API Changes (for automation & release notes)

Added

  • Config general.yaml -> output -> visualize_ep_factor_searches (default false).
  • SearchUpdater.__init__(..., visualization_enabled: bool = True) and the public attribute SearchUpdater.visualization_enabled.
  • NonLinearSearch._visualize_fit, NonLinearSearch._visualize_before_fit (private class attributes, default True).

Changed Behaviour

  • NonLinearSearch.optimise(...) (EP factor search entry point): sets _visualize_fit = visualize_ep_factor_searches and _visualize_before_fit = visualize_ep_factor_searches or number == 0 around fit, resetting both to True in a finally.
  • NonLinearSearch.pre_fit_output: analysis.visualize_before_fit now also requires _visualize_before_fit.
  • SearchUpdater.visualize: returns immediately when visualization_enabled is False.
  • NonLinearSearch._updater: re-applies _visualize_fit to the cached updater on every access.

Migration

  • None required. To keep per-factor EP images, set visualize_ep_factor_searches: true under output: in your general.yaml.

Heart RED override (development only)

This PR is opened under the PyAutoBrain/AUTONOMY.md "Human override for Heart RED (development only)". It is a development-shipping override only. It does not claim to fix Heart, and Heart remains RED for release purposes. Merge still needs a separate explicit human /prm with every required check green.

  • Authorisation (live human, 2026-09-24, Claude Code CLI session): asked "Does your override extend to opening PR 2 now as a stacked PR (base = PR 1 branch, retargeted to main after PR 1 merges), and PR 3 the same way once it is green?", the human selected "Yes, same override for PR 2 and PR 3".
  • Exact current RED reasons (pyauto-heart readiness --json, verdict red, score 45, ts 2026-09-24T15:11:12.973142+00:00):
    1. release validation FAILED (stage integrate)
    2. workspace validation not passing (4 failed, cloud#35579888156: autolens notebooks/cluster/modeling.ipynb, autolens notebooks/weak/a2744.ipynb, autolens scripts/cluster/modeling.py, +1 more)
    3. manifest drift: hub organism blurb (organs present) — 7 mismatch(es) vs PyAutoMind/repos.yaml
  • Branch gates passed: full serial test_autofit 2885 passed / 2 skipped on head 1cd4a5b; the new EP-visuals tests are red on PR 1 source; EP harness moments bit-identical to PR 1; downstream workspace impact (iii) none.
  • Permitted scope: commit, push, and opening this stacked pending-release PR. No merge, release or release rehearsal, and no bypassing of tests, checks or branch protection.

Generated by the PyAutoLabs agent workflow.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EQdWrHM9BUx1q2zZRy6Y7N

New config key `general.yaml -> output -> visualize_ep_factor_searches`
(default false). Under expectation propagation, `NonLinearSearch.optimise`
now turns off each factor search's per-search visuals (analysis.visualize /
visualize_combined and plot_results) and draws before-fit visuals only on the
first search of each factor. Samples, summaries and the EP optimiser's own
output (graph.info, graph.png, ep_history.csv) are unchanged. Set the key
true to restore the previous behaviour.

- NonLinearSearch: class-level `_visualize_fit` / `_visualize_before_fit`
  switches, set around `self.fit` in `optimise` and reset in `finally`;
  `pre_fit_output` gates before-fit visuals on them.
- SearchUpdater: `visualization_enabled` flag; `visualize()` is a no-op when
  False. `_updater` propagates `_visualize_fit` on every access.
- The key is read with `.get(..., False)` so user configs that predate it
  keep working.

Users lose per-factor model_fit/corner images by default under EP (intended).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@Jammy2211 Jammy2211 added the pending-release PR queued for the next release build label Sep 24, 2026
Base automatically changed from feature/ep-factor-search-overhead to main September 24, 2026 17:46
@Jammy2211
Jammy2211 merged commit aff2f36 into main Sep 24, 2026
4 checks passed
@Jammy2211
Jammy2211 deleted the feature/ep-factor-search-overhead-p2 branch September 24, 2026 17:47
@Jammy2211 Jammy2211 removed the pending-release PR queued for the next release build label Sep 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant