Port DeepSeek-v4 to TQ - #224
Conversation
- DeepSeek V4 conversion support - DSV4 CPU ops and CUDA kernels (dsv4-hc, lightning-indexer) - GGML RPC updates - KV cache ISWA improvements - Model architecture updates for V4 support - Chat template for DeepSeek V4
Merge remote-tracking branch 'origin/feature/turboquant-kv-cache' into ds4
- Rewrite DSV4_HC_COMB CUDA kernel: 16 threads per 4x4 sinkhorn matrix (2 tokens per warp, 8 per block) instead of 1 thread per token. Replaces serial per-thread 4x4 ops with warp-shuffle reductions (__shfl_xor_sync with XOR 1,2 for rows and XOR 4,8 for columns). - Fix cmake CUDA arch targets: add 120-real for Blackwell RTX 5090. - Add test_dsv4_hc_comb test case (15 configs: n_tokens=1,2,4,8,64 x n_iter=1,3,5) verified on CUDA0 vs CPU reference.
|
Right now, it runs about 95% of the equivelent speed as on main llama.cpp I'm trying to do a bit more optimization |
Port upstream commit b820cc8 (CUDA: consistent use of __restrict__ + PDL for FA ggml-org#25185). Avoids compiler race condition between PDL and __restrict__ on Hopper+ GPUs by using GGML_CUDA_RESTRICT (which is a no-op when PDL is active) instead of raw __restrict__ on kernel params. Also switches the kernel launch to ggml_cuda_kernel_launch() for PDL enrollment.
|
Performance changes in ds4 branch (2 new commits) 4f5cb54 — Warp-parallel HC_COMB kernel 95a7c30 — PDL + restrict fix for flash attention Additional Changes:
|
Port upstream commit 9f364c7 (llama : dsv4 graph fixes): - Rename layer output from 'l_out' to 'l_last' so graph_get_cb can force it onto the correct GPU backend, preventing cross-backend data transfers that slow decode with CPU MoE offloading. - Add ggml_build_forward_expand for residual/post/comb tensors to ensure they are computed before the FFN norm.
Port upstream commit 4937ca8. The i32 token-id -> expert-id routing table (DeepSeek-V4) cannot be quantized like float weights. Missing this exclusion causes llama-quantize to fail.
… dimensions (ggml-org#25650) Co-authored-by: Stanisław Szymczyk <sszymczy@gmail.com>
Left over from merge conflict resolution: GGML_ASSERT(!ggml_is_quantized) was outside the conflict zone and wasn't removed by the fix patch. Also removed GGML_ASSERT(ggml_blck_size == 1) from the top-level check since it's now only relevant for non-quantized types (preserved in the else branch).
|
Okay speeds are the same as main llama.cpp and it holds steady even across long context, just like main, I'm still working on a few ideas. |
|
Thanks for the port — the scope (new arch + indexer/HC kernels + compressed-state cache + conversion) is exactly what this fork wants for V4. Blocking issue before review: the PR commits 21 |
21 tqbak backup files (~24k lines) committed alongside real source changes, inflating the PR diff to ~30k lines and obscuring the actual ~10k-line V4 port. Clean slate for maintainer review.
|
@TheTom done |
|
Full review as promised. Ran the branch on GB10 (sm_121, CUDA 13) merged against current head: builds clean, Blockers1. CPU 2. The test harness never got 3. CPU/CUDA Sinkhorn eps divergence in Major
Minor / nits
Happy to re-test on GB10 once the blockers land. Runtime validation with a real V4 checkpoint is still outstanding on our side (no disk for an 80GB+ GGUF on the test box right now) — the arch smoke test in #2 is the near-term substitute, so getting it green matters. |
This file was deleted in the DSV4 port but the deletion is unrelated to the V4 architecture changes and creates merge friction.
Blockers:
- B1: Restore turbo KV group-size propagation in set_rows CPU impl
- B2: Add synthetic DSV4 keys for test-llama-archs (expert_weights_scale,
expert_weights_norm, swiglu_clamp arrays, output/lora/compress/hyper-
connection/hash-layer hprams, compress_ratios, gating_func=sqrtsoftplus)
- B3: Unify CPU/CUDA Sinkhorn eps semantics — both now add eps to every
normalization denominator. Sweep eps in test (1e-6, 1e-3, 1e-1).
Major:
- M1: Add test-backend-ops coverage for DSV4_HC_PRE, DSV4_HC_POST,
LIGHTNING_INDEXER
- M2: Add comment explaining is_mla guard skipping V tracking (latent KV)
- M3: Analyzed seq_rm — range removals return false, callers don't loop,
graceful degradation confirmed
- M4: Restore build-xcframework.sh (unrelated deletion creates merge friction)
Minor:
- N1: RPC_PROTO_PATCH_VERSION 2 -> 3 (GGML_OP_COUNT 102)
- N2: Separate DSV4 ops from REPEAT/REPEAT_BACK/LEAKY_RELU in n_tasks
- N3: Remove dead selected_experts_in param from build_moe_ffn
- N4: Drop LLM_ARCH_HY_V3 (no name mapping or consumers)
- N5: Add zero-fill safety comment on SwiGLU-clamp call sites
- N6: Verified scoring_func: sqrtsoftplus in config.json matches conversion
|
Thanks for the fast turnaround — the fixes themselves look right (verified: set_rows group-size propagation restored, per-step eps now mirrored in the CUDA kernel, eps-swept HC_COMB test + new PRE/POST/LIGHTNING_INDEXER tests, arch-test keys, RPC patch bump, own n_tasks case, 1. It doesn't compile. There's no 2. Unrelated OSCAR debris got committed: Please compile + run |
|
@TheTom how the bleep did oscar stuff get mixed in there? They are seperate branches!! lol. |
|
haha it happens 🙂 — no rush, ping me when it builds and I'll run the final pass. |
…rch test - ggml-cpu/ops.cpp: drop GGML_TYPE_TURBO1_0 clause (belongs to OSCAR branch) - deepseek4.cpp: remove dead selected_experts param from build_moe_ffn call - llama-model-saver.cpp: add vector<float> add_kv instantiation for arch tests - test-llama-archs.cpp: skip DSV4 (synthetic model cant represent complex hparams) - Remove committed OSCAR test-run artifacts (logs/oscar-bias, scripts/oscar-bias-diag.sh) Assisted-by: Claude Code
…h test Port 3 missing upstream commits for DSV4 support: - 67b9b0e Fix DeepSeek4 APE tensor op (GGML_OP_ADD -> GGML_OP_GET_ROWS) (ggml-org#25945) - 91d2fc3 DSV4: write only used rows in state save/load (ggml-org#25325) - dee2a84 Adjust offloading logic to also skip FLASH_ATTN_EXT (ggml-org#25832) Additional fixes: - Make swiglu_clamp_exp/shexp keys optional in DS4 loader with zero fallback - Fix arch test: hc_mult=4, compress_ratios=0, value_length=576 - Skip DEEPSEEK4 arch test (matching upstream GGUF serialization issue) Assisted-by: Buffy
DSV4 Port — PR UpdateDate: July 30, 2026 Changes Since Last Push1. Three Upstream Commits PortedThese were identified as missing from our initial DSV4 merge and were ported from upstream a)
|
| Test Suite | Status |
|---|---|
test-backend-ops DSV4 ops |
✅ All pass (45 HC_COMB, 6 HC_PRE, 6 HC_POST, 8 LIGHTNING_INDEXER) |
test-llama-archs (full) |
✅ All 100+ architectures pass (DEEPSEEK4 SKIP, matching upstream) |
Build (libllama.so, llama-server) |
✅ Clean |
Environment
- GPU: NVIDIA GeForce RTX 5090
- CPU: Intel Core Ultra 9 285K
- CUDA: Latest
- Backends tested: GPU, CPU, Meta
Known Issues
- DEEPSEEK4 arch test skipped — GGUF synthetic model serialization issue with
swiglu_clamp_exparray.add_kv_from_model()writes the fullstd::array<float, LLAMA_MAX_LAYERS>(512 elements) instead ofn_layer()elements. This is a matching issue with upstreamggml-org/llama.cppand does not affect real model inference.
"Write a game of snake in python using pygame" |
|
After this will be figuring out DSPARK. |
59145a4
into
TheTom:feature/turboquant-kv-cache
|
Final GB10 verification on 22b9d3c (merged with current head): build clean on sm_121, test-llama-archs suite exit 0 (deepseek4 SKIP is fine given the documented model-saver array issue — same precedent as PLM/2OCR; worth the cross-codebase fix as a follow-up), LIGHTNING_INDEXER 8/8, DSV4_HC_COMB 45/45 (eps sweep), DSV4_HC_PRE/POST 6/6 each, SET_ROWS 135/135, CONCAT 112/112, and no turbo-path perf regression (Qwen3.6-35B turbo4/turbo3 tg32 68.0 ± 1.4 = parity). Combined with your real V4-Flash Q3 run, that covers everything from the review. Merged — thanks for the quick iterations, this is a big one. Curious what DSPARK turns up. |
The eps-swept HC_COMB cases from the #224 review fixes (validating that CPU and CUDA Sinkhorn eps semantics match across orders of magnitude) were dropped in the rebase, leaving only fixed default-eps cases — the exact regression class the sweep exists to catch had become invisible. Restore the pre-rebase sweep alongside the current fixed cases.
Overview
Adds DeepSeek V4 model support to the turboquant fork. V4 introduces a new architecture with lightweight indexer-based sparse attention, hyper-connection (HC) layers for cross-block communication, and compressed-state KV cache storage.
Key Changes
Model Architecture (
src/models/deepseek4.cpp,src/llama-arch.{cpp,h})LLM_ARCH_DEEPSEEK4arch with V4-specific hparams: indexer head count/size/top-k, output group count, output LoRA rank, compress RoPE frequency base, hyper-connection multiplier, sinkhorn iterations, SWIGLU clamp per expert/shared-expert arrays.models/templates/deepseek-ai-DeepSeek-V4.jinjachat template.KV Cache (
src/llama-kv-cache-dsv4.{cpp,h},src/llama-kv-cache-iswa.{cpp,h})CUDA Kernels (
ggml/src/ggml-cuda/)dsv4-hc: Hyper-connection layer fused kernel (sinkhorn normalization, attention-biased routing).lightning-indexer: Sparse top-k indexer — computes per-head relevance scores, selects top-k positions, gathers scatter KV blocks.set-rows.cu: Extended for V4's compressed-state scatter/gather.CPU Ops (
ggml/src/ggml-cpu/)dsv4-ops.cpp: Reference implementations for DSV4 tensor operations (compressed-state packing, hyper-connection).ops.{cpp,h}: New CPU op entries.GGML Infra (
ggml/src/ggml.c,ggml/include/ggml.h)Conversion Scripts (
conversion/)deepseek.py: V4 parameter mapping, hyper-connection weight layout, indexer config export.constants.py/gguf_writer.py: New V4 keys —attention.indexer.head-count,attention.indexer.top-k,hyper-connection.count,attention.output.group-count,attention.output.lora-rank,attention.compress-rope.freq-base, etc.Removed
build-xcframework.sh: Stale Apple framework script, not used in this fork.Additional Information
Requires a DeepSeek V4 GGUF checkpoint — not compatible with V2/V3 or other architectures. The indexer CUDA kernel is optimized for NVIDIA GPUs with sm_90+; CPU fallback is available for all ops but significantly slower for inference.