Skip to content

docs: DSpark speculative-decoding feasibility & adaptive-placement spec - #413

Merged
pekkah merged 2 commits into
masterfrom
claude/dspark-feasibility-61y4au
Jul 1, 2026
Merged

docs: DSpark speculative-decoding feasibility & adaptive-placement spec#413
pekkah merged 2 commits into
masterfrom
claude/dspark-feasibility-61y4au

Conversation

@pekkah

@pekkah pekkah commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • Surveys DeepSeek's DSpark/DeepSpec speculative-decoding framework (DFlash parallel backbone + rank-256 Markov head + confidence-scheduled verification) and checks it against what SharpInference already has (MtpDecoder, SpeculativeDecoder, TierPlanner, HardwareProfile).
  • Specs a DSparkPlacementPlanner that auto-decides whether the draft head runs on GPU, CPU, or is disabled, based on measured VRAM/RAM headroom — with user-overridable CLI flags/env vars (--dspark-place, --dspark-verify-len, --dspark-min-confidence, SHARPI_DSPARK_*) following the existing pinGpuLayers/SpecType precedent.
  • Lays out a phased rollout (safetensors loader → CPU-only draft pass → decoder → placement planner → CUDA/heterogeneous benchmarking → confidence scheduler → server integration) and calls out open risks (undocumented Markov-head math, no DSpark head for MoE architectures, unvalidated PCIe-cost heuristic for CPU-draft/GPU-target placement).
  • Docs-only change; no code in this repo is touched.

Went through an internal review pass (fact-checking claims against the actual source, plus a design-quality pass) before opening this PR; fixes already folded in:

  • Corrected the --draft-model + Vulkan-target claim (rejected outright today, not routed to a CPU draft).
  • Filled in the missing dspark_qwen3_14b_block7 param count.
  • Pointed the safetensors-loader work at the existing SafetensorsLoader in SharpInference.Diffusion instead of proposing a redundant one, and called out the NativeAOT/trim-safe JSON parsing constraint from CLAUDE.md.
  • Fixed the RAM-headroom formula (LayerPlacement has no per-CPU-layer byte field today) and had the planner reuse TierPlanner's reserved-VRAM-floor logic instead of re-deriving it.
  • Spelled out that the runtime free-VRAM recheck is a concrete Phase 3 step, and noted the coupling between placement margins and the variable verify length from §7.

Test plan

  • N/A — documentation only, no build/test surface affected.

Generated by Claude Code

claude added 2 commits July 1, 2026 08:09
Surveys DeepSeek's DSpark/DeepSpec framework, maps it onto our existing
speculative-decoding infra (MtpDecoder, SpeculativeDecoder, TierPlanner,
HardwareProfile), and specs an auto-placement planner (GPU-colocated vs
CPU vs off) for the draft head with user-overridable CLI/env flags,
mirroring the pinGpuLayers / SpecType conventions already in the codebase.
- Correct the Vulkan+--draft-model claim: RunCommand.cs rejects that
  combo outright rather than falling back to a CPU draft.
- Fill in the dspark_qwen3_14b_block7 param count (3.42B).
- Point the safetensors-loader work at the existing SafetensorsLoader
  in SharpInference.Diffusion instead of proposing a second one, and
  call out the NativeAOT/trim-safe JSON parsing constraint from
  CLAUDE.md.
- Fix the RAM-headroom formula: LayerPlacement has no per-CPU-layer
  byte field today, so note the plumbing (or new field) needed.
- Have DSparkPlacementPlanner reuse TierPlanner's reserved-VRAM-floor
  helper instead of re-deriving it, and spell out that the runtime
  free-VRAM recheck is a concrete Phase 3 step, not implicit.
- Note the coupling between §4 placement margins and §7's variable
  verify length so Phase 5 revisits rather than assumes them.
