Skip to content

feat(ds4): add DSpark speculative runtime + optimizations #496

Draft
davide221 wants to merge 10 commits into
codex/ds4-rocmfpx-serverfrom
codex/deepseek4-dspark-draft
Draft

feat(ds4): add DSpark speculative runtime + optimizations #496
davide221 wants to merge 10 commits into
codex/ds4-rocmfpx-serverfrom
codex/deepseek4-dspark-draft

Conversation

@davide221

@davide221 davide221 commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Stack

Depends on #503, which depends on #502:

#502 ROCmFPX ggml -> #503 DeepSeek4 target -> #496 DSpark runtime

This branch was rebuilt directly on #503 so it does not carry or conflict with older copies of the target and fused-decode changes.

Summary

  • bridge DeepSeek4/MTP DSpark auxiliary heads into the draft GGUF contract
  • add the DeepSeek4 DSpark loader, proposal graph, target feature capture, batched verification, and rollback loop
  • add confidence-based adaptive verification width while retaining fixed-width controls
  • keep standard AR unchanged unless DFLASH_DS4_SPEC is enabled

Validation

  • Release HIP build for gfx1151;gfx1201
  • R9700 DSpark load + forward at context 42: 20,480 finite floats, RMS 0.2820
  • feat(ds4): add fused HIP decode for ROCmFPX #503 fused AR path remains selected when DFLASH_DS4_FUSED_DECODE=1
  • coherent greedy generation with local and remote DSpark execution
  • git diff --check

Follow-up

Remote DSpark execution and shared transport are isolated in #505.

davide221 added 3 commits July 8, 2026 17:23
Ports the ROCmFP4/ROCmFPX ggml work (previously lucebox-ggml #36, on the
old submodule pointer) into the vendored server/deps/llama.cpp tree.

- ROCmFP4/ROCmFPX quant types + CPU reference conversions (ggml/rocmfp4,
  ggml/rocmfpx) and the ggml type-trait registrations.
- CUDA/HIP dequant, copy, getrows, MMVQ vecdot, MMVF, unary and FA paths
  for the new types.
- Fused DS4 hyper-connection op (GGML_OP_DS4_HC) with the register-resident
  sinkhorn kernel; inert unless emitted by the DS4 fused-decode path.
- DS4 SwiGLU split op plumbing for the fused FFN matvec paths.

Layered on current main, so the main-side ggml work is preserved
(fp64 RoPE reduction, #497 RDNA MMQ tile, LUCE_MMQ_DP_MAX_NE1,
MMVQ_MAX_MOE_BATCH_SIZE, fused dual set_rows, raw-span guard).

Review fixes on top of #36:
- ggml_ftype_to_ggml_type: handle the 11 new ROCmFPX ftypes (dominant-type
  mapping) so the enum switch is -Wswitch/-Werror clean.
- FP6 MMVQ vecdot: pad qs[] to avoid a stack over-read of the last window
  (bit-identical; the over-read bits were already masked out).
The non-HIP fallback of rocmfp4_get_int_from_codebook_16 /
rocmfp4_get_low_int_from_codebook_16 called get_int_from_table_16, which is
defined in vecdotq.cuh. TUs that pull in this header without vecdotq.cuh
(fattn-chunked.cu reaches it via the fattn dequant chain) failed to compile
under nvcc:

  rocmfp4_hip_codebook.cuh: error: identifier "get_int_from_table_16" is undefined

The HIP path never hit this (it uses __builtin_amdgcn_perm), so the ROCm CI
and the Strix build stayed green while the sm_86 CUDA build broke.

Fix: inline the generic table expander (the generic branch of
get_int_from_table_16, verbatim) as a static helper in this header, so the
fallback no longer depends on include order. Bit-identical; the HIP hot path
is unchanged.
Server-side DeepSeek V4 Flash changes from #494, rebased onto the vendored
ROCmFPX ggml tree (no submodule pointer). Byte-identical to the validated
#494 server files.

Correctness (default ON):
- Token-by-token prefill by default; chunked prefill only fits inside the
  raw SWA ring, so long prompts / multi-turn degraded. Chunked stays
  available via DFLASH_DS4_CHUNKED_PREFILL for short-prompt benchmarking.
- Clear the cache buffer at new-sequence prefill (kv_offset==0) so requests
  2..N are byte-stable instead of pooling over leftover compressor state.
- Route non-hybrid (all-hot) placement through the HC-complete layer-range
  path; deepseek4_step's non-hybrid branch is HC-less and generates garbage.
- Key the cached decode-attn graph on the flush pattern; the old key
  collided once the compressed-KV ring filled, reusing a stale-topology
  graph.
