Skip to content

feat(xla): add sparse DeepStack prefill - #893

Merged
inureyes merged 6 commits into
mainfrom
feature/issue-867-deepstack-prefill
Jul 24, 2026
Merged

inureyes merged 6 commits into
mainfrom
feature/issue-867-deepstack-prefill

Conversation

@inureyes

@inureyes inureyes commented Jul 23, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Add the distinct optional prefill_embeddings_deepstack.main entry with compact [Nv], [K, Nv, hidden], and [K] side tensors and post-language-layer sparse residual injection.
  • Validate config pairing, descriptors, byte counts, expanded-sequence positions, target layers, finite features, and static bounds in Rust and again in the C ABI.
  • Wire optional VMFB compilation/loading, artifact identity, single-session and ragged batch execution, and request-owned cancellation/error cleanup without changing decode state.
  • Preserve token prefill, ordinary embeddings prefill, and decode IR byte-for-byte when DeepStack is declared.
  • Add a diagnostic-only graph that reuses the production shared layer loop and exposes every post-hook hidden state for the fixed MLX Qwen3-VL oracle; it is never loaded into serving sessions.

Validation

  • cargo fmt --all -- --check
  • cargo test -p mlxcel-xla --lib (193 passed, 6 opt-in ignored, 0 failed)
  • cargo test -p mlxcel-xla --lib deepstack (9 passed)
  • cargo clippy -p mlxcel-xla --lib --tests -- -D warnings
  • IREE_CUDA_HOME=... IREE_CUDA_COMPILE=... cargo clippy -p mlxcel-xla --lib --features iree -- -D warnings
  • CARGO_TARGET_DIR=... python3 spike/openxla/deepstack_prefill_check.py compiled and ran both production and diagnostic Qwen3-shaped VMFBs on IREE local-task. The fixture ports Qwen3VLModel::deepstack_process semantics and exactly checks the full first/middle/last [3, 256, 4] post-hook residual tensor against visual-row values 11/21/31, final logits, and every K/V element for both graphs.

Closes #867

@inureyes inureyes added status:review Under review type:enhancement New features, capabilities, or significant additions priority:medium Medium priority area:architecture Architecture and code structure changes area:core mlxcel-core: MLX FFI, primitives, KV cache, layers area:inference Generation, sampling, decoding (incl. speculative, DRY) labels Jul 23, 2026
@inureyes

Copy link
Copy Markdown
Member Author

Addressed the acceptance-coverage gap in 0adb6ab:

  • Added a diagnostic-only DeepStack prefill graph that reuses the production shared transformer loop and captures every first/middle/last post-hook residual state.
  • Ported the fixed MLX Qwen3VLModel::deepstack_process fixture: visual positions 1..=3, unit hidden states, feature value 10, and exact post-hook visual rows 11/21/31.
  • Ran both production and diagnostic VMFBs under IREE local-task. The oracle now compares the complete [3, 256, 4] post-hook tensor, final logits, and every K/V element; no output is ignored.
  • Revalidated 193 passing library tests, 9 focused DeepStack tests, fmt, and default/IREE Clippy with warnings denied.

No CSV files were added or changed.

@inureyes

Copy link
Copy Markdown
Member Author

Addressed the selected-capacity validation ordering gap in 12bf0b6:

  • JSON parsing now validates only intrinsic DeepStack schema properties (positive maximum, sorted/unique/in-range target layers).
  • with_context_capacity and emission validate the visual maximum against the caller-selected static capacity.
  • Regression coverage proves context capacity 512 with visual maximum 300 is accepted, while selected capacity 256 with maximum 300 is rejected.

Validation:

  • cargo test -p mlxcel-xla --lib deepstack -- --nocapture: 9 passed
  • cargo test -p mlxcel-xla --lib: 193 passed, 6 ignored
  • default Clippy with -D warnings: passed
  • diagnostics/IREE-feature Clippy with -D warnings: passed
  • real IREE local-task production and diagnostic entries: both matched all expected outputs
  • git diff --check: clean
  • CSV changes: none

@inureyes
inureyes force-pushed the feature/issue-867-deepstack-prefill branch from 12bf0b6 to 09f1aba Compare July 23, 2026 22:09
@inureyes

Copy link
Copy Markdown
Member Author

