[Runner] Never pad a step past max_num_batched_tokens - #3466
Open
gutianyu-google wants to merge 2 commits into
Open
[Runner] Never pad a step past max_num_batched_tokens#3466gutianyu-google wants to merge 2 commits into
gutianyu-google wants to merge 2 commits into
Conversation
gutianyu-google
force-pushed
the
fix/token-paddings-include-max-batched
branch
2 times, most recently
from
September 4, 2026 18:49
12b3330 to
dfb2979
Compare
gutianyu-google
marked this pull request as ready for review
September 4, 2026 18:55
gutianyu-google
requested review from
a1yssan13,
gxd3,
jrplatin,
kyuyeunk,
mrjunwan-lang,
sixiang-google and
wenxindongwork
as code owners
September 4, 2026 18:55
wenxindongwork
approved these changes
Sep 4, 2026
Collaborator
|
btw, you can also just use |
gutianyu-google
force-pushed
the
fix/token-paddings-include-max-batched
branch
from
September 4, 2026 23:18
dfb2979 to
6549988
Compare
get_token_paddings() builds the token buckets by doubling (or by VLLM_TPU_BUCKET_PADDING_GAP steps) until the budget is covered, so a full chunked-prefill step is padded to the next bucket above max_num_batched_tokens * dp whenever the budget is not itself a bucket. With max_num_batched_tokens=16640 and dp=16 a 16640-token chunk runs at the 32768-token shape per rank (97% padding). On TPU7x with Qwen3-0.6B (TP8 x DP16, page_size 128) that padded shape also returns wrong last-position logits: the first sampled token of ~90% of requests is garbage before generation recovers on the next decode step. The same chunk padded to 18432, 16384 or 4096 is correct. Add include_max_token_size to get_token_paddings() and enable it for the runner's token-bucket table so the exact budget is always a bucket. Larger buckets are kept, so max_num_tokens and pre-allocation are unchanged. Validated end-to-end (MaxText/tunix GRPO, 2048 requests): first token correct 2048/2048 with the patch vs 0-256/2048 without, and the prefill step is ~4 s/step faster than the VLLM_TPU_BUCKET_PADDING_GAP=32768 workaround. Signed-off-by: Tianyu Gu <tianyugworker@gmail.com>
gutianyu-google
force-pushed
the
fix/token-paddings-include-max-batched
branch
from
September 7, 2026 05:22
6549988 to
83a4e61
Compare
…ets above it Instead of a new flag on get_token_paddings, the runner now builds its bucket list with build_token_paddings: the generated buckets capped at the budget, the budget itself (rounded up to a multiple of the minimum bucket), and the user's compilation_sizes, merged and deduplicated in one place. Buckets above the budget are unreachable (the scheduler never exceeds it) and only cost a compile each and oversize the preallocated token buffers. A budget that is already a bucket yields the stock list.
Contributor
Author
|
Done, thanks! |
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.
[Runner] Never pad a step past
max_num_batched_tokensProblem
TPUModelRunnerbuildsnum_tokens_paddingswithget_token_paddings(min, max_num_batched_tokens * dp_size, gap).With the default
VLLM_TPU_BUCKET_PADDING_GAP=0the buckets double until they cover the budget, so a fullchunked-prefill step is padded to the next power of two whenever the budget is not one itself. Example
(Qwen3-0.6B, TP8 x DP16,
max_num_batched_tokens=16640): a 16640-token prefill chunk runs at the 32768-tokenshape per rank — 97% padding.
On that shape we also observe a silent correctness problem: the last-position logits of the padded prefill step
are wrong, so the first sampled token of ~90% of requests is garbage (
tắc,iquement,人力, ...) beforethe model recovers on the next decode step. Reproduced on TPU7x with page_size 128, 1 KV head/device
(tpu-inference @ be9cdf0): first token correct for 0/2048 requests at the 32768 shape, 2048/2048 when the
same chunk is padded to 18432 (
VLLM_TPU_BUCKET_PADDING_GAP=32768), 16384 (max_num_batched_tokens=12544),or 4096. The kernel-level cause at the 32768 shape is not localized here; this PR removes the trigger
and the padding waste.
Change
runner/utils.py::build_token_paddings(min, max, gap, additional_sizes): the runner's bucket list is now the generatedbuckets capped at the budget (rounded up to a multiple of
min_token_size), the budget itself, and the user'sadditional_config.compilation_sizes, merged and deduplicated in one place. The budget enters through the same mergethat already handled
compilation_sizes; no new flag onget_token_paddings, which is unchanged.max_num_batched_tokensper rank, sothey are unreachable and only cost a compile each and oversize the preallocated token buffers (
max_num_tokensisderived from the last bucket). With a 16640 budget the list ends
..., 8192, 16384, 16640instead of..., 8192, 16384, 32768. User-suppliedcompilation_sizesare kept as given, even above the budget.runner/tpu_runner.py: builds the list through the helper. A budget that is already a bucket (e.g. 8192, 16384)yields the stock list, so those configurations see no change.
tests/runner/test_utils.py: capped list for the exponential and bucketed gaps, stock list for a power-of-two budget,rounding of the budget, and
compilation_sizespreserved and deduplicated.Validation
get_token_paddings.first token correct for 2048/2048 requests (LENDIST census), generation distribution identical to the
VLLM_TPU_BUCKET_PADDING_GAP=32768workaround; without it 0-256/2048. Run 51 (this patch, no env): first token correct 2048/2048 at steps 0 and 1; 29.3% / osl 4477 at step 0 (workaround run: 27.5% / 4391 — same distribution, different samples); step-1 engine_generate 84.5 s vs 88.5 s with the 18432 workaround and 82.9 s on the corrupted 32768 shape, i.e. the exact-budget bucket also pads less than the gap workaround.