Skip to content

Move mlx-core from v0.31.1 to v0.32.2 now that mlx-c binds new_thread_unsafe_stream #513

Description

@spokvulcan

The app builds its Metal kernels from a fork of mlx-core pinned at v0.31.1 (July 2026). Upstream is at v0.32.2. The move was attempted on 2026-07-27 and parked: mlx 0.31.2 made a stream's GPU command encoder thread-local, and our Swift-concurrency runtime evaluates arrays from whatever thread a task resumes on, so every test that hopped threads died with There is no Stream(gpu, 0) in current thread. The proper fix, new_thread_unsafe_stream, was not reachable from Swift because mlx-c had no binding for it. docs/mlx-core-fork.md has the full account and the re-attempt checklist.

What changed: the binding landed. ml-explore/mlx-c#122 (merged 2026-08-27) exposes it as mlx_stream_new_thread_unsafe, and upstream mlx-swift main already carries the regenerated header. mlx-swift does not yet create its default streams through it, so step 1 of the checklist is now "adopt the binding in mlx-swift" rather than "wait for mlx-c".

What the move involves (from the parked branch pin-tesseract-2026-07-27 in both forks, which built green against mlx main at the time):

  1. Rebase the parked branch onto mlx v0.32.2 / current mlx-swift main in spokvulcan/mlx and spokvulcan/mlx-swift; re-run tools/update-mlx.sh and check the hand-maintained JIT kernel list for kernels added since (a missing one is a link error, not a build error).
  2. Make mlx-swift's default streams thread-unsafe streams via the new binding, shaped as an upstream mlx-swift PR.
  3. Re-port the carries that do not rebase: C4, C5, C7 (they patch the command-buffer struct upstream merged into CommandEncoder) and re-check C6 against the regex removal in mlx#3869. Re-measure each per the experiments ledger's A/B protocol before re-accepting. The DFlash2 loop's kernel carries (qmv_wide backport, mma8 QMM tiles, SDPA variants, dynamicSlice, fast-math custom kernels, profiler probes) rebase onto the new base and need the fixture identity check (scripts/dflash2-bench.sh --bench-check on travel/code/math).
  4. Keep the two GPU.setCommitLimits call sites in LLMActor working: their Swift surface rides C4+C7, so they go dark on the new base until those are re-ported.
  5. Move the three lockstep Package.swift pins and update docs/mlx-core-fork.md.

Why now: the 2026-09-15 vendor re-pin (mlx-swift-lm to upstream main, swift-transformers to 1.3.4, swift-jinja to 2.5.1) left mlx-core as the only fork level still on a July base, and the qmv_wide backport it carries is already upstream in v0.32.0, so the carry list shrinks on the move.

Not in scope of the re-pin PR: this is a multi-day port with re-measurement, tracked here separately.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    needs-triageMaintainer needs to evaluate this issue

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions