在 SageMaker HyperPod 上拆分大模型 Prefill 与 Decode:用 vLLM 构建可独立扩缩的推理链路

2026-07-10 29 预计阅读时间: 1 分钟
来源: aws.amazon.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

大模型在线推理并不是一种均匀的计算任务。Prefill 阶段需要并行处理整段输入,通常更依赖算力和显存带宽;Decode 阶段逐 token 生成结果,更看重低延迟、KV Cache 容量与持续调度能力。来源方案在 Amazon SageMaker HyperPod 上结合 vLLM 和 HyperPod Inference Operator,实现了 Disaggregated Prefill and Decode(DPD),让两个阶段可以分别部署、扩缩和调优。

为什么要把两个阶段拆开

在传统共置部署中,同一个 vLLM 实例既执行 Prefill,也执行 Decode。这种模式部署简单,但两类负载会竞争 GPU:长提示词可能占用大量计算资源,正在生成 token 的请求则可能因此出现延迟抖动。

DPD 将一次推理拆成两个资源域:

  • Prefill Worker 读取提示词,计算首轮隐藏状态并建立 KV Cache。
  • KV 传输层把后续解码所需的数据交给 Decode Worker。
  • Decode Worker 复用这些状态,持续生成 token。
  • 路由或编排组件负责请求关联、实例选择、失败处理和流量控制。

拆分后的关键收益不是“凭空减少计算量”,而是可以按照不同瓶颈配置 GPU。例如,Prefill 池可以使用计算吞吐更高的实例并承接批量长上下文,Decode 池则按并发序列数和 KV Cache 压力扩容。

代价也很明确:KV Cache 必须跨进程甚至跨节点传输,网络吞吐、拓扑距离和序列化开销都会进入请求关键路径。如果提示词很短、生成量较少,新增的数据传输和调度成本可能抵消拆分收益。

Operator 在这里解决什么问题

HyperPod Inference Operator 把推理工作负载放进 Kubernetes 式的声明式控制循环。对于 DPD,Operator 的价值不只是启动两个 Pod,还包括维护目标副本数、处理节点故障,以及让 Prefill、Decode 和服务入口形成可持续运维的部署单元。

生产设计时应把以下参数分开管理:

维度 Prefill 池 Decode 池
主要容量指标 输入 token/s、首 token 延迟 活跃序列数、输出 token/s、单 token 延迟
常见压力来源 长上下文、突发批量请求 长输出、高并发、KV Cache 占用
扩缩依据 队列长度、待处理输入 token 活跃请求、生成队列、GPU KV Cache 使用率
网络要求 快速输出 KV 数据 稳定接收 KV 数据并保持低尾延迟

不要只按 GPU 利用率扩缩。Decode Worker 即使计算单元没有跑满,也可能已经受限于显存中的 KV Cache;Prefill Worker 则可能在请求间歇期利用率骤降,但队列里已经积累了大量输入 token。

可以这样检查并准备集群

下面的命令可以直接用于已配置 kubectl 的 HyperPod Kubernetes 环境。它们不假定 Operator 的 CRD 名称,而是先从集群中发现实际安装的资源类型,避免把版本相关的 API 名称写死。

# 查看与 HyperPod、推理或模型服务相关的 CRD
kubectl get crd -o name \
  | grep -Ei 'hyperpod|inference|model|endpoint'

# 查看 GPU 节点及其可分配资源
kubectl get nodes \
  -o custom-columns='NAME:.metadata.name,GPU:.status.allocatable.nvidia\.com/gpu,TYPE:.metadata.labels.node\.kubernetes\.io/instance-type'

# 确认 NVIDIA 设备插件暴露了 GPU
kubectl get pods -A -o wide \
  | grep -Ei 'nvidia|device-plugin'

# 部署后观察 Pod 分布、重启和节点位置
kubectl get pods -A -o wide \
  | grep -Ei 'prefill|decode|vllm'

如果第一条命令返回了 Operator 提供的 CRD,可以继续执行:

# 将 <resource> 替换为集群实际返回的资源名
kubectl explain <resource> --recursive
kubectl get <resource> -A

这一步很重要:来源摘要没有给出具体 CRD 版本和字段,因此实际清单应以集群中安装的 HyperPod Inference Operator API 为准。

一个可改造的 vLLM DPD 配置骨架

下面是一个最小 Kubernetes 配置骨架,用来明确 Prefill 与 Decode 的资源边界。它假设当前 vLLM 镜像支持 NIXL KV connector,并使用 kv_producerkv_consumer 角色;不同 vLLM 版本的 connector 名称、角色参数和额外协调地址可能不同,运行前应通过 vllm serve --help 和对应版本文档确认。生产环境中,可把相同的容器参数迁移到 HyperPod Inference Operator 的自定义资源中,由 Operator 接管生命周期。

运行前需要修改镜像标签、模型路径、GPU 数量和节点选择标签:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-prefill
spec:
  replicas: 2
  selector:
    matchLabels:
      app: vllm-prefill
  template:
    metadata:
      labels:
        app: vllm-prefill
        inference-role: prefill
    spec:
      containers:
        - name: vllm
          image: vllm/vllm-openai:<validated-version>
          args:
            - serve
            - /models/your-model
            - --host=0.0.0.0
            - --port=8000
            - --tensor-parallel-size=1
            - --kv-transfer-config={"kv_connector":"NixlConnector","kv_role":"kv_producer"}
          resources:
            limits:
              nvidia.com/gpu: 1
          ports:
            - name: http
              containerPort: 8000
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: vllm-decode
spec:
  replicas: 4
  selector:
    matchLabels:
      app: vllm-decode
  template:
    metadata:
      labels:
        app: vllm-decode
        inference-role: decode
    spec:
      containers:
        - name: vllm
          image: vllm/vllm-openai:<validated-version>
          args:
            - serve
            - /models/your-model
            - --host=0.0.0.0
            - --port=8000
            - --tensor-parallel-size=1
            - --kv-transfer-config={"kv_connector":"NixlConnector","kv_role":"kv_consumer"}
          resources:
            limits:
              nvidia.com/gpu: 1
          ports:
            - name: http
              containerPort: 8000

把文件保存为 dpd-workers.yaml 后,可以先做服务端校验,再交给集群:

kubectl apply --dry-run=server -f dpd-workers.yaml
kubectl apply -f dpd-workers.yaml
kubectl rollout status deployment/vllm-prefill
kubectl rollout status deployment/vllm-decode

这份骨架只定义了两个 Worker 池,并不构成完整 DPD 服务。还需要由 HyperPod Inference Operator 对应的资源、兼容路由器或编排层建立 Prefill 到 Decode 的请求关联与 KV 传输。不要把两个 Deployment 简单挂到同一个随机负载均衡 Service 后就认为完成了 DPD,因为普通 Service 不理解推理阶段和 KV Cache 所属关系。

上线前用数据决定是否拆分

评估 DPD 时,至少分别记录 TTFT(Time to First Token)、TPOT(Time per Output Token)、端到端延迟和吞吐量。测试流量要覆盖真实的输入与输出长度分布,而不是只跑固定的短提示词。

一个务实的采用清单是:

  • 固定模型、量化方式和 vLLM 版本,对比共置部署与 DPD。
  • 分别测试短输入短输出、长输入短输出、短输入长输出和长输入长输出。
  • 观察 Prefill 队列、Decode 活跃序列、GPU 显存以及 KV 传输带宽。
  • 验证 Prefill 或 Decode Pod 重启时,请求是否重试、失败或丢失状态。
  • 检查跨可用区或跨低速网络调度是否显著拉高尾延迟。
  • 为两个池设置独立扩缩信号,并限制最大副本数,避免拥塞在阶段之间来回放大。

DPD 更适合输入长度、输出长度或并发模式差异明显的服务。若模型较小、流量稳定且上下文较短,共置部署通常更容易运维。SageMaker HyperPod、vLLM 与 HyperPod Inference Operator 的组合提供了拆分和调度基础,但最终是否值得采用,应由真实请求分布、KV 传输成本和故障恢复结果共同决定。


相关推荐