跳转至

解码上下文并行(DCP)

解码上下文并行(DCP)在张量并行(TP)组中的设备之间沿序列维度对KV缓存进行分片。它在不向进程世界添加设备的情况下消除了冗余的KV缓存存储。

vLLM Ascend不支持预填充上下文并行。本文档仅描述DCP和独立的DSA-CP稀疏注意力路径。

KV缓存布局

DCP以交错布局跨rank存储令牌。交错粒度由cp_kv_cache_interleave_size控制,其默认值为1

对于大小为dcp_size的DCP,一个虚拟块包含block_size * dcp_size个令牌。对于令牌x

  • virtual_block_index = x // (block_size * dcp_size)
  • offset_in_virtual_block = x % (block_size * dcp_size)
  • local_block_index = offset_in_virtual_block // cp_kv_cache_interleave_size
  • target_rank = local_block_index % dcp_size

槽位映射计算使用此布局,因此每个DCP rank仅存储其本地序列分片。当前实现要求block_size % cp_kv_cache_interleave_size == 0

DCP block table

注意力执行

后端结构

DCP是作为相应v1注意力后端的特化实现,而不是其并行副本:

  • DCPMetadataBuilderMixin负责DCP组/rank发现以及访问每个rank的上下文长度矩阵。
  • DCPImplMixin负责DCP集合通信以及常见的部分输出/LSE合并。
  • GQA、MLA和SFA DCP构建器继承其v1元数据构建器。它们仅添加DCP元数据字段或临时暴露DCP特定的缓存视图。
  • GQA、MLA和SFA DCP实现继承其v1实现,并且仅覆盖通信或缓存布局不同的内核阶段。

常规v1构建器仍然是请求分类、填充、掩码、图元数据和常见KV缓存元数据的权威来源。DCP特定的元数据不包含在常规v1元数据模式中。

预填充和分块预填充

在分块或缓存预填充期间,本地查询必须关注分布在DCP组中的KV缓存分片。

  • MLA收集上下文KV缓存,恢复请求连续顺序,并为当前查询块计算注意力。
  • GQA在DCP组中收集查询头,针对每个本地KV分片计算注意力,并合并部分输出和LSE值。

DCP prefill

解码

解码收集每个DCP rank所需的查询头,针对本地KV缓存分片计算注意力,并在DCP组中合并部分输出和LSE值。

DCP decode

GLM-5.2 SFA DCP复制索引器

GLM-5.2使用带有LightningIndexer的稀疏Flash注意力(SFA)。对于DCP,索引器需要完整的序列视图来选择与非DCP SFA相同的稀疏top-k块,而更大的SFA KV缓存应保持分片以保留DCP的内存优势:

  • LightningIndexer缓存在每个DCP rank上复制,因此索引选择使用完整的序列。
  • SFA KV缓存保持DCP本地。来自复制索引器视图的全局索引在SFA运行之前被重新映射到本地KV索引。
  • 在预填充或混合批次期间,只有稀疏块表引用的KV块在当前层写入其KV缓存后被压缩并全收集。
  • 仅解码批次保留DCP SFA Q收集和结果合并路径。

prefill_context_parallel_size=1decode_context_parallel_size>1时,此模式会自动为SFA稀疏模型选择。它要求decode_context_parallel_size == tensor_parallel_size

对于GLM-5.2 DSA-CP部署,启用FlashComm1和DSA-CP,并保持CP交错大小等于KV缓存块大小:

export VLLM_ASCEND_ENABLE_FLASHCOMM1=1

vllm serve <glm-5.2-model> \
  --tensor-parallel-size <N> \
  --prefill-context-parallel-size 1 \
  --decode-context-parallel-size <N> \
  --block-size <B> \
  --cp-kv-cache-interleave-size <B> \
  --additional-config '{"enable_dsa_cp": true}'

复制索引器会按DCP世界大小的比例增加索引器缓存内存;SFA KV缓存本身保持分片。

SFA DSA-CP o_proj路径

SFA DSA-CP执行有意复用常规TP分片的o_proj。这既适用于混合角色实例,也适用于PD分离的P节点;它不是独立的面向用户的o_proj TP开关。运行时路径支持两种布局:

  • 仅解码批次保留解码TP路径。 SFA输出在TP组中通过all-to-all交换,然后原始的TP分片o_proj正常运行。
  • 预填充或混合批次,包括PD分离P节点上的批次,产生的SFA输出与TP分片的o_proj输入布局不直接兼容。 在o_proj前向传播之前,每个rank将TP分片的o_proj权重和所有输入分片的量化参数全收集到临时全权重缓冲区中。 全权重o_proj前向传播对该批次运行一次,然后模块恢复到TP参数别名。

存储不变性在于,原始的 TP 分片 o_proj 参数仍然是唯一持久化的真实来源。 o_proj_tp_* 张量是原始参数存储的别名。 o_proj_full_* 张量是仅用于预填充/混合全收集执行的可重用通信缓冲区。 它们绝不能成为 TP 权重的第二个持久化副本。

这种耦合保留了现有的解码TP行为,支持混合角色和仅P实例上的预填充/混合DSA-CP批次,并避免在每个TP rank上持久化全权重副本。

相关文件

  • 槽位映射:vllm_ascend/worker/block_table.py
  • 输入和注意力元数据:vllm_ascend/worker/model_runner_v1.py
  • 共享DCP后端能力:vllm_ascend/attention/context_parallel/common_cp.py
  • GQA DCP后端:vllm_ascend/attention/context_parallel/attention_cp.py
  • MLA DCP后端:vllm_ascend/attention/context_parallel/mla_cp.py
  • SFA DCP后端:vllm_ascend/attention/context_parallel/sfa_cp.py
  • DSA-CP后端:vllm_ascend/attention/context_parallel/dsa_cp.py