Skip to content

Reconcile the fork onto upstream v0.32.2 (two carried deltas) - #4

Merged
ttupper92618 merged 2 commits into
foxlight/v0.32.2-basefrom
foxlight/v0.32.2-reconcile
Oct 16, 2026
Merged

ttupper92618 merged 2 commits into
foxlight/v0.32.2-basefrom
foxlight/v0.32.2-reconcile

Conversation

@ttupper92618

Copy link
Copy Markdown

Reconciles the Foxlight fork onto upstream v0.32.2. The base branch foxlight/v0.32.2-base is the tag itself. It carries the fork's two remaining deltas; neither has an upstream equivalent in v0.32.2. The CVE-2026-5843 gate that the fork once carried is upstream now.

  1. BatchKVCache lazy-graph leak. update_and_fetch advances offset as an mx.array and never forces it to evaluate. On decode steps that build no mask nothing consumes it, so its graph grows one node per token. This is re-carried from 11648d2. Upstream Make "state" of cache return full state ml-explore/mlx-lm#1778 moved the return to keys_and_values(), so the mx.depends line now sits just before it. Upstream attempts (Guard batch cache metadata against lazy-graph accumulation ml-explore/mlx-lm#1731, Periodically evaluate cache state during decode (#1662) ml-explore/mlx-lm#1780, Bound ArraysCache metadata evaluation during batched decoding ml-explore/mlx-lm#1872) were closed unmerged.
  2. DeepSeek-V3.2 indexer, batch > 1. With left padding, take_along_axis(mask, topk_indices) mis-selects mask entries. The fix rebuilds the mask from the gathered indices against each row's padding. Re-carried unchanged from 587b88a. The code path runs only for L == 1 decode, so dropping the mask when no row is padded is safe, because a single query's causal mask is all-true. Upstream Fix deepseek_v32 Indexer evicting attention sinks from sparse top-k ml-explore/mlx-lm#1552 is still open.

Evidence (Apple Silicon test node, mlx 0.32.4)

The leak reproduces on the published mlx-lm==0.32.2 and is gone with this branch. The measurement is a decode-only BatchKVCache loop that evaluates each step's keys and values and nothing else:

Decode steps v0.32.2: RSS growth / time to evaluate offset this branch
5,000 15.1 MB / 9.2 ms 2.9 MB / 0.0 ms
20,000 54.7 MB / 37.8 ms 3.4 MB / 0.0 ms

Tests on this branch: tests/test_prompt_cache.py, test_models.py, test_gated_delta.py and test_generate.py give 185 passed, 1 skipped, 102 subtests passed.

Follow-up outside this repo

Skulk's fork-wheel.yml must stamp 0.32.2.post1 through setuptools-scm, because upstream ml-explore#1916 generates _version.py. That change, the wheel publish and Skulk's coordinated MLX pin move land in Skulk.

ttupper92618 and others added 2 commits October 16, 2026 02:35
BatchKVCache.update_and_fetch advances `offset` as an mx.array
(`self.offset = self.offset + n`) and never forces it to evaluate. On
decode steps that build no mask nothing else consumes it, so its lazy
graph grows by one node per token for the life of the cache (a memory
leak on long runs). Tying `offset` and `left_padding` into `keys` with
mx.depends evaluates them with every step.

Re-carried from 11648d2 onto v0.32.2. The surrounding code moved: the
method now returns through `keys_and_values()` (upstream ml-explore#1778), so the
mx.depends line sits just before that return. v0.32.2 still has no
equivalent; upstream's attempts at this fix (ml-explore#1731, ml-explore#1780, ml-explore#1872) were
closed unmerged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With left padding (batch > 1), `mx.take_along_axis(mask, topk_indices)`
gathers the padded attention mask by the indexer's top-k positions and
mis-selects entries, so padded rows attend to the wrong keys. Rebuild the
mask from the gathered indices against each row's left padding instead,
and drop it when no row is padded.

Re-carried from 587b88a onto v0.32.2, where the surrounding code is
unchanged and the buggy take_along_axis line is still present; upstream
ml-explore#1552 proposing a fix remains open.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-16T07:41:08.310379Z 57c4b0e PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 57c4b0ef5c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread mlx_lm/models/deepseek_v32.py Resolved
@ttupper92618
ttupper92618 merged commit f2f4932 into foxlight/v0.32.2-base Oct 16, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant