本文分享自华为云社区《普惠 DeepSeek-V4:Kthena + 昇腾 3 分钟搭建 PD 分离推理

一、背景介绍

在大模型推理部署中,Prefill-Decode(P/D)分离是一种被广泛采用的性能优化架构。随着大语言模型参数量不断增长,推理过程中的计算资源消耗和延迟问题日益突出。传统的一体化推理架构难以同时优化首token延迟(TTFT)和整体吞吐率(TPOT),而P/D分离通过将推理过程拆分为两个独立阶段,让每个阶段使用最适合其计算特性的并行策略,实现了显著的性能提升。

本文将详细介绍如何通过Kthena控制器,在昇腾NPU上部署DeepSeek-V4-Flash模型,完成P/D分离的实践。我们会深入解析P/D分离的技术原理、Kthena的编排能力,以及ModelRoute如何实现P/D实例的自动发现与KV传输协作。

相关部署模板参考Kthena项目地址:

https://github.com/volcano-sh/kthena/tree/main/examples/models/deepseek-v4-flash

二、P/D分离技术原理

2.1 大模型推理的两阶段解析

大语言模型的推理过程是一个自回归生成过程,本质上分为两个截然不同的阶段:

Prefill阶段(首token生成)

Prefill阶段负责处理用户输入的prompt,将完整的输入序列通过模型前向传播,生成第一个输出token。这个阶段具有以下特征:

  • 计算密集型:需要处理整个输入序列,每个token都需要与所有输入token进行注意力计算
  • 并行度高:输入序列的所有位置可以并行计算,适合较大的张量并行(TP)规模
  • 内存访问模式:KV Cache首次生成,需要写入到高速缓存中
  • 延迟敏感:用户等待首token的时间直接影响体验

在我们的配置中,Prefill阶段采用DP(数据并行)=2、TP(张量并行)=8的配置,利用更大的张量并行度来加速矩阵运算:

--data-parallel-size 2 \

--tensor-parallel-size 8 \

--max-num-batched-tokens 8192 \

--max-num-seqs 4 \

Decode阶段(增量生成)

Decode阶段是自回归生成过程,每次只处理一个新生成的token,并将其加入序列进行下一轮推理。这个阶段的特点与Prefill截然不同:

  • Memory-Bound型:每次只计算一个token,但需要读取完整的KV Cache
  • 并行度需求低:单个token的计算量有限,过大的张量并行反而增加通信开销
  • 吞吐率敏感:需要最大化单位时间内生成的token数量
  • KV传输频繁:每个Decode实例都需要访问所有Prefill实例生成的KV Cache

Decode阶段采用DP(数据并行)=8、TP(张量并行)=2的配置,通过更大的数据并行来提升整体吞吐:

--data-parallel-size 8 \

--tensor-parallel-size 2 \

--max-num-batched-tokens 144 \

--max-num-seqs 48 \

2.2 为什么P/D分离能提升性能

传统的单体架构面临"一刀切"的困境:为了同时满足Prefill和Decode的需求,必须在并行策略上做出妥协,导致两个阶段都无法达到最优。而P/D分离的核心价值在于解耦

维度

单体架构

P/D分离

张量并行

折中值(如TP=4)

Prefill用TP=8,Decode用TP=2

数据并行

固定值

各角色独立扩展

资源配置

统一规格

按需分配

扩缩容

整体调整

独立扩缩容

以DeepSeek V4为例:

  • Prefill优化:更大的TP size(8)加速注意力计算,更大的批处理量(8192 tokens)提升吞吐
  • Decode优化:更大的DP size(8)支持更多并发序列,更小的TP size(2)减少通信开销

2.3 KV Cache传输机制

P/D分离后,Prefill和Decode之间需要高效传输KV Cache,这是P/D分离架构中最关键的技术挑战之一。

在我们的部署中,使用Mooncake Connector V1实现KV传输:

--kv-transfer-config \

'{"kv_connector": "MooncakeConnectorV1",

  "kv_role": "kv_producer",     # Prefill为producer

  "kv_port": "9000",

  "engine_id": "$MOONCAKE_ENGINE_ID",

  ...

}'

Mooncake KV传输原理

  1. Producer端(Prefill):生成的KV Cache通过Mooncake引擎传输到Decode节点
  2. Consumer端(Decode):从Mooncake引擎拉取KV Cache用于注意力计算
  3. Engine ID:每个P/D实例组有唯一的engine ID(${GROUP_NAME}_${ROLE_ID}),确保数据传输到正确的目标
