perf(ZIBR): single-pass relabel-and-sum for pure bus merges#330
Open
luke-kiernan wants to merge 1 commit into
Open
perf(ZIBR): single-pass relabel-and-sum for pure bus merges#330luke-kiernan wants to merge 1 commit into
luke-kiernan wants to merge 1 commit into
Conversation
Contributor
Performance ResultsPrecompile Time
Execution TimeCells show median (min–max) over 5 samples; delta compares medians.
|
59c222b to
555185b
Compare
The bus merge applied by ZeroImpedanceBranchReduction went through `_merge_ybus_buses!`, which does per-entry CSC structural inserts to sum each removed bus's row/column into its survivor, followed by a `data[bus_ix, bus_ix]` slice. On a large sparse Ybus each insert shifts the whole backing store, so the cost scales with merges × nnz. On main these systems merged 0 buses (the old `iszero(real(Y))` gate), so the path was skipped via the empty-reduction short-circuit; the per-branch L2 criterion now correctly merges low-impedance branches (e.g. 28 on the Eastern Interconnect), making this path hot. A pure bus merge (no eliminations or admittance additions — only ZIBR produces one) is just an index relabeling, so the merge and the bus-removal slice are fused into a single O(nnz) pass: relabel each entry's row/column to the surviving index and let `sparse()` sum collisions. Adjacency is rebuilt the same way, then re-derived for survivors (anti-parallel branches cancel in the signed sum). The general elimination path (radial/degree-two/Ward) is unchanged. Eastern Interconnect Build Ybus: ~505 ms -> ~375 ms (residual merge overhead ~140 ms -> ~40 ms). Adds a rewire-and-rebuild oracle test; all reduction tests (33k assertions) pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
ef11ed8 to
658a561
Compare
4b86712 to
c919d37
Compare
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.
Stacked on #329. Removes the Build-Ybus regression that #329's correctness fix surfaced.
Why
#329's per-branch L2 criterion correctly merges low-impedance branches that the old
iszero(real(Y))gate skipped. Onmainthese large systems merged 0 buses, so the reduction short-circuited (isempty(reduction) && return ybus); now they merge a handful (28 on the Eastern Interconnect), which makes the merge machinery hot for the first time.That machinery —
_merge_ybus_buses!→_accumulate_csc_col_into!— sums each removed bus's row/column into its survivor with per-entry CSC structural inserts, each of which shifts the whole backing store of a 78k×78k matrix, then slices out the removed buses withdata[bus_ix, bus_ix]. Cost scales with merges × nnz.Measured (Eastern, 78,484 buses, same machine):
mainResidual merge overhead over the no-merge baseline drops from ~140–190 ms to ~40 ms.
What
A pure bus merge (only ZIBR produces one — radial/Ward add admittances, degree-two adds series branches) is just an index relabeling, so the merge and the bus-removal slice are fused into a single O(nnz) pass: relabel each entry's row/column to the surviving index and let
sparse()sum collisions. Adjacency is rebuilt the same way, then re-derived for survivors (anti-parallel branches cancel in the signed sum, mirroring the existing repair)._is_pure_merge_reduction(merges present; noremoved_buses/series_branch_map/removed_arc_to_surviving_bus/added maps). The general elimination path is untouched, so radial/degree-two/Ward are byte-for-byte unchanged._apply_reductioncall, so the fast path fires on the ZIBR step even when other reductions follow it.Tests
ZIBR fast merge matches a rewire-and-rebuild oracle: merging bus 3 into bus 2 across a zero-impedance line equals an independently built system where bus 3's branch is rewired onto bus 2 and the ZI line removed (the huge ZI entries cancel in the row/column sum).anti-parallel merge keeps a bus's degree.🤖 Generated with Claude Code