Repository navigation
qwen4exp : 1M context (uint32 QSA block ids, depth-bounded indexer scratch, RoPE-scaled slots) - #215
gaetan-puleo wants to merge 5 commits into
Conversation
qsa_prefill stored the union's block ids as uint16 with 0xFFFF as the padding sentinel, so it supported at most 262140 keys (65535 blocks of 4) and refused a deeper n_kv. The model gate let the maskless selection through up to 16M keys, so a prefill ubatch past 262140 keys reached a kernel that refused the op and aborted. Store the block ids as uint32 with 0xFFFFFFFF as the sentinel, bound both selected-key kernels by GGML_QSA_MAX_KEYS = 1048576, the largest context the Qwen3.8 Flash Next card supports with YaRN, and bound the model-side gate by the same value (QSA_MASKLESS_MAX_KV) so a deeper n_kv takes the masked route. Same change as #124, ported to the reworked qsa3 kernel. PPL unchanged (2.0156/3.1703/3.1732), pp4096 2151 t/s, pp4096 @ d100000 1791 t/s. With -c 1048576 --rope-scaling yarn --rope-scale 4 --yarn-orig-ctx 262144, a needle placed at 5% of a 280k-token prompt is retrieved (1787 t/s prefill).
The indexer scored fixed strips of 512 queries: its raw score is F32 [n_blocks, n_idx_h, strip] and the ReLU a second tensor of that size, 2 x 2 GiB at n_kv = 1M. The strip now halves (rounding up) while the raw score exceeds 2^27 elements (its size at 262144 keys), down to 64 queries. Shorter contexts are unchanged; split KV streams keep one strip per ubatch as before. -c 1048576: compute buffer 5520 -> 2257 MiB, GTT at load 114220 -> 110956 MiB, prefill speed and PPL unchanged. An 840k-token prompt with a needle at 5% is answered correctly (1455 t/s prefill, 15.7 t/s decode at that depth).
n_ctx_slot() capped every slot at the model's training context, so --rope-scaling yarn --rope-scale 4 on a 262144-token model still limited slots to 262144 tokens (a 280k prompt was rejected with -c 1048576). Cap at base / rope_freq_scale when a frequency scale below 1 is given (--rope-scale N or --rope-freq-scale), unless --rope-scaling none (the context then ignores the scale). The base is --yarn-orig-ctx for YaRN when it is given, else the training context. With -c 1048576 and YaRN x4 the slot serves 1048576 tokens (an 840k-token prompt ran without overriding the GGUF context length).
- the model-side QSA depth gate applies to every backend: say that it mirrors the HIP kernels bound, and that Vulkan flash_attn_sel (about 8M keys) also takes the masked route above 1M. - GGML_QSA_MAX_KEYS moves below the GGML_CUDA_CC_IS_* block instead of splitting it. - server: the reported cap is n_ctx_max (no longer named n_ctx_train), and the warning says it is the training context or what --rope-scale extends it to.
|
ok time to fix this one, i'll do it this evening |
Resolve the qwen4exp_use_block_selection conflict: master (#213) bounded the selected-key depth at 262140 for prefill / 262144 for decode (uint16 block ids); this branch stores the ids as uint32 and both kernels take GGML_QSA_MAX_KEYS, so the single QSA_MASKLESS_MAX_KV bound replaces master's depth_ok. Assisted-by: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LzX5gKRb4zet7tS9WfznrG
|
The 262140 prefill ceiling bites at the model's native 262144 context, and it fails as We run Qwen3.8 Flash Next in production on a Ryzen AI Max+ 395 (128 GB, Deterministic - the same 84116.75 MiB on every one of ~25 retries over a 60 minute log. BisectBisected through the toolbox image tags (the engine is published as
The only commit touching this path in that window is // before
n_kv > hparams.indexer_top_k + ratio - 1 && n_kv <= 16777216 && ...
// after
const bool depth_ok = n_kv <= 262140 || (n_stream == 1 && ubatch.n_tokens <= 512 && n_kv <= 262144);
n_kv > hparams.indexer_top_k + ratio - 1 && depth_ok && ...Why 262144 is the bad number
Falling off the maskless route is not a graceful degradation for this model at this depth:
With To be clear about intent: the new gate is correct - #215's own description says a prefill Asks
Workaround we are landing
Verified / not verified
Assisted-by: DeepSeek Harness (qwen3.8-FN) |
Stacked on #213 (it changes the reworked qsa3 kernel of that PR). Lifts the 262140-key limit of the QSA prefill attention, so Qwen3.8 Flash Next serves up to 1M tokens with YaRN, and bounds the indexer scratch that grew with depth.
Commits
qsa_prefillstored the union's block ids as uint16 with 0xFFFF as padding, so it refused n_kv > 262140, while the model gate sent maskless ubatches there up to 16M keys: a prefill past 262140 keys aborted. Block ids are uint32 (sentinel 0xFFFFFFFF), both selected-key kernels and the model gate are bounded byGGML_QSA_MAX_KEYS = 1048576, deeper contexts take the masked route. Same change as cuda : widen QSA selected-key block ids to uint32 and lift the depth bound to 1M #124, ported to the reworked kernel (VGPR count unchanged at 192, no spill).F32 [n_blocks, n_idx_h, strip]and its ReLU were 2 x 2 GiB at 1M. The strip halves (rounding up) while the raw score exceeds 2^27 elements (its size at 262144 keys), down to 64. Nothing changes up to 262144 keys. Split KV streams keep one strip per ubatch, as before.n_ctx_traineven with--rope-scale. The cap is nowbase / rope_freq_scalefor a scale < 1 (not with--rope-scaling none; the base is--yarn-orig-ctxfor YaRN when given). Limitation: an UNSPECIFIED scaling type is not resolved against the GGUF's training type (no public getter); for a GGUF whose training type isnonethe server would over-report the slot size.Measurements (gfx1151, UD-Q4_K_XL,
-c 1048576 --rope-scaling yarn --rope-scale 4 --yarn-orig-ctx 262144)