Repository navigation
[Performance]: Cache group-invariant DSA-CP drafting metadata across kv-cache groups - #14916
Conversation
|
Warning Gemini encountered an error creating the summary. You can try again by commenting |
|
👋 Hi! Thank you for contributing to the vLLM Ascend project. The following points will speed up your PR merge:
If CI fails, you can run linting and testing checks locally according Contributing and Testing. |
pisceskkk
left a comment
There was a problem hiding this comment.
LGTM.
btw, do you have a report about acceptance ratio compared between w/ and w/o this pr?
Thank you for your review. I have re-added the benchmark test results for DSpark's acceptance rate. |
|
This pull request has conflicts, please resolve those before we can evaluate the pull request. |
I’m not sure what the baseline acceptance rate is for this model with DSpark, but this number looks a bit low to me. It might be better to include a baseline for comparison. |
Yes, I used a random dataset, so the acceptance rate will be lower. The acceptance rate results are similar for /w and /wo. ============ Serving Benchmark Result ============ Failed requests: 0 Maximum request concurrency: 3 Benchmark duration (s): 276.57 Total input tokens: 5000400 Total generated tokens: 35000 Request throughput (req/s): 0.36 Output token throughput (tok/s): 126.55 Peak output token throughput (tok/s): 64.00 Peak concurrent requests: 5.00 Total token throughput (tok/s): 18206.57 ---------------Time to First Token---------------- ---------------Speculative Decoding--------------- Acceptance rate (%): 28.22 Acceptance length: 2.98 Drafts: 11807 Draft tokens: 82649 Accepted tokens: 23321 Per-position acceptance (%): Position 0: 58.32 Position 1: 39.78 Position 2: 30.63 Position 3: 24.38 Position 4: 20.23 Position 5: 14.52 Position 6: 9.66 ==================================================== Our performance in real-world data testing was similar. |
|
/rerun Rerun (failed jobs only):
|
d88a79d to
6f95598
Compare
…kv-cache groups Signed-off-by: frankie <wangyongsheng686@gmail.com>
6f95598 to
e6e5064
Compare
|
/rerun Rerun (failed jobs only):
|
LGTM, I have no other question, thanks for contribution! |
Thank you for your review. The current PR is failing to run successfully in CI testing on an A3 8-card CPU. Could you please take a look? |
|
/rerun [Bot]: rerun completed. Rerun (failed jobs only):
|
- Pad seq_lens_cpu to the graph-dispatch request count so batch dims stay stable across ACL graph capture/replay - Cache SAS metadata in per-draft-index preallocated buffers for address stability - Use per-draft-index RoPE cache (use_cache=True) so cos/sin tensor addresses stay stable across draft steps - Replace magic number 1024 with SAS_METADATA_SIZE constant - Add no-op update_graph_params hook for ACL graph dispatch Adapted to the cross-kv-cache-group drafting metadata cache from vllm-project#14916: per-draft stable buffers are filled after the shared-cache lookup so both cache-hit and cache-miss paths end up with stable tensor addresses. Signed-off-by: frankie <wangyongsheng686@gmail.com>
…kv-cache groups (vllm-project#14916) ### What this PR does / why we need it? Only `format_dsa_slot_mapping` and `build_dspark_swa_indices` (which depend on each group's `block_table` / `slot_mapping`) genuinely differ per group, so the two calls cannot be merged into one. Instead, this PR makes the second call nearly free by reusing the existing `common_ratio_to_sas_metadata` cross-group sharing convention and computing every group-invariant sub-result once per step. Key changes: - `LLMBaseProposer.build_draft_attn_metadata`: creates **one shared dict** before the group loop and passes it **unconditionally** to every group's `build_for_drafting` (DSpark branch) and `build()` (non-DSpark branch). Previously the `build()` branch was gated on `use_compress` and created a fresh dict per group, which defeated `build()`'s built-in cross-group cache and did not satisfy its `assert common_ratio_to_sas_metadata is not None`. - `AscendDSACPMetadataBuilder.build_for_drafting` / `build_req_metadata_for_drafting`: consume the shared dict as a cross-group cache isolated by `("draft_for_drafting", draft_index)`, reusing split statistics, `input_positions`/`cos`/`sin`, device/CPU local token metadata, `max_local_*`, `local_cos`/`local_sin`, `start_pos`, the `seq_lens_cpu` sync fallback, A5 `cu_seqlens_ori_kv`, and the `sas_metadata` op result (guarded by `num_heads`/`head_dim`); a debug log is emitted on cache hit. Correctness: cached items depend only on group-invariant fields of `common_attn_metadata` (`positions` / `seq_lens` / `query_start_loc`), never on per-group `block_table` / `slot_mapping`; shared tensors are read-only consumers of the returned metadata. Paths without a shared dict (e.g. `attn_update_stack_num_spec_norm`, which receives per-group-updated metadata, and `dummy_run`, which creates a fresh dict per draft step) keep an empty cache and behave exactly as before. dataset gsm8k 07:30:13 PM run_single_eval-d47 prefect.task_runs 07:30:13 PM run_single_eval-d47 prefect.task_runs Overall report table: +---------+-----------+----------+----------+-------+---------+---------+ | Model | Dataset | Metric | Subset | Num | Score | Cat.0 | +=========+===========+==========+==========+=======+=========+=========+ | illm | gsm8k | mean_acc | main | 1319 | 0.9682 | default | +---------+-----------+----------+----------+-------+---------+---------+ ### Does this PR introduce _any_ user-facing change? No. This is a pure performance optimization on the speculative-decoding metadata-building path; no API/interface/behavior change. ### Gain The second build_for_drafting time was reduced from 3.5ms to 1.2ms. ## Before <img width="1391" height="735" alt="99965a92e8edbe18169541a601d9fd1b" src="https://github.com/user-attachments/assets/4f9d6f17-71cf-429b-ab06-fe7f9262f41f" /> ## After <img width="1404" height="803" alt="74fec5ffc9257614e05f86d6d7cd9b2f" src="https://github.com/user-attachments/assets/48bee76d-c069-4afa-8c26-e39f0d1d05b8" /> - vLLM main: vllm-project/vllm@ba07e4a Signed-off-by: frankie <wangyongsheng686@gmail.com>
- Pad seq_lens_cpu to the graph-dispatch request count so batch dims stay stable across ACL graph capture/replay - Cache SAS metadata in per-draft-index preallocated buffers for address stability - Use per-draft-index RoPE cache (use_cache=True) so cos/sin tensor addresses stay stable across draft steps - Replace magic number 1024 with SAS_METADATA_SIZE constant - Add no-op update_graph_params hook for ACL graph dispatch Adapted to the cross-kv-cache-group drafting metadata cache from vllm-project#14916: per-draft stable buffers are filled after the shared-cache lookup so both cache-hit and cache-miss paths end up with stable tensor addresses. Signed-off-by: frankie <wangyongsheng686@gmail.com>
- Pad seq_lens_cpu to the graph-dispatch request count so batch dims stay stable across ACL graph capture/replay - Cache SAS metadata in per-draft-index preallocated buffers for address stability - Use per-draft-index RoPE cache (use_cache=True) so cos/sin tensor addresses stay stable across draft steps - Replace magic number 1024 with SAS_METADATA_SIZE constant - Add no-op update_graph_params hook for ACL graph dispatch Adapted to the cross-kv-cache-group drafting metadata cache from vllm-project#14916: per-draft stable buffers are filled after the shared-cache lookup so both cache-hit and cache-miss paths end up with stable tensor addresses. Signed-off-by: frankie <wangyongsheng686@gmail.com>
…kv-cache groups (vllm-project#14916) ### What this PR does / why we need it? Only `format_dsa_slot_mapping` and `build_dspark_swa_indices` (which depend on each group's `block_table` / `slot_mapping`) genuinely differ per group, so the two calls cannot be merged into one. Instead, this PR makes the second call nearly free by reusing the existing `common_ratio_to_sas_metadata` cross-group sharing convention and computing every group-invariant sub-result once per step. Key changes: - `LLMBaseProposer.build_draft_attn_metadata`: creates **one shared dict** before the group loop and passes it **unconditionally** to every group's `build_for_drafting` (DSpark branch) and `build()` (non-DSpark branch). Previously the `build()` branch was gated on `use_compress` and created a fresh dict per group, which defeated `build()`'s built-in cross-group cache and did not satisfy its `assert common_ratio_to_sas_metadata is not None`. - `AscendDSACPMetadataBuilder.build_for_drafting` / `build_req_metadata_for_drafting`: consume the shared dict as a cross-group cache isolated by `("draft_for_drafting", draft_index)`, reusing split statistics, `input_positions`/`cos`/`sin`, device/CPU local token metadata, `max_local_*`, `local_cos`/`local_sin`, `start_pos`, the `seq_lens_cpu` sync fallback, A5 `cu_seqlens_ori_kv`, and the `sas_metadata` op result (guarded by `num_heads`/`head_dim`); a debug log is emitted on cache hit. Correctness: cached items depend only on group-invariant fields of `common_attn_metadata` (`positions` / `seq_lens` / `query_start_loc`), never on per-group `block_table` / `slot_mapping`; shared tensors are read-only consumers of the returned metadata. Paths without a shared dict (e.g. `attn_update_stack_num_spec_norm`, which receives per-group-updated metadata, and `dummy_run`, which creates a fresh dict per draft step) keep an empty cache and behave exactly as before. dataset gsm8k 07:30:13 PM run_single_eval-d47 prefect.task_runs 07:30:13 PM run_single_eval-d47 prefect.task_runs Overall report table: +---------+-----------+----------+----------+-------+---------+---------+ | Model | Dataset | Metric | Subset | Num | Score | Cat.0 | +=========+===========+==========+==========+=======+=========+=========+ | illm | gsm8k | mean_acc | main | 1319 | 0.9682 | default | +---------+-----------+----------+----------+-------+---------+---------+ ### Does this PR introduce _any_ user-facing change? No. This is a pure performance optimization on the speculative-decoding metadata-building path; no API/interface/behavior change. ### Gain The second build_for_drafting time was reduced from 3.5ms to 1.2ms. ## Before <img width="1391" height="735" alt="99965a92e8edbe18169541a601d9fd1b" src="https://github.com/user-attachments/assets/4f9d6f17-71cf-429b-ab06-fe7f9262f41f" /> ## After <img width="1404" height="803" alt="74fec5ffc9257614e05f86d6d7cd9b2f" src="https://github.com/user-attachments/assets/48bee76d-c069-4afa-8c26-e39f0d1d05b8" /> - vLLM main: vllm-project/vllm@ba07e4a Signed-off-by: frankie <wangyongsheng686@gmail.com>
What this PR does / why we need it?
Only
format_dsa_slot_mappingandbuild_dspark_swa_indices(which depend on each group'sblock_table/slot_mapping) genuinely differ per group, so the two calls cannot be merged into one. Instead, this PR makes the second call nearly free by reusing the existingcommon_ratio_to_sas_metadatacross-group sharing convention and computing every group-invariant sub-result once per step.Key changes:
LLMBaseProposer.build_draft_attn_metadata: creates one shared dict before the group loop and passes it unconditionally to every group'sbuild_for_drafting(DSpark branch) andbuild()(non-DSpark branch). Previously thebuild()branch was gated onuse_compressand created a fresh dict per group, which defeatedbuild()'s built-in cross-group cache and did not satisfy itsassert common_ratio_to_sas_metadata is not None.AscendDSACPMetadataBuilder.build_for_drafting/build_req_metadata_for_drafting: consume the shared dict as a cross-group cache isolated by("draft_for_drafting", draft_index), reusing split statistics,input_positions/cos/sin, device/CPU local token metadata,max_local_*,local_cos/local_sin,start_pos, theseq_lens_cpusync fallback, A5cu_seqlens_ori_kv, and thesas_metadataop result (guarded bynum_heads/head_dim); a debug log is emitted on cache hit.Correctness: cached items depend only on group-invariant fields of
common_attn_metadata(positions/seq_lens/query_start_loc), never on per-groupblock_table/slot_mapping; shared tensors are read-only consumers of the returned metadata. Paths without a shared dict (e.g.attn_update_stack_num_spec_norm, which receives per-group-updated metadata, anddummy_run, which creates a fresh dict per draft step) keep an empty cache and behave exactly as before.dataset gsm8k
07:30:13 PM
run_single_eval-d47
prefect.task_runs
07:30:13 PM
run_single_eval-d47
prefect.task_runs
Overall report table:
+---------+-----------+----------+----------+-------+---------+---------+
| Model | Dataset | Metric | Subset | Num | Score | Cat.0 |
+=========+===========+==========+==========+=======+=========+=========+
| illm | gsm8k | mean_acc | main | 1319 | 0.9682 | default |
+---------+-----------+----------+----------+-------+---------+---------+
Does this PR introduce any user-facing change?
No. This is a pure performance optimization on the speculative-decoding metadata-building path; no API/interface/behavior change.
Gain
The second build_for_drafting time was reduced from 3.5ms to 1.2ms.
Before
After