Hoist invariant sum() out of calculate_force_terms inner loop (~16% faster) - #111
Merged
Conversation
calculate_force_terms recomputed `sum(_slice)` on every iteration of its `for CVkey: for theta:` double loop, in the condition `if len(error_messages) == sum(_slice)`. `_slice = list(range(self.Itheta+1))` is invariant over both loops, so this summed ~Itheta integers ~671k times per representative scroll run -- about 18% of total solve time. Hoist it to a single `n_slice_sum = sum(_slice)` before the loops. The result is bit-identical (all reported quantities -- volumetric/adiabatic efficiency, mass flow, forces -- match to full precision) and cuts ~16% off the wall-clock of examples/scroll_compressor.py (16.4s -> 13.7s), with no compilation and no API change. Found via native sampling (cProfile's per-call overhead masks it). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Scroll.calculate_force_termsrecomputedsum(_slice)on every iteration of itsfor CVkey: for theta:double loop, inside the conditionif len(error_messages) == sum(_slice). Since_slice = list(range(self.Itheta+1))is invariant across both loops, this summed ~Ithetaintegers ~671,000 times per representative scroll run — about 18% of total solve time.This hoists it to a single
n_slice_sum = sum(_slice)before the loops.Impact
examples/scroll_compressor.py(16.4s → 13.7s), interpreted/default build — no compilation, no API change.How it was found
Native stack sampling of the unprofiled solve showed
builtins.sumat ~18% of solve time; cProfile masks this because its per-call overhead inflates the millions of cheap delegation calls instead. cProfile's call graph (print_callers) then pinned the caller tocalculate_force_terms.Note (not changed here)
The condition
len(error_messages) == sum(_slice)looks like it may have been intended aslen(...) == len(_slice)(i.e. "every force evaluation for this CV failed, so print the unique errors"). This PR preserves the existing behavior exactly and only removes the redundant recomputation; the suspected logic question is left for a separate decision.Test Plan
examples/scroll_compressor.pyruns and all reported quantities are bit-identical tomaster🤖 Generated with Claude Code