Rebased PR #893 onto origin/main@e739ca1 (merged PR #894) and preserved both contracts:

  • M-RoPE keeps its explicit 1D/3D position mode, signed per-request rope_delta, fail-closed config validation, and ragged slot lifecycle.
  • DeepStack keeps its distinct optional VMFB, compact owned payload, post-layer hook, Rust/C validation, single/ragged execution, diagnostic graph, and prefill-only ownership.
  • Rebase integration commit 09f1aba forwards the embedded M-RoPE delta for DeepStackPrepared batch requests and exercises that combination through cancellation and slot reuse.
  • Both internal runtime config variants are boxed after the combined schemas crossed Clippy's large-enum threshold; this is load-time indirection only and does not change emitted or native contracts.

Validation:

  • focused DeepStack suite: 9 passed
  • focused M-RoPE suite: 8 passed
  • mixed text/M-RoPE/DeepStack ragged slot lifecycle: 1 passed
  • full mlxcel-xla library suite: 203 passed, 6 ignored
  • default Clippy with -D warnings: passed
  • IREE-feature Clippy with the pinned CUDA IREE source/build tree and -D warnings: passed
  • real IREE local-task DeepStack production and diagnostic VMFBs: both matched all expected outputs, including the full Qwen3-VL post-hook state tensor, final logits, and every K/V element
  • cargo fmt --all -- --check and git diff --check: passed
  • CSV changes: none

Issue #867's six acceptance criteria were checked against this evidence. The branch was updated with --force-with-lease; no merge was performed.

inureyes added 4 commits July 24, 2026 08:13
Add a distinct embeddings-prefill entry that injects compact per-layer multimodal residuals immediately after configured language layers.

Validate payload shape, positions, target layers, and static bounds in Rust and the C ABI. Wire optional compilation, single and ragged execution, cancellation ownership, and a real IREE local-task fixture.

Refs #867
Expose post-hook residuals from a diagnostic-only graph that reuses the production prefill layer loop.

Port the fixed MLX Qwen3-VL DeepStack fixture and compare every first, middle, and last residual row, final logits, and all K/V elements in real IREE local-task execution.

Refs #867
Separate context-independent DeepStack schema checks from the static visual-bound check so parsing does not assume the historical 256-token default.

Apply the bound only after RuntimeConfig selects the actual context capacity, with 512/300 acceptance and selected-capacity rejection coverage.

Refs #867
Rebasing DeepStack prefill over the multimodal RoPE runtime exposed that its prepared batch variant was not carrying the signed decode delta into a slot, which would make later ragged decode coordinates diverge from the prepared prompt.

Forward the embedded prepared-position delta for DeepStack requests and exercise that variant in the mixed text/M-RoPE cancellation and slot-reuse regression. Box both internal runtime config variants so their combined M-RoPE and DeepStack schemas keep the IREE feature build within Clippy's enum-size contract.

Validation: focused DeepStack and M-RoPE suites, full mlxcel-xla library suite, default and IREE-feature Clippy, and the production/diagnostic DeepStack local-task oracle.

Refs #867
@inureyes
inureyes force-pushed the feature/issue-867-deepstack-prefill branch from 09f1aba to 14a039f Compare July 23, 2026 23:21
@inureyes

Copy link
Copy Markdown
Member Author

Rebased the DeepStack branch onto origin/main at 09641945 after #895 merged, then force-pushed the rewritten commits with --force-with-lease.

Integration review:

  • The rebase completed without textual conflicts. The only files touched by both lines of work were emitter/config.rs and iree.rs.
  • feat(xla): admit image requests in CLI and continuous-batch serving #895's LLaVA wrapper handling remains intact: root config.json selects nested text_config, including the wrapper-level quantization fallback.
  • feat(xla): admit image requests in CLI and continuous-batch serving #895's canonical / language_model.* dense checkpoint namespace resolution remains intact alongside the optional DeepStack artifact/runtime path.
  • This PR's final diff does not touch the root MediaRequestMetadata, image preprocessing, XLA serve worker/admission, backend, loading, or CLI files.
  • M-RoPE rope_delta remains preserved for DeepStack-prepared batch inputs.

Validation after the rebase:

  • cargo fmt --all -- --check — passed
  • DeepStack-focused mlxcel-xla tests — 9 passed
  • M-RoPE-focused mlxcel-xla tests — 8 passed
  • mixed text/M-RoPE slot cancellation and reuse test — 1 passed
  • full cargo test -p mlxcel-xla --lib — 204 passed, 6 ignored
  • default mlxcel-xla Clippy with -D warnings — passed
  • IREE-feature mlxcel-xla Clippy with -D warnings — passed
  • real-IREE DeepStack production/diagnostic oracle — passed; both EXEC @main runs matched expected outputs, including fixed Qwen3-VL post-hook states, logits, and every K/V value
  • root xla-iree worker/admission tests — 6 passed
  • root xla-iree image preprocessing tests — 7 passed
  • root XLA backend image-capability test — 1 passed
  • root XLA CLI partial-image and output-audio rejection tests — 2 passed
  • git diff --check — passed
  • tracked/untracked CSV check — no CSV files in the PR diff or worktree

