Skip to content

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

Open
mloubout wants to merge 1 commit into
mainfrom
cire-int-invariants
Open

compiler: compute sparse position/floor in fp64 to fix off-by-one cell shift#2992
mloubout wants to merge 1 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 87.82609% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 78.23%. Comparing base (e401545) to head (307d39c).

Files with missing lines Patch % Lines
tests/test_gpu_openacc.py 0.00% 9 Missing ⚠️
tests/test_mpi.py 0.00% 3 Missing ⚠️
devito/symbolics/inspection.py 77.77% 0 Missing and 2 partials ⚠️

❗ There is a different number of reports uploaded between BASE (e401545) and HEAD (307d39c). Click for more details.

HEAD has 23 uploads less than BASE
Flag BASE (e401545) HEAD (307d39c)
17 4
pytest-gpu-gcc- 6 1
pytest-gpu-icx- 3 0
pytest-gpu-aomp-amdgpuX 1 0
pytest-gpu-nvc-nvidiaX 1 0
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #2992      +/-   ##
==========================================
- Coverage   83.54%   78.23%   -5.31%     
==========================================
  Files         257      251       -6     
  Lines       53922    53432     -490     
  Branches     4613     4600      -13     
==========================================
- Hits        45047    41803    -3244     
- Misses       8076    10764    +2688     
- Partials      799      865      +66     
Flag Coverage Δ
pytest-gpu-aomp-amdgpuX ?
pytest-gpu-gcc- 43.21% <40.00%> (-34.97%) ⬇️
pytest-gpu-icx- ?
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?

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

subs[inner] = DOUBLE(v)

exprs = [uxreplace(e, subs) for e in exprs]
return exprs, aliases

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.

blank line


# 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 ?

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 from 038d26b to 307d39c Compare August 6, 2026 16:01
The linear interpolator computes `(c - o)/h` in the grid's dtype, which
for fp32 grids rounds coord/origin/spacing to fp32. That rounding can
push the position across an integer boundary, so `floor((c - o)/h)`
picks a different cell than the fp64-truth cell -- and CPU vs GPU can
disagree on the fractional part while agreeing on the integer position,
producing inconsistent injection weights.

Compute `pos = (c - o)/h` and `floor(pos)` in fp64 by casting the fp32
free symbols and by substituting the spacing symbols with their fp64
decimal value (recovered via the fp32 short-form round-trip).

A new CIRE subpass `CireInvariantsSparse` hoists `pos` and `floor(pos)`
out of the per-stencil-point inner loop into per-source preamble Arrays.
The floor tab is stored as int32 (half the memory of an fp64 tab, no
precision loss), and bare `floor(pos)` uses inside `pos - floor(pos)`
are rewritten to `DOUBLE(int_tab)` so both consumers share the tab.

The `sympy_dtype` inference is taught to recognize `Cast` (outermost
and inner) so the printer emits `floor` (fp64) instead of `floorf`
(fp32) when a `DOUBLE(...)` cast is present in the expression.
@mloubout
mloubout force-pushed the cire-int-invariants branch from 307d39c to f25a1eb Compare August 6, 2026 19:27
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