# Prefill配置

"kv_role": "kv_producer"

# Decode配置

"kv_role": "kv_consumer"

Mooncake具备昇腾NPU优化的高性能通信库,能够实现节点间KV Cache的低延迟传输,是P/D分离能够实际落地的关键技术。

三、为什么P/D分离需要适配的Router

3.1 路由在P/D分离架构中的核心作用

在P/D分离架构中,请求的路由不再是简单地分发到某个后端实例,而是需要智能地协调Prefill和Decode两个阶段,这与传统微服务路由有本质区别。

传统微服务路由

Client Request → Router → Backend Instance (处理完整请求)

P/D分离路由

Client Request → Router → Prefill Instance (生成首token)

                         ↕ (KV传输)

                       Decode Instance (完成剩余生成)

3.2 路由需要解决的挑战

挑战一:请求生命周期管理

一个完整的请求在P/D架构中需要经过多个阶段:

  1. 请求首先路由到Prefill处理
  2. Prefill生成首token后,需要将请求转交给Decode
  3. Decode可能需要多轮生成,每轮都涉及KV传输
  4. 最终结果需要汇总返回给用户

这要求Router必须理解P/D的请求流程,而不仅仅是做简单的负载均衡。

挑战二:P/D实例发现与匹配

  • Prefill和Decode实例数量可能不同(1P2D、2P1D等)
  • 请求需要在正确的Prefill和Decode实例之间传递
  • 需要跟踪每个请求当前由哪个实例处理

挑战三:KV传输的协调

KV Cache的传输需要满足以下条件:

  • Prefill生成的KV必须传输到处理该请求的Decode实例
  • Mooncake的engine_id需要正确配置以匹配P/D实例
  • 传输超时和错误处理

挑战四:流量分配策略

不同场景下可能需要不同的P/D配比:

  • 计算密集型场景:增加Prefill副本
  • IO密集型场景:增加Decode副本
  • Router需要支持动态调整流量分配

3.3 ModelRoute的适配设计

Kthena的ModelRoute正是为解决上述挑战而设计的适配层。它不仅负责基本的请求路由,还需要理解P/D分离的语义,协调Prefill和Decode的协作。

四、ModelRoute配置详解

4.1 整体配置结构

apiVersion: networking.serving.volcano.sh/v1alpha1

kind: ModelRoute

metadata:

  name: deepseek-v4

  namespace: default

spec:

  modelName: "deepseek_v4"

  rules:

  - name: "default"

    targetModels:

    - modelServerName: "deepseekv4-pd"

---

apiVersion: networking.serving.volcano.sh/v1alpha1

kind: ModelServer

metadata:

  name: deepseekv4-pd

  namespace: default

spec:

  inferenceEngine: vLLM

  model: "deepseek_v4"

  workloadPort:

    port: 7100

    protocol: http

  workloadSelector:                                   # 工作负载选择器

    matchLabels:

      modelserving.volcano.sh/name: deepseekv4-pd     # 这是最基本的标签匹配,用于识别属于该服务的所有Pod。

    pdGroup:                                          # P/D分组配置

      groupKey: "modelserving.volcano.sh/group-name"  # 指定用于分组的标签key

      prefillLabels:                                  # 标记哪些Pod是Prefill角色

        modelserving.volcano.sh/role: prefill

      decodeLabels:                                   # 标记哪些Pod是Decode角色

        modelserving.volcano.sh/role: decode

  trafficPolicy:

    timeout: "300s"

    retry:

      attempts: 3

      retryInterval: "150ms"

  kvConnector:

    type: mooncake

其中P/D分组配置(pdGroup)是实现P/D识别的关键配置

  • groupKey:指定用于分组的标签key,具有相同groupKey值的Pod属于同一个P/D实例组。这解决了一个关键问题:当我们部署多个P/D实例组时(如2×(1P1D)),Router需要知道哪些Prefill和Decode属于同一个组。
  • prefillLabels:标记哪些Pod是Prefill角色。
  • decodeLabels:标记哪些Pod是Decode角色。

4.2 实例发现的实现机制

Kthena控制器通过以下步骤实现P/D实例的自动发现:

步骤1:标签注入

在deepseek-serv.yaml中定义的ModelServing资源会被Kthena控制器处理,自动为每个Pod注入标签:

metadata:

  labels:

    modelserving.volcano.sh/name: deepseekv4-pd

    modelserving.volcano.sh/group-name: <group-id>  # 自动生成

    modelserving.volcano.sh/role: prefill/decode    # 根据role名称

    modelserving.volcano.sh/role-id: <role-id>      # 自动生成