The branch head is now 14a039fbb1e74e96353fb0d3fc111f82ef782fc6.

Prepare DeepStack requests against the loaded runtime position mode and carry that explicit contract through the Rust/C ABI so M-RoPE [3,S] payloads are validated and uploaded without collapsing to 1D. Commit signed decode deltas only after native prefill succeeds and reject incompatible single or ragged requests before scheduler mutation.

Replace the internal scheduler mutation regression with public single and batch real-IREE fixtures covering negative and positive deltas, first-decode parity, failure-state retention, cancellation, slot reuse, and wrong-mode rejection. Extend the fixed Qwen3-VL production/diagnostic oracle to run both 1D and M-RoPE positions with exact hooks, logits, and K/V.

Refs #867
@inureyes

Copy link
Copy Markdown
Member Author

Implemented the final HIGH-severity DeepStack/M-RoPE corrections in da7706f.

Key changes:

  • DeepStack single and batch preparation now uses the loaded runtime position mode, preserving public PreparedPositions::Mrope3D buffers and signed rope deltas.
  • The DeepStack C ABI now carries an explicit position mode, rejects mode disagreement, and validates 1D [S] versus M-RoPE [3,S] descriptors including exact byte lengths.
  • Sequential state commits the signed rope delta only after native prefill succeeds.
  • Internal scheduler mutation coverage was replaced with public single/batch fixtures covering negative and positive deltas, first-decode parity, failure-state retention, cancellation, slot reuse, pending admission, and wrong-mode rejection.
  • The fixed Qwen3-VL IREE oracle now executes both 1D and M-RoPE production and diagnostic entries and checks post-hook states, logits, and every K/V value.

Validation:

  • DeepStack focused tests: 11 passed
  • M-RoPE focused tests: 8 passed
  • Full mlxcel-xla tests: 205 passed, 6 ignored
  • Root real-IREE prepared-prefill integration: 2 passed
  • Fixed real-IREE oracle: 4 exact runs passed (1D production/diagnostic and M-RoPE production/diagnostic)
  • Root feat(xla): admit image requests in CLI and continuous-batch serving #895 admission regressions: worker 6 passed; preprocess 7 passed; capability 1 passed; CLI partial-image 1 passed; CLI audio 1 passed
  • Root xla-iree C compilation/no-run: passed
  • Default cargo clippy --fix --allow-dirty --allow-staged -p mlxcel-xla --lib --tests -- -D warnings: passed with no rewrite
  • IREE library/tests Clippy and root integration-test Clippy: passed
  • cargo fmt --all -- --check, git diff --check, and Python syntax validation: passed
  • CSV audit: no changed or untracked CSV files

The PR remains open and unmerged for CI/review.

Route sequential prefill completion and M-RoPE coordinate calculation through one private transactional state so a failed native prefill cannot replace the last successful signed delta. Exercise that state from public DeepStack requests and assert the exact first decode coordinate before and after a failed replacement.

Share the production DeepStack admission conversion with scheduler tests, then carry public negative, positive, and zero deltas through pending ownership and slot admission. Assert row-specific coordinates and verify cancellation plus same-slot text reuse restores a zero delta without mutating internal prepared positions.

Refs #867
@inureyes

Copy link
Copy Markdown
Member Author

Closed the final mutation-sensitivity evidence gap in 2ec2a10.

The production public API remains unchanged. Sequential prefill completion and decode-coordinate calculation now share a private transactional DecodePositionState: only an Ok native prefill result commits the next signed delta. The focused public-DTO regression proves a DeepStack request with sequence_len=4, delta=-2 commits first decode coordinate 2, then a failed replacement carrying delta=+5 leaves coordinate 2 unchanged.

Batch admission now shares one private conversion helper between the production submit_deepstack_prepared call site and the scheduler regression. Public DeepStackPreparedPrefill requests carrying -1, +2, and 0 are asserted while pending, after slot admission, and as exact first decode coordinates 3, 6, and 4. Cancelling the positive-delta row and admitting text into the same slot proves reuse restores coordinate 4 with delta zero. No test mutates PreparedIreePositions or scheduler deltas to manufacture the state under test.

Validation:

  • DeepStack focused: 13 passed
  • M-RoPE focused: 8 passed
  • Full mlxcel-xla: 207 passed, 6 ignored
  • Root real-IREE public prepared-prefill integration: 2 passed
  • Default Clippy fix mode: passed with no rewrite
  • IREE library/tests Clippy: passed
  • Root real-IREE integration-test Clippy: passed
  • cargo fmt --all -- --check and git diff --check: passed
  • Changed/untracked CSV audit: empty

PR #893 remains open and unmerged.

@inureyes
inureyes merged commit 2c3950f into main Jul 24, 2026
5 checks passed
@inureyes inureyes added status:done Completed and removed status:review Under review labels Jul 24, 2026
@inureyes
inureyes deleted the feature/issue-867-deepstack-prefill branch July 24, 2026 00:09
@inureyes inureyes self-assigned this Aug 31, 2026
be-free-snowboy pushed a commit to freestylejs/snowbrain-mlxcel that referenced this pull request Oct 27, 2026
* feat(xla): add sparse DeepStack prefill

Add a distinct embeddings-prefill entry that injects compact per-layer multimodal residuals immediately after configured language layers.

Validate payload shape, positions, target layers, and static bounds in Rust and the C ABI. Wire optional compilation, single and ragged execution, cancellation ownership, and a real IREE local-task fixture.

Refs lablup#867

* test(xla): verify DeepStack hooked states

Expose post-hook residuals from a diagnostic-only graph that reuses the production prefill layer loop.

Port the fixed MLX Qwen3-VL DeepStack fixture and compare every first, middle, and last residual row, final logits, and all K/V elements in real IREE local-task execution.

Refs lablup#867

* fix(xla): validate DeepStack against selected capacity

Separate context-independent DeepStack schema checks from the static visual-bound check so parsing does not assume the historical 256-token default.

Apply the bound only after RuntimeConfig selects the actual context capacity, with 512/300 acceptance and selected-capacity rejection coverage.

Refs lablup#867

* fix(xla): preserve M-RoPE state in DeepStack batches

Rebasing DeepStack prefill over the multimodal RoPE runtime exposed that its prepared batch variant was not carrying the signed decode delta into a slot, which would make later ragged decode coordinates diverge from the prepared prompt.

Forward the embedded prepared-position delta for DeepStack requests and exercise that variant in the mixed text/M-RoPE cancellation and slot-reuse regression. Box both internal runtime config variants so their combined M-RoPE and DeepStack schemas keep the IREE feature build within Clippy's enum-size contract.

Validation: focused DeepStack and M-RoPE suites, full mlxcel-xla library suite, default and IREE-feature Clippy, and the production/diagnostic DeepStack local-task oracle.

Refs lablup#867

* fix(xla): preserve DeepStack M-RoPE positions

Prepare DeepStack requests against the loaded runtime position mode and carry that explicit contract through the Rust/C ABI so M-RoPE [3,S] payloads are validated and uploaded without collapsing to 1D. Commit signed decode deltas only after native prefill succeeds and reject incompatible single or ragged requests before scheduler mutation.

Replace the internal scheduler mutation regression with public single and batch real-IREE fixtures covering negative and positive deltas, first-decode parity, failure-state retention, cancellation, slot reuse, and wrong-mode rejection. Extend the fixed Qwen3-VL production/diagnostic oracle to run both 1D and M-RoPE positions with exact hooks, logits, and K/V.

Refs lablup#867

* test(xla): pin DeepStack signed decode state

Route sequential prefill completion and M-RoPE coordinate calculation through one private transactional state so a failed native prefill cannot replace the last successful signed delta. Exercise that state from public DeepStack requests and assert the exact first decode coordinate before and after a failed replacement.

Share the production DeepStack admission conversion with scheduler tests, then carry public negative, positive, and zero deltas through pending ownership and slot admission. Assert row-specific coordinates and verify cancellation plus same-slot text reuse restores a zero delta without mutating internal prepared positions.

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

Labels

area:architecture Architecture and code structure changes area:core mlxcel-core: MLX FFI, primitives, KV cache, layers area:inference Generation, sampling, decoding (incl. speculative, DRY) priority:medium Medium priority status:done Completed type:enhancement New features, capabilities, or significant additions

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(xla): add per-layer multimodal feature injection to prefill

1 participant