Repository navigation
scheduler: re-measure a full window after a regime change before the MTP gate probes (concurrency-sweep bimodal on main) - #200
Merged
Conversation
…MTP gate probes After a width- or depth-regime change the gate pulled its probe forward so hard that the first in-regime step closed a one-step window, and that single step replaced the current mode's throughput baseline. When a batch jumps from width 1 straight into a wider bucket (every prefill landed before the first batched step), that step is the bootstrap: one token per sequence plus lazy CUDA-graph captures. On the concurrency-sweep gate (nvidia/Qwen3.8-27B-NVFP4) it read 33.5 tok/s while verify was delivering ~70, the serial probe read 56.4, and the gate switched the C=8 cell to plain decode (run-1792544951131605812 on main e29809d). Whether the jump is 1->8 or 2/4->8 is a prefill/decode timing race, which is why C=8 came out as either ~54 or ~47 tok/s against the 50.5 floor on main and on every branch measured. In the six runs whose server logs were read, all six slow cells carry that switch at their start and no fast cell does. The current mode now re-measures over one full window in the new regime before the probe opens, and arbitration waits until neither baseline is stale, so it only ever compares two same-regime, full-window numbers. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This was referenced Oct 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The concurrency-sweep gate (
nvidia/Qwen3.8-27B-NVFP4) is bimodal on main. C=8 reads either ~54 or ~47 aggregate tok/s against a 50.5 floor, on main and on every branch measured:e29809db95ddfabb6eCause: the MTP throughput gate, not the model or the kernels.
MTP gate: switching Mtp -> Serialat its start, and no fast cell has one.note_width()pulls the probe forward so far that the first in-regime step closes a one-step window. That single step replaces the current mode's EWMA.switching Mtp -> Serial (current 33.5 tok/s vs other 56.4 tok/s, margin 8.2, depth=734), while verify was delivering ~70 tok/s (8 / 0.113 s TPOT).Fix (
crates/spark-server/src/scheduler/mtp_gate.rs):WINDOW_STEPSwindow before the probe opens.WINDOW_STEPS' own doc already says one window "amortizes bootstrap/propose transients"; the one-step close violated that.arbitratenow refuses while either baseline is stale. Previously a probe that straddled a regime change could count a losing window: a fresh other-mode number against a stale current one.Tests (
mtp_gate/tests.rs):one_bootstrap_step_cannot_set_a_new_regime_baselinereplays the production cell's walls and token counts. On the old gate it switches to Serial; with the fix it stays Mtp.stale_current_baseline_cannot_count_a_losing_window.Evidence
All on sparky (GB10), 2026-10-21,
nvidia/Qwen3.8-27B-NVFP4through its own gate recipe (--pull-request-gate), interleaved, 180 s cooldown before every run. Fix =e29809db9+ this commit (binary sha256cd3630581c3ec0a9); main =e29809db9(98d17fab2a3ae5cc). Logs:~/code/perf/nq-gatefix/.concurrency-sweep, gate auto (default): aggregate tok/s; floors 16.2 / 33.5 / 50.5 / 72.0
run-1792567787441788471run-1792568223349315164run-1792568634145330563run-1792569078596206207run-1792569487975168857run-1792569926943462361run-1792570337375061294run-1792570743391640982ATLAS_MTP_GATE_FORCE=1), the same box earlier tonight gave C=8 56.8–58.5 and C=16 79.4–79.9 on both main and qwen4_exp: serve NVIDIA's Qwen3.8-Flash-Next FP4-Local on its native formats (one GB10) #195, 6/6 PASS. The fix sits just under that because the gate still pays its periodic serial refresh.decode-floor (C=1): fix 25.2 tok/s median over 3 pinned runs (accept_len_mean 2.76), main 25.2 tok/s (2.76). Identical, as expected: C=1 never changes width regime.
All numbers are observed under this fingerprint, 5 and 3 repeats. The mechanism is shown by the switch lines, not inferred from the throughput.
Test plan
cargo test -p spark-server --bins mtp_gate: red on the unfixed gate, green with the fixcargo fmt --all -- --check,cargo clippy -p spark-server --testsGenerated with Devin