步骤2标签查询

ModelRoutepdGroup配置会被控制器用于查询匹配的Pod

1. 查询所有 labels[modelserving.volcano.sh/name] = deepseekv4-pd Pod

2. labels[modelserving.volcano.sh/group-name] 分组

3. 在每个组内识别prefillLabelsdecodeLabels匹配的Pod

步骤3动态维护

当发生扩缩容时:

  • 新Pod创建后自动获得标签
  • Router实时感知Pod变化
  • 无需手动更新配置

4.3 KV传输的协调

ModelRoute通过以下配置协调KV传输:

kvConnector:

  type: mooncake

Mooncake Connector的工作流程

  1. Prefill启动时
     
    • 从环境变量获取GROUP_NAMEROLE_ID
    • 构建engine_id = ${GROUP_NAME}_${ROLE_ID}
    • 启动Mooncake Server,监听KV请求
  2. Decode启动时
     
    • 使用相同的GROUP_NAME但不同的ROLE_ID
    • 配置为kv_consumer角色
    • 通过engine_id连接到对应Prefill的Mooncake Server
  3. 请求处理时
     
    • Prefill处理用户输入,生成KV Cache
    • KV Cache通过Mooncake传输到对应Decode实例
    • Decode使用接收到的KV继续生成

4.4 流量策略配置

trafficPolicy:

  timeout: "300s"

  retry:

    attempts: 3

    retryInterval: "150ms"

这些配置确保了请求在P/D之间的可靠传递:

  • timeout:整个生成过程可能需要较长时间,设置5分钟超时
  • retry:如果请求在Prefill或Decode环节失败,自动重试

五、Kthena编排的核心优势

5.1 声明式编排简化运维

传统方式下,部署P/D分离架构需要:

  • 手动创建和管理多组Deployment/Service
  • 手动配置Service之间的发现机制
  • 手动管理标签选择器和Endpoints

使用Kthena的ModelServing,仅需声明式配置:

apiVersion: workload.serving.volcano.sh/v1alpha1

kind: ModelServing

metadata:

  name: deepseekv4-pd

spec:

  replicas: 1

  template:

    roles:

    - name: prefill

      replicas: 1

    - name: decode

      replicas: 1

控制器会自动完成:

  • 创建和管理Prefill/Decode的Pod
  • 注入必要的标签(group-name、role、role-id)
  • 设置健康检查
  • 配置资源限制

5.2 灵活的P/D比例调整

单实例1P1D

roles:

- name: prefill

  replicas: 1

- name: decode

  replicas: 1

调整为2P1D(提升Prefill吞吐)

roles:

- name: prefill

  replicas: 2    # 从1改为2

- name: decode

  replicas: 1

调整为1P2D(提升Decode吞吐)

roles:

- name: prefill

  replicas: 1

- name: decode

  replicas: 2    # 从1改为2

部署2组独立的1P1D实例(横向扩展)

spec:

  replicas: 2    # 整体副本数设为2,每组自动生成1P1D

我们测试了以下几种灵活的P/D比例配置:

部署模式

Prefill replicas

Decode replicas

说明

1P1D

1

1

基础配置

2P1D

2

1

提升Prefill吞吐,适合输入长度较大的场景

1P2D

1

2

提升Decode吞吐,适合输出长度较大的场景

2×(1P1D)

2组P/D实例

2组P/D实例

横向扩展,整体吞吐翻倍

所有这些调整都只需修改yaml配置并执行:

kubectl apply -f deepseek-serv.yaml

Kthena控制器会自动处理Pod的创建、销毁和负载均衡。

5.3 自动服务发现

在传统的P/D部署中,需要手动配置服务发现:

  • Prefill服务需要知道所有Decode实例的地址
  • Decode服务需要知道所有Prefill实例的地址
  • 扩缩容时需要手动更新配置

Kthena通过pdGroup和标签机制实现了自动服务发现:

  • 新增的Prefill或Decode实例自动被Router识别
  • 使用相同的group-key的实例自动组成P/D组
  • 无需手动配置实例地址

六、部署实践

6.1 模型准备

为了加速部署和启动过程,我们将DeepSeek-V4-Flash模型权重预先下载到所有计算节点的 /models/DeepSeek-V4-Flash-w8a8-mtp 目录下。该目录应包含完整的模型权重文件、配置文件以及chat_template.jinja模板文件。

