Skip to content

perf(research): reuse exact inverses in the downset block-solve replay (3.4x, identical finite evidence) - #4947

Merged
Mister-Meeseeks merged 3 commits into
CrocSwap:mainfrom
JoyboyBrian:perf/replay-runtime-jb
Oct 23, 2026
Merged

Mister-Meeseeks merged 3 commits into
CrocSwap:mainfrom
JoyboyBrian:perf/replay-runtime-jb

Conversation

@JoyboyBrian

Copy link
Copy Markdown
Contributor

Result

The registered replay of research/downset-block-solve-bound runs about 3.4x faster with identical printed evidence. One change in that package's own verify.py: inv reuses the residual-checked exact inverse of an identical input matrix and returns a fresh copy.

registered command before (best / median of 3) after (best / median of 3) speedup (best)
python3.12 -I -W error -B verify.py 23.44 s / 23.51 s 6.95 s / 6.98 s 3.37x
python3.12 -I -O -W error -B verify.py 24.16 s / 24.51 s 6.71 s / 6.99 s 3.60x
scripts/research_package.py --package … (both commands) ≈ 47.6 s (sum of the two above) 14.90 s (one run) ≈ 3.2x

Timing method: wall time from time.perf_counter() around a subprocess.run of the exact registered argv, on the same fixture and the same machine (Apple Silicon, macOS, CPython 3.12). Other agents were running CPU work on the machine at the same time, so treat the absolute numbers as approximate. The ratio held in every run.

Bottleneck. cProfile of the unmodified verifier: inv takes 52.8 s of 59.8 s profiled (88%), through 33,409 calls. Instrumentation shows only 808 distinct input matrices (leading sections t[:k,:k] and the same factors recur for every downset). After the change, the remaining time is mostly mul. A trial that also memoized mul saved about another 15%. I left that out because it doesn't pay for the extra code.

Equivalence evidence

  • Printed receipt: both registered commands print the same status (PASS_DOWNSET_BLOCK_SOLVE), claim_type, no_new_kappa and the identical finite_evidence object. I diffed the JSON key by key against the pre-change output. The counts are 10 fixtures, 46 trees, 2,380 states, 9,520 matrix identities, 9,372 partition blocks, the spectral-certificate count, 11 controls, and 2,244 / 2,160 / 1,940 wrong-order / missing-endpoint / wrong-sign witnesses. The only differing fields are source_sha256["verify.py"] and source_sha256["README.md"], which hash the edited files. The package has no frozen receipt file.
  • Retained checks: every distinct matrix is still eliminated and residual-checked (A·A⁻¹ = A⁻¹·A = I) once. A singular input raises before anything is stored. The witness counts above prove that all identity and spectral checks still run on every state. They also show the three distinguishing controls (wrong order, omitted endpoint, inverse sign) still fire the same number of times.
  • Invalidation control (new, committed first, before the optimization): inverse_reuse_controls() requires three things. A caller's mutation of a returned inverse must not affect a later call. A different matrix of the same shape must get its own inverse. A singular matrix of a seen shape must still reject. It passed on the unmodified code too, with identical counts. Scratch mutation run against the new code:
    • unmodified: accepted
    • shape-only cache key: rejected (inverse is keyed by the exact input)
    • shared uncopied cache entry: rejected (returned inverse is a private copy)
    • elimination with the singular check removed: rejected (ZeroDivisionError)
  • Existing rejection controls (controls(): singular inverse, invalid partitions, PSD/spectral and leading-premise controls) are unchanged and still pass.

Task and overlap

Card replay-runtime (track verifier-engineering): "Can one measured replay bottleneck be sped up without dropping coverage?" Base cef4b52f2a59009865bf8eabde1be3f159063703.

Selection: I ranked registered packages by their longest recent research-packages.yml CI job, then timed the top candidates locally. downset-block-solve-bound (≈47 s locally, 197 s in CI) had a single dominant, self-contained bottleneck in a package-local verifier. That verifier has no frozen receipt and is not pinned by any other SOURCES.json/VERIFY.json. python3 scripts/find_overlap.py --task replay-runtime and find_overlap.py 'downset-block-solve-bound' found no open PR touching this package. The precedent work is #4090 (P112 census popcnt) and #4547 (portable-replay repair), which touch other packages.

Claim: #1166 (comment)

Test plan

  • python3.12 -I -W error -B research/downset-block-solve-bound/verify.py: PASS, finite_evidence identical to the base
  • python3.12 -I -O -W error -B research/downset-block-solve-bound/verify.py: PASS, identical
  • python3 scripts/research_package.py --package research/downset-block-solve-bound --check-only: PASS_PACKAGE_METADATA_AND_PINS
  • python3.12 -B scripts/research_package.py --package research/downset-block-solve-bound: PASS_REGISTERED_RESEARCH_PACKAGE … outcome=completed (14.9 s)
  • python3.12 -B scripts/check_research_commit.py --package research/downset-block-solve-bound --check-source-history: PASS_RESEARCH_COMMIT_BYTES
  • python3.12 -W error -B -m unittest discover -s tests -p 'test_research_onboarding.py': 26 tests OK
  • Scratch mutation run of the reuse controls (results above; not committed)

Not run: the complete frontier replay, Lean and Docker (not affected). No other package or shared script was changed.

Commits

  1. test(...): add the exact-input inverse reuse controls (pass on the unmodified code)
  2. perf(...): memoize the residual-checked inverse
  3. docs(...): README note on reuse, controls, timings and credit

Open next questions

  • Can mul be made cheaper without memoizing it? It is now most of the remaining ~7 s. Why it matters: this would give another ~15–30%. First step: fraction-free integer products over a common denominator per fixture. Blocked by: nothing, but the gain is small relative to CI setup.
  • Do other Fraction-heavy package verifiers repeat the same exact inversions? Many verifiers use the same inv pattern (e.g. matrix-algebra-three-factor takes about 37 s locally). Why it matters: the same exact-input reuse could apply wherever the distinct-to-total call ratio is small. First step: instrument distinct vs total inputs before changing anything. Blocked by: per-package frozen receipts that hash their verifier.

Credit

The mathematics, fixtures and all checks are Nick Petalas's (research/downset-block-solve-bound). This PR changes only replay runtime and adds reuse controls. Precedent: kumagi's #4090 (popcnt census speedup) and pinterbanget's #4547 (portable-replay repair). Prepared by Brian (JoyboyBrian) with substantial Claude Code assistance. Apache-2.0.

🤖 Generated with Claude Code

Controls that a returned inverse is a private copy, that inverses are
keyed by the exact input matrix, and that a singular matrix of a seen
shape still rejects. They pass on the unmodified elimination and guard
the memoization that follows. Printed finite_evidence is unchanged.
The replay calls the exact Fraction Gauss-Jordan inverse 33,409 times
on only 808 distinct matrices (about 88% of the runtime under cProfile).
Memoize the residual-checked inverse by its exact input and return a
fresh copy. Each distinct matrix is still eliminated and residual-checked
once; printed finite_evidence and the status token are unchanged under
both registered commands. Local best-of-3: 23.44s -> 6.95s (-W error),
24.16s -> 6.71s (-O).
@Mister-Meeseeks
Mister-Meeseeks merged commit 3fd7d44 into CrocSwap:main Oct 23, 2026
2 checks passed
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.

2 participants