mirror of
https://github.com/ikawrakow/ik_llama.cpp.git
synced 2026-07-20 09:45:35 +00:00
main
9
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
9d07d8681e |
perplexity: fix int overflows in large context x vocab buffer sizing (#2150)
Several buffer sizes and pointer offsets in examples/perplexity compute counts as
n_ctx / n_token / n_chunk / index times nv (or n_vocab) using int operands. At 16k
context with a >=131k-vocab model, n_ctx*nv exceeds INT_MAX (16384*131076 = 2^31+),
overflowing to a negative int that becomes a huge size_t in resize/ctor -> std::length_error
crash. Affects:
- --kl-divergence-base / --kl-divergence: log_probs.resize, the token/logits writes,
the compare-path base pointer (segfault at 32k) and inner offsets, and the read reserve
- hellaswag_score / winogrande_score / multiple_choice_score: batch_logits(n_vocab*n_ctx)
Cast the counts/indices to size_t at each site. Byte-identical below the overflow threshold;
the offset accesses that were already size_t (i_logits, eval_pairs.first) are unchanged.
Repro: llama-perplexity -c 16384 --kl-divergence-base out.dat on any >=131k-vocab model
(the hellaswag/winogrande/multiple_choice allocs overflow the same way at large -c).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
27d6291222 |
Fix uninitialized MROPE/IMROPE position sections in legacy-batch decode path (#2149)
For IMROPE models (Qwen3.5/QWEN35MOE) the RoPE op reads 4 position sections per token, but the legacy null-pos decode fallback (llama_batch_get_one path, used by llama-perplexity/llama-cli/llama-eval-callback) sized the position vector to n_tokens. llama_set_inputs then copies n_tokens*4 out of that n_tokens-sized vector, an out-of-bounds read that feeds garbage into 3 of the 4 rope sections, giving wrong and run-to-run non-deterministic RoPE. Build the sections like the explicit-pos path (text t,t,t,0). Standard-rope (NEOX) unchanged; VL image input uses the explicit-pos builder. Qwen3.5-4B self-vs-self same-top: 91.3% -> 100.0% (CUDA), single-thread CPU likewise. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
7ae6b337a7 |
P100 tile-f32 exact-retile: half2 K/V smem staging (2-blocks/SM + leaner inner loop) (#2142)
Faster fp32-class replacement for the tile_f32 flash-attention inner path on P100
(sm_60). Bit-identical fp32 arithmetic to the un-retiled kernel (same-top 99.28% =
the float-reorder floor; QK differs only in accumulation order, ~1 ulp; P.V
bit-identical), restructured via half2 K/V shared-memory staging that both cuts
shared memory and leans the inner loop.
Measured +4-9% vs the un-retiled fp32 tile kernel, back-to-back. The speedup is a
COMPOUND of two effects the staging produces together (shares not isolated):
(1) occupancy: smem 36992 -> 28800 B/block admits 2 blocks/SM where the un-retiled
kernel fits only 1 (2*28800=57600<=65536; 80 regs would allow 3, smem is the
ceiling); a genuine 1->2 gain, corroborated by a cross-family perf panel;
(2) a leaner inner loop: ~2x fewer QK-loop smem loads, the dropped score round-trip,
one fewer barrier.
__launch_bounds__(...,2) only PINS the target the smem reduction already reaches (a
(...,1) bound compiles bit-identically), so the directive is not itself a lever, and a
3rd block does not help (cost-curve + an implemented regs-80->124 attempt confirm smem
caps occupancy at 2).
Validated on P100 as the drop-in for the carve-out path (pr-p100-fp16). Reviewed by a
6-model Claude council + a cross-family cloud perf panel; the panel corrected an earlier
'not occupancy' framing to this compound one.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
||
|
|
7174a124ca |
CUDA: route P100 (sm_60) decode flash-attention to fp32 vec kernel (#2144)
On P100 (GP100, sm_60) the fp16 vec kernel used for decode (batch<=8) accumulates the online-softmax denominator and the P*V product in fp16, flipping ~3-4% of decode top-1 tokens vs an all-fp32 reference (llama.cpp#25593). Decode is memory-bandwidth-bound on P100, so routing sm_60 decode to the in-tree vec_f32 kernel is free (tg128 ~identical). Gated on cc == CC_PASCAL && Q->ne[1] <= 8 (decode only) inside the !fp16_mma_available block, so the prefill tile_f16 path, the D=256 prefill vec path, and fast_fp16_available() are untouched, and the is_pascal_mla_absorbed_decode early-return (MLA) is unaffected. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
f616fff7d9 |
sm graph: reshape folded-head MLA tensors to 3D before the per-head split (#2130)
Loading a deepseek2 model with -sm graph across 2 or more GPUs segfaults during model load, in the per-head split of the MLA attn_k_b/attn_v_b tensors. In the ik-converted GGUFs these ship 2D with the heads folded into ne[1] (DSV2-Lite attn_k_b is [128, 8192]). distribute_mla_tensors_for_split_mode_graph splits them with prepare_split_tensors(2, ...), which takes the head count from ne[2]. With the heads still in ne[1] each split comes out n_head times too large and the upload reads past the end of the host buffer. It is host-side (compute-sanitizer is clean) and happens at any device count >= 2. Fix: reshape the 2D layout to 3D [head_dim, inner, n_head] before the split, the same head-outermost interpretation ggml_reshape_3d already uses on the non-split path. Metadata-only, guarded on ne[2]==1 so it is a no-op for GGUFs that already ship these tensors 3D. Tested on DeepSeek-V2-Lite-Chat Q4_K_M (only what fits across the GPUs here): -sm graph PPL matches -sm layer and CPU within stderr (7.26 / 7.24 / 7.24, wikitext-2 n_ctx 2048), coherent generation at 2, 3 and 4 GPU splits, and a REAP-pruned DSV2-Lite in parity too. GLM-DSA, Mistral4 and larger deepseek GGUFs share the split path so I expect the same fix to cover them, untested here. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
a8cf53fd69 |
CUDA: fix flash attention for gpt-oss (SWA + attention sinks) on the tile kernels (no-tensor-core GPUs) (#2087)
* CUDA: use the mask tensor stride (nb31) in the tile FA kernels, not ne11 The tile flash-attention kernels (no-tensor-core GPUs, e.g. Pascal/sm_60) indexed the KQ mask using ne11 (= K->ne[1]) as the row stride. The SWA windowing in ggml_cuda_flash_attn_ext (the n_swa branch) re-points K/V/mask to the last nton tokens, setting ne11 = nton while the mask keeps its original row stride nb31. Indexing by ne11 then reads across mask rows and yields NaN once the window slice engages (context past nton). Use the mask's own stride nb31/sizeof(half); in the non-sliced case this equals ne11, so it is a no-op there. Matches how the vec kernel already computes its mask offset, and how mainline llama.cpp fixed the same latent bug in its unified tile kernel. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * CUDA: apply attention sinks in the tile FA kernels (gpt-oss) The tile flash-attention kernels took a sinks argument but never applied it, so gpt-oss (which has a per-head sink logit) got a wrong softmax denominator with -fa 1 while the -fa 0 path (ggml_soft_max_add_sinks) matched CPU. Apply the sink after the KV loop, mirroring the vec kernel: the sink joins the running max and adds exp(sink - max) to the denominator once, rescaling kqsum and VKQ. Only ip==0 adds it so it is counted once across the parallel_blocks KV split (the epilogue writes the sink-inclusive max/denominator into dst_meta before the combine). The per-head index is blockIdx.y (the same index the slope uses). Guarded by non-null sinks, so non-sink models are unaffected. This is the tile-kernel equivalent of mainline llama.cpp PR #15178; the wmma kernel is left untouched (no Turing/Volta hardware to validate here, but the same defect likely applies). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
72201359dd |
CUDA: MLA flash-attention decode on Pascal (vec_f32 K=576/V=512), incl. Q8_0 KV (#2079)
On GPUs without FP16 tensor cores (Pascal / sm_60, e.g. Tesla P100) MLA flash-attention decode falls back to the CPU. The !fp16_mma_available path routes decode to the f16 vector kernel, whose is_supported check requires K == V head sizes; MLA's absorbed head sizes are 576/512 (asymmetric), so it is rejected and attention runs on the CPU. With --cpu-moe that recomputes the full MLA attention on the CPU every decoded token, which dominates decode at long context. Route Pascal MLA decode (Q->ne[1] <= 8 && K == 576 && V == 512) to the f32 vector kernel and enable that kernel for the 576/512 case, including Q8_0 KV. Scope: decode only (batch <= 8). Prefill (batch > 8) and -fa 0 are untouched; tensor-core GPUs never reach this branch. Aligned head sizes are byte-identical (the asymmetric/Q8_0 work folds to a no-op at compile time), so no other model or configuration is affected. - fattn.cu: route 576/512 decode to vec_f32 in the !fp16_mma dispatch and its is_supported mirror. - fattn-vec-f32.cu/.cuh: accept + instantiate 576/512 (F16 and Q8_0); fix latent issues exposed by the first asymmetric/large-head use (KQ-row granularity uses FATTN_KQ_STRIDE not Dv; guard the dst store to tid < Dv; guard the softmax exp on the KV tail; size Q_i32 by ceil; only convert K/V to F16 when the type is F16). All are no-ops for the previously-exercised symmetric cases. - fattn-vec-f32.cuh / fattn-vec-common.cuh: guard the Q8_0 ragged tail (Dk=576 is 144 int32 lanes = 4.5 warps) with the ragged-dim idiom; compile-time-constant for aligned head dims, so it folds away. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
87fc8701ff |
GLM-DSA: fix -fa 0 garbage perplexity on the batch>8 indexer path (#2069)
The batch >8 indexer path in build_deepseek2_dsa_indexer accumulates the per-head scores with ggml_add_inplace into an accumulator that is seeded from a view of KQ_mask. On -fa 0, KQ_mask is the raw F32 input tensor, so the in-place writes land in the shared KQ_mask buffer and corrupt the causal mask that build_deepseek2_dsa_sparse_mask and the later softmax layers read back, which gives garbage perplexity. -fa 1 is unaffected (its F16 mask is cast to a private F32 buffer), and the small-batch path added in #2067 is unaffected (it uses a non-inplace add). Take a private copy of the seed in the batch >8 -fa 0 path (raw F32 mask) before the accumulation, matching what those two paths already do. 4K -fa 0 --dsa PPL goes from thousands to 2.7134 (dense 2.6972, -fa 1 --dsa 2.7111). -fa 1 and non-DSA builds are byte-identical. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> |
||
|
|
9da563d09d |
deepseek2 : GLM-DSA sparse attention (lightning indexer), --dsa off by default (#2045)
* Add GLM-5.2/DeepSeek-V3.2 DSA lightning indexer (batch-local, single-seq prefill) Implements the sparse top-k "lightning indexer" attention for LLM_ARCH_GLM_DSA in build_deepseek2_layer_attention (ik's deepseek2 graph). What it does (per layer, gated on model.arch==GLM_DSA && indexer_attn_q_b): - indexer_q = indexer_attn_q_b(q_lora latent), split rope(64)/nope(64), NEOX-rope the pe part, concat. indexer_k = indexer_attn_k(attn_norm out), LayerNorm w/ bias, same rope/concat (single key head, MQA). - scores = relu(indexer_k . indexer_q), scaled per-head weights (indexer_proj), summed over heads, + base causal mask, then ggml_top_k(min(top_k, n_tokens)). - sparse mask: ggml_fill(-inf) -> ggml_set_rows(0) at top_k positions -> + causal, used in the soft_max_ext attention path (-mla 1 -fa 0) instead of KQ_mask. Simplifications (intentional, proven sound): - Batch-local: no indexer KV-cache. Indexer keys are the current batch tokens. - Walsh-Hadamard transform omitted: orthonormal rotation, (Hq).(Hk)==q.k, no score change. Validation (GLM-5.2-UD-IQ2_M, 3x P100, -mla 1 -fa 0): - Compiles clean (CUDA sm_60); loads and runs. - c512 -b512 (n_seq=1) PPL = 2.7760, byte-identical to dense baseline (indexer disabled) = 2.7760, all 8 chunks match -> indexer is an exact no-op when top_k>=n_tokens. Proves correctness-preservation. - 3105-token prompt completion (top_k=2048 < 3105 -> indexer ACTIVELY masks): prompt-eval produces coherent, accurate continuation, identical to dense for the prompt+early-gen tokens. No NaN/crash. Confirms the masking path works in prefill. Known limitations (documented follow-ups, NOT handled): - Single-sequence prefill only. Multi-sequence batches (n_seq>1, e.g. perplexity default n_batch>n_ctx) and kv_head>0 (decode) break the batch-local key->slot mapping. n_seq>1 -> NaN (use n_batch==n_ctx). Decode (kv_head>0): each generated token sees only itself as an indexer key, so generation degenerates into repetition after the prompt (dense A/B stays coherent) -- this is the decode-cache stub, the documented next step. - Flash-attn path (-fa 1, F16 mask) still uses dense KQ_mask (soft_max path only). - Decode indexer KV-cache + Hadamard cached-K storage not implemented. Runtime gate: DSA_INDEXER_DISABLE=1 falls back to dense attention (for A/B). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * GLM-5.2 DSA indexer: decode-correct via persistent indexer-K cache Make the lightning-indexer correct for DECODE (not just prefill). Previously the indexer was batch-local, so a generated token only scored against itself and generation degenerated. Now the indexer keys are cached across the full context. Changes - llama_kv_cache: add per-layer indexer-key cache `kr_l` [indexer_head_size, kv_size] (F16, MQA single head), allocated alongside the MLA latent cache for GLM_DSA. - build_deepseek2_dsa_indexer: write the batch's (Hadamard-rotated) indexer keys to kr_l at kv_head, read back the full [128, n_kv] cached keys, and score the indexer queries against ALL past keys. Returns the full descending argsort of the scores. - Walsh-Hadamard rotation of indexer q/k (cparams.dsa_indexer_hadamard, default on; filled in llama_set_inputs). Score-preserving; improves cached-K F16 precision. - build_deepseek2_dsa_sparse_mask: rank-based full-coverage scatter (write a 0/-BIG penalty into EVERY key slot keyed by rank) instead of partial set_rows into a -inf fill — the CUDA in-place set_rows does not preserve an un-written base, which had corrupted decode when n_kv > top_k. - Attention-sink force-inclusion (DSA_SINK, default 1): boost the first key(s) so the sink always survives top-k. The IQ2_M-quantized indexer under-ranks the sink, and masking it collapsed decode; with the boost, top_k=2048 over n_kv>2048 stays coherent. ggml backend fixes (needed by the indexer) - CUDA argsort: report unsupported when padded ncols > 1024 (one-thread-per-column bitonic launch limit) so the scheduler falls back to the CPU argsort. Fixes "invalid configuration argument" for top_k over a large n_kv. - CUDA cpy/dup: support I32 -> I32 (top_k index copies / cross-backend moves). Validation (GLM-5.2-UD-IQ2_M, 3xP100 + --cpu-moe, -mla 1 -fa 0) - c512 PPL = 2.0743, byte-identical to dense (all 8 chunks): no-op path exact. - Short-context decode (300 tok): coherent, identical to dense. - Long-context decode (2521-tok prompt, n_kv>top_k, real masking of ~474 keys, 120+ tok generated): coherent with the sink boost; dense A/B also coherent. Gated behind arch==GLM_DSA + indexer tensors + kr_l cache; DSA_INDEXER_DISABLE=1 forces dense. Remaining: FA path still uses the dense KQ_mask; multi-sequence (n_seq>1) batches; deepseek32 arch wiring. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * GLM-5.2 DSA indexer: wire sparse mask into the flash-attention path (-fa 1) The DSA sparse top-k mask is now applied on the -fa 1 path (our serving config), not just -fa 0 soft_max. c512 PPL on -fa 1 = 2.0743, byte-identical to dense (no regression, indexer no-op exact at n_kv <= top_k). Gated arch==GLM_DSA with DSA_INDEXER_DISABLE escape; -fa 0 path unchanged. Long-context -fa 1 decode coherence (n_kv > top_k, mask actually biting) validation is still running at commit time; the FA mask reuses the same full-coverage scatter proven coherent on the -fa 0 decode path, so it should hold, but confirm before relying on long-context -fa 1. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * GLM-5.2 DSA indexer: UPDATE 4 — MLA-FA fix merged, FA path validated, multi-seq characterized Document the re-validation after cherry-picking the MLA-FA vec-decode fix (5f18dcc0): - FA path is ALIVE. Long-ctx -fa 1 decode (2521-tok prompt > top_k, mask actively biting) is now COHERENT at -mla 1 and -mla 3, vs the pre-fix degeneration into "0.0.0.0..." repetition. Matches dense (DSA_INDEXER_DISABLE) and -fa 0 controls. - c512 -fa 1 PPL: indexer-ON == dense == 2.0854, byte-identical all 8 chunks (exact no-op when n_kv <= top_k; no regression). The 2.0743->2.0854 shift is the MLA-FA fix changing V accumulation, not an indexer artifact (ON==dense proves it). - Indexer is feature-complete + validated for single-seq prefill+decode on both -fa 0 and -fa 1, at -mla 1 and -mla 3 (the R740 serving target). Remaining PR gaps, characterized honestly: - Multi-seq (n_seq>1) with active mask is BROKEN (n_seq=2 c4096 PPL 62.6 vs dense multi-seq 2.54 and single-seq indexer 3.05). No NaN/crash anymore. Root cause: the indexer uses a single scalar kv_head/n_kv for the whole ubatch; multi-seq needs per-sequence cache writes + per-sequence top-k. Fix deferred (structural). - deepseek32 arch: N/A in this fork. DSA lives entirely under LLM_ARCH_GLM_DSA; there is no LLM_ARCH_DEEPSEEK32 enum. Documented the steps to add one if a real deepseek32 GGUF is ever served. Also commit DSA_REFERENCE.md (verbatim mainline deepseek32/glm-dsa source, the port reference), trimmed of a stray agent-handoff footer. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * GLM-5.2 DSA indexer: per-sequence attention sink — fix multi-seq (n_seq>1) UPDATE 5. The DSA lightning indexer was numerically broken for multi-sequence batches once the top-k mask bites (n_kv > top_k): c4096 n_seq=2 PPL 62.6 vs dense 2.54, while single-seq was fine. Root cause: the attention-sink force-include boosted the GLOBAL key range [0, n_sink) by +1e20, which only protects sequence 0's sink. With several sequences packed contiguously into one ubatch (seq 0 at cells [0,n0), seq 1 at [n0,n1), ...), every non-first sequence's sink lives at cell n0.. (not cell 0), got no boost, and was dropped from top-k once the mask bites — collapsing that sequence (chunk[2]=61.2 while chunk[1]=2.33). The cache write and score/argsort were already per-sequence correct: tokens are placed contiguously like the main K cache, and the base KQ_mask (filled from kv_self.cells[i].has_seq_id) already drives cross-seq keys to -inf before argsort. Only the sink was anchored at the wrong (global) cell. Fix: replace the global arange sink boost with a per-graph input tensor inp_dsa_sink {n_kv, n_tokens} (F32), filled on the CPU in llama_set_inputs from kv_self.cells exactly like the KQ_mask: inp_dsa_sink[j,i] = 1e20 iff cell[i].pos in [0,n_sink) AND cell[i].has_seq_id(seq_of_query_j), else 0 so each query force-includes only its OWN sequence's sink. For a single contiguous sequence from pos 0 this is exactly the old "cell index < n_sink" set with the same magnitude, so n_seq==1 is byte-identical. Validation (3x P100, -ngl 99 --cpu-moe -mla 3 -fa 1, wikitext-2): - c4096 n_seq=2 indexer chunk[2]: 61.2 -> 3.07 (== single-seq 3.05). - c2048 topk=1024 (mask bites): n_seq=4 == n_seq=1 chunk-for-chunk (2.5005/2.6080/2.7759/3.1137 vs .../3.1138) -> multi-seq is numerically identical to processing each sequence alone. - c512 n_seq=1 indexer ON == dense, all 4 chunks byte-identical (no regression). n_seq=4 at full c4096 (n_kv=16384) OOMs the P100 compute buffer (capacity, not correctness; n_seq=4 proven correct at c2048/n_kv=8192). GLM-5.2 DSA indexer is now sequence-correct for n_seq>=1, prefill+decode, soft_max+FA, -mla 1/-mla 3. Fully general and PR-ready. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * GLM-5.2 DSA indexer: UPDATE 6 — serving-correctness (kr_l maintained across shift/defrag/seq-ops; per-seq sink on first-present pos) An adversarial review found the indexer was proven on the perplexity path but not the serving path: the persistent indexer-K cache kr_l was written/read but never *maintained* by the KV-cache mutators, and the attention sink anchored on absolute pos<n_sink (wrong after multi-turn seq_rm). This closes those gaps and pins down what is actually reachable on the MLA model. kr_l maintenance: - build_k_shift (llama-build-context.cpp): rotate the indexer keys by the same per-cell delta as the main K. The cached key is H*concat(RoPE(k_pe,pos),k_nope), so un-Hadamard (H sym/orthonormal => H*H=I) -> RoPE-delta the pe sub-block -> re-Hadamard. Exact because GLM-DSA has no rope-scaling metadata (ext_factor=0, attn_factor=1, freq_scale=1), so NEOX RoPE is pure/composable. Params mirror the forward indexer RoPE exactly (rope_factors=nullptr); no DEEPSEEK2 yarn-shift leak. Non-in-place (cont->rope->concat->re-Had->cpy), no aliasing. K-shift Hadamard input filled in llama_set_k_shift with the identical Sylvester construction. - build_defrag: kr_l row-move mirrors the k_l move (defrag never changes pos, so no re-RoPE). max_moves divisor 6->9 *n_layer when the indexer cache is present. - seq_rm/seq_cp/seq_keep are metadata-only (verified) so kr_l rows stay matched to cells; seq_add/seq_div set has_shift and route through K-shift. No seq-op change. Per-seq sink (llama.cpp llama_set_inputs): anchor on each sequence's FIRST PRESENT pos (min present pos over the scored n_kv span), not absolute pos<n_sink. After multi-turn seq_rm drops a sequence's early tokens its earliest survivor has pos>=n_sink; the absolute test would protect nothing. Fresh seq at pos 0 => min=0 => byte-identical to the old behaviour. Serving-shift finding (the whole point): a RoPE context-shift on this model is REFUSED BY THE ENGINE. get_can_shift() returns false for all MLA models (is_mla_model() includes GLM_DSA); llama_kv_cache_update returns 1 -> "main : failed to eval". Reproduced AND isolated with a dense control (DSA_INDEXER_DISABLE=1): dense fails identically at the same token. The failure is pre-existing MLA engine behaviour, independent of the indexer. On the MLA path the shift never happens, so the indexer's kr_l can never desync via K-shift; the build_k_shift kr_l block is correct-and-dormant (documented loudly in code). Validation (3x P100, -ngl 99 --cpu-moe -mla 3 -fa 1, GGML_CUDA_NO_PINNED=1, numactl --interleave=all, wikitext-2): - No regression: c512 n_seq=1 indexer ON == dense == 2.1957 +/- 0.12031, byte-identical all 4 chunks (2.2770/2.8741/2.3956/2.1957). - Multi-seq: c4096 n_seq=2 chunk[1]=2.33 chunk[2]=3.07 healthy (== UPDATE 5; per-seq sink change did not regress). - Serving shift: engine-refused for MLA, dense control fails identically. - Independent adversarial review: GO, no correctness defect in the diff. - Build clean (llama-cli, llama-perplexity, sm_60). Comments updated (build_deepseek2.cpp): multi-seq+FA no longer limitations; sink description matches per-seq min-pos anchoring; BIG=1e30 masks on both soft_max and FA paths. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * GLM-5.2 DSA indexer: UPDATE 7 — FIX latent graph-reuse cache-fixup omission for the kr_l indexer cache update_cache_copies() re-points the K/V cache writes to the current kv_head whenever a compute graph is REUSED (can_reuse_graph reuses iff kv_self.n == prev->n_kv). The persistent indexer-key cache write (kr_l) is a separate ggml_cpy whose destination view bakes kv_head at graph-build time, and it was NEVER registered for that fixup. Under FA the cache pads to 256, so consecutive single-token decode ubatches share the same padded n_kv and the graph IS reused; without the fixup the kr_l write keeps landing in the first ubatch's slot and later ubatches never populate their own recent index-key cells (those cells stay at the alloc-zeroed 0.0). Structurally identical to the MiniMax MSA bug (fork commit 133d14c9). Fix (mirrors the K/V cache_copies fixup, same shape as MSA 133d14c9): - llama-context.h: new std::vector<CacheCopy> dsa_cache_copies. - llama.cpp ctor: resize dsa_cache_copies to n_layer (null entries -> no-op when DSA off). - build_deepseek2.cpp: register the kr_l ggml_cpy as dsa_cache_copies[il] = {kr_cpy, kr->nb[1]}. - llama.cpp update_cache_copies(): re-point each registered cpy view_offs = kv_head*step and patch src[1]->data/data, exactly like K/V, with the c.cpy->view_src == kv_self.kr_l[il] (+ null/op) guard the MSA fix omitted. soft_max / non-DSA paths byte-identical. Validation (GLM-5.2-UD-IQ2_M, 3x P100 -ngl 99 --cpu-moe -t 32, NO_PINNED, P2P-disable patch re-applied to get a working multi-GPU baseline — see UPDATE 7.3; that patch was lost in the upstream rebase and is required separately): - c512 -fa1 -mla3 indexer ON: 2.1983 (== prior baseline; build healthy). - Long-ctx FA decode, 2735-tok recall prompt, -mla3 -fa1 temp0, reuse ON (default): coherent, correct deep-context recall ("Dr. Mariana Velasquez ... Daniel Okonkwo") on BOTH the fixed and the unfixed binary. - ub128 PPL -fa1 -mla3 reuse ON, unfixed: 1.7239/1.8211/2.1888/2.4517, healthy (no inflation). Honest scope: the bug is real in code but LATENT for GLM-DSA at its configured top_k=2048 (permissive selection keeps the genuinely-attended recent blocks even when reuse leaves some recent index-key cells stale), unlike MSA's tighter top-k where it inflated PPL ~2x. The fix is correct and prevents the latent corruption from biting at any tighter top_k / longer ctx / future serving config. The pre-P2P-patch "nan" seen at ub128 was P2P corruption, not this bug. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * GLM-DSA: convert sparse-attention control from env vars to CLI args (off by default) Implements ikawrakow's direction from discussion #2040: the DSA sparse indexer must be controllable via command-line argument (not environment variables), and must be OFF by default for now. Control surface, before -> after: DSA_INDEXER_DISABLE (env, inverted: on-by-default) -> --dsa / -dsa (cparams.dsa, default false; opt-in, dense-by-default) DSA_TOPK_OVERRIDE (env) -> --dsa-top-k N / -dsatk N (cparams.dsa_top_k, default -1 == model's configured indexer_top_k) DSA_HADAMARD_DISABLE, DSA_SINK (env) -> kept as DEBUG-ONLY env knobs (clearly commented; no CLI surface, not system on/off controls) Plumbing mirrors existing boolean/int feature flags (-mla, -khad): include/llama.h llama_context_params {bool dsa; int dsa_top_k;} src/llama.cpp default_params (false / -1); cparams assignment src/llama-cparams.h llama_cparams {bool dsa=false; int dsa_top_k=-1;} common/common.h gpt_params {bool dsa=false; int dsa_top_k=-1;} common/common.cpp arg parse + help text + cparams copy src/graphs/build_deepseek2.cpp gate now checks cparams.dsa instead of getenv; top-k override reads cparams.dsa_top_k. Stays arch-gated to LLM_ARCH_GLM_DSA. When --dsa is off (default) the indexer function is never called -> existing dense MLA path, byte-identical to no-feature. Validation (GLM-5.2-UD-IQ2_M, 3x P100, -ngl 99 --cpu-moe -mla 3 -fa 1, wikitext-2, 4 chunks @ c2560): --dsa OFF (default, dense): PPL 2.4151 (graph nodes 4166) --dsa ON, default top_k=2048: PPL 2.4697 (graph nodes 8846) --dsa ON, --dsa-top-k 1024: PPL 3.5107 Off-by-default runs the dense path; ON activates the indexer (node count jumps, PPL shifts as the top-k mask bites once n_kv > top_k). No env var is consulted for the primary on/off or the top-k knob. Graph-parallel (-sm graph) interaction (the item ikawrakow flagged): Under -sm graph the MLA layers are TP-split (wo->extra) and route to build_deepseek2_tp_attention(), which contains NO indexer code. So --dsa is silently a NO-OP under -sm graph: it does not error or crash, it runs dense. Empirically, --dsa --dsa-top-k 1024 under -sm graph gives PPL 2.4308 (chunks 1.6967/1.7906/2.1664/2.4308) -- the dense baseline (2.4151), NOT the DSA top_k=1024 numbers (3.5107). The 0.016 delta is f16 TP-reduce numerics, not DSA. Conclusion: DSA "works under deepseek2" only on the non-TP (layer) path; serving DSA with -sm graph would require wiring the indexer into the TP attention path (or a dedicated DSA arch). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * GLM-DSA: warn that --dsa is inactive under -sm graph/attn (TP path runs dense MLA) The DSA lightning indexer is built only in the layer-mode (non-TP) attention path. Under -sm graph / -sm attn the tensor-parallel attention path has no indexer, so --dsa would silently run dense MLA. Emit a clear one-time LLAMA_LOG_WARN at context creation instead of degrading silently. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * GLM-DSA: drop in-tree dev reference docs from the PR branch DSA_REFERENCE.md and the R740 progress note are development scratch, not part of the submission. Remove them so the PR diff is code-only. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * GLM-DSA: fix CPU-only crashes in the sparse-attention path PR #2045 adds GLM-DSA sparse attention but was validated on CUDA (--cpu-moe). A CPU-only build (-ngl 0 --dsa) crashes in four spots where the CUDA backend tolerates something the CPU backend does not. These make GLM-5.2 --dsa run coherently on CPU; with --dsa off they are no-ops (DSA CPU path only). 1. set_rows into an F32 dest segfaults (ggml.c set_rows_f32): type_traits[F32].from_float is NULL, so the DSA sparse-mask scatter calls a NULL fn (segfault at ip=0). memcpy when the dest is F32. CUDA has a real F32 set_rows path, so this only bit the CPU build. 2. ggml_add(F32 score, F16 mask) aborts on CPU (build_deepseek2_dsa_indexer and build_deepseek2_dsa_sparse_mask): under -fa 1 the dense KQ_mask is F16 and CPU add only accepts F32+F16 when src0 is F16. Cast the causal mask view to F32. CUDA's add accepts the mixed types. 3. dsa_fa_mask dim-1 concat must be F32 on CPU (build_deepseek2_dsa_fa_mask): CPU ggml_concat only supports F16 along dim 0; do the row (dim-1) concat in F32 then cast the result to F16. CUDA supports the F16 dim-1 concat. 4. indexer k_norm epsilon is 0 -> ggml_norm aborts (llama-hparams.cpp): the lightning-indexer k_norm is a non-RMS LayerNorm using f_norm_eps, but the GLM-DSA GGUF only carries the RMS eps so f_norm_eps stays 0 (GGML_ASSERT(eps > 0)). Mirror the RMS eps. CUDA's norm doesn't assert on eps=0. Validated: GLM-5.2 UD-Q4_K_M, single-socket Xeon w7-2475X, CPU-only (-ngl 0 --dsa) - coherent at 49K+ ctx, correct 30K needle retrieval, prefill flat with length (~32 tok/s, the O(L) DSA signature) vs the dense build's O(L^2) decline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * DSA: loop over attention heads + use builtin Hadamard * DSA: ggml_blend * DSA: remove a bunch of unnecessary ggml_cont * DSA: fix CUDA blend - but something is still wrong * DSA: use ggml_top_k instead of ggml_argsort when FA is ON * CUDA: add CUB based argsort * DSA: avoid graph leaves * Various * GLM-5.2 DSA: IndexShare (shared layers reuse full-layer top-k) GLM-5.2's indexer_types marks 21 'full' layers that compute their own lightning-indexer top-k and 57 'shared' layers that reuse the previous full layer's top-k. This port computed an independent top-k on every layer, which mis-selects keys on the 57 shared layers (the transformers reference sets indexer=None on shared layers and reuses prev_topk). Shared layers now reuse the most-recent full layer's selection. Full/ shared map derived from the config rule (full iff il<=1 or il%4==2), which reproduces indexer_types exactly; loader can later override from GGUF metadata. Built on #2063's tree; head-loop/ggml_hadamard/ggml_blend/ argsort/FA-mask unchanged. 4K PPL (unsloth IQ2_M, top_k 2048, CPU): DSA-on 3.1922 -> 2.7111, dense 2.6972 (~97% of the gap). top_k>=n_kv reproduces dense exactly. Single- seq and 4x8 parallel decode coherent. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * Apply suggestion from @ikawrakow --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: mgkwill <168222+mgkwill@users.noreply.github.com> Co-authored-by: Kawrakow <iwankawrakow@gmail.com> |