Repository navigation
Upgrade MLX core 0.31.1 → 0.32.0 (M5 Neural-Accelerator nax fixes) + keep resource-count trim - #3
Merged
Merged
Conversation
Co-authored-by: mm65x <mm65x@users.noreply.github.com>
…lore#3088) Signed-off-by: Ihar Hrachyshka <ihar.hrachyshka@gmail.com>
Co-authored-by: Angelos Katharopoulos <a_katharopoulos@apple.com>
Co-authored-by: Robert Johansson <robert@Mac-Mini-KI.lan> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Angelos Katharopoulos <katharas@gmail.com> Co-authored-by: Angelos Katharopoulos <a_katharopoulos@apple.com>
Signed-off-by: Bvicii <yizhanhuang2002@gmail.com>
Co-authored-by: katlun-lgtm <264247399+katlun-lgtm@users.noreply.github.com> Co-authored-by: Cheng <git@zcbenz.com>
…ore#3633) Co-authored-by: Angelos Katharopoulos <a_katharopoulos@apple.com>
…pose (ml-explore#3729) Co-authored-by: katlun-lgtm <264247399+katlun-lgtm@users.noreply.github.com> Co-authored-by: Cheng <git@zcbenz.com>
…l-explore#3597) Co-authored-by: Cheng <git@zcbenz.com>
Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Angelos Katharopoulos <a_katharopoulos@apple.com>
Co-authored-by: Cheng <git@zcbenz.com>
Co-authored-by: Cheng <git@zcbenz.com>
The Metal allocator throws `[metal::malloc] Resource limit (N) exceeded` when num_resources_ (the live+cached Metal buffer COUNT) reaches resource_limit_ (the iogpu.rsrc_limit sysctl, default ~499000). Freed buffers are recycled into a size-keyed cache whose only trim is by BYTES (release_cached_buffers takes a bytes-to-free target, max_pool_size_ ~= physical RAM). Under churn with many distinct buffer shapes (varied prompt lengths, growing KV caches, multiple co-resident models) the cache fills with entries never reused at that exact size, so the COUNT climbs to the limit while byte usage stays modest and the byte trim never fires — the process crashes mid-inference on a machine with most of its RAM free. malloc() now also reclaims by count: when num_resources_ crosses a 90% high-water mark of resource_limit_, it clears the (pure-reuse) buffer cache so the count drops back to the live working set. Clearing the cache only costs re-allocation, never correctness, so the count limit becomes unreachable by any request mix or batching method while the existing byte limits keep total memory bounded. Adds get_num_resources()/get_resource_limit() to the public memory API (metal + no_gpu + cuda backends) so the count and its ceiling are observable from callers. Adds an MLX_RESOURCE_LIMIT env override that can only LOWER the ceiling (clamped to the OS limit, strictly validated) to exercise the trim deterministically and as an operator safety valve.
…top of 0.32.0 (this branch supersedes it)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Our M5 Max providers can only get the GPU Neural-Accelerator speedup (Apple's
_nax/ Metal Performance Primitives path; ~2.5–4× compute-bound prefill/TTFT) if the MLX C++ core actually contains the nax kernels and their fixes. Our submodule was pinned to MLX 0.31.1 (d5213411), which predates the nax MoE work — so on M5 the MoE expert matmul silently fell off the nax path and we captured ~0× of the win.This branch is upstream MLX 0.32.0 (
b410f6c) + our resource-count trim re-applied (aa480bd8), i.e. it brings in all the nax fixes while preserving the Darkbloom allocator patch our provider depends on.What this includes (was missing on 0.31.1)
gather_qmmNAXbkfix (bk 32 → 64): the gather-qmm NAX kernels are instantiated withBK=64only; the old value made the kernel-name lookup fail → MoE experts fell back off nax. This is the single most important fix for GPT-OSS / Gemma-4 (both MoE).steel_gemm_segmented_nax.*): was entirely absent on 0.31.1.CMAKE_OSX_DEPLOYMENT_TARGET ≥ 26.2(see build note below).What's preserved
The "Bound Metal buffer COUNT, not just bytes, in MetalAllocator" patch (orig
d5213411, re-applied asaa480bd8). Our provider relies on the public getters it adds —MLX.Memory.numResources/resourceLimitare read byEngineCore.swiftandCheckpointCapturePipeline.swiftto drive count-aware capacity + checkpoint-pressure decisions. Upstream 0.32.0 independently added thenum_resources_/resource_limit_members and aclear_cache()-path reclaim, so the merge keeps upstream's base count logic and adds our public getters + high-waterclear()inmalloc+MLX_RESOURCE_LIMIToverride with no duplicated members.git diff origin/main..HEADis exactly the trim (5 files, +105/−1) — nothing else diverges from upstream 0.32.0.Conflict resolutions
mlx/backend/metal/allocator.cpp— includes (kept<algorithm>/<cassert>/<cerrno>);mallocreclaim region (kept the autorelease pool + count-aware comment for the high-waterclear()we add).mlx/backend/no_gpu/allocator.cpp— kept upstream's realset_cache_limit(delegates tocommon_allocator) and added the trim'sget_num_resources/get_resource_limitstubs.ml-explore#3622 makes the nax kernels compile only when
MLX_METAL_VERSION ≥ 400 AND MACOS_SDK_VERSION ≥ 26.2 AND CMAKE_OSX_DEPLOYMENT_TARGET ≥ 26.2. So a nax-enabledmlx.metallibhas a minimum OS of macOS 26.2 and will not launch on older macOS. The M5 provider artifact must be built with the macOS 26.2 SDK + deployment target 26.2 (and avoid the Xcode 26.5 NAX-shader miscompile — use 26.4 / a validated toolchain). M4 / pre-26.2 providers keep building the standard (non-nax) artifact, unchanged.Verification
git grepfor conflict markers: none.mlx/version.h= 0.32.0;gather_qmm_naxbk = 64;steel_gemm_segmented_nax.metalpresent; getters present inmemory.h+allocator.h.is_nax_available()==true, nax kernels in metallib,gather_qmm_naxdispatches (tracked in DAR-351).Before / After
flowchart LR subgraph Before["Before — submodule @ 0.31.1 + trim"] A1[M5 request: prefill] --> B1[gather_qmm bk=32] B1 --> C1[NAX kernel-name lookup FAILS] C1 --> D1[fallback simdgroup_matrix path] D1 --> E1[~0x of nax speedup] end subgraph After["After — 0.32.0 + trim, built w/ 26.2 SDK"] A2[M5 request: prefill] --> B2[gather_qmm bk=64 + segmented nax] B2 --> C2[NAX matmul2d / cooperative tensors] C2 --> D2[Neural Accelerator] D2 --> E2[~2.5-4x prefill/TTFT] endPairs with the
mlx-swiftsubmodule-bump PR (pointsSource/Cmlx/mlxat this branch's tip) and DAR-351 (nax telemetry).