Repository navigation
perf(activevln): grammar-trie speculation and lossless throughput - #11
Merged
hootandy321 merged 8 commits intoOct 21, 2026
Merged
hootandy321 merged 8 commits into
hootandy321 merged 8 commits into
Conversation
ruff format --check flags one expression in batching_activevln.py and one call in modeling_activevln.py on this base. Formatting only. Signed-off-by: longxmas <1185267696@qq.com>
The phrase tree (tree_decode) drafts a few common phrases, advances one token per forward once a reply leaves the tree, and supports greedy decoding only. With grammar_tree_budget=N the batched runtime drafts the whole reply instead: a trie over the R2R/RxR action grammar, ranked by an online prior built from the policy's own past replies, of which the N most likely nodes are verified in one tree-attention forward. Acceptance is exact. Greedy decoding keeps the argmax path and sampling uses standard rejection sampling against the draft, so the output distribution is unchanged and the grammar tree also works with do_sample. The phrase tree still rejects sampling. R2R, 64 episodes, B=4 greedy: decode forwards per batch drop from 2.95 with the phrase tree to 2.22 at N=32, and throughput rises from 19.75 to 22.28 frames/s (10.32 without a tree). With the official sampling settings the grammar tree reaches 22.28 frames/s, 2.23x the sampling baseline. Signed-off-by: longxmas <1185267696@qq.com>
Opt-in runtime options for ActiveVLN batched replay; the defaults keep the previous path. - gpu_preprocess: uint8 frames are resized and normalised on the GPU by a bit-exact port of the slow Qwen2-VL image processor (Pillow bicubic fixed point, float64 rescale, float32 normalise). Tokens and positions are computed once per prompt text and frame size. - attention_kernel="gqa": split-KV Triton kernel that packs the query heads sharing a KV head into one program; probabilities stay FP32-faithful (probability_parts=3). - skip_padded_queries: GQA programs whose rows are all padding do no KV work; live rows keep the exact partition and reduction order. - incremental_kv_commit: owned per-row KV buffers copy only the new turn instead of the whole history. - vision_kernel="segmented"/"fused": attention inside each window or image with FP32-faithful probabilities instead of a dense masked SDPA; "fused" adds a fused QKV split + vision RoPE kernel and the rounded RMSNorm/SwiGLU kernels. - benchmark_batch: uint8_observations hands the exact uint8 source frame to the processor; timings split host and device preparation. On R2R (64 episodes, 4089 frames, greedy, grammar tree budget 32) gpu_preprocess, incremental_kv_commit, uint8 observations and skip_padded_queries reproduce their reference actions frame for frame; gqa and the vision kernels change BF16 reduction order only. Signed-off-by: longxmas <1185267696@qq.com>
Each decode step now makes one pinned non-blocking upload, memoizes stop reasons, builds history pads from seen tokens, keeps scores as float lists, compacts the pooled KV in batches and reuses the commit layer views. Replays are bitwise identical (4089/4089 at B=4 and B=8). benchmark_batch also accepts batch sizes 12 and 16. Signed-off-by: longxmas <1185267696@qq.com>
Prefill padded every row of a batch to the longest turn: 18.8% of the text-prefill tokens at B=8. With packed_prefill, the turns of a batch run as one row of back-to-back tokens, padded only to a token bucket. - gqa_split_kv_attention gains a packed mode: a program table of (row, query block) entries, per-row token starts and a device query extent. The extent equals the padded query length, so split partitions and results match the padded launch bit for bit. - _text_forward writes packed KV with index_copy_ into per-token pool slots; bucket-padding tokens go to spare slots past the row capacities. - Graphs are keyed by (token bucket, key bound per split count) and share static input buffers. R2R replay (4089 frames, same-time baselines): B=8 N=23 39.56 -> 41.97 fps, B=4 N=31 34.48 -> 35.92 fps. Per-call divergence 7.1% / 7.5%, within the batch-size noise floor (7.9-11.1%); no fallbacks; peak memory lower. Signed-off-by: longxmas <1185267696@qq.com>
With gpu_preprocess, tokens and positions are cached per prompt, but each cache miss (two per episode) still ran the Qwen processor's CPU image pipeline only to discard its patches: 7.0 ms per miss. - ActiveVLNProcessor.process_turn_tokens caches the image grid per frame size and expands and tokenizes the text exactly as the Qwen processor does: 0.85 ms per miss, identical fields on all 128 R2R turns checked. - prepare_devices moves every row's token tensors in one pinned, non-blocking transfer instead of four synchronous copies per row; frames go through a pinned staging buffer. R2R replay outputs are identical frame for frame (4089/4089). Preparation drops from 0.85 to 0.64 ms/frame at B=8 and from 1.09 to 0.71 at B=4 (41.78 -> 42.36 fps at B=8 N=23). Signed-off-by: longxmas <1185267696@qq.com>
With query_lengths, keys at or past position + count are masked for every live query, yet the GQA kernel still loaded their values, so a NaN left in those slots reached the output as 0 * NaN. Packed prefill writes its padding tokens, whose outputs are unspecified, to spare slots that a pool relocation can later hand to a row; the row then emits all-zero tokens from the step its context reaches them, and so does the next episode in that row. Partitions still divide the full extent, so live outputs are bitwise unchanged whenever the stale slots are finite. The failure surfaced on R2R B=8 N=23 (episode 64 from step 83) and B=4 N=31 (episode 48 from step 9) only after an unrelated change to the projection code. Signed-off-by: longxmas <1185267696@qq.com>
Tree verification and singleton decode run every linear on 24-192 rows, where cuBLAS leaves 10-35% of the 4090's bandwidth unused. With decode_linear=True those projections use Triton kernels that accumulate in FP32 in sequential K order without split-K, so results depend on neither tiles nor row count and differ from cuBLAS only by output rounding. Q, K and V share one launch; gate and up share one with the rounded SwiGLU in the epilogue, bitwise equal to rounded_swiglu of the two projections. Prefill row counts and narrow weights stay on cuBLAS. R2R replay, on vs off on the same GPU (two GPUs each): B=8 N=23 +1.8% / +2.0% (best 43.34 fps), B=4 N=31 +3.3% / +2.0% (best 37.58 fps), B=8 N=15 +3.0% / +2.0% (best 43.62 fps); decode drops 0.4-0.8 ms/frame. Per-call divergence is 5.5-7.7%, below the batch-size noise floor (7.9-11.1%). With the option off, outputs are identical frame for frame to the parent commit. Signed-off-by: longxmas <1185267696@qq.com>
yufoo1
self-requested a review
October 20, 2026 17:46
hootandy321
merged commit Oct 21, 2026
d288bad
into
bench/activevln-rxr-oom-fix
1 of 3 checks passed
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
Test plan
pytestActiveVLN / GQA / vision / decode_linear suites on the lab 4090 envattention_kernel=gqa,gpu_preprocess,packed_prefill,decode_linear, …)