Skip to content

Fix missing stream in gather matmul indices cast - #4687

Merged
zcbenz merged 1 commit into
ml-explore:mainfrom
petrukha-ivan:fix-gather-indices-stream
Oct 14, 2026
Merged

zcbenz merged 1 commit into
ml-explore:mainfrom
petrukha-ivan:fix-gather-indices-stream

Conversation

@petrukha-ivan

Copy link
Copy Markdown

indices_or_default casts indices without forwarding the caller’s stream, so gather_mm, gather_qmm, and gather_qqmm on a non-default stream insert extra cross-stream fences per call and stall the caller’s stream. This PR passes the caller’s stream to the cast.

  • ☑️ I understand it is strictly prohibited to use AI to write PR description
  • AI usage disclosure: Claude Opus 5.5 to find the root cause of the slowdown

@zcbenz
zcbenz merged commit bebd642 into ml-explore:main Oct 14, 2026
30 checks passed
@BrewTestBot BrewTestBot mentioned this pull request Oct 15, 2026
3 tasks done
ronaldmannak pushed a commit to PicoMLX/mlx that referenced this pull request Oct 16, 2026
ronaldmannak added a commit to PicoMLX/mlx-swift that referenced this pull request Oct 16, 2026
The same class of bug as integer floor_divide: an MLX op built on the
calling thread's own default stream instead of the stream it was given.
Evaluating the result on any other thread stops the process with
"There is no Stream(gpu, N) in current thread".

PicoMLX/mlx pico/0.32.3 cherry-picks both upstream fixes from v0.32.4:

- ml-explore/mlx#4687: gather_mm and gather_qmm cast non-uint32
  indices to uint32 without the stream. MoE layers that route with
  int32 indices hit it.
- ml-explore/mlx#4663: layer_norm's CPU fallback multiplied without the
  stream, and SDPA's boolean-mask fallback (CUDA only, since Metal
  takes boolean masks directly) built its where without it.

StreamTests gains testGatherMMWithInt32IndicesEvaluatesOnAnotherThread
and testLayerNormOnTheCPUEvaluatesOnAnotherThread. Without #4687, the
gather test stops the process with that error. Without #4663, the CPU
layer_norm evaluation never returns: the test fails after 30 seconds,
and then the process stops with the same error. The floor_divide test
now shares their helper, which waits at most 30 seconds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants