Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect native NaN values, warn about them #911

Open
inducer opened this issue Feb 5, 2025 · 4 comments
Open

Detect native NaN values, warn about them #911

inducer opened this issue Feb 5, 2025 · 4 comments

Comments

@inducer
Copy link
Owner

inducer commented Feb 5, 2025

x-ref: inducer/pytools#287

This might be a good place, though the mapper obviously would need to be renamed.

cc @matthiasdiener

@matthiasdiener
Copy link
Collaborator

matthiasdiener commented Feb 5, 2025

Hmm, for the simple test in

loopy/test/test_target.py

Lines 390 to 399 in 698f295

def test_nan_support(ctx_factory, target):
from pymbolic.primitives import NaN, Variable
from loopy.symbolic import parse
ctx = ctx_factory()
queue = cl.CommandQueue(ctx)
knl = lp.make_kernel(
"{:}",
[lp.Assignment(parse("a"), np.nan),
, parse (and thus FunctionToPrimitiveMapper) does not seem to be called with a nan argument. Is there a better place to perform this replacement?

@inducer inducer changed the title Replace NaN values with pymbolic NaNs Detect native NaN values Feb 5, 2025
@inducer inducer changed the title Detect native NaN values Detect native NaN values, warn about them Feb 5, 2025
@inducer
Copy link
Owner Author

inducer commented Feb 5, 2025

On second thought, replacing "native" NaNs with pymbolic NaNs in one central location is probably not happening---there are too many possible "ways in", as you point out.

My next idea was to warn about them at code gen time, but it turns out that this is already being done:

elif np.isnan(expr):
from warnings import warn
warn("Encountered 'bare' floating point NaN value. Since NaN != NaN,"
" this leads to problems with cache retrieval."
" Consider using `pymbolic.primitives.NaN` instead of `math.nan`."
" The generated code will be equivalent with the added benefit"
" of sound pickling/unpickling of kernel objects.", stacklevel=1)
from pymbolic.primitives import NaN
data_type = expr.dtype.type if isinstance(expr, np.generic) else None
return self.map_nan(NaN(data_type), type_context)

The analogous check for Python is missing though:

def map_constant(self, expr, enclosing_prec):
if isinstance(expr, np.generic):
return repr(expr).replace("np.", "_lpy_np.")
else:
return repr(expr)

So that still needs to be added.

Did you see the warning above?

@matthiasdiener
Copy link
Collaborator

So that still needs to be added.

I can go ahead and this a warning there. Should this also do a pymbolic.primitives.NaN replacement, like in the C codegen?

Did you see the warning above?

I did see the warning in some tests; it could probably be improved though:

  • also mention np.nan in addition to math.nan
  • "sound pickling/unpickling of kernel objects" seems bit misleading - isn't pickling in fine general, just the cache retrieval is an issue?

@inducer
Copy link
Owner Author

inducer commented Feb 5, 2025

Should this also do a pymbolic.primitives.NaN replacement, like in the C codegen?

Maybe just warn? I'm not sure Python code gen has really been tested for NaNs. If you're willing to take on that test, then sure, it's probably easiest to do NaN codegen via replacement.

I agree with your warning improvements.

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

No branches or pull requests

2 participants