Skip to content

fix(core): DSRunner memory_efficient output/monitors; eager check bound validation#851

Merged
chaoming0625 merged 1 commit into
masterfrom
fix/audit-20260619-toplevel-glue
Jun 18, 2026
Merged

fix(core): DSRunner memory_efficient output/monitors; eager check bound validation#851
chaoming0625 merged 1 commit into
masterfrom
fix/audit-20260619-toplevel-glue

Conversation

@chaoming0625

@chaoming0625 chaoming0625 commented Jun 18, 2026

Copy link
Copy Markdown
Member

Fresh review of top-level glue (dynsys, runners, delay, mixin, transform, check, shims).

  • CriticalDSRunner(memory_efficient=True) returned None instead of model outputs (list.append inside tree_map); now accumulates and stacks per-step outputs on a leading time axis.
  • Highmemory_efficient monitors came out time-major vs the standard path's batch-major in BatchingMode; now axis-matched.
  • Highcheck.is_float/is_integer bound checks never raised eagerly (a pure_callback swallowed the raise for concrete predicates); added a concrete fast-path that raises directly, preserving the deferred path under tracing.

⚠️ Blast radius: check.is_float/is_integer with bounds now actually reject invalid input across all call sites (valid defaults verified to still construct). In-scope: 441 passed. Findings: docs/issues-found-20260619-toplevel-glue.md.

Summary by Sourcery

Fix DSRunner memory-efficient output and monitor layout while tightening eager bound-checking behavior.

Bug Fixes:

  • Ensure DSRunner(memory_efficient=True) returns time-stacked model outputs instead of None, matching the standard path for both scalar and pytree outputs.
  • Align memory-efficient monitor axis ordering with the standard batch-major layout in BatchingMode so monitor shapes no longer depend on the memory_efficient flag.
  • Make is_float and is_integer min_bound/max_bound checks raise eagerly for out-of-bound values while preserving deferred in-jit error signaling.
  • Update jit_error and jit_error_checking_no_args to raise synchronously for concrete predicates, and adjust tests to reflect the new error behavior.
  • Prevent DSRunner tests from leaking a modified global dt across test cases by restoring the default dt after each test.

Documentation:

  • Add an audit report documenting identified issues and their fix/record status for top-level glue components.

Tests:

  • Add regression tests covering DSRunner memory_efficient outputs and monitor shapes, including batched models and update methods that return None.
  • Add regression tests asserting eager bound checks and jit_error helpers raise or not raise as expected in both eager and jitted contexts.
  • Strengthen existing coverage tests for check.* utilities to expect the new eager-raising semantics.

….is_float/is_integer bounds

- DSRunner(memory_efficient=True) returned None instead of model outputs
  (list.append inside tree_map); now accumulates and stacks per-step outputs
  along a leading time axis (Critical)
- memory_efficient monitors came out time-major vs the standard path's
  batch-major for BatchingMode; moveaxis to match (High)
- check.is_float/is_integer min_bound/max_bound never raised eagerly
  (pure_callback swallowed the raise for concrete predicates); add a
  concrete-predicate fast path that raises directly, keeping the deferred
  cond/callback path under tracing (High)

Findings recorded in docs/issues-found-20260619-toplevel-glue.md
@chaoming0625 chaoming0625 merged commit 3204311 into master Jun 18, 2026
2 of 5 checks passed
@sourcery-ai

sourcery-ai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Reviewer's Guide

Fixes DSRunner’s memory_efficient output stacking and monitor axis layout, and restores eager bound-checking semantics in check utilities while adding regression tests and documenting audit findings.

File-Level Changes

Change Details Files
Fix memory_efficient DSRunner output accumulation to return time-stacked model outputs and keep None when update() returns no value.
  • Replaced per-step tree_map list.append accumulation with a flat Python list of outputs and a final tree_map+jnp.stack over time
  • Ensured empty index ranges return (None, None) instead of malformed pytrees
  • Standardized stacking to a leading time axis using bm.as_jax/jnp.stack to match the non-memory-efficient path
brainpy/runners.py
Align memory_efficient monitor layout with standard batch-major monitors for batched models.
  • During memory_efficient predict() finalization, detect BatchingMode with data_first_axis='B' and move the time axis behind batch for collected monitors
  • Convert monitor lists to NumPy arrays and use np.moveaxis for ndim>=2 to yield consistent (B, T, ...) layouts with the standard path
brainpy/runners.py
Add eager fast-paths for jit_error and jit_error_checking_no_args so bounds checks actually raise for invalid values while preserving deferred behavior under JIT.
  • In jit_error, short-circuit concrete non-tracer predicates by evaluating pred eagerly and calling the error function directly when True
  • In jit_error_checking_no_args, short-circuit concrete predicates by raising the provided Exception immediately when True and returning otherwise
  • Adjusted the pure_callback true branch helper to accept *args to be compatible with JAX callbacks
brainpy/check.py
Update and extend tests to cover DSRunner memory_efficient behavior, monitor axes, and eager bound-check semantics, and to avoid global dt leakage between tests.
  • Introduce a _DtRestoreMixin in dyn_runner_test to snapshot and restore the global dt after each test, and mix it into TestDSRunner/TestMemoryEfficient
  • Add TestMemoryEfficient cases covering scalar and pytree outputs, monitor equality, None-returning update(), and batched monitor axis layout
  • Add TestBoundChecks to verify is_float/is_integer min/max bounds raise eagerly, within-bounds values pass, and jit_error_checking_no_args behaves correctly both eagerly and under jax.jit
  • Update existing check_coverage_test tests to expect exceptions for out-of-bound values and concrete True predicates now that errors propagate eagerly
brainpy/dyn_runner_test.py
brainpy/check_test.py
brainpy/check_coverage_test.py
Record audit findings for the top-level glue audit, including this PR’s fixes and remaining low/medium issues, in documentation.
  • Add docs/issues-found-20260619-toplevel-glue.md summarizing critical, high, medium, and low findings, marking which are fixed vs recorded-only
  • Document specific IDs (P14-C1, P14-H1, P14-H2, P14-M2, P14-L1-4) with rationale, repro snippets, and status for future reference
docs/issues-found-20260619-toplevel-glue.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 3 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="docs/issues-found-20260619-toplevel-glue.md" line_range="9-10" />
<code_context>
+
+Branch: fix/audit-20260619-toplevel-glue
+
+Counts: Critical 1, High 2, Medium 1, Low 4. Fixed 4 (C1, H1, H2 + the M2 test-fragility);
+recorded-only 4 (M2 source-level, L1, L2, L3, L4).
+
+| ID | Severity | File | Status |
</code_context>
<issue_to_address>
**issue (typo):** Recorded-only count does not match the listed items.

The text says "recorded-only 4" but lists five items: "M2 source-level, L1, L2, L3, L4." Please update either the count or the list so they match.

```suggestion
Counts: Critical 1, High 2, Medium 1, Low 4. Fixed 4 (C1, H1, H2 + the M2 test-fragility);
recorded-only 5 (M2 source-level, L1, L2, L3, L4).
```
</issue_to_address>

### Comment 2
<location path="docs/issues-found-20260619-toplevel-glue.md" line_range="117-119" />
<code_context>
+  *concrete* (eager) predicate, `jax.pure_callback` only raises when the staged computation is
+  executed — under an eager `cond` the callback's exception is never surfaced synchronously, so
+  the function returns normally. (`true_err_fun(arg, transforms)` also had the wrong arity for a
+  no-operand callback.) Result: every eager out-of-bound check is a no-op.
+- Why it's a bug: parameter validation across the codebase silently accepts invalid values, e.g.
+  `bp.dnn.Dropout(prob=2.0)` / `prob=-1`, negative frequencies, non-positive integer sizes,
</code_context>
<issue_to_address>
**nitpick (typo):** Consider changing 'out-of-bound' to 'out-of-bounds' for standard phrasing.

In the final sentence of this bullet, update the phrase so it uses the standard 'out-of-bounds' wording.

```suggestion
  executed — under an eager `cond` the callback's exception is never surfaced synchronously, so
  the function returns normally. (`true_err_fun(arg, transforms)` also had the wrong arity for a
  no-operand callback.) Result: every eager out-of-bounds check is a no-op.
```
</issue_to_address>

### Comment 3
<location path="docs/issues-found-20260619-toplevel-glue.md" line_range="239" />
<code_context>
+  `math/object_transform/variables.py` (out of scope); **already fixed** there
+  (`size_without_batch` now returns `(10,)` for a `(4,10)` batched Variable). Verified.
+
+left_unfixed_chm: none in scope. H-45's fix lives outside this scope (variables.py) and is
+already applied upstream.
</code_context>
<issue_to_address>
**suggestion (typo):** Possible typo in 'left_unfixed_chm'.

The name 'left_unfixed_chm' is unclear and looks like a typo or unclear abbreviation. Please rename it to something more descriptive and correctly spelled (e.g., `left_unfixed_issues`).
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +9 to +10
Counts: Critical 1, High 2, Medium 1, Low 4. Fixed 4 (C1, H1, H2 + the M2 test-fragility);
recorded-only 4 (M2 source-level, L1, L2, L3, L4).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (typo): Recorded-only count does not match the listed items.

The text says "recorded-only 4" but lists five items: "M2 source-level, L1, L2, L3, L4." Please update either the count or the list so they match.

Suggested change
Counts: Critical 1, High 2, Medium 1, Low 4. Fixed 4 (C1, H1, H2 + the M2 test-fragility);
recorded-only 4 (M2 source-level, L1, L2, L3, L4).
Counts: Critical 1, High 2, Medium 1, Low 4. Fixed 4 (C1, H1, H2 + the M2 test-fragility);
recorded-only 5 (M2 source-level, L1, L2, L3, L4).

Comment on lines +117 to +119
executed — under an eager `cond` the callback's exception is never surfaced synchronously, so
the function returns normally. (`true_err_fun(arg, transforms)` also had the wrong arity for a
no-operand callback.) Result: every eager out-of-bound check is a no-op.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick (typo): Consider changing 'out-of-bound' to 'out-of-bounds' for standard phrasing.

In the final sentence of this bullet, update the phrase so it uses the standard 'out-of-bounds' wording.

Suggested change
executed — under an eager `cond` the callback's exception is never surfaced synchronously, so
the function returns normally. (`true_err_fun(arg, transforms)` also had the wrong arity for a
no-operand callback.) Result: every eager out-of-bound check is a no-op.
executed — under an eager `cond` the callback's exception is never surfaced synchronously, so
the function returns normally. (`true_err_fun(arg, transforms)` also had the wrong arity for a
no-operand callback.) Result: every eager out-of-bounds check is a no-op.

`math/object_transform/variables.py` (out of scope); **already fixed** there
(`size_without_batch` now returns `(10,)` for a `(4,10)` batched Variable). Verified.

left_unfixed_chm: none in scope. H-45's fix lives outside this scope (variables.py) and is

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (typo): Possible typo in 'left_unfixed_chm'.

The name 'left_unfixed_chm' is unclear and looks like a typo or unclear abbreviation. Please rename it to something more descriptive and correctly spelled (e.g., left_unfixed_issues).

@github-actions github-actions Bot added documentation Improvements or additions to documentation tests labels Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant