文档(金鹏): 2026-08-06 章节 48 篇文章摘要归档
- 46 篇原文+摘要双文件归档(按 来源/作者 分层,复用本地归档 20 篇+新抓取 26 篇) - 即梦生成 9 组主题配图(大图+列表缩略图)存入 知识/金鹏/20260806/ - 章节重组为 9 个主题分组并挂接摘要引用
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
# pd分离在vllm中用法
|
||||
|
||||
> **来源**:CSDN 博客(博主:小徐炸酱面)
|
||||
> **作者**:小徐炸酱面(qq_44319972)
|
||||
> **发布日期**:2025-12-01(2025-12-02 修改)
|
||||
> **原文链接**:https://blog.csdn.net/qq_44319972/article/details/155456852
|
||||
|
||||
---
|
||||
|
||||
### 1. 背景:为什么需要 PD 分离
|
||||
|
||||
大模型在线服务一般包含两种阶段:
|
||||
|
||||
- **Prefill 阶段**
|
||||
- 输入:完整的 prompt
|
||||
- 动作:一次性跑完所有输入 token 的前向,构建 KV Cache
|
||||
- 特点:
|
||||
- **计算密集**(GEMM-heavy,吃算力)
|
||||
- 对显存需求大(一次性占用大量 KV)
|
||||
- 对带宽要求相对没那么极端(一次性大算子)
|
||||
- **Decode 阶段**
|
||||
- 输入:每轮只处理很少的新 token(一般 1~几 token)
|
||||
- 动作:基于已有 KV Cache 不断迭代生成新 token
|
||||
- 特点:
|
||||
- 单步计算量相对小
|
||||
- 访问 KV Cache 频繁,**更吃显存带宽 / 内存带宽 / 通信带宽**
|
||||
- 很多小 kernel,调度频率高
|
||||
|
||||
**PD 分离(Producer / Decoder Separation)** 的目标就是:
|
||||
|
||||
- 把 prefill 和 decode 拆到**不同的进程 / 节点 / 设备**上
|
||||
- 利用不同节点的算力/带宽特性,整体提升吞吐、降低延迟
|
||||
|
||||
### 2. PD 分离的基本概念与架构
|
||||
|
||||
#### 2.1 角色定义
|
||||
|
||||
- **P 节点(Producer)**
|
||||
- 负责:prefill 阶段
|
||||
- 对应操作:
|
||||
- 处理新请求的 prompt
|
||||
- 运行大批量 GEMM
|
||||
- 把得到的 KV Cache 写入某种共享介质(或通过 KV 通道发送给 D 节点)
|
||||
- 资源特征:
|
||||
- 更看重:**算力、GPU FLOPs**
|
||||
- 对长尾小请求和频繁通信不是特别敏感
|
||||
- **D 节点(customer)**
|
||||
- 负责:decode 阶段
|
||||
- 对应操作:
|
||||
- 不断从 KV 中取数据
|
||||
- 迭代生成每个 request 的后续 token
|
||||
- 资源特征:
|
||||
- 更看重:**显存带宽 / 网络带宽 / 延迟**
|
||||
- 关注 tail latency(TPOT、e2e)
|
||||
|
||||
#### 2.2 KV Cache 的流转
|
||||
|
||||
PD 分离的**核心**就是:**prefill 生成的 KV,如何让 decode 能够用起来**。
|
||||
|
||||
一般数据流可以抽象成:
|
||||
|
||||
1. 请求进来,P 节点接收并执行 prefill
|
||||
2. P 节点为该 request 分配 KV Block(或 Block 列表)
|
||||
3. P 节点把 KV 的位置信息 + request 的 metadata 通过某种 **KV Connector / RPC 通道** 告诉 D 节点
|
||||
4. D 节点接管该 request 的 decode:
|
||||
- 知道对应 KV 在哪里
|
||||
- 在后续 decode 中,始终通过 KV Connector 访问这些 KV
|
||||
|
||||
典型注意事项:
|
||||
|
||||
- 如果有 DP/TP,P/D 侧的并行策略也要匹配(否则会出现 KV 维度不一致、block id 对不上等问题)
|
||||
- 如果跨机器,需要额外考虑网络带宽、RDMA、压缩等问题
|
||||
|
||||
### 3. vLLM 中的 PD 分离思路(概念层面)
|
||||
|
||||
> 这里以 "vLLM + 自研 PD 功能" 的思路来整理,只写通用逻辑,不绑死具体实现细节。
|
||||
|
||||
#### 3.1 与调度器(scheduler)的关系
|
||||
|
||||
vLLM 的 serving 里,有一个统一的 scheduler 管理:
|
||||
|
||||
- 新请求的进入(prefill 阶段)
|
||||
- 已有请求的继续 decode
|
||||
- 每一轮 step,要算多少 token(`num_scheduled_tokens`)
|
||||
- 每个 request 一共已经算了多少 token(`num_computed_tokens`)
|
||||
|
||||
PD 分离后,逻辑可以拆解为:
|
||||
|
||||
1. **Producer 侧 scheduler**:只负责 prefill
|
||||
2. **Decoder 侧 scheduler**:只负责 decode
|
||||
3. 通过某种方式保证两边对 request 状态的约定一致,例如:
|
||||
- request id
|
||||
- 已生成 token 数
|
||||
- KV block id 列表
|
||||
- 当前是否已经结束(EOS / abort)
|
||||
|
||||
### 4. 在 vLLM 中使用 PD 分离的典型启动方式(示意)
|
||||
|
||||
> 下面用伪代码/伪命令展示结构,变量名你可以换成你们环境里的 `VLLM_USE_V1` / `vllm_PD_ROLE` / `kv_transfer_config` 等。
|
||||
|
||||
#### 4.1 不分离时(baseline)
|
||||
|
||||
```
|
||||
# 单机单进程示意
|
||||
python3 -m vllm.entrypoints.openai.api_server \
|
||||
--model /data/models/Qwen3-32B \
|
||||
--tensor-parallel-size 2 \
|
||||
--dtype bfloat16 \
|
||||
--max-model-len 32768 \
|
||||
--port 8000 \
|
||||
--host 0.0.0.0
|
||||
```
|
||||
|
||||
Benchmark 示意:
|
||||
|
||||
```
|
||||
python3 benchmarks/benchmark_serving.py \
|
||||
--backend openai-chat \
|
||||
--base-url http://<host>:8000 \
|
||||
--endpoint /v1/chat/completions \
|
||||
--model Qwen3-32B \
|
||||
--tokenizer /data/models/Qwen3-32B \
|
||||
--dataset-name random \
|
||||
--random-input-len 2000 \
|
||||
--random-output-len 200 \
|
||||
--request-rate 5 \
|
||||
--num-prompts 100 \
|
||||
--percentile-metrics ttft,tpot,e2el
|
||||
```
|
||||
|
||||
#### 4.2 1P1D(单机或双机)
|
||||
|
||||
**4.2.1 Producer 节点**
|
||||
|
||||
```
|
||||
export VLLM_USE_V1=1
|
||||
export vllm_PD_ROLE=producer
|
||||
|
||||
python3 -m vllm.entrypoints.openai.api_server \
|
||||
--model /data/models/Qwen3-32B \
|
||||
--tensor-parallel-size 2 \
|
||||
--max-model-len 32768 \
|
||||
--max-num-batched-tokens 8192 \
|
||||
--max-num-seqs 32 \
|
||||
--port 8209 \
|
||||
--host 0.0.0.0 \
|
||||
--kv-transfer-config \
|
||||
'{"kv_connector":"P2pNcclConnector",
|
||||
"kv_role":"kv_producer",
|
||||
"kv_rank":0,
|
||||
"kv_parallel_size":2,
|
||||
"kv_buffer_size":1,
|
||||
"kv_port":9109,
|
||||
"kv_connector_extra_config":{
|
||||
"proxy_ip":"0.0.0.0",
|
||||
"proxy_port":30001,
|
||||
"http_port":8109
|
||||
}}' \
|
||||
&> Qwen3-32B-producer.log &
|
||||
```
|
||||
|
||||
**4.2.2 Decoder 节点(D,kv_consumer)**
|
||||
|
||||
> ⚠️ 原文此处的代码块与 Producer 节点完全相同(`vllm_PD_ROLE=producer`、`kv_role:"kv_producer"`),疑为作者复制粘贴遗漏修改。按原文忠实保留如下,实际部署时 Decoder 侧应改为 `vllm_PD_ROLE=decoder` / `kv_role:"kv_consumer"`、`kv_rank` 相应调整。
|
||||
|
||||
```
|
||||
export VLLM_USE_V1=1
|
||||
export vllm_PD_ROLE=producer
|
||||
|
||||
python3 -m vllm.entrypoints.openai.api_server \
|
||||
--model /data/models/Qwen3-32B \
|
||||
--tensor-parallel-size 2 \
|
||||
--max-model-len 32768 \
|
||||
--max-num-batched-tokens 8192 \
|
||||
--max-num-seqs 32 \
|
||||
--port 8209 \
|
||||
--host 0.0.0.0 \
|
||||
--kv-transfer-config \
|
||||
'{"kv_connector":"P2pNcclConnector",
|
||||
"kv_role":"kv_producer",
|
||||
"kv_rank":0,
|
||||
"kv_parallel_size":2,
|
||||
"kv_buffer_size":1,
|
||||
"kv_port":9109,
|
||||
"kv_connector_extra_config":{
|
||||
"proxy_ip":"0.0.0.0",
|
||||
"proxy_port":30001,
|
||||
"http_port":8109
|
||||
}}' \
|
||||
&> Qwen3-32B-producer.log &
|
||||
```
|
||||
|
||||
**`kv-transfer-config` 参数解释:**
|
||||
|
||||
- **`kv_connector`**:用什么通道传 KV。现在用:`P2pNcclConnector`,表示走 NCCL P2P 通信。
|
||||
- **`kv_role`**:这个进程是**发 KV 的**还是**收 KV 的**。
|
||||
- P:`"kv_producer"`
|
||||
- D:`"kv_consumer"`
|
||||
- **`kv_rank`**:在这组通道里的编号,从 0 开始。多个并行通道时,用它来区分是谁↔谁。
|
||||
- **`kv_parallel_size`**:一共有几路 KV 通道(也可以理解为这组里有多少 rank)。一般设成和 TP/world size 一致。P 和 D 必须一样。
|
||||
- **`kv_buffer_size`**:通道里最多允许多少块 KV "在路上"。值越大,流水越深、占用显存可能越多;不确定就先用 `1`,稳一点。
|
||||
- **`kv_port`**:KV 通道用的基础端口。P / D 两边要一致,别和其他服务冲突。
|
||||
|
||||
**`kv_connector_extra_config` 里的:**
|
||||
|
||||
- **`proxy_ip`**:KV 代理服务的 IP,或者要连的那台机的 IP。单机可以写 `0.0.0.0` 或 `127.0.0.1`,跨机就写对端/代理机的 IP。
|
||||
- **`proxy_port`**:KV 代理服务监听的端口。P / D 配成同一个值,比如 30001。
|
||||
- **`http_port`**:**Decoder vLLM HTTP 服务的端口**(就是 D 起 server 时的 `--port`)。用来让 KV 组件知道 D 的 HTTP 在哪里。
|
||||
|
||||
**关于 xPyD:**
|
||||
|
||||
一般来说 xPyd,其中每一个 p 节点或者 d 节点都要能独立加载完整个模型。
|
||||
|
||||
总卡数量:总 GPU 数 = (P + D) × TP × DP
|
||||
|
||||
最后使用 vllm 自带的代理端口转发即可:
|
||||
|
||||
```
|
||||
python3 vllm/examples/online_serving/disaggregated_serving_p2p_nccl_xpyd/disagg_proxy_p2p_nccl_xpyd.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
> **下载说明**:本文原文含大量 CSDN 页面噪声(侧边栏推荐文章、广告、评论 UI、VIP 弹窗等),已剔除非作者内容,仅保留正文与代码;CSDN 推荐栏中出现的其他博主的 PD 分离相关文章摘要未纳入。
|
||||
@@ -0,0 +1,80 @@
|
||||
# 📊 文章摘要:pd分离在vllm中用法
|
||||
|
||||
> **原文**:[2025-12-01_pd分离在vllm中用法.md](./2025-12-01_pd分离在vllm中用法.md)
|
||||
> **原文链接**:https://blog.csdn.net/qq_44319972/article/details/155456852
|
||||
> **来源**:CSDN 博客
|
||||
> **作者**:小徐炸酱面(qq_44319972)
|
||||
> **发布日期**:2025-12-01(2025-12-02 修改)
|
||||
> **摘要日期**:2026-08-06
|
||||
> **价值评级**:⭐⭐ 中
|
||||
|
||||
---
|
||||
|
||||
## 核心命题
|
||||
|
||||
> **KV 流转** — vLLM 中 PD 分离工程化的核心是"prefill 生成的 KV 如何让 decode 用起来",本文给出 kv-transfer-config 的参数级配置说明。
|
||||
|
||||
---
|
||||
|
||||
## 文章概要
|
||||
|
||||
本文是 vLLM PD 分离的实操笔记,把部署要点收敛为一个核心问题:"prefill 生成的 KV,如何让 decode 能够用起来"。文章先定义 P 节点(Producer,看重算力/FLOPs)与 D 节点(customer,看重显存/网络带宽与 tail latency),梳理 KV 流转四步(prefill→分配 KV Block→经 KV Connector/RPC 通道传递位置信息与 metadata→decode 持续访问),再给出 1P1D 场景下 producer 与 decoder 的完整启动命令,逐项解释 kv-transfer-config 的 kv_connector/kv_role/kv_rank/kv_parallel_size/kv_buffer_size/kv_port 及 proxy 三项参数含义,并给出 xPyD 总卡数公式((P+D)×TP×DP)。价值在于参数级细节是综述类文章不具备的、可直接指导部署。局限:无性能验证,且 decoder 示例疑似复制粘贴错误,需修正后使用。
|
||||
|
||||
---
|
||||
|
||||
## 关键要点
|
||||
|
||||
1. **核心即 KV 流转** — PD 分离成败在于 prefill 产出的 KV 能否高效被 decode 使用,抽象为 KV Connector/RPC 通道 + 状态约定 `[分类: 共识]`
|
||||
2. **P/D 角色差异** — P 节点看重算力/GPU FLOPs,对长尾小请求不敏感;D 节点看重显存/网络带宽,关注 tail latency(TPOT、e2e) `[分类: 共识]`
|
||||
3. **并行策略必须匹配** — 有 DP/TP 时 P/D 两侧并行策略须一致,否则出现 KV 维度不一致、block id 对不上等问题 `[分类: 共识]`(实操经验)
|
||||
4. **kv-transfer-config 参数详解** — kv_role(producer/consumer)、kv_rank、kv_parallel_size(与 TP/world size 一致且 P/D 必须相同)、kv_buffer_size(流水深度,不确定先用 1)、kv_port 及 proxy_ip/proxy_port/http_port 的设置原则 `[分类: 共识]`(实操)
|
||||
5. **xPyD 规模公式** — 总 GPU 数 = (P+D)×TP×DP;每个 P/D 节点都须能独立加载完整模型,对外经 disagg_proxy 端口转发 `[分类: 共识]`(实操)
|
||||
6. **调度器拆分** — Producer 侧与 Decoder 侧各自 scheduler,以 request id、已生成 token 数、KV block id 列表、EOS/abort 状态对齐两边约定 `[分类: 共识]`
|
||||
|
||||
---
|
||||
|
||||
## 批判性分析
|
||||
|
||||
### 假设前提
|
||||
|
||||
假设读者已熟悉 vLLM(V1 引擎、scheduler 概念);假设 NCCL 网络与 KV 代理服务可用;假设 KV 通道数(kv_parallel_size)与 TP world size 对齐。
|
||||
|
||||
### 论据与逻辑
|
||||
|
||||
无性能数据,属经验整理而非验证性文章;Decoder 节点示例与 Producer 完全相同(vllm_PD_ROLE 与 kv_role 未改,原文已加注提示),说明示例未经实际运行验证,照抄会部署失败——这是论据链的关键缺口;但参数解释与 vLLM 官方文档一致,整体可信度尚可。
|
||||
|
||||
### 边界与局限
|
||||
|
||||
仅覆盖 P2pNcclConnector 的 1P1D(单机/双机)场景,未涉及 SharedStorage/LMCache/MultiConnector、多机大规模部署与 kv_buffer_size 调优;作者自述"示意/伪代码",不能替代官方文档。
|
||||
|
||||
---
|
||||
|
||||
## 可引用金句
|
||||
|
||||
> "PD 分离的**核心**就是:**prefill 生成的 KV,如何让 decode 能够用起来**。"
|
||||
|
||||
> "如果有 DP/TP,P/D 侧的并行策略也要匹配(否则会出现 KV 维度不一致、block id 对不上等问题)"
|
||||
|
||||
---
|
||||
|
||||
## 总体评价
|
||||
|
||||
**亮点**:
|
||||
- kv-transfer-config 各参数逐项解释,实战稀缺
|
||||
- 给出可直接照做的启动命令与 xPyD 卡数公式
|
||||
- 诚实标注"示意/伪代码"并提示 DP/TP 匹配等坑点
|
||||
|
||||
**不足**:
|
||||
- decoder 示例疑似复制粘贴错误,须自行修正(角色应改为 kv_consumer)
|
||||
- 无性能验证数据,经验未经实测背书
|
||||
- 场景覆盖窄(仅 P2pNccl 的 1P1D)
|
||||
|
||||
**适用场景**:准备在 vLLM V1 上搭建 PD 分离服务的工程师,作为起步配置参考。
|
||||
|
||||
**关联建议**:对照 vLLM 官方文档 Disaggregated Prefilling 章节与 KV Connector API V1;参考 cr7258 文中五种 KV Connector 的对比做扩展选型。
|
||||
|
||||
---
|
||||
|
||||
## 配图
|
||||
|
||||

|
||||
Reference in New Issue
Block a user