从ModelScope下载模型权重

# 安装ModelScope

pip install modelscope



# 下载DeepSeek V4 Flash模型

modelscope download --model Eco-Tech/DeepSeek-V4-Flash-w8a8-mtp --local_dir /models/DeepSeek-V4-Flash-w8a8-mtp

如果使用git-lfs进行大文件管理,也可以:

# 安装git-lfs

git lfs install



# 克隆模型仓库

GIT_LFS_SKIP_SMUDGE=1 git clone https://www.modelscope.cn/Eco-Tech/DeepSeek-V4-Flash-w8a8-mtp.git /models/DeepSeek-V4-Flash-w8a8-mtp



# 进入目录并下载LFS大文件

cd /models/DeepSeek-V4-Flash-w8a8-mtp

git lfs pull

注意事项

  • 确保所有计算节点的模型目录路径一致(/models/DeepSeek-V4-Flash-w8a8-mtp
  • 可以在共享存储(如NFS)上预先下载模型,然后挂载到各个节点
  • 模型下载完成后,建议验证文件完整性:
    ls -la /models/DeepSeek-V4-Flash-w8a8-mtp/
    # 应包含 config.json, model.safetensors, chat_template.jinja 等文件

     

6.2 完整部署流程

Step 1: 创建ConfigMap(包含启动脚本)

kubectl apply -f config.yaml

config.yaml定义了Prefill和Decode的启动脚本,包含:

  • 环境变量配置
  • vLLM启动参数
  • Mooncake KV连接配置

Step 2: 部署ModelServing

kubectl apply -f deepseek-serv.yaml

创建完整的P/D分离实例,包括:

  • Prefill实例(1副本)
  • Decode实例(1副本)
  • 自动注入的标签和配置

Step 3: 配置路由

kubectl apply -f modelRoute.yaml

创建ModelRoute和ModelServer两个对象:

  • ModelRoute:定义路由规则
  • ModelServer:定义后端服务

6.2 验证部署

# 查看ModelServing状态

kubectl get modelserving deepseekv4-pd



# 查看所有相关Pod

kubectl get pods -l modelserving.volcano.sh/name=deepseekv4-pd



# 查看Pod详情(确认标签)

kubectl get pods -l modelserving.volcano.sh/name=deepseekv4-pd -o wide



# 检查Pod日志

kubectl logs -l modelserving.volcano.sh/role=prefill

kubectl logs -l modelserving.volcano.sh/role=decode

6.3 扩缩容操作

扩缩容Prefill

# 编辑配置

kubectl edit modelserving deepseekv4-pd

# 将 prefill.replicas 从 1 改为 2



# 或者使用patch

kubectl patch modelserving deepseekv4-pd --type='json' \

  -p='[{"op": "replace", "path": "/spec/template/roles/0/replicas", "value": 2}]'

扩缩容Decode:

kubectl patch modelserving deepseekv4-pd --type='json' \

  -p='[{"op": "replace", "path": "/spec/template/roles/1/replicas", "value": 2}]'

七、总结

通过本次实践我们验证了 Kthena 在昇腾 NPU 环境下部署 DeepSeek-V4-Flash 模型 P/D 分离(Prefill/Decode Disaggregation) 架构的完整可行性。

主要成果

  • 成功实现P/D分离部署,Prefill和Decode独立运行
  • 通过Mooncake KV传输实现P/D协作
  • 支持灵活的P/D比例调整(1P1D、2P1D、1P2D等)
  • 支持多实例横向扩展

Kthena的核心价值

  1. 简易性:声明式配置替代复杂的手动编排,控制器自动处理Pod管理和标签注入
  2. 灵活性:通过replicas字段即可独立调整P/D比例,无需修改其他配置
  3. 自动发现:pdGroup机制实现P/D实例的自动识别和配对
  4. KV协调:与Mooncake深度集成,确保KV传输的正确路由

综上所述,P/D 分离是提升大模型分布式推理效能的核心技术路径,而 Kthena 的适配 Router 设计与编排逻辑,为这一复杂架构在生产环境中的标准化部署提供了确定性的方案,确保了大模型服务在昇腾算力底座上的高效稳定运行。

相关部署模板参考Kthena项目地址:

https://github.com/volcano-sh/kthena/tree/main/examples/models/deepseek-v4-flash

Kthena GitHub地址

https://github.com/volcano-sh/kthena 

更多信息,欢迎访问 Kthena 官网:

https://kthena.volcano.sh/

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