Skip to content

compiler: Match product keys in subs_if_composite via a factor index - #3059

Open
EdCaunt wants to merge 1 commit into
mainfrom
bespoke-index
Open

EdCaunt wants to merge 1 commit into
mainfrom
bespoke-index

Conversation

@EdCaunt

@EdCaunt EdCaunt commented Oct 16, 2026 •

Copy link
Copy Markdown
Contributor

Tweak to substantially improve CPML-like operator compilation times on PRO backends.

Composite subs keys that are all products used to go through SymPy's subs, i.e. one full traversal per key. MulSubsIndex files each key under one of its factors, walks the expression once, and turns sub-multiset matches into a single compound uxreplace rule. Where SymPy could still rewrite a product the multiset test rejects (powers, differing coefficients), or where keys overlap or chain, it falls back to expr.subs.

Previously, every Mul key meant a full sympy subs pass over the expression, so the cost was keys × nodes. MulSubsIndex replaces that with one pass:

  • Index the keys. Each Mul key is filed under the base of one of its factors, preferably an Indexed. Its factor multiset is stored with it, e.g. {w[i0]: 1, p[x+3]: 1}.
  • Walk the expression once. For each Mul node, only the keys filed under that node's own factors are candidates. Most nodes have none, so they cost nothing.
  • Test sub-multiset inclusion. A key matches if its factors are contained in the node's factors (Counter <=). For example, a*b matches a*b*c, leaving c.
  • Rewrite in one go. All matches go into a single compound uxreplace rule, {a*b*c: {a: value, b: None}}, so the result is value*c, built without re-evaluation.
  • Defer to sympy whenever sympy might still rewrite a product that the inclusion test rejects, or the result depends on the order in which sympy applies the keys:
    • near-misses, such as powers (a**2*b**2, 1/(a*b)) or a different coefficient;
    • a repeated factor;
    • overlapping keys;
    • a replacement value that another key could match.

Note that this is completely cooked by Claude in its first iteration and will need substantial review and revision before it is ready for merge.

@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.36641% with 10 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.25%. Comparing base (0164e85) to head (1af8ee1).
⚠️ Report is 11 commits behind head on main.

Files with missing lines Patch % Lines
devito/symbolics/manipulation.py 88.63% 5 Missing and 5 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3059      +/-   ##
==========================================
- Coverage   84.26%   84.25%   -0.01%     
==========================================
  Files         258      258              
  Lines       56982    57189     +207     
  Branches     4854     4893      +39     
==========================================
+ Hits        48016    48187     +171     
- Misses       8139     8171      +32     
- Partials      827      831       +4     
Flag Coverage Δ
pytest-gpu-aomp-amdgpuX 68.38% <15.90%> (-0.19%) ⬇️
pytest-gpu-gcc- 79.04% <92.36%> (+<0.01%) ⬆️
pytest-gpu-icx- 78.95% <92.36%> (-0.03%) ⬇️
pytest-gpu-nvc-nvidiaX 68.96% <15.90%> (-0.17%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

This branch has not been deployed

No deployments
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.

1 participant