YaRN rope scaling, 4-bit F4 packed KV cache, and hybrid paged attention for Qwen3.5-Next long-context serving - #2375
Closed
JLFN wants to merge 1 commit into
Closed
Conversation
…ext serving Summary This squashed commit brings the Qwen3.5-Next long-context serving work to master: YaRN rope scaling pinned to the llama.cpp reference implementation, a 4-bit F4 packed KV cache for paged attention, hybrid paged-KV allocation restricted to the full-attention layers of the hybrid model, host-memory parking of recurrent prefix snapshots, a halved paged-prefill chunk size for the 262144-token window, a MoE router topk fix on CUDA, and the lockfile security remediation. The target workload is serving the Qwen3.6-14B-A3B Q4_K_M GGUF (qwen35moe, 40 layers, 90 experts, full_attention_interval 4) with up to 320000 tokens of context on a 12 GB consumer GPU. Context / Problem Serving the model at its native 262144-token window on a 12 GB card leaves no room for the KV cache at the model dtype; serving at 320000 was impossible. Two independent levers are needed: YaRN rope scaling to extend the positional window beyond the native context, and a 4-bit packed KV cache to cut cache memory 4x. YaRN must match llama.cpp value-for-value (the rope tables are position-dependent and a drift is invisible until long context), and candle-core cannot store DType::F4 on CUDA at all, so the cache uses custom packed U8 storage inside the paged-attention kernels. Scope YaRN rope scaling (new) - layers.rs: RotaryEmbedding::new_partial_yarn mirrors llama.cpp yarn resolution (get_mscale cancellation in llama-context.cpp against the 1 + 0.1*ln(scale) re-fold in ggml rope_yarn; net table scale 1.0199427025 for factor 1.220703125; corr_dims low/high ramp, beta_fast 32, beta_slow 1). - models/qwen3_next.rs: Config.rope_scaling; the model builds new_partial_yarn for rope_type "yarn" and rejects other types. - rope_override.rs: new RopeOverride type threaded from CLI through ModelSelected and the GGUF loader to config synthesis. - gguf/normal_config.rs: forced override neutralizes embedded GGUF rope.scaling metadata that would otherwise reject the checkpoint, then inserts the yarn block and sets max_position_embeddings to the target. - CLI: --rope-scaling yarn|none, --rope-scale, --yarn-orig-ctx, --override-ctx on the GGUF format options of run and serve. F4 4-bit KV cache (paged-attn + core) - cache_engine.rs: PagedCacheType::F4, block-shape math 32 values per 16-byte cell row for K, head_dim/2 byte-rows for V. - reshape_and_cache_kernel.cu: reshape_and_cache_f4_kernel writes symmetric 4-bit values with one scale per 32-value K cell and one per token/head for V; race-free 2-pair-per-thread byte writes. - pagedattention.cuh + pagedattention_v1/v2_*.cu: inline F4 dequant in attention; gather_kv_cache and copy_blocks gain U8/F4 paths; kv scales become per-cell tensors guarded by a Mutex. - Storage: 5 KB/token for the 10 paged layers vs 20 KB/token BF16 (4x). Hybrid paged-KV allocation - qwen3_next.rs and vision_models/qwen3_5/text.rs expose HybridPagedKvCacheConfig; paged blocks are allocated only for the 10 full-attention layers (3, 7, 11, 15, 19, 23, 27, 31, 35, 39). Recurrent prefix snapshots in host memory - prefix_cacher.rs: conv_state/recurrent_state moved to Device::Cpu before caching (each snapshot ~63 MB f32 for 30 GDN layers; GPU residency would cost ~1 GB VRAM per cache fill). Paged prefill chunk - pipeline/mod.rs: DEFAULT_PAGED_PREFILL_CHUNK_SIZE 4096 to 2048. MoE router topk fix - ops.rs: cuda_topk operates on a contiguous copy instead of a final-logits row view, restoring full-row topk on CUDA. Dependencies - Cargo.lock-only (no manifest changes): anyhow, crossbeam-epoch, memmap2, quinn-proto (CVE-2026-25800), rand, tar. Remaining 7 vulnerable packages (10 advisories) recorded as accepted risk in OSV-EVIDENCE.md. Docs - YARN-SOURCE-VERIFICATION.md: llama.cpp source-line evidence (rope pipeline, mscale chain, corr_dims, IMROPE-to-NEOX equivalence) plus Phase B rebuild and Phase C serve evidence. - F4-KV-STORAGE-ASSESSMENT.md: candle-core storage limits, the packed format, and authoritative per-token cache numbers. - OSV-EVIDENCE.md: remediation list and accepted-risk set. Verification - cargo test -p mistralrs-core --test yarn_rotary: 4 passed (positions 262144, 262145, 319999 match the llama.cpp pipeline to <= 5e-12). - cargo test -p mistralrs-core --lib qwen35moe_yarn_override: 2 passed. - F4 tests: f4_cache_storage (candle limits, pack/unpack tolerance), f4_kv_layout (CPU mirror of kernel indexing), f4_gpu (CUDA kernel vs CPU reference round-trip). - Binary rebuilt with cuda + flash-attn; serve boot shows F4 packed u8 cache, yarn flags honored, 320000 available context. - Serve evidence (RTX 4070 SUPER 12 GB, Qwen3.6-14B-A3B FableVibes Q4_K_M): run 1 reached prompt ~252k then CUDA_ERROR_OUT_OF_MEMORY at GPU peak 11807/12282 MiB; run 2 (after freeing ~0.5 GB of non-server GPU consumers) reached prompt 275837 with 99.83% prefix-cache hit rate, stable F4 cache, no overflow. Full 320000 completion not yet verified. - OSV scan at push time: 800 packages scanned, 7 vulnerable (10 advisories), all documented accepted-risk, no new findings. Known limitations - F4 caches exist only in the Standard paged-attention layout/kernels; the engine forces the Standard backend when the cache type is F4, and any CPU-hosted layer in the device map disables paged attention entirely, so F4 and host-RAM offloaded KV are mutually exclusive. - The F4 startup log over-reports the reserved cache budget 2x (blocks are packed U8); the correction is cosmetic and frees no real memory. - F4-vs-BF16 logit equivalence at long context has not been measured; per- value error bound is max_abs/16. - The 320000-token full-window serve on this 12 GB card is VRAM-bounded (observed ceiling ~275k-280k); the CPU/RAM layer-offload route to exceed it is a planned follow-up.
Code Metrics Report━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Language Files Lines Code Comments Blanks ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ C Header 24 4497 3151 790 556 CSS 3 281 252 5 24 CUDA 124 26446 21759 1707 2980 Dockerfile 1 35 19 9 7 HTML 2 27 27 0 0 JavaScript 3 582 567 12 3 Jinja2 7 694 656 5 33 JSON 27 18278 18275 0 3 Makefile 1 18 16 0 2 MDX 37 6771 0 4994 1777 Metal Shading Lan| 37 14416 11408 1136 1872 PowerShell 1 657 571 31 55 Python 152 12617 10486 480 1651 Shell 3 1071 852 115 104 Plain Text 53 10687 0 9209 1478 TOML 28 1397 1213 43 141 TypeScript 11 1658 1418 66 174 YAML 3 25 23 2 0 ───────────────────────────────────────────────────────────────────────────────── Jupyter Notebooks 3 122 83 23 16 |- Markdown 1 60 30 22 8 |- Python 1 122 113 1 8 (Total) 304 226 46 32 ───────────────────────────────────────────────────────────────────────────────── Markdown 275 12394 0 9265 3129 |- BASH 25 306 225 48 33 |- Dockerfile 2 14 12 0 2 |- JSON 6 289 289 0 0 |- PowerShell 1 1 1 0 0 |- Python 135 7349 6119 306 924 |- Rust 62 3845 2851 396 598 |- TOML 7 116 97 0 19 (Total) 24314 9594 10015 4705 ───────────────────────────────────────────────────────────────────────────────── Rust 728 399029 360689 5489 32851 |- Markdown 427 10136 452 8486 1198 (Total) 409165 361141 13975 34049 ───────────────────────────────────────────────────────────────────────────────── Svelte 19 1974 1832 50 92 |- CSS 1 4 4 0 0 |- JavaScript 19 921 767 25 129 (Total) 2899 2603 75 221 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Total 1542 536839 444257 42715 49867 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ |
Author
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.
Summary
This PR merges the Qwen3.5-Next long-context serving work back to master. It adds YaRN rope scaling pinned to the llama.cpp reference implementation, a 4-bit F4 packed KV cache for paged attention, hybrid paged-KV allocation that restricts the paged cache to the full-attention layers of the hybrid model, host-memory parking of recurrent prefix snapshots, a halved paged-prefill chunk size for the 262144-token window, a MoE router topk fix on CUDA, and the lockfile security remediation. The target workload is serving the Qwen3.6-14B-A3B Q4_K_M GGUF (qwen35moe, 40 layers, 90 experts, full_attention_interval 4) with up to 320000 tokens of context on a 12 GB consumer GPU.
Origin and included prior work (feat/qwen35-native-context-fix)
Items 2 through 7 below - the F4 cache, the hybrid paged-KV allocation, the recurrent-snapshot host parking, the paged-prefill chunk change, the MoE router topk fix, and the lockfile remediation, with their tests - were developed and verified earlier on the fork branch feat/qwen35-native-context-fix (tip f93428e, pushed to JLFN/mistral.rs). That branch has no pull request of its own: its 34-file, +1623/-161 diff against master is a strict subset of this PR's 51-file diff, byte-identical in every file except the YaRN additions on top (items 1 and 8 below) and a small extension to f4_cache_storage.rs. The YaRN long-context work (item 1) is the new layer this PR adds over that native-context base, and both together are squashed into the single commit b7f9c90.
Changes by area
Verification
Known limitations
Commits
One squashed commit (b7f9c90) ahead of master: the full substantive long-context work condensed into a single conventional commit, 51 files changed, 2182 insertions, 192 deletions. The session-handoff document and the separate CPU-offload experiment branch are intentionally not part of this pull request; the offload work is a planned follow-up.