Skip to content

fix: propagate NaN in arg reductions - #4291

Open
atirna wants to merge 13 commits into
ml-explore:mainfrom
atirna:fix/arg-reduce-nan
Open

fix: propagate NaN in arg reductions#4291
atirna wants to merge 13 commits into
ml-explore:mainfrom
atirna:fix/arg-reduce-nan

Conversation

@atirna

@atirna atirna commented Aug 16, 2026

Copy link
Copy Markdown

Proposed changes

Fixes #4274 by making argmin and argmax select the first NaN, matching MLX min/max propagation and NumPy/PyTorch behavior. The implementation covers CPU, Metal, and CUDA reduction paths, including pairwise GPU reductions where separate partials contain NaNs.

Checklist

  • I have read the CONTRIBUTING document
  • I have run pre-commit run --all-files to format my code / installed pre-commit prior to committing changes (passed on the formatting commit; see 03694f5)
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the necessary documentation (if needed)

Tests

  • cmake --build build-metal --target tests -j2
  • ./build-metal/tests/tests --test-case='test arg reduce NaN' (14 assertions)
  • ./build-metal/tests/tests --test-case='test arg reduce*' (190 assertions)

atirna added 2 commits August 16, 2026 10:26
Apply the repository clang-format (v21) to the CUDA arg-reduce changes so
pre-commit CI passes on the PR.
@zcbenz zcbenz added the await verification This pull request is non-trivial and requires a human expert to verify its correctness. label Aug 16, 2026
@erwinzhang7

Copy link
Copy Markdown
Contributor

Sorry about that, I checked for prs before setting up a fork CI and didn't check after. Just tested yours and it's solid. Good work!

@atirna

atirna commented Aug 16, 2026

Copy link
Copy Markdown
Author

hey @erwinzhang7 thank you! for taking time to check this pr. sorry it ended up being competing pr

@erwinzhang7 erwinzhang7 mentioned this pull request Aug 16, 2026
4 tasks
@zcbenz zcbenz added low priority and removed await verification This pull request is non-trivial and requires a human expert to verify its correctness. labels Aug 19, 2026

@zcbenz zcbenz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

std::isnan and cuda::std::isnan are guaranteed to simply return false for integers so there is no need to add a wrapper. For metal isnan is probably not overloaded for integers but I would prefer adding overloads ourselves than adding a confusing is_nan wrapper.

@zcbenz zcbenz added the await response This pull request is waiting for response from the author. label Aug 25, 2026
atirna added 3 commits August 26, 2026 20:13
std::isnan and cuda::std::isnan already return false for integers.
Metal gets integral isnan overloads instead of a named wrapper.
std::isnan(complex64_t) only sees real(), so argmin/argmax skipped an
imag NaN while min/max already propagate it via x != x.
@atirna

atirna commented Aug 26, 2026

Copy link
Copy Markdown
Author

dropped the is_nan wrappers. cpu uses x != x like max/min so complex imag nan counts, cuda is cuda::std::isnan, metal has integer isnan overloads.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

await response This pull request is waiting for response from the author. low priority

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] mx.argmax / mx.argmin skip NaN while mx.max / mx.min propagate it

3 participants