Cost and fuse preserved pullbacks, and cancel indirect Deltas - #5362
Draft
pbrubeck wants to merge 4 commits into
Draft
Cost and fuse preserved pullbacks, and cancel indirect Deltas#5362pbrubeck wants to merge 4 commits into
pbrubeck wants to merge 4 commits into
Conversation
pbrubeck
force-pushed
the
pbrubeck/zany-matvec
branch
from
August 20, 2026 15:01
39f1e41 to
eee9def
Compare
pbrubeck
force-pushed
the
pbrubeck/zany-matvec
branch
from
August 20, 2026 15:10
eee9def to
a458257
Compare
pbrubeck
commented
Aug 20, 2026
pbrubeck
force-pushed
the
pbrubeck/zany-matvec
branch
from
August 22, 2026 15:40
e4536ab to
5bc40c9
Compare
dham
marked this pull request as draft
August 25, 2026 15:29
This was referenced Aug 29, 2026
A form whose arguments share a pullback can either expand that map into scalar monomials, exposing factorisation across its entries, or keep it whole so that both argument axes read one tabulation. Neither wins everywhere, so factorise both ways and keep the cheaper plan, skipping the second factorisation when no assignment holds a map to preserve. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M6QZ26z2p9o7sYzxZXV1B3
One preserved linear map per ComponentTensor gave one loop nest each, so the single fused nest that expansion produces became several loops over the same extent, and that cost more than the flops preservation saves. Reuse one iname per bound index while the tabulations stay adjacent; a statement the schedule placed between them closes the loop, so the memo resets there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M6QZ26z2p9o7sYzxZXV1B3
A padded basis transformation selects its columns with a Delta over a variable index. Monomial collection only cancels a Delta that surfaces as a factor of a monomial, and one buried in a preserved linear map never does, so it would reach code generation as a full-width contraction against an identity. Cancel the indirect Deltas up front, leaving the plain-index ones to monomial collection. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M6QZ26z2p9o7sYzxZXV1B3
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01M6QZ26z2p9o7sYzxZXV1B3
pbrubeck
force-pushed
the
pbrubeck/zany-matvec
branch
from
September 8, 2026 17:54
3485f84 to
89b91e6
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.
TLDR
This is the TSFC half of firedrakeproject/fiat#284 and firedrakeproject/fiat#281.
It does three things. TSFC costs two factorisation plans and keeps the cheaper
one, instead of choosing by a rule. Loopy puts adjacent shared tabulations in
one loop, instead of one loop each. And TSFC cancels the indirect Deltas that
select a padded basis transformation's columns, which is what makes fiat#281's
transformation viable at all.
Raviart--Thomas in 3D loses a third of its operations. Q and NCE do not change.
Base:
main. Needs firedrakeproject/fiat#281. The TSFC half offiredrakeproject/fiat#286 is stacked on this branch in #5438.
What this does
Cost the two plans (
tsfc/spectral.py).A pullback reaches TSFC as a sum over one argument axis. There are two ways to
handle it.
Neither wins everywhere. So
flattenbuilds both plans and keeps the cheaperone by
estimate_cost. It skips the second plan whenhas_linear_mapssaysthere is no map to keep, so the extra work is only paid where it can help.
On a CG degree 3 Laplacian in 2D, keeping the map costs 8,305 operations against
8,125 for expanding it. Only a cost model rejects it there.
Fuse adjacent tabulations (
tsfc/loopy.py).One kept map per
ComponentTensorgave one loop each, so a single fused nestbecame three loops over the same extent. TSFC now reuses one iname per bound
index and fuses them back.
The iname is reused only between adjacent tabulations. Impero can place
other statements between two tabulations that depend on each other, and one
iname cannot be both inside and outside such a statement.
statement_blocktherefore resets the memo on any statement that is not a
ComponentTensorEvaluate.Cancel the indirect Deltas (
tsfc/spectral.py).fiat#281 selects a padded transformation's columns with a Delta over a variable
index. Monomial collection only cancels a Delta that surfaces as a factor of a
monomial, and one buried in a kept linear map never does, so it would reach code
generation as a full-width contraction against an identity.
Integralscancelsthe indirect Deltas up front and leaves the plain-index ones to monomial
collection.
This is not an optimisation, it is what makes the padded transformation usable.
Paired with fiat#281 and without it, the Johnson--Mercier action in 3D costs
319,963 operations against 44,248 on
main.Effect
Raviart--Thomas is where keeping the pullback pays. On
inner(u, v)*dx + inner(curl(u), curl(v))*dx,mainagainst this PR:Arithmetic falls 32% at degree 3 and 33% at degree 5 in 3D. There are 31% fewer
scalar temporaries and 20% fewer lines of C.
Q and NCE do not change. On a tensor-product cell no sum depends on exactly one
argument index, so the second plan is never built.
The zany elements need the whole stack
This PR paired with fiat#281 regresses the Johnson--Mercier and Argyris actions,
because a padded transformation reads its reference tabulation once per padded
column. fiat#286 and #5438 are what tabulate that contraction one time. Numbers
are in #5438; do not merge this pair on its own.
Validation
tests/tsfcpaired with fiat#281: 386 passed. That pairing did not buildbefore this split, because the branch also carried fiat#286's call site.
AI assistance
Claude Code was used for the split, the benchmarking and this description. The
human contributor remains responsible for understanding, validating and
maintaining the changes.
🤖 Generated with Claude Code
https://claude.ai/code/session_01A1NNAv95LANgpBX61ozPE2