Hi team, first — thanks a lot for mlx-swift. I've been building an in-process MLX inference app on top of it and it's been really solid.
I ran into a bug while working on continuous batching. When I decode a single token for a batch ([B, H, 1, D], scalar offset, B > 1), MLXNN.RoPE / MLXFast.RoPE only computes row 0 correctly — the other rows come out as garbage / NaN, looks like uninitialized memory. At B = 1 everything is fine, so I guess that's why it stayed hidden for so long.
After digging a bit I realized it's not a new problem — it's the same as ml-explore/mlx#3496 (Swift side) and ml-explore/mlx#3494 (Python side), and it was already fixed in mlx-core by ml-explore/mlx#3498 (76a977ca — the single-token Metal path was launching an N grid instead of B*N). That fix went into mlx-core 0.32.0.
The thing is, it hasn't reached mlx-swift yet: 0.31.6 (the latest) still pins Source/Cmlx/mlx at v0.31.1 (ce45c52), which is before the fix. So anyone doing batched decode on mlx-swift still hits it today.
Small repro on 0.31.6 (Apple Silicon, Metal):
let rope = RoPE(dimensions: 8, base: 10000)
let r = MLXRandom.normal([1, 1, 8]).asType(.float16)
let x = concatenated([r.expandedDimensions(axis: 0),
r.expandedDimensions(axis: 0)], axis: 0) // [B=2,1,1,8], two identical rows
let y = rope(x, offset: 1)
// abs(y - y[0]).max() -> NaN / nonzero, expected 0.0
// Works with an array offset MLXArray([1, 1]), or on mlx-core >= 0.32.0
Would it be possible to bump Source/Cmlx/mlx to a commit that includes ml-explore/mlx#3498 (mlx-core >= 0.32.0), or cherry-pick those few lines onto the current pin? If it helps I'm happy to open the PR myself.
Thanks again for all the work on this.
Hi team, first — thanks a lot for mlx-swift. I've been building an in-process MLX inference app on top of it and it's been really solid.
I ran into a bug while working on continuous batching. When I decode a single token for a batch (
[B, H, 1, D], scalar offset,B > 1),MLXNN.RoPE/MLXFast.RoPEonly computes row 0 correctly — the other rows come out as garbage / NaN, looks like uninitialized memory. AtB = 1everything is fine, so I guess that's why it stayed hidden for so long.After digging a bit I realized it's not a new problem — it's the same as ml-explore/mlx#3496 (Swift side) and ml-explore/mlx#3494 (Python side), and it was already fixed in mlx-core by ml-explore/mlx#3498 (
76a977ca— the single-token Metal path was launching anNgrid instead ofB*N). That fix went into mlx-core 0.32.0.The thing is, it hasn't reached mlx-swift yet: 0.31.6 (the latest) still pins
Source/Cmlx/mlxat v0.31.1 (ce45c52), which is before the fix. So anyone doing batched decode on mlx-swift still hits it today.Small repro on 0.31.6 (Apple Silicon, Metal):
Would it be possible to bump
Source/Cmlx/mlxto a commit that includes ml-explore/mlx#3498 (mlx-core >= 0.32.0), or cherry-pick those few lines onto the current pin? If it helps I'm happy to open the PR myself.Thanks again for all the work on this.