Skip to content

dspark: scope scheduler no-draft pause defaults by backend - #776

Open
vincenzopalazzo wants to merge 1 commit into
antirez:mainfrom
vincenzopalazzo:pr/dspark-sched-retune
Open

dspark: scope scheduler no-draft pause defaults by backend#776
vincenzopalazzo wants to merge 1 commit into
antirez:mainfrom
vincenzopalazzo:pr/dspark-sched-retune

Conversation

@vincenzopalazzo

Copy link
Copy Markdown

Summary

  • Scope the three DSpark scheduler no-draft pause defaults (NO_DRAFT_SKIP, SHORT_ACCEPT_NO_DRAFT_SKIP, COLD_LOW_CONFIDENCE_SKIP) by backend, following the existing DSpark confidence-gate precedent (0.6 Metal / 0.7 CUDA).
  • Metal keeps the current 3/4/7 defaults unchanged; CUDA defaults to 0/0/0 (no pauses).
  • Env overrides are untouched, so any value stays reachable on any backend. No new mechanism, no new flags.
  • On DGX Spark (GB10) this is worth up to +8.4% generation speed at stock --dspark settings, with no measured regression outside run-to-run noise.

Root cause

After a declined proposal the scheduler pauses proposing for 3/4/7 cycles. That trade was tuned for Metal, where a propose stage is cheap relative to decode. On CUDA the economics invert: GB10 decode is memory-bound at ~55-60 ms/token while a propose stage costs ~20 ms, so a paused cycle saves ~20 ms but every accept it forfeits costs a full extra decode. The pauses are most expensive exactly where DSpark is strongest — edit/refactor/QA prompts where the model re-emits prompt spans and accepts long drafts right after a declined cycle.

The pause counters are deterministic cycle counts, not wall-clock measurements, so unlike the timing-based scheduler knobs (which stay opt-in for reproducibility) changing their default keeps greedy DSpark output reproducible across runs.

Benchmarks

DGX Spark (GB10, sm_121, CUDA), DeepSeek-V4-Flash IQ2XXS+w2Q2K+AProjQ8+SExpQ8+OutQ8 quant. "Old" restores the previous defaults via env on the same binary, so the comparison isolates the default change:

./ds4 --cuda -m model.gguf --dspark --mtp DeepSeek-V4-Flash-DSpark-support.gguf \
  --temp 0 --nothink --tokens 128 -p "$PROMPT"
# old defaults: DS4_DSPARK_SCHEDULER_NO_DRAFT_SKIP=3 \
#   DS4_DSPARK_SCHEDULER_SHORT_ACCEPT_NO_DRAFT_SKIP=4 \
#   DS4_DSPARK_SCHEDULER_COLD_LOW_CONFIDENCE_SKIP=7

Generation t/s, medians of 3:

workload old defaults new defaults delta
edit (add doc comments) 17.91 19.41 +8.4%
refactor (rewrite function) 19.62 21.13 +7.7%
QA over a passage 17.78 18.42 +3.6%
code from scratch 18.67 18.97 +1.6%
prose 17.56 17.37 -1.1%
math steps 20.59 20.38 -1.0%

The two small negatives are inside the ~1% run-to-run band observed on this machine; the wins are far outside it. DSpark stats on the refactor prompt at the new defaults: accept_rate 83.5%, avg_accept 1.42, net_saved +1172 ms over 128 tokens.

Plain decode is unaffected (the pause logic only runs inside the DSpark scheduler); before/after ds4-bench sweep per CONTRIBUTING.md:

./ds4-bench --cuda -m model.gguf --prompt-file speed-bench/promessi_sposi.txt \
  --ctx-start 2048 --ctx-max 65536 --step-incr 2048 --gen-tokens 128 --csv ...
ctx main prefill/gen t/s retune prefill/gen t/s
2048 808.2 / 17.67 805.5 / 17.48
8192 873.2 / 14.98 870.7 / 14.87
16384 864.2 / 14.85 863.2 / 14.70
32768 849.8 / 14.24 846.7 / 14.14
65536 815.7 / 13.58 823.6 / 13.54

All 32 frontiers agree within ≤1.1% (plain decode never enters the DSpark scheduler; the drift is run-to-run noise — the main sweep ran first on a cold server).

Metal defaults resolve to the same 3/4/7 values as before, so Metal behavior is unchanged by construction; the change builds clean on macOS (make) and CPU (make cpu). I don't have a Metal machine with the model to re-run the Metal speed check — it would be great if someone can sanity-run it, though no change is expected.

Verification

make cuda-regression MODEL=...    # OK
DS4_BIN=./ds4 DS4_DSPARK_MODEL=... DS4_DSPARK_SUPPORT=... \
  DS4_DSPARK_FIXTURE_TOKENS=64 sh tests/dspark_acceptance_fixture.sh
# hello / redis / math / python_reverse / c_add: 5/5 output_match=1
make        # macOS build clean
make cpu    # builds

Related measurements: #773.

The scheduler pauses proposing for 3/4/7 cycles after a declined
proposal. Those lengths were tuned for Metal propose economics; on
CUDA (GB10, memory-bound decode at ~55-60 ms/token vs ~20 ms propose)
the pauses never win and cost up to 8% generation speed on edit and
refactor style prompts, where the model re-emits prompt spans and
DSpark accepts long drafts. Scope the three defaults by backend like
the existing DSpark confidence-gate default: Metal keeps 3/4/7, CUDA
defaults to 0/0/0. Env overrides are unchanged, and the pause counters
stay deterministic cycle counts, so greedy DSpark output remains
reproducible.

Benchmarks (DGX Spark GB10, IQ2XXS+w2Q2K quant, --temp 0 --nothink,
128 tokens, medians of 3, old defaults restored via env on the same
binary): edit 17.91 -> 19.41 t/s, refactor 19.62 -> 21.13, QA over a
passage 17.78 -> 18.42, code 18.67 -> 18.97, prose and math unchanged
within noise. make cuda-regression OK, DSpark acceptance fixture 5/5
output_match=1, make cpu builds, macOS build clean.
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.

1 participant