[DCP] Support dcp kv_cache interleave size > 1#26696
[DCP] Support dcp kv_cache interleave size > 1#26696LucasWilkinson merged 13 commits intovllm-project:mainfrom
Conversation
|
👋 Hi! Thank you for contributing to the vLLM project. 💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in #pr-reviews, coordinate on features in #feat- channels, or join special interest groups in #sig- channels. Just a reminder: PRs would not trigger full CI run by default. Instead, it would only run You ask your reviewers to trigger select CI tests on top of Once the PR is approved and ready to go, your PR reviewer(s) can run CI to test the changes comprehensively before merging. To run CI, PR reviewers can either: Add If you have any questions, please reach out to us on Slack at https://slack.vllm.ai. 🚀 |
There was a problem hiding this comment.
Code Review
This pull request introduces support for configurable interleave size for KV cache in Decode Context Parallelism (DCP), which is a nice enhancement for flexibility. The changes also include refactoring the dcp_local_seq_lens computation into a utility function. The implementation is mostly solid, but I've identified a couple of areas for improvement. One is a misleading error message in an assertion, and the other is an opportunity to refactor a new utility function for better readability and efficiency. Addressing these points will improve the code quality.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
aa23faa to
397fd51
Compare
656e08c to
46ec829
Compare
| @@ -52,6 +53,7 @@ def detailed( | |||
| tp_base: int = 4, | |||
| pp_base: int = 1, | |||
| dcp_base: int = 1, | |||
| cp_kv_cache_interleave_size: int = 1, | |||
There was a problem hiding this comment.
please call this dcp_kv_cache_interleave_size
There was a problem hiding this comment.
After prefill cp (#25852) is supported, this kv_cache_interleave_size will be used for both dcp and pcp, shall we keep this name for future usage?
There was a problem hiding this comment.
sure; by that logic we should update dcp_local_seq_lens to cp_local_seq_lens too but we can do that in the pcp PR
vllm/v1/worker/block_table.py
Outdated
| self, | ||
| req_indices: np.ndarray, | ||
| positions: np.ndarray, | ||
| cp_kv_cache_interleave_size: int = 1, |
There was a problem hiding this comment.
since this is a constant pass it via the init
There was a problem hiding this comment.
Thanks for review, we have already passed it via init
vllm/utils/__init__.py
Outdated
| @@ -3426,3 +3426,35 @@ def unique_filepath(fn: Callable[[int], Path]) -> Path: | |||
| if not p.exists(): | |||
| return p | |||
| i += 1 | |||
|
|
|||
|
|
|||
| def get_dcp_local_seq_lens( | |||
There was a problem hiding this comment.
we should find a better spot for this; this is too broad of a utils file for a feature specific utility
There was a problem hiding this comment.
Now we put this function in vllm/v1/attention/backends/utils.py, same place as CommonAttentionMetadata.dcp_local_seq_lens definition, this should be a more appropriate spot
vllm/v1/worker/gpu_model_runner.py
Outdated
| @@ -1276,6 +1287,14 @@ def _prepare_inputs( | |||
| logits_indices | |||
| ) | |||
|
|
|||
| # update seq_lens of decode reqs under DCP. | |||
| if self.dcp_world_size > 1: | |||
| self.dcp_local_seq_lens.gpu[:num_reqs] = get_dcp_local_seq_lens( | |||
There was a problem hiding this comment.
I think it might actually be better to compute get_dcp_local_seq_lens using host buffers and then do a non-blocking copy to self.dcp_local_seq_lens.gpu (see: CpuGpuBuffer.copy_to_gpu)
There was a problem hiding this comment.
(then when async scheduling is enabled it will be overlapped)
There was a problem hiding this comment.
Modified as suggested, thanks for review
vllm/v1/worker/gpu_model_runner.py
Outdated
| @@ -256,6 +258,11 @@ def __init__( | |||
| self.is_multimodal_pruning_enabled = False | |||
| self.max_model_len = model_config.max_model_len | |||
| self.dcp_world_size = self.parallel_config.decode_context_parallel_size | |||
| try: | |||
| self.dcp_rank = get_dcp_group().rank_in_group | |||
There was a problem hiding this comment.
delay to get_dcp_local_seq_lens calling is better?
There was a problem hiding this comment.
In some cases we might need to know how seq_len is split globally, instead of only local seq_len on current dcp_rank, for example in our current npu mla impl, we need the global seq_len split message to calculate a mask for following update_lse (if no kv_cache is stored on some (d)cp_ranks, then there's no need to do corresponding update_lse), so we think it's better to return the full seq_len split result from get_dcp_local_seq_lens, and each dcp_rank can select their corresponding part as needed.
There was a problem hiding this comment.
nit: I think we can simplify this to:
self.dcp_rank = 0 if self.dcp_world_size <= 1 else get_dcp_group().rank_in_group
that way we'll still get the benefit of the assert in get_dcp_group() an if a test sets self.dcp_world_size > 1 it should be initializing the dcp group anyways
There was a problem hiding this comment.
better way to get dcp_rank 👍 Modified as suggested
vllm/v1/worker/block_table.py
Outdated
| self, | ||
| req_indices: np.ndarray, | ||
| positions: np.ndarray, | ||
| cp_kv_cache_interleave_size: int = 1, |
There was a problem hiding this comment.
nit: maybe no default val is better
There was a problem hiding this comment.
Thanks for review, now we pass this arg via init, since it's a constant
6fce752 to
6ddf209
Compare
Signed-off-by: QiuChunshuo <qiuchunshuo@huawei.com>
Signed-off-by: QiuChunshuo <qiuchunshuo@huawei.com>
|
This pull request has merge conflicts that must be resolved before it can be |
Signed-off-by: QiuChunshuo <qiuchunshuo@huawei.com>
Signed-off-by: Qiu <qiuchunshuo@huawei.com>
LucasWilkinson
left a comment
There was a problem hiding this comment.
LGTM! Thanks for all the hardwork and sorry about the back and forth
we should refactor reorg_kvcache at somepoint (maybe use a triton kernel) but that can be done in the future; i appreciate the clarify comments/renaming!
Signed-off-by: QiuChunshuo <qiuchunshuo@huawei.com>
Head branch was pushed to by a user without write access
Signed-off-by: zhangsicheng5 <zhangsicheng5@huawei.com> Signed-off-by: QiuChunshuo <qiuchunshuo@huawei.com> Signed-off-by: Qiu <qiuchunshuo@huawei.com> Co-authored-by: QiuChunshuo <qiuchunshuo@huawei.com>
|
Hello! I have a question: If I am not using PD disaggregation—specifically when deploying an MLA-based model with DCP8—would setting cp_kv_cache_interleave_size to 64 yield any performance gains compared to the default of 1? |
Theoretically, when PD disaggregation is not used, the value of |
Purpose
1. cp_kv_cache_interleave_size support
In dcp scenario, kv_cache is split across dcp ranks, current implementation (#23734) split kv_cache with a token-level interleave style: token_idx i is stored on GPU whose dcp_rank == i % dcp_world_size.
For the convenience of pd disaggregate support, we add the cp_kv_cache_interleave_size argument to control the interleave size of kv_cache split size: store interleave_size tokens on dcp i, then store next interleave_size tokens on dcp i+1. The default value of cp_kv_cache_interleave_size is 1, which is same as original token-level interleave implementation. By setting cp_kv_cache_interleave_size to block_size, we can split kv_cache with a block-level interleave style, and makes it easy to support pd disaggregate with dcp > 1: D nodes only need to pull the corresponding kv_cache blocks, without need to rearange tokens in blocks.
Only dcp with cp_kv_cache_interleave_size is supported now, but the case of (p)cp is also considered and is easy to extend in the future.
2. Move dcp_local_seq_lens computation to utils
Move dcp_local_seq_lens computation to utils and pass it by metadata, so other attn backends can reuse it.
Test Plan
Model: DeepSeek-V2-Lite-Chat
Dataset: gsm8k
Test Result
tp2 dcp2, original code
tp2 dcp2, interleave_size = 1
tp2 dcp2, interleave_size = 64
Essential Elements of an Effective PR Description Checklist
supported_models.mdandexamplesfor a new model.