feat(autotune): separate general and decode attention warmup - #1549
Merged
Conversation
Rebuild decode benchmark inputs using the configured KV length, preserve real request lengths for lookup, and bucket run keys by 512 tokens. Include sliding windows in static keys and support omitted argument defaults. Validated with 168 tests, cold-start and restart service checks covering 32 requests, and 8 FP32 numerical comparisons.
Rebuild shared-group KV inputs for stage1 and initialized intermediate results for stage2 before decode attention tuning. Use the configured KV length for tuning keys and the actual request length for normal lookup, while preserving stage1 BLOCK_N and stage2 buffer capacity. Add coverage for rebuilt inputs, effective-block keys, numerical accuracy, CUDA Graph execution, and cached configuration reuse. Validation: 250 unit/regression tests; Qwen3-4B + EAGLE3 service tuning, 8K/16K FP32 attention checks, and cache reuse after restart. Stage2-only service outputs match exactly; changing stage1 BLOCK_N can change BF16 greedy outputs.
Rebuild request mappings and lengths for int4 decode tuning while preserving packed K/V, quantization scales, and intermediate buffer layouts. Bucket run keys by 512 tokens and retain actual KV lengths before CUDA Graph capture. Bump the kernel config version to invalidate old tuning entries. Replace FA3 wrapper kwargs with explicit softmax_scale and return_softmax_lse parameters. Validation: 65 int4/autotuner regression checks and 34 FA3 wrapper tests; Qwen3-4B int4 service outputs and logprobs match across 23 cases, selected configs pass 8K/16K FP32 checks, and restart reuses the cached configs.
Rebuild request mappings and sequence lengths for decode attention searches using the configured target length, defaulting to 16K. Bucket run keys by 512 tokens and preserve the actual decode length before CUDA graph updates. Keep int8 caches, scales and intermediate layouts intact, and bump the normal int8 stage1 configuration version to v4. Validation: 150 tests passed. All 48 candidates passed 96 FP32 reference comparisons at 8K and 16K. Service checks covered long and concurrent requests, CUDA graph capture and configuration reuse after restart. Identical configurations produced identical tokens in all 23 service pairs; selected configurations can change greedy output relative to defaults.
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.
Problem
The existing autotuner uses a single model warmup phase. That works for general/prefill kernels, but decode attention is difficult to tune correctly:
Changes
This PR separates autotuning into
GENERALandDECODE_ATTENTIONwarmup phases.Before each decode CUDA Graph is captured, LightLLM runs one ordinary decode forward under the decode-attention warmup scope. Only kernels marked as
DECODE_ATTENTIONmay search configurations in this scope. The selected configuration is then used by the following CUDA Graph capture.The autotuner also gains:
rebuild_input_funcfor constructing representative benchmark inputs outside graph capture;warmup_all_exist_configswitch for stateful kernels that cannot safely replay every cached configuration;Decode attention treats
FORCE_AUTOTUNEas adaptive tuning so identical kernels used by many layers do not repeatedly retune. To force a fresh decode search, delete that kernel's cached configuration directory before restarting.After all startup argument normalization, an enabled decode CUDA Graph also caps
graph_max_batch_sizeatrunning_max_req_size. Larger graph batches cannot be reached by the scheduler and only consume extra capture time and GPU memory. The original value is retained when CUDA Graph is disabled.Covered decode kernels
Representative-input tuning is added for:
num_splits);The representative KV length is controlled by:
The default is 32K. KV-length run keys are bucketed where appropriate to reduce redundant searches while normal execution still selects configurations using the real request length.
Decode autotuning is supported only during service startup warmup. It is not performed for live runtime requests. The MTP recurrent linear-attention kernel therefore reuses the startup dummy state pool and disables cached-configuration prewarming; cloning its full persistent state pool would substantially increase memory use and distort benchmark timings.
Intermediate stage outputs that are fully overwritten are also excluded from
mutates_argsto avoid unnecessary clones during tuning.Validation
Unit and kernel validation:
git diff --check, Python compilation, Black, and Flake8 pass;Service validation used Qwen3.5-27B, native MTP step 3, BF16 weights, FP32 SSM state, FA3 full attention, Triton linear attention, NVIDIA H200 GPUs, and decode CUDA Graphs:
The service matrix was run with a 16K decode autotune target before the default changed to 32K. The new 32K default is covered by the targeted autotune key and input-construction tests; it has not been rerun through the full service matrix.
All requests completed successfully with finite log probabilities. Tuning disabled produced no operator configuration files; adaptive tuning produced 12 expected FA3 and MTP linear-attention configuration files.
The measured throughput effect was workload-dependent rather than a universal improvement. Across the initial matrix, output throughput ranged from -10.7% to +6.1%. The TP2/MMLU/concurrency-32 regression was repeated three times and averaged -5.5%. With prefill CUDA Graph enabled, the same case averaged -0.03%. Score changes across the 200-sample comparisons ranged from -2.0 to +0.5 percentage points; the sample size and batching-related output variation do not establish a tuning-induced accuracy change.
The full service matrix was run at commit
361fdcd5. Later changes that reuse stage-2 inputs, avoid cloning overwrite-only outputs, document the stateful warmup exception, and rename the pytest modules were covered by their targeted kernel and graph tests.