DeepseekV4: Add fused hyper-connection ops - #25585
Conversation
|
@am17an looks like there's an overlap with #25421 . I added the Sinkhorn step as a standalone SINKHORN_NORM op, you've fused the whole HC block, which is the better call. I came at this from the AMD side. Profiling deepseek-v4-flash on an MI250X, the decomposed Sinkhorn was ~30% of gpu kernel time across ~250k tiny 4×4 dispatches, fusing it gave me +60.9% decode / +7.4% prefill on 4 GCDs. Since we're solving the same thing, want to join forces? I'm happy to close mine and help on this one, especially validating/tuning it on MI250X if that's not already done/ any other additions you would like to delegate ? |
|
@jadenmach2 sure, thanks! I've only tested these on nvidia gpus |
|
@am17an The new ops are producing nans sometimes: |
This is just my wild guess, but isn't that because of uninitialized sentinel tensors? |
|
Yeah I think that's the most likely cause. AFK in case @fairydreaming you want to pick this up, otherwise I will fix in a few hours |
|
@ggerganov @am17an This should fix it: #25822 |
Squash-rebase of the ds4-flash-experiments branch (post-cleanup: 8 dead flags + MOE_TILE/FP4_RT ops removed, LID_CACHE_MXFP4 default-on) onto current upstream, which had independently evolved DeepSeek-V4 (fused HC ops ggml-org#25585, kv_stream cache refactor ggml-org#25702, seq_rm fix ggml-org#25588, lightning-indexer ggml-org#24231). Reconciliation (per Teej's calls — keep our tuned versions, adopt upstream only where cleanly additive): - KV cache: adopted upstream's kv_stream per-stream views; kept our kv_stash MTP frontier-rewind AND our frontier-aware seq_rm (upstream's ggml-org#25588 seq_rm rejects the 1-token-tail eviction our server/MTP post_decode relies on -> aborts; caught in re-validation, reverted to ours). - HC fusion: kept OUR validated bandwidth-minimal HC op; upstream's HC_PRE/COMB/ POST sit dormant. Renamed our colliding ggml_dsv4_hc_post -> _hc_fused_post (+ test struct); fixed models.h class decl to match our deepseek4 impl. - Server: adapted our --cache-disk L2 tier to upstream's split prompt-cache (server_prompt vs server_prompt_cache_state / server_prompt_data). - Kept all unique work: LID indexer CUDA kernels, CSA_TILE, FA_SPLIT/FA_MERGE, fp4-mma + packed MXFP4 container, radix/int8/dec, power governor, MTP, CVEC. - experiments/ untracked (repo-local ignore) — branch delta is code only. Verified on the rebased tree: - build clean (cli + server + tests) on upstream 86d86ed - DSV4 backend-ops 2/2 all kept ops (LID_TOPK/UNION/MEMB, HC_FUSED, QAT_SET_ROWS, FA_MERGE) - llama-cli shallow smoke c8192: coherent, byte-identical greedy to pre-rebase - llama-server c32768 + MTP + --cache-disk (LAN): MTP 21.5 t/s (draft 47/95 accepted), 3 requests no crash, --cache-disk spill + 660-tok disk restore Not yet run: deep-context (>=131k) serving — defer to an attended run (wedge risk).
…, OpenCL Q6_K/Adreno, CORS, checkpoint min-step, prompt cache refactor, MoE expert API stays) Upstream highlights since 6be7459: - model: DFlash speculative with KV rotation (ggml-org#25823) - model: Hy3 (hy_v3) with MTP speculative decoding (ggml-org#25395) - model: DeepseekV4 with fused hyper-connection ops (ggml-org#25585) - ggml: 0.17.0, LIGHTNING_INDEXER, out_prod, f16 set_rows - vulkan: Q2_0 support, native e2m1/e4m3 conversions, transfer-queue race fix - CUDA: MMQ kernel config refactor (ggml-org#24127), tighter MMQ src1 buffer for fp4 (ggml-org#25613), CUDA graphs on Volta/Turing, MoE gate/up dedup, CUDA Virtual Devices - ROCm: hexagon L2 cache rework, native fp4, FP16/INT8 coopmat on AMD - SYCL: Battlemage flash attention via oneDNN XMX, XIELU op, fp16 conv2d_dw - OpenCL: Q6_K GEMM/GEMV fix, ragged-tile MoE prefill FP16, Adreno vectorized LD/ST, A7x optimizations, ABS op - kleidiai: SME2 f32 kernel, SME vs SME2 dispatch - server: refactor prompt cache state ownership (ggml-org#25649) - new server_prompt_cache_state separates prompt metadata from KV data - server: evict checkpoints within min-step (ggml-org#25472) - server: text-only slot save/restore with mtmd (ggml-org#25076) - server: --cors-* options (ggml-org#25655) - server: refactored server_stream (ggml-org#25541) - server: respect min-step when splitting prompt batches (ggml-org#25420) - server: move chat-template thinking probe inside init try/catch (ggml-org#24093) - common: auto-download dflash/eagle3 HF sidecars (ggml-org#25811), drop --stdin mutual-exclusion, align tokenize usage - conversion: BitNetForCausalLM, dflash tokenizer fix, split MTP export for HY V3 - llama-quant: exclude i32 ffn_gate_tid2eid routing table, allow manual tensor types with --pure - llama-batch: fix allowed decreasing pos in a seq (ggml-org#25449), n_keep_tail in split_equal for recurrent - llama: refactor fused ops (ggml-org#24646), TP fix for Phi3/Bert/Plamo2/3/ChatGLM - ui: agentic content UX, reasoning effort on mobile add sheet, MCP panel fixes, thinking menu fix - vendor: BoringSSL 0.20250713.0 - tests: actually exercise test-recurrent-state-rollback, ds_v4_hc sentinel init, export-graph-ops graceful exit CachyLLama preservation work (conflict resolution): 1. tools/server/server-task.h: Accept upstream's server_prompt refactor (no data member, clear() method). Move our t_last_used field from server_prompt to server_prompt_cache_state (where it now lives after the refactor). server_prompt_cache_state already has the size() method, so our old size() on server_prompt is no longer needed. 2. tools/server/server-context.cpp (create_checkpoint): Take upstream's min-step eviction pre-filter as the FIRST pass, then keep our existing highest-pos_min eviction as the capacity overflow fallback. These are complementary: min-step removes redundant checkpoints from the same task; highest-pos_min keeps the rec-window-friendly checkpoints when at cap. 3. tools/server/server-context.cpp (handle_completions_impl): Keep our std::vector<server_task> tasks batching for multi-prompt requests and per-user concurrency check, AND take upstream's res->set_req(&req) for spipe ownership transfer. 4. tools/server/server-task.cpp: Fix references to entry.tokens -> entry.prompt.tokens, entry.checkpoints -> entry.prompt.checkpoints, entry.n_tokens() -> entry.prompt.n_tokens(). Update find_eviction_candidate return type from list<server_prompt>::iterator to list<server_prompt_cache_state>::iterator. 5. ggml/src/ggml-cuda/mmq.cuh + new mmq-config-rdna3_5.cuh: Upstream's massive MMQ refactor moved per-architecture config into separate files but did NOT add RDNA3.5 (gfx1150/1/2/3, Strix Halo). Create mmq-config-rdna3_5.cuh (231 CASE entries) derived from rdna2 with nthreads=128 (4 warps) and I=48 (smaller X tile) matching our original Strix Halo tuning. Wire into both host and device dispatch paths before the RDNA4 / RDNA2 fallback. 6. README.md and AGENTS.md: Keep CachyLLama-specific links and project context where upstream added parallel content. Verified: - cmake --build builds clean (Release, CPU-only) - llama-server starts, --help shows all CachyLLama flags preserved: --cache-ssd-hot-ram, --cache-ssd-warm-ram, --cache-ssd-system-prompts, --cache-ssd-system-max-days, --cache-ssd-no-fsync, --cache-ssd-max-conversations, --max-concurrent-per-user - /expert-stats and /expert-tracking endpoints preserved - 55/58 tests pass; 3 failures unrelated to merge: - test-tokenizers-ggml-vocabs: missing model downloads - test-jinja-py: missing jinja2 Python module - test-quant-type-selection: snapshot mismatch on upstream's new MXFP4_MOE heuristic Custom CachyLLama files untouched (no upstream conflicts): - common/kv-ssd-cache.{cpp,h}, common/kv-ssd-posix.h, common/kv-ssd-system-cache.{cpp,h} - common/kv_page_manager.{cpp,h} - tools/server/server-context-page-manager.{cpp,h} - tools/server/server-context-ssd-cache.{cpp,h} - test_kv_page_manager.cpp, tests/test-ssd-cache-caps.cpp - STRIX_HALO_NOTES.md, docs/development/user-isolation-design.md - .github/workflows/build-cpu.yml, build-cuda-windows.yml, build-vulkan.yml
* dsv4 hc-ops * add missing files; * add cparams * update rpc version * address review comments * address review comments
* dsv4 hc-ops * add missing files; * add cparams * update rpc version * address review comments * address review comments
* dsv4 hc-ops * add missing files; * add cparams * update rpc version * address review comments * address review comments
Merge upstream ggml-org/llama.cpp master (876a432) into fork master. Fork point was 2026-07-06 (20a04b2): 330 commits behind, 965 ahead. 37 files conflicted; all resolved by hand (never --theirs), plus fixes for cleanly-merged files that referenced APIs changed elsewhere. Brings in DSpark speculative decoding (8407527) and the DeepSeek V4 work that landed after our fork point, including the fused hyper-connection ops (0dc74e3, ggml-org#25585), DS4 seq_rm fix, graph-split reduction, MTP tensor loading, dflash K/V rotation and sidecar auto-download. Upstream removals that forced fork-side ports: * -sm row / CUDA split buffers removed (74976e1). Dropped our copy of the split-buffer implementation (no fork code in it) and rewrote ggml_cuda_mul_mat onto upstream's early-return dispatch, re-inserting the ML8_FP8 route, the F8_E4M3 guard and the TQ4_1S/TQ3_1S kernels. ggml_cuda_Memcpy2DPeerAsync is kept -- it carries our no-P2P host staging. * mmq.cuh rewritten upstream (<type,J,fallback>, y_scale, stream-k helper). Ported the MAD-88 routed-expert pointer hook to the new kernel signature, args struct and both launch sites. * WMMA flash-attention kernel deleted upstream; our RDNA4 path now leads. * use_mmap/use_mlock/use_direct_io collapsed into llama_load_mode. Weight paging now strips only the mmap bit instead of forcing no-mmap. * llama_context auto-FA/GDN resolution folded into resolve_fused_ops(); the WP attention-island guard is re-injected there, scoped to flash-attn. * server: draft/MTP context now built by common_speculative_init_from_params, so --spec-draft-n-ctx and the MTP tier-disable move onto params_dft; slot memory ops go through slot.mem; migrated two subprocess sites to common_subproc; folded our byte-backpressure into upstream's server_pipe (upstream's drops the oldest item, which would corrupt a proxied body). Fork-visible behaviour changes: * GGML_TYPE_Q2_0 is 56 here, not upstream's 42 -- 42 is our TURBO3_0 and type ids are on-disk. Our turbo/ml8 GGUFs stay readable; an upstream Q2_0 GGUF needs reconversion. gguf-py kept in sync. * DS4 per-layer output renamed l_out -> l_last upstream; added l_last to the WP FFN-island pin or it silently stops firing on DeepSeek V4. * Dropped our -ffast-math on HIP: upstream sets -funsafe-math-optimizations instead because -ffast-math implies -ffinite-math-only, which breaks ggml's INFINITY masking. Do not reinstate. * --flash-attn off with a turbo/quantized cache is now an error rather than a silent override, matching upstream. * DFlash conversion delegates to the target model's vocab class instead of hardcoding the deepseek-v3 pre-tokenizer. ABI: llama_model_params gained load_mtp. Every binary that consumes it must be rebuilt on BOTH machines (llama, llama-server, llama-wp-expert-worker, test-wp-expert-worker) -- a partial target list is what crash-looped the fleet on 2026-07-30. Verified: no conflict markers; fork-marker counts vs backup flat or up (kv-tier, wp_, weight_pager, mt_pagedattn, mt::, MAD-, routed_expert, ml8, spec-draft-n-ctx); every hip_xdev function survives; all fork flags still register in arg.cpp; CPU build (llama, llama-server, llama-cli) clean. Backup: backup/pre-upstream-sync-2026-07-31 (e6b6856). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018kbRS3KuJquSpjpZXdtSNp
* dsv4 hc-ops * add missing files; * add cparams * update rpc version * address review comments * address review comments
Merges 251 upstream commits on top of the fork's 392. Base was 22b208b (2026-07-15). What this brings in for DeepSeek V4: - CUDA kernels for the hyper-connection ops and the lightning indexer (dsv4-hc.cu, lightning-indexer.cu, upstream ggml-org#25585 and ggml-org#25545). These landed upstream after our base, so the graph no longer needs a CPU fallback for those ops. - MTP and DSpark support (ggml-org#25784), the wo_a reshape fix on load, and the same-K/V-cache-type enforcement (ggml-org#25871). - Exclusion of the i32 ffn_gate_tid2eid routing table from quantization, which the fork did not carry. Conflict resolution kept both architectures everywhere the two sides touched the same code: - llama-kv-cache: kept the fork's default-off attention-rotation policy and its env overrides, took upstream's GLM_DSA addition to the DSA indexer arch list. - llama-context: moved the TurboQuant flash-attention auto-enable above upstream's generic quantized-V check, which would otherwise reject turbo cache types under -fa off, and dropped the fork's older V-cache check in favour of upstream's. - mmq.cuh: kept the fork's int64 offsets in all three of upstream's new NVFP4 branches. - fattn.cu: dropped the WMMA block, since upstream removed that kernel and its helpers entirely; kept the RDNA4 turbo path. - ggml-cuda.cu: kept the host-staged cross-device copy and routed its peer copy through upstream's new virtual-to-physical device mapping. - chat.cpp: rebuilt on upstream's file with the fork's Inkling and Laguna parsers and the leading-whitespace tolerance reapplied; thinking_end_tag became thinking_end_tags upstream. - laguna.cpp/laguna.py and mtmd-image.cpp: took upstream, which already carries the fork's own upstreamed review fixes plus later refinements. - Removed the inherited upstream workflows again, per 0c9a069. GGML_OP_COUNT is 103: upstream's 101 plus the fork's TURBO_WHT and FLASH_ATTN_EXT_BANDED. Also drops a duplicate LLM_ARCH_LAGUNA case in test-llama-archs that the merge would otherwise have left in moe_mandatory.
* dsv4 hc-ops * add missing files; * add cparams * update rpc version * address review comments * address review comments
Overview
Add the sinkhorn ops to the DeepseekV4 graph. Graph nodes go from 29k to 8k with this change. Big increases in the TG + PP
Additional information
Requirements