[None][perf] Add batched-pybind fast-path in TorchSampler.update_requests for gpt-oss-120b - #16564
Conversation
…-perf-sanity-py-test-e2-c87588) Signed-off-by: Chenfei Zhang <chenfeiz@nvidia.com>
📝 WalkthroughWalkthrough
ChangesGreedy sampler batch fast path
Estimated code review effort: 3 (Moderate) | ~15–30 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
tongyuantongyu
left a comment
There was a problem hiding this comment.
LGTM. I updated the description a bit: Non beam search does not mean greedy only, sampling such as top-k is also eligible.
Empirical A/B across gpt-oss GB200 cases (fix wheel vs
|
| Case | Mode | Conc | N | ToT mean | Fix mean | Gain% | CV_tot | CV_fix | t-stat | Verdict |
|---|---|---|---|---|---|---|---|---|---|---|
| gpt-oss ctx_only con=4 | ctx_only | 4 | 0/0 | — | — | — | — | — | — | incomplete |
| gpt-oss ctx_only con=512 | ctx_only | 512 | 0/0 | — | — | — | — | — | — | incomplete |
| gpt-oss e2e con=1024 | e2e | 1024 | 3/3 | 17004.44 | 17107.86 | +0.61% | 0.99% | 1.97% | +0.48 × | in_noise |
| gpt-oss gen_only con=1024 | gen_only | 1024 | 6/6 | 13187.43 | 13055.73 | -1.00% | 1.36% | 1.12% | -1.39 × | in_noise |
| gpt-oss gen_only con=128 | gen_only | 128 | 3/3 | 7509.22 | 7585.61 | +1.02% | 0.41% | 0.65% | +2.28 × | marginal_gain_noisy |
| gpt-oss gen_only con=4 | gen_only | 4 | 3/3 | 901.68 | 927.56 | +2.87% | 3.40% | 3.00% | +1.08 × | success_noisy |
| PENALTY deepseek-v32 MTP1 con=2048 | gen_only | 2048 | 3/3 | 27260.28 | 27341.83 | +0.30% | 1.22% | 0.99% | +0.33 × | in_noise |
(Skipped: gen_only con=512 dep2 — already measured at +2.26% in the original PR body.)
Key takeaways
- No statistically significant regression on any gpt-oss case, including
gen_only con=1024(which came in -1% butt=-1.39at N=6 fails p<0.05). gen_only con=128shows the cleanest signal:+1.02%with tight CV (0.41% / 0.65%) andt=+2.28(borderline significant at N=3).e2e con=1024andgen_only con=4trend positive but within noise.con=4at CV 3% is expected — batch=4 sampler tail is only tens of μs, so the win is small in absolute terms and drowned by iter-time variance.- ctx_only cases are unmeasurable via
output_token_throughput— the harness runs prefill only, no gen loop → no bench log → no throughput metric. The fast-path is theoretically ≤ 0.3% here (sampler fires once per request for the first-token emit), well below the noise floor. - Penalty probe (deepseek-v32 MTP1 con=2048):
+0.30%,t=+0.33. The eligibility check runs and rejects at check 3 (get_spec_tree_manager() != None) on every gen iter — no detectable cost. See threaded reply for the detailed breakdown.
Method
For every (case, side) pair I:
- Provisioned a per-rep dir on lyris (no rebuild — same two wheels).
- Ran a parametrized
slurm-disaggregated-ci-pytest/trigger.shwith--wheel-dir <tot|fix> --run-count 1. - Grepped
Output token throughput (tok/s)fromdisagg-*/trtllm-benchmark.0.0.log. - Computed mean, stdev, CV, and Welch t on the resulting per-rep lists.
Raw per-rep numbers and the launcher/parser scripts are in out/gpt-oss-120b-seeds/comparison/ in my repair-bot checkout.
Fixes pre-commit type-check (mypy) failure: sampler.py:3687: error: Invalid index type "int | None" for "list[list[list[int]]]"; expected type "SupportsIndex" [index] The batched-pybind fast-path indexes new_tokens_step0 and finish_reasons by req.py_seq_slot, which is typed int | None. Narrow to int via an assert (same pattern the pre-existing code uses at sampler.py:2566, 2723, 2737, 3571). Runtime-invariant: py_seq_slot is always assigned before a request reaches the sampler (see set_first_gen_scores at sampler.py:2723). Signed-off-by: Chenfei Zhang <chenfeiz@nvidia.com>
|
/bot run --disable-fail-fast |
|
PR_Github #60602 [ run ] triggered by Bot. Commit: |
|
PR_Github #60602 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #60681 [ run ] triggered by Bot. Commit: |
|
PR_Github #60681 [ run ] completed with state
|
|
/bot run --disable-fail-fast |
|
PR_Github #60856 [ run ] triggered by Bot. Commit: |
|
PR_Github #60856 [ run ] completed with state |
…ests for gpt-oss-120b (NVIDIA#16564) Signed-off-by: Chenfei Zhang <chenfeiz@nvidia.com>
Summary
disagg-gen_only-*workloads forgpt-oss-120b-fp4on GB200,the gen-worker per-iter bubble (~8.8 ms) is dominated by the host-side sampler
tail in
TorchSampler.update_requests— a Python loop that fires 256 per-requestpybind chatter calls (
req.add_new_tokenetc.) afterstate.sampler_event.synchronize().sampler.py:3654. When the wholebatch requires no beam search, no logprobs, no draft tokens, no stop-word
lists, and no speculative-tree manager, collapse the per-request loop into a
single batched
add_new_tokens_to_requests(...)call plus one linear finish-reasonscan. Cached eligibility flag (
_batch_fastpath_eligible) is set once in__init__to avoid a property call per iter. Falls through to the unchangedper-request path on any invariant break; runs entirely post-
sampler_event.synchronize()so CUDA-graph capture/replay is unaffected.
output_token_throughput(higher is better)[9002.96, 9135.99, 9318.70], CV=1.73%Test plan
no
pytest.skip/time.sleep, no CUDA-graph disable, noexcept:fallback).finish_if_reason's{END_ID, LENGTH, STOP_WORDS}set; bookkeeping (py_num_accepted_draft_tokens=0,py_rewind_len=0,py_decoding_iter += 1) mirrors the existing MTP=0 branch.add_new_tokens_to_requestsbatched pybind is already used byTRTLLMSampler(see
sampler.py:5125); no new C++ binding introduced.Automation
Automated fix generated by repair-bot
auto_perf_stabilizeworkflow.Run key:
perfstab-perf-test-perf-sanity-py-test-e2-c87588Test case:
perf/test_perf_sanity.py::test_e2e[disagg-gen_only-gb200_gpt-oss-120b-fp4_8k1k_con512_ctx1_tp1_gen1_dep2_eplb0_mtp0_ccb-NIXL]Summary by CodeRabbit