@pekkah
pekkah merged commit 2a8bf14 into master Jul 1, 2026
1 check passed
@pekkah
pekkah deleted the claude/dspark-feasibility-61y4au branch July 1, 2026 18:19

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a feasibility and adaptive-placement specification for DSpark Speculative Decoding, detailing placement options, auto-placement algorithms, user overrides, and a phased rollout plan. Feedback on the specification highlights a logical conflict in subtracting the expert cache budget from free VRAM, the risk of using total system RAM instead of actual available RAM for headroom calculations, and a technical inaccuracy regarding PCIe round-trip overhead for independent draft models.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread docs/dspark-plan.md
Comment on lines +110 to +111
2. **Compute GPU headroom.** `vramFree = hardware.VramBytes - targetPlacement.GpuWeightBytes
- targetPlacement.GpuKvBytes - targetPlacement.ExpertCacheBudgetBytes (if MoE) - reserved`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There is a logical conflict in subtracting targetPlacement.ExpertCacheBudgetBytes from hardware.VramBytes when computing vramFree for DSpark:

  1. Since ExpertCacheBudgetBytes is defined as the remaining VRAM after trunk weights, KV, and reserved space are subtracted, subtracting it here would reduce vramFree to nearly zero (or just the scratch buffer size), preventing DSpark from ever being placed on the GPU for MoE models.
  2. If DSpark were to be supported on MoE models in the future, the DSpark draft head should carve its allocation out of the remaining VRAM before the SLRU expert cache budget is determined, rather than treating the entire expert cache budget as an untouchable prior allocation.
  3. Since DSpark is currently inapplicable to MoE architectures (as noted in §9), this term is always 0 for all currently supported targets anyway, making its inclusion in the formula unnecessary and potentially confusing.

Comment thread docs/dspark-plan.md
Comment on lines +121 to +123
With that available: `ramFree = hardware.RamBytes - cpuResidentTrunkBytes - reserved`. If
`ramFree >= draftHeadBytesCpuQuant * 1.15` **and** `hardware.CpuCores >= 4` (a floor below
which a sequential-ish per-token draft chain would itself become the bottleneck) → **`Cpu`**.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using hardware.RamBytes (which represents the total physical system memory or container limit) as the baseline for ramFree is highly optimistic and risky.

In real-world environments, a significant portion of system RAM is already consumed by the OS, other processes, and the current process's own non-trunk allocations. Assuming all non-trunk RAM is free can easily lead to over-allocation, triggering heavy disk paging/swapping or Out-Of-Memory (OOM) crashes when loading a multi-gigabyte draft model (1.4B–3.4B parameters).

To make this safer and more robust, consider:

  1. Querying the actual available/free physical memory instead of total memory. In .NET, GC.GetGCMemoryInfo() provides MemoryLoadBytes (used physical memory), so TotalAvailableMemoryBytes - MemoryLoadBytes can be used to estimate the actual free RAM.
  2. Applying a much larger safety buffer or a conservative scaling factor if total RAM must be used as the baseline.

Comment thread docs/dspark-plan.md
Comment on lines +131 to +134
- **PCIe cost of `Gpu` vs `Cpu` isn't symmetric with `--draft-model`'s existing CPU case.**
When target=GPU and draft=CPU, every draft step round-trips the current hidden
state/token across PCIe and back for verification — unlike the existing all-CPU draft
path (target and draft both CPU, no PCIe at all) or the existing all-GPU draft path (no

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The assertion that "every draft step round-trips the current hidden state/token across PCIe and back" is inaccurate for independent draft models like DSpark:

  1. Unlike draft frameworks that depend on the target model's hidden states (such as EAGLE), DSpark is an independent draft model (using a DFlash backbone + Markov head) with its own weights.
  2. Therefore, the CPU draft model only needs the last accepted token ID(s) to seed its generation, and it produces $k$ candidate token IDs. The only data transferred across PCIe are these small token ID arrays (integers), which has negligible latency (microseconds).
  3. The actual bottleneck for a CPU-draft / GPU-target setup is the CPU execution latency of the 1.4B–3.4B parameter draft model itself, not the PCIe transfer overhead.

Correcting this in the spec will help align the performance heuristics with the actual hardware bottlenecks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants