Reuse DSpark snapshots for immediate session rewinds - #1003
emilianbold wants to merge 1 commit into
Conversation
Restore the last frontier and replay the retained tail on supported Metal sessions, avoiding full-prefix rebuilds. Preserve safe fallback behavior and add rollback-miss tests.
|
Thanks @emilianbold for this great PR! The benchmark numbers (111 ms median vs up to 100s full prefill rebuilds) match the severe Degenerate Rebuild latency we observed on long-context tool-calling sessions on Apple Silicon. This provides the exact engine-level complement needed for PR #1000's server-level stop-token rollback. I went through the implementation and ran local testing on Apple Silicon. Here are a couple of architectural observations and suggestions that could make this even more powerful: 1. Zero-Replay Frontier Rollback when
|
|
@aaa2015 thanks the the feedback. Some of that can be follow-ups but none seem mandatory. I think the current PR has the best size to be reasonably reviewed and merged. |
Speculative decoding can become slow when the server decides to roll back to a token boundary based on the model's protocol (e.g. near tool-call boundaries). For DeepSeek, truncating the token history alone cannot restore the compressed/recurrent state, so the fallback requires rebuilding the retained prefix.
Rollback for speculative rejection is already handled inside the inference engine using snapshots. However, that rollback opportunity was not retained for a subsequent server-requested rewind.
This tiny PR retains a weak handle to the latest usable snapshot (only one) until it is consumed or an operation invalidates its dependencies. It reuses existing snapshot buffers, adding only a small metadata record. This allows a server-triggered rollback to restore the frontier and replay a short tail. On a miss, it preserves the existing truncate-and-invalidate behavior.
The initial fast path covers fully accepted greedy-verifier blocks on resident, text-only, non-TP Metal DSpark sessions.
Experiments demonstrated degenerate cases in heavy tool-use sessions where, with snapshot reuse deliberately disabled, prefix rebuilding consumed over half of the observed session wall time. Individual rebuilds became more expensive as context grew.
This does not mean speculative decoding should be the default. We gain speed in tool-call generation, but I do not see a clear overall advantage over plain decoding on my machine. (Selectively speculating during tool-call generation might do better, but that is a separate idea not implemented here.)
Reviewer Numbers
Measured on an M5 Max, 40 GPU cores, 128 GB RAM, using Flash 0731 IQ2XXS-w2Q2K and matching DSpark support.
For a 4,095-token starting prefix, the conditional rewind benchmark measured 26ms for 1 token, 132 ms for 5 tokens.
The real-use logs provide the stronger motivation:
Note the real-use logs were from different sessions, so do not present their total-duration difference as a measured end-to-end speedup.