Repository navigation
Vendor mlx core v0.32.3 (with a floor_divide fix for unsigned integers) - #22
Conversation
Replace Source/Cmlx/mlx with upstream ml-explore/mlx v0.32.3 (64ea011) plus
the carried patches (SSD expert streaming, TurboKV, iOS I/O guards, quieter
Metal logging), merged with git rather than copied. Conflicts were limited to
mlx/io/load.{h,cpp}, where 0.32.3 reworked ParallelFileReader's thread pool;
the upstream design is kept and only the iOS guards are carried on top.
Regenerated Source/Cmlx/mlx-generated and the include dirs with
tools/update-mlx.sh (moe_stream.metal is carried by hand).
Build fixes for the new core: exclude the new CUDA sources from the Cmlx
target, and make mlx_gather_qmm pass nullopt for the new global_scale
argument (mlx #4458; mlx-c has not caught up). FP8Tests now expects NaN for
the E4M3FN bytes 0x7F and 0xFF, which 0.32.3 decodes correctly (mlx #4376).
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
mlx v0.32.3's gated delta NAX kernel does not compile with the macOS 27 SDK (get_destination_cooperative_tensor rejects decltype of the operand variables), which breaks the mlx.metallib build with -DMLX_ENABLE_NAX=1. Apply the same change as upstream mlx #4594, which landed after v0.32.3, to gated_delta_update_nax.h and regenerate mlx-generated. Drop this commit when the vendored core moves past #4594. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
mlx v0.32.3 (#4515) made integer floor_divide round toward negative infinity by adding remainder, less, not_equal, logical_and and subtract after the divide. For unsigned dtypes that correction is always zero. mlx-swift-lm's MoE expert sort calls order.floorDivide(topK) on uint32 indices in every layer; on this core a streamed-experts decode step died with a Metal GPU timeout (kIOGPUCommandBufferCallbackErrorTimeout) on every run, and decode was slower even when it survived. Found by bisecting 0.32.2..0.32.3: #4515 is the first bad commit, and the 0.32.2 core never fails the same request. Return the plain quotient for unsigned dtypes. Signed integers keep the upstream fix. FloorDivideTests covers both. Drop this when upstream makes the same change. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
mlx 0.32.3 sorted gatherMM / gatherQuantizedMM (sortedIndices: true) call the new ahead-of-time kernel gather_mm_offsets. SwiftPM builds default.metallib only from the files listed in KERNEL_LIST in tools/fix-metal-includes.sh, which did not include it, so the sorted path aborts with "Unable to load kernel gather_mm_offsets" in any consumer that has no mlx.metallib next to its binary. Add the kernel to KERNEL_LIST and regenerate mlx-generated/metal. SortedGatherTests covers the sorted and unsorted gatherMM (float16, bfloat16, float32) and gatherQuantizedMM paths. Inputs are small integers, so every sum is exact and the Metal results are compared with arrayEqual against a CPU reference; there is no tolerance to tune. Without the kernel the tests abort with the error above. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The Xcode project lists the files the Cmlx target must not compile
(kernel sources, CUDA, tests, python and benchmarks). The 0.32.3 sync
added files that are not on that list, so `xcodebuild -scheme MLX`
failed:
- mlx/backend/metal/kernels/{cross_entropy,gated_delta_update,
gated_delta_update_nax}.{h,metal} and gather_mm_offsets.metal
(the generated copies in mlx-generated/metal are the ones built)
- mlx/backend/cuda/{cholesky.cu,cusolver_utils.*,wddm.*} and
tests/cuda_tests.cpp (need CUDA headers / doctest)
- the new python tests and benchmarks
Also exclude the fork's mlx/backend/metal/kernels/moe_stream.metal.
Its generated copy is already built, so linking default.metallib failed
with a duplicated symbol 'streamed_moe_gemm'.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
pull_request.yml only runs its build/test jobs on ml-explore/mlx-swift (self-hosted runner), and the integration workflows copy a full mlx.metallib from the Python wheel. Neither exercises the Metal kernels that SwiftPM itself bundles into default.metallib, so a kernel missing from KERNEL_LIST in tools/fix-metal-includes.sh only fails at run time. Likewise nothing builds xcode/MLX.xcodeproj, whose exclusion list needs an update for every new file in Source/Cmlx/mlx. - mlx-tests: build MLXTests with Xcode and run them with no mlx.metallib on disk (a guard step fails if one shows up), so the tests load the metallib SwiftPM built from Source/Cmlx. - xcodeproj-build: xcodebuild build-for-testing -scheme MLX. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
|
Thanks for taking on the 0.32.3 sync, @CodeAndCanvas728 — the vendored tree matches upstream v0.32.3 apart from the expected fork patches, and the full local test run is clean. While testing I found two things our fork CI can't see (it copies
I also added a small CI workflow that runs MLXTests with no These are three regular commits on top of yours ( |
Takes the mlx core from v0.32.2 to v0.32.3 (the follow-up proposed in SharpAI/SwiftLM#204). The core PRs it brings in include #4505 and #4487 (lower SDPA memory), #4567 and #4572 (gather_mm / gather_qmm), #4458/#4483 (global scale in qmm), and #4020 (
fastgated delta kernels).What is in it
Source/Cmlx/mlxis upstreamv0.32.3plus the carried patches (SSD streaming, TurboKV, iOS I/O guards, quieter Metal logging), merged with git rather than copied. The only conflicts were inmlx/io/load.{h,cpp}, where 0.32.3 reworkedParallelFileReader's thread pool (#4408). The upstream design is kept and only the iOS guards are carried on top.mlx-generatedand the include dirs are regenerated withtools/update-mlx.sh. mlx-c stays atebc88f1(itsmainis a version bump on top).Package.swift.mlx_gather_qmmpassesnulloptfor the core's newglobal_scaleargument (mlx #4458). The C API does not expose it yet.FP8Testsnow expects NaN for the E4M3FN bytes0x7F/0xFF, which 0.32.3 decodes correctly (#4376).mlx.metallibbuild with-DMLX_ENABLE_NAX=1. Drop it when the core moves past #4594.floor_dividecorrection for unsigned integers. See below.The floor_divide finding
With plain 0.32.3, a request through
SwiftLM --stream-expertsdied with a Metal GPU timeout (kIOGPUCommandBufferCallbackErrorTimeout) on its first decode step, every time, on a 35B-A3B MoE. 0.32.2 never failed the same request.Bisecting 0.32.2..0.32.3 gives #4515 "Fix floor_divide for integers" as the first bad commit (the commit right before it is good). It makes integer
floor_dividecorrect for negative operands by addingremainder,less,not_equal,logical_andandsubtractafter the divide. mlx-swift-lm's MoE expert sort callsorder.floorDivide(topK)on uint32 sort indices in every layer, so every layer now builds seven ops where it built one. For unsigned dtypes the correction is always zero, so the fork returns the plain quotient there. Signed integers keep upstream's behaviour.FloorDivideTestscovers both.I have not found why the extra ops lead to a timeout rather than just being slower, and standalone
floor_divideis correct and equally fast on both cores. Reverting #4515 alone also makes the crash go away. I can write this up for ml-explore/mlx if useful.Measurements
16 GB M2 Air, Qwen3.5-35B-A3B 4-bit (mixed 4/5/8-bit affine),
SwiftLM --stream-experts, SwiftLM'sprofile_runner.pyrestricted to the Baseline and TurboQuant KV configs (the MTP configs do not apply to this model). Two alternating runs each, 0.32.2 vs this PR:The 0.32.3 wins that target newer chips (#4505's lower SDPA peak, #4567/#4572 gather_mm) do not show on an M2 with this model: it is parity, not a speedup. Without the floor_divide patch the same build crashed on a code prompt and decoded about 20% slower on the profile prompt. A per-op microbenchmark (quantized matmul at 4/5/8 bit, gather_qmm, SDPA at D=256, router top-k) showed no difference in speed or accuracy between the two cores. On a model that fits in RAM (no
--stream-experts) decode was identical (about 50 tok/s on both).Tests
xcodebuild test -scheme mlx-swift-Package: 394 tests, 0 failures (2 skipped).swift test --filter SwiftLMTestsagainst this branch: 276 tests, 0 failures../build.sh(Xcode 27.0).Notes
ml-explore/mlx-swiftbumps its core to 0.32.3 or later, the next sync will conflict onSource/Cmlx/mlx.update_dependencies.ymlflow, not in this PR.🤖 Generated with Claude Code