Skip to content

[BUG] mx.distributed.all_max / all_min silently drop NaN (inconsistent with mx.max/mx.min) #4072

Description

@JasonHonKL

Describe the bug

The distributed cross-rank reduce uses std::max / std::min
(mlx/distributed/reduction_ops.h:17-35), which are not NaN-propagating
(std::max(nan, x) returns x when nan is the first argument). So if
exactly one rank has a NaN at a position, all_max / all_min return
the other ranks' non-NaN value and the NaN vanishes — the failure is
silently swallowed.

To Reproduce

import mlx.core as mx
# 2-rank group
nan = float("nan")
x = mx.array([1.0, nan if rank == 0 else 2.0, 3.0])  # rank 0 has NaN at idx 1
m = mx.distributed.all_max(x)
mx.eval(m)   # -> array([1.0, 2.0, 3.0])   WRONG: should be [1.0, nan, 3.0]

Expected behavior

[rank 0] AMAX [1.0, 2.0, 3.0]
[rank 0] AMIN [1.0, 0.5, 3.0]
[rank 1] AMAX [1.0, 2.0, 3.0]
[rank 1] AMIN [1.0, 0.5, 3.0]
local mx.max([1,nan,3]) = nan (propagates NaN)
local mx.min([1,nan,3]) = nan (propagates NaN)

BUG REPRODUCED: all_max dropped the single-rank NaN (mx.max would propagate it).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions