Skip to content

Fp16 constant weights - #3015

Open
mloubout wants to merge 7 commits into
mainfrom
fp16-constant-weights
Open

Fp16 constant weights#3015
mloubout wants to merge 7 commits into
mainfrom
fp16-constant-weights

Conversation

@mloubout

@mloubout mloubout commented Sep 2, 2026

Copy link
Copy Markdown
Contributor

On top of #3012

TODO:

Add a knob for fp16 weights

@mloubout mloubout added the API api (symbolics, types, ...) label Sep 2, 2026
@codecov

codecov Bot commented Sep 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 73.68421% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 83.19%. Comparing base (b330c14) to head (9759188).

Files with missing lines Patch % Lines
devito/operator/operator.py 0.00% 2 Missing and 1 partial ⚠️
devito/ir/cgen/printer.py 60.00% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #3015      +/-   ##
==========================================
- Coverage   83.26%   83.19%   -0.08%     
==========================================
  Files         257      257              
  Lines       54822    54836      +14     
  Branches     4693     4695       +2     
==========================================
- Hits        45649    45620      -29     
- Misses       8352     8386      +34     
- Partials      821      830       +9     
Flag Coverage Δ
pytest-gpu-aomp-amdgpuX 68.63% <52.63%> (?)
pytest-gpu-gcc- 78.32% <73.68%> (-0.02%) ⬇️
pytest-gpu-icx- 78.27% <73.68%> (+<0.01%) ⬆️
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.

The Weights of a non-expanded derivative were always built at the default
precision, so a `float16` stencil got `float` coefficients. Every
wavefield*weight product then bound to the mixed-precision operators and
was promoted, defeating the point of the half-precision wavefield.
`_gen_value` printed the initializer with the printer's default dtype
rather than the Array's, which stamped a `float` suffix onto the entries
of a `double` Array and silently rounded them to single precision.

Route it through a new `initvalue` printer hook, which also gives the
targets a place to specialize an initializer whose type cannot be built
from a plain literal.
`_prec` floors an untyped real literal at `float32` so that an integer
default doesn't degrade the arithmetic around it. That floor also caught
`float16`, which is never a fallback but an explicit request, so every
literal in a half-precision Operator printed one type too wide.

Only apply the floor when the default is not already a real type.
The stability check sums the whole field and asks whether the result is
finite. The accumulator took the field's own dtype, so in half precision
it overflowed within a few thousand points and reported an instability
that wasn't there -- making `errctl=max`, the very option one reaches for
to diagnose a suspected instability, unusable exactly where it is needed.

Give it at least single precision.
A real literal in an otherwise integer expression is emitted at the
Operator's precision, floored at `float32` so that an integer default
does not degrade it. An Operator working in half wants that floor most
of the time -- half is a storage format, and the accuracy of the
literals is worth more than the width of the multiply -- but not always.

Give the printer a flag for it, off by default, and have `_printer`
pick up a Target's second printer where one is offered.
The same coefficients at two precisions are two different arrays, but
neither `__eq__` nor `_hashable_content` looked at the dtype, so the
first one built answered for both. An Operator asking for its weights in
one precision would be handed whichever an earlier Operator had cached.

Compare and hash on it. The name goes in rather than the type itself,
which does not order and so cannot be sorted alongside the rest.
Whether an Operator working in half also computes in half decides what
is calculated, not how quickly: the literals and the FD coefficients are
rounded to three decimal digits. That is a mathematical choice, so it
belongs with `interp-mode` in `sym_opt` rather than among the codegen
options, and is validated and defaulted alongside it.
@mloubout
mloubout force-pushed the fp16-constant-weights branch from 75d6b31 to 9759188 Compare September 3, 2026 12:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

API api (symbolics, types, ...)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant