跳转至正文

最佳实践:P/D 分离

概览

本指南演示如何利用 vLLM 对 P/D 分离的支持以及 NIXL 来部署 Llama-70B。本指南已在以下环境验证:

  • 配备 InfiniBand 网络连接的 8xH200 集群
  • GKE 上配备 RoCE 网络连接的 8xH200 集群

警告:我们仍在调查并优化其他硬件和网络配置的性能

在此示例中,我们将演示 Llama-3.3-70B-Instruct-FP8 的部署,配置如下:

  • 4 个 TP=1 的 Prefill 工作节点
  • 1 个 TP=4 的 Decode 工作节点

P/D 最佳实践

P/D 分离在平衡吞吐量和交互性方面提供了更大的灵活性(参考)。特别是由于消除了 Prefill 阶段对 Decode 阶段的干扰,P/D 分离可以实现更低的逐标记延迟 (ITL),从而提高交互性。对于给定的 ITL 目标,P/D 分离可通过以下方式提高总体吞吐量:

  • 针对计算密集型(P)和延迟敏感型(D)工作负载分别优化工作节点
  • 通过更广泛的并行性减少模型副本数量(从而增加 KV 缓存 RAM)

然而,P/D 分离并不适用于所有工作负载。我们建议针对具有以下特征的工作负载探索 P/D 分离:

  • 大型模型(例如 Llama-70B+,而非 Llama-8B)
  • 较长的输入序列长度(例如 10k ISL | 1k OSL,而非 200 ISL | 200 OSL)
  • 具有广泛专家并行 (EP) 机会的稀疏 MoE 架构

因此,在调优 P/D 部署时,我们建议关注以下参数:

  • 异构并行:部署并行度较低但副本数较多的 P 节点,以及并行度较高但副本数较少的 D 节点
  • xPyD 比例:调优 P 节点与 D 节点的比例,以确保与您的 ISL|OSL 比例保持平衡

对于利用广泛 EP 的极大型模型,当 ISL|OSL 比例也较高时,KV 缓存传输的流量可能会与专家并行产生竞争。我们建议在尝试使用 TCP 之前,先从用于 KV 缓存传输的 RDMA 开始,因为 TCP 传输需要对 NIXL 下的 UCX 进行更多调优。

硬件要求

本指南要求 8 个任意类型的 Nvidia GPU,并且工作负载中的所有 Pod 之间均需通过 InfiniBand 或 RoCE 实现 RDMA。

先决条件

安装

使用 helmfile 来组合并安装技术栈。部署该技术栈的命名空间将衍生自 ${NAMESPACE} 环境变量。如果您未设置此变量,在本示例中将默认为 llm-d-pd

部署

cd guides/pd-disaggregation
helmfile apply -n ${NAMESPACE}

注意: 您可以设置 $RELEASE_NAME_POSTFIX 环境变量来更改版本名称。这是我们支持并发安装的方式。例如:RELEASE_NAME_POSTFIX=pd-2 helmfile apply -n ${NAMESPACE}

注意: 本指南默认使用 Istio 作为提供商,请参阅 网关选项 以安装特定提供商。

Gateway 选项

要指定您的网关选择,可以使用 -e <gateway option> 标志,例如:

helmfile apply -e kgateway -n ${NAMESPACE}

要查看支持哪些 Gateway 选项,请参考我们的 Gateway 提供商先决条件文档。每个提供商的 Gateway 配置都在 gateway-configurations 目录中进行跟踪。

您还可以自定义 Gateway,更多信息请参阅我们的 Gateway 自定义文档

基础设施提供商详情

本指南在分离式服务中使用通过 InfiniBand 或 RoCE 的 RDMA 进行 KV 缓存传输。配置加速器网络所需的资源属性尚未通过 Kubernetes 动态资源分配 (DRA) 实现标准化,因此在 Helm chart 中按基础设施提供商进行了参数化。如果您的提供商有自定义设置,则需要在部署前更新 chart。

安装 HTTPRoute

请遵循特定提供商的说明来安装 HTTPRoute。

为 "kgateway" 或 "istio" 安装

kubectl apply -f httproute.yaml -n ${NAMESPACE}

为 "gke" 安装

kubectl apply -f httproute.gke.yaml -n ${NAMESPACE}

验证安装

  • 首先,您应该能够列出所有 helm release,以查看已安装到所选命名空间中的 3 个 chart。
helm list -n ${NAMESPACE}
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
gaie-pd llm-d-pd 1 2025-08-24 12:54:51.231537 -0700 PDT deployed inferencepool-v1.2.0 v1.2.0
infra-pd llm-d-pd 1 2025-08-24 12:54:46.983361 -0700 PDT deployed llm-d-infra-v1.3.6 v0.3.0
ms-pd llm-d-pd 1 2025-08-24 12:54:56.736873 -0700 PDT deployed llm-d-modelservice-v0.3.17 v0.3.0
  • 通过此示例,您开箱即用应拥有以下资源
kubectl get all -n ${NAMESPACE}
NAME READY STATUS RESTARTS AGE
pod/gaie-pd-epp-54444ddc66-qv6ds 1/1 Running 0 2m35s
pod/infra-pd-inference-gateway-istio-56d66db57f-zwtzn 1/1 Running 0 2m41s
pod/ms-pd-llm-d-modelservice-decode-84bf6d5bdd-jzfjn 2/2 Running 0 2m30s
pod/ms-pd-llm-d-modelservice-prefill-86f6fb7cdc-8kfb8 1/1 Running 0 2m30s
pod/ms-pd-llm-d-modelservice-prefill-86f6fb7cdc-g6wmp 1/1 Running 0 2m30s
pod/ms-pd-llm-d-modelservice-prefill-86f6fb7cdc-jx2w2 1/1 Running 0 2m30s
pod/ms-pd-llm-d-modelservice-prefill-86f6fb7cdc-vzcb8 1/1 Running 0 2m30s

NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/gaie-pd-epp ClusterIP 10.16.0.255 <none> 9002/TCP,9090/TCP 2m35s
service/gaie-pd-ip-bb618139 ClusterIP None <none> 54321/TCP 2m35s
service/infra-pd-inference-gateway-istio LoadBalancer 10.16.3.74 10.16.4.3 15021:31707/TCP,80:34096/TCP 2m41s

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/gaie-pd-epp 1/1 1 1 2m36s
deployment.apps/infra-pd-inference-gateway-istio 1/1 1 1 2m42s
deployment.apps/ms-pd-llm-d-modelservice-decode 1/1 1 1 2m31s
deployment.apps/ms-pd-llm-d-modelservice-prefill 4/4 4 4 2m31s

NAME DESIRED CURRENT READY AGE
replicaset.apps/gaie-pd-epp-54444ddc66 1 1 1 2m36s
replicaset.apps/infra-pd-inference-gateway-istio-56d66db57f 1 1 1 2m42s
replicaset.apps/ms-pd-llm-d-modelservice-decode-84bf6d5bdd 1 1 1 2m31s
replicaset.apps/ms-pd-llm-d-modelservice-prefill-86f6fb7cdc 4 4 4 2m31s

注意: 这假设您的 ${NAMESPACE} 中没有其他指南部署,并且您没有通过 ${RELEASE_NAME} 环境变量更改默认 Release 名称。

使用该组件栈

有关开始发起推理请求的说明,请参阅 我们的文档

调优选择性 PD

在 Prefill-Decode 分离的上下文中,选择性 PD 是 inference-scheduler 中的一项功能,尽管它默认是禁用的。此功能允许即使在部署了 P/D 的情况下也仅路由到 Decode 节点。要启用它,您需要在 GAIE values 文件 中为 pd-profile-handler 插件设置 threshold(阈值)值。您可以在此处查看该值

cat gaie-pd/values.yaml | yq '.inferenceExtension.pluginsCustomConfig."pd-config.yaml"' | yq '.plugins[] | select(.type == "pd-profile-handler")'
type: pd-profile-handler
parameters:
threshold: 0 # update this
hashBlockSize: 5

您可能希望使用选择性 PD 的一些场景包括:

  • 当提示词足够短,以至于将推理拆分为 Prefill 和 Decode 阶段、然后在两个 GPU 之间开启 KV 传输的工作量,大于在同一个 Decode 推理节点上完成两个阶段的工作量时。
  • 当 Prefill 单元处于满负荷状态时。

有关此插件的信息,请参阅我们的 pd-profile-handler 文档(位于 inference-scheduler 中)

清理

移除部署

# Remove the model services
helmfile destroy -n ${NAMESPACE}

# Remove the infrastructure
helm uninstall ms-pd -n ${NAMESPACE}
helm uninstall gaie-pd -n ${NAMESPACE}
helm uninstall infra-pd -n ${NAMESPACE}

注意:如果您设置了 $RELEASE_NAME_POSTFIX 环境变量,您的发布名称将与上述命令不同:infra-$RELEASE_NAME_POSTFIXgaie-$RELEASE_NAME_POSTFIXms-$RELEASE_NAME_POSTFIX

清理 HTTPRoute

请按照特定提供商的说明删除 HTTPRoute。

清理 "kgateway" 或 "istio"

kubectl delete -f httproute.yaml -n ${NAMESPACE}

清理 "gke"

kubectl delete -f httproute.gke.yaml -n ${NAMESPACE}

自定义

有关自定义指南的信息以及构建自己的指南的技巧,请参阅 我们的文档

内容来源

此内容自动同步自 llm-d/llm-d 仓库 main 分支上的 guides/pd-disaggregation/README.md

📝 如需建议修改,请 编辑源文件创建 Issue