Repository navigation
feat(csr): sparse one-term expressions and sparse broadcast in merges - #1034
Conversation
Build cost — v1 vs legacyv1 build peak & time relative to legacy, on this commit — not a comparison against master (that is CodSpeed).
Full table (time + peak, mean)📊 Interactive plots + CSV: download the semantics-report-v1-vs-legacy artifact from this run. Report-only · not a gate · refreshed on every push · obsolete once legacy is dropped. |
Merging this PR will not alter performance
Comparing Footnotes
|
In a sparse model, Variable.to_linexpr builds CSR directly from labels (from_labels), and merges over different dims broadcast sparsely instead of densifying. CSR rows are canonicalized lazily when a constraint is added; stored arrays are read-only.
2235980 to
12c6b29
Compare
Making the CSR path faster and bridging to a full data backend.
Related: #1019, #1033, #1011, #969.
Note
The following content was generated by AI.
Changes proposed in this Pull Request
In a sparse model (
Model(sparse=True)), linear expressions now stay sparse from the start, and sums over operands with different dimensions no longer densify.Variable.to_linexprbuilds the CSR store directly from the variable labels (CSRLinearExpression.from_labels), so2 * x,x + yand1*x + 2*y + 3*zare CSR-backed. This runs at dense parity: the earlier cost of one-term CSR expressions came from the genericfrom_densescatter (54 ms vs 13 ms for2 * xon a 2000 × 500 grid).x.groupby(g).sum() + wwithwover a subset of the dims) broadcasts rows on the sparse grid (Grid.broadcast_rows,CSRLinearExpression.broadcast) instead of densifying. This works for all joins and in xarray's dimension order. MultiIndex dims and non-unique labels still densify with an explicit reason.ntermcounts stored terms. Rows are brought into canonical form once, when a constraint is added.sum_duplicates) raises instead of corrupting another expression.to_dense()keeps the order of repeated terms.fillna(expr)warns once.Behavior change
In a sparse model, operations on variable arithmetic that have no sparse path now densify with a
PerformanceWarning, where the expression used to be dense and silent:simplify,assign_coords,drop_sel,expand_dims,shift(fill_value=...),where(callable), multiplication or comparison with a new dimension,mergealong a new dimension,fillna(expr).x * y,x ** 2,rollingandcumsumstay dense without a warning.Known open points
(x + y).sum("a")is about 12 % slower than on master (row gather of 2M terms).1*x + 2*y + 3*zuses 111 MB instead of 95 MB.Benchmarks (2000 × 500 grid; master sparse / branch sparse / branch dense)
On master, variable arithmetic is dense even in a sparse model.
2*xx + y1*x + 2*y + 3*z(x + y).sum("b")(x + y).sum("a")e.sum()1*x + 2*y >= 1Tests: 7598 passed, 1522 skipped (Xpress excluded locally because of a license limit).
Checklist
AGENTS.md).doc.doc/release_notes.rstof the upcoming release is included.