- Compressor decode graphs read state/comp-cache through the ggml_set_rows
  result tensors so the current-step writes are explicit graph dependencies.
- Default DeepSeek4 chat prefix when the request has no system message, so
  the ROCmFPX "Src" GGUF stops behaving like a base model under bare prompts
  (explicit caller system prompts are preserved).

Perf, byte-identical default:
- Persistent HC matvec pool (row-split preserves per-row accumulation order)
  and f16c dot kernels with scalar-order adds.
- Per-step decode scalar inputs uploaded in 2 tensor_sets instead of ~430.

Opt-in, default OFF (documented as not bit-identical):
- DFLASH_DS4_FUSED_DECODE single-graph decode with GGML_OP_DS4_HC.
- DFLASH_DS4_FFN_RAW_MMID / DFLASH_DS4_FFN_FUSED_COMBINE accumulation reorder.
- DFLASH_DS4_ROCMFPX_HC_GPU GPU HC pre-mix.
@davide221

Copy link
Copy Markdown
Contributor Author

Validation update (2026-07-09): the converter/loader bridge in this PR was validated on lucebox2 with the converted DSpark drafter artifact. In the follow-on DeepSeek4 runtime worktree, DSpark loads successfully, prefill feature capture and generation are wired, the batched-verify causality bug is fixed, and causal batched output matched exact sequential verification in paired probes. Adaptive EWMA width and fused batched verify are working; fused verify reached approximately 20 tok/s (peak 20.1 tok/s), versus roughly 13–15 tok/s for the earlier dynamic causal path. Exact sequential verification measured 1.78–1.91 accepted candidates per 4-candidate step. These runtime changes are follow-on work in the hub-494 experiment worktree and are not claimed as already included in PR 496.

@davide221

Copy link
Copy Markdown
Contributor Author

Updated DSpark adaptive width in 1fc4f00.

  • Fused Markov generation now returns confidence scores in the existing token-id synchronization (no extra host round trip).
  • A compatible confidence head automatically selects q=2/q=3/q=4 from cumulative prefix confidence.
  • Artifacts without a compatible confidence head fall back to the existing EWMA controller.
  • No new environment variables or rejected confidence+EWMA hybrid policy were added.
  • Expert k=3 is not included.

Validation on lucebox2 / gfx1151 with the exact committed source:

  • HIP dflash_server build: pass.
  • GSM 5/5 + MATH 5/5: 10/10.
  • Server-side decode: 1,485 tokens / 50.769 s = 29.25 tok/s weighted.
  • Fixed-q=4 reference: 29.49 tok/s weighted.

The confidence policy therefore retains essentially all high-acceptance throughput while adapting verification width on harder prompts.

Return confidence scores from the fused Markov graph in the existing token-id synchronization, then select q=2/q=3/q=4 from cumulative prefix confidence. Compatible DSpark artifacts enable the policy automatically; artifacts without a confidence head retain the existing EWMA controller. No new deployment configuration is introduced.\n\nValidated on gfx1151: GSM+Math 10/10 at 29.25 tok/s weighted, within 0.8% of fixed q=4, with adaptive behavior retained on low-acceptance prompts.
@davide221
davide221 force-pushed the codex/deepseek4-dspark-draft branch from 1fc4f00 to 867c9b8 Compare July 10, 2026 20:27
@davide221 davide221 changed the title feat(dflash): bridge DeepSeek4 DSpark aux heads feat(deepseek4): add DSpark speculative runtime Jul 10, 2026
@davide221
davide221 changed the base branch from main to codex/ds4-rocmfpx-server July 10, 2026 20:33
@davide221 davide221 changed the title feat(deepseek4): add DSpark speculative runtime feat(ds4): add DSpark speculative runtime + optimizations Jul 13, 2026
Remove the no-op single-wave MMVQ shared reduction, add opt-in fixed-K FP2/FP3 and partially-unrolled FP4FAST q=1 kernels, and use AMD v_perm_b32 for packed FP3 decode.

A fully build-matched Lucebox3 A/B used ROCm 7.2.4, gfx1151, wave32, -O3, FA_ALL_QUANTS=ON, fused DS4 decode, expert top-k 4, and HC-GPU disabled. Five balanced GSM8K runs per binary improved mean AR throughput from 24.270 +/- 0.018 to 25.664 +/- 0.014 tok/s: +5.744% +/- 0.122% at 95% confidence.

All ten measured runs remained 5/5 with exactly 583 output tokens. Generated fused/plain specializations report zero private segment, dynamic stack, SGPR spills, and VGPR spills.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants