Skip to content

compiler: compute sparse position/floor in fp64 to fix off-by-one cell shift - #2992

Closed
mloubout wants to merge 0 commit into
mainfrom
cire-int-invariants
Closed

compiler: compute sparse position/floor in fp64 to fix off-by-one cell shift#2992
mloubout wants to merge 0 commit into
mainfrom
cire-int-invariants

Conversation

@mloubout

@mloubout mloubout commented Aug 5, 2026

Copy link
Copy Markdown
Contributor
  • Precompute indices ones when using coordinates (bit cheaper for lots of recs)
  • Upcast to double for indices compuation to avoid fp32 truncation errors shifting the result.

The lifiting is implemented as a Cire pass this way it'll catch generic floor/... as well

@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 29.72973% with 26 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.35%. Comparing base (110463b) to head (915bc6d).

Files with missing lines Patch % Lines
tests/test_interpolation.py 12.50% 14 Missing ⚠️
devito/symbolics/inspection.py 0.00% 3 Missing and 1 partial ⚠️
tests/test_dse.py 0.00% 4 Missing ⚠️
devito/ir/cgen/printer.py 50.00% 1 Missing and 1 partial ⚠️
devito/types/sparse.py 77.77% 2 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (110463b) and HEAD (915bc6d). Click for more details.

HEAD has 12 uploads less than BASE
Flag BASE (110463b) HEAD (915bc6d)
18 10
pytest-gpu-gcc- 6 4
pytest-gpu-icx- 3 2
pytest-gpu-nvc-nvidiaX 1 0
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #2992       +/-   ##
===========================================
- Coverage   83.54%   52.35%   -31.20%     
===========================================
  Files         257      257               
  Lines       53922    53952       +30     
  Branches     4613     4619        +6     
===========================================
- Hits        45050    28245    -16805     
- Misses       8074    24704    +16630     
- Partials      798     1003      +205     
Flag Coverage Δ
pytest-gpu-aomp-amdgpuX 68.54% <52.94%> (-0.02%) ⬇️
pytest-gpu-gcc- 43.27% <29.72%> (-34.91%) ⬇️
pytest-gpu-icx- 43.12% <29.72%> (-34.99%) ⬇️
pytest-gpu-nvc-nvidiaX ?

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.

@mloubout
mloubout force-pushed the cire-int-invariants branch from 24006cd to 04411cd Compare August 5, 2026 19:28
@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@mloubout
mloubout force-pushed the cire-int-invariants branch 4 times, most recently from 1ad6fd3 to 038d26b Compare August 6, 2026 02:46

@FabioLuporini FabioLuporini left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the main question that I have is: why not inlining DOUBLE(...) casts directly when building the interpolation operation? why is this implemented via hoisting into fp64 scalars?

Comment thread devito/passes/clusters/aliases.py Outdated
yield self._do_generate(exprs, exclude, cbk_search)


def _is_floor(e):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is quite hacky, let the search look for the specific type if it really needs to be that specific

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment thread devito/passes/clusters/aliases.py Outdated
Comment thread devito/passes/clusters/aliases.py Outdated

# Predicate on Cluster used to pick which ones this pass fires on.
# Subclasses override to target a different kind of cluster.
_cluster_filter = staticmethod(lambda c: c.is_dense)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why don't we always do it with all floors (and maybe not just that), be it dense or sparse ?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so why do we need this _cluster_filter at all?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Foir the standard pass that is for dense cluster
  • For easier extension/specialization in the future

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure agree. If you restrict it to dense clusters, for example, divisions won't be hoisted anymore in sparse clusters. And imho it doesn't make much sense that the base CireInvariants class restricts to dense; if anything, it should be selected subclasses

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't new only lifted. It always have filtered to dense but can change it if you want but it's gonna change probably a lot of tests

Comment thread devito/passes/clusters/aliases.py Outdated
issubclass(k.dtype, np.integer)):
continue
inner = k.base
if _is_floor(inner) and (v.free_symbols & aliaseds):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

instead of just floors, we could name this class CireInvariantGeometry or something like that, and have it target all step-wise math operations that are so accuracy-sensitive

you could have for example a _types class attribute, and use it here

@mloubout
mloubout force-pushed the cire-int-invariants branch 4 times, most recently from da61a3e to 173da0d Compare August 7, 2026 11:58
Comment thread devito/passes/clusters/aliases.py Outdated
out of an inner loop is a strict win regardless of the cluster kind.
"""

_cluster_filter = staticmethod(lambda c: True)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here... not sure we need it

@mloubout
mloubout force-pushed the cire-int-invariants branch 5 times, most recently from a8550da to dd910c8 Compare August 8, 2026 22:40
Comment thread devito/passes/clusters/aliases.py Outdated
else:
# E.g., `x0_blk0` or (`a[y_m+1]` => `y not in imapper`)
# E.g., `x0_blk0` (outer to writeto, must stay in ispace
# so later passes -- `Lift`, `Fuse` -- see it)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not that "so later passes see it", it's that w/o it, it'd be wrong

Comment thread devito/passes/clusters/aliases.py Outdated

# Predicate on Cluster used to pick which ones this pass fires on.
# Subclasses override to target a different kind of cluster.
_cluster_filter = staticmethod(lambda c: c.is_dense)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure agree. If you restrict it to dense clusters, for example, divisions won't be hoisted anymore in sparse clusters. And imho it doesn't make much sense that the base CireInvariants class restricts to dense; if anything, it should be selected subclasses

Comment thread devito/core/operator.py Outdated
"""

PAR_CHUNK_NONAFFINE = 3
PAR_CHUNK_NONAFFINE = 1

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why, this is an important change

Comment thread tests/test_dse.py Outdated
assert summary1[('section0', None)].ops == 9
assert summary1[('section1', None)].ops == 9
assert summary1[('section2', None)].ops == 31
assert summary1[('section3', None)].ops == 46

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a lot of code changes...

@mloubout
mloubout force-pushed the cire-int-invariants branch from 0e461ab to 74f833a Compare August 10, 2026 03:10
@mloubout mloubout closed this Aug 10, 2026
@mloubout
mloubout force-pushed the cire-int-invariants branch from 915bc6d to 110463b Compare August 10, 2026 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants