文档教程开发工具【免费下载链接】pysheeetPython Cheat Sheet项目地址https://gitcode.com/gh_mirrors/py/pysheeet点击查看免费下载本篇技术指南完整解读 pysheeet 仓库附录文档 disaggregated-prefill-decode.rst 中的实验在 AWS EFA 网络上用 vLLM 0.15.1 NIXLNVIDIA Inference Xfer Library搭建分离式 prefill/decodePD服务并与数据并行、无状态负载均衡路由两种基线做同集群对比。读者将掌握 PD 架构的完整部署链路容器镜像、Slurm 编排、路由代理、基准脚本以及KV cache 跨节点传输在真实推理负载下的代价与收益边界从而判断该架构是否适合自己的工作负载。一、背景prefill 与 decode 互相干扰是分离架构的动机在标准 LLM 服务中每个节点同时承担 prefill 与 decode 两阶段prefill 是计算密集型并行处理整个输入 promptdecode 是显存带宽密集型自回归逐 token 生成。当两个阶段共享同一 GPU 池时长 prefill 请求会阻塞 decode 迭代抬高并发请求的 token 间延迟ITL。分离式 prefill/decode 通过把两个阶段分配到独立的节点组来消除这种干扰prefill 节点完成 prompt 处理后将 KV cache 通过高带宽互联传输给 decode 节点。NIXL 提供 KV cache 传输机制在 AWS 上通过LIBFABRIC后端经 EFA 完成传输。直觉上这很有吸引力——decode 节点不受 prefill 干扰token 生成应保持平稳的低延迟。但分离引入了新的成本KV cache 传输开销、长输入下 prefill 节点饱和、以及每个阶段可用集群容量减少。本实验正是为了回答相比数据并行和简单的无状态负载均衡路由这些权衡是否值得二、实验架构vLLM NixlConnector vllm-router EFA本实验使用 vLLM 的NixlConnector编排分离式服务用vllm-router作为反向代理在各节点组之间做请求负载均衡。完整实验代码位于仓库的 src/nixl 目录包含四个核心文件文件作用Dockerfile构建含 GDRCopy/EFA/UCX/NIXL/vLLM 全套组件的自定义镜像Makefilemake docker make save构建并打包镜像vllm.sbatchSlurm 下编排多节点 vLLM 服务拓扑由--route/--prefill控制bench.sh封装vllm bench serve的基准客户端透明处理镜像加载nixl.sbatch两节点 NIXL 原始带宽/延迟微基准编排核心数据通路prefill 节点kv_producer完成计算后通过 NIXL 的LIBFABRIC后端把 KV cache 经 EFA RDMA 直写GPU-direct到 decode 节点kv_consumervllm-router负责把请求先路由到 prefill 端点、再把后续 decode 流量路由到 decode 端点。三、容器镜像从 CUDA 12.8 基础镜像构建完整推理栈实验使用自定义 Docker 镜像基于nvidia/cuda:12.8.1-devel-ubuntu24.04构建软件栈与版本见 DockerfileGDRCopyv2.5.1GPU-direct 内存注册提供gdrdrv设备驱动EFA installerv1.47.0AWS Elastic Fabric Adapter 支持安装到/opt/amazon/efa与/opt/amazon/openmpiUCXv1.20.0以 verbs、rdmacm、dm、EFA transport 编译--with-verbs --with-rdmacm --with-dm --with-efa并链接 GDRCopyNIXLv0.10.1以LIBFABRIC后端构建供 KV cache 传输使用通过 meson 传入-Ducx_path与-Dlibfabric_path/opt/amazon/efanixlbench独立的 NIXL 带宽/延迟微基准依赖 etcd-cpp-apiPyTorch2.9.1cu128、flash-attn2.8.1、DeepGEMMv2.1.1.post3DeepSeek MLA 内核启用VLLM_USE_DEEP_GEMM1vLLM0.15.1含NixlConnector支持、sglang0.5.9、rayvllm-router跨分离节点组的负载均衡代理值得注意的环境配置DockerfileENV OPAL_PREFIX/opt/amazon/openmpi \ OMPI_MCA_pmlob1 \ OMPI_MCA_btltcp,self \ FI_PROVIDERefa \ FI_EFA_FORK_SAFE1 \ FI_EFA_USE_DEVICE_RDMA1 \ FI_LOG_LEVELwarn \ UCX_TLS^cuda_ipc \ UCX_NET_DEVICESall \ PYTHONPATH/opt/nixl/benchmark其中FI_EFA_USE_DEVICE_RDMA1与UCX_TLS^cuda_ipc是让传输真正走 EFA 设备 RDMA 的关键镜像构建末尾还会执行一次验证ucx_info、fi_info、nixlbench、import nixl。镜像通过 Makefile 构建并保存为便携 tarballmake docker make savemake save实际执行docker save nixl:latest | pigz nixl-latest.tar.gz。该 tarball 在 Slurm 作业启动时由各节点并行pigz -dc ... | docker load解压加载。四、服务编排vllm.sbatch 的两种拓扑控制维度vllm.sbatch 是实验的指挥中心接受两个关键 flag 控制服务拓扑--route R把分配的节点切成 R 个相同大小的组每组运行一个独立 vLLM 实例head 节点上的vllm-router进程在组间轮询分发请求。若NUM_NODES % ROUTE_SIZE ! 0会直接报错退出vllm.sbatch。--prefill P每组内指定 P 个节点为纯 prefillkv_producer其余为纯 decodekv_consumer。每组至少保留 1 个 decode 节点NUM_DECODE NODES_PER_GROUP - NUM_PREFILL 1否则报错。prefill/decode 之间通过NixlConnectorLIBFABRIC后端经 EFA 传输 KV cache。当--prefill 0默认时组内所有节点运行标准数据并行服务。脚本计算DP nodes_per_group * (8 / TP)GPUS_PER_NODE8默认TP8即DP_LOCAL1并按此启动 vLLMvllm serve ... \ --data-parallel-size ${dp} \ --data-parallel-size-local ${DP_LOCAL} \ --data-parallel-address group_head_ip \ --data-parallel-rpc-port port其中从第 2 个节点开始以--data-parallel-start-rank ${i * DP_LOCAL} --headless启动 workerhead 节点则带--host 0.0.0.0 --port port。4.1 分离模式下的 prefill / decode 启动参数分离模式下每个 prefill 与 decode 节点都是独立的 vLLM 进程并显式配置 KV 传输对应 vllm.sbatch 中的实际启动命令# Prefill 节点kv_producer vllm serve ... \ --data-parallel-size 1 \ --kv-transfer-config.kv_connector NixlConnector \ --kv-transfer-config.kv_role kv_producer \ --kv-transfer-config.kv_load_failure_policy fail \ --kv-transfer-config.kv_connector_extra_config.backends LIBFABRIC # Decode 节点kv_consumer vllm serve ... \ --data-parallel-size 1 \ --kv-transfer-config.kv_connector NixlConnector \ --kv-transfer-config.kv_role kv_consumer \ --kv-transfer-config.kv_load_failure_policy fail \ --kv-transfer-config.kv_connector_extra_config.backends LIBFABRIC要点kv_load_failure_policy fail表示 KV cache 加载失败即中止不静默降级保证实验数据干净backends LIBFABRIC的语法表示追加后端而非覆盖。每组内 prefill 节点端口为base_port idecode 节点端口为base_port NUM_PREFILL ibase_port 8000 g * NODES_PER_GROUP。4.2 路由策略round_robin 与 consistent_hash PD 分离路由器策略取决于模式对应 vllm.sbatch# 纯 DP 组round-robin 轮询各组端点 vllm-router \ --policy round_robin \ --worker-urls http://GROUP0_IP:8000 http://GROUP1_IP:8001 \ --intra-node-data-parallel-size 1 \ --host 0.0.0.0 --port 8010 # PD 分离consistent_hash --vllm-pd-disaggregation # 初始请求送往 prefill 端点后续 decode 流量送往 decode 端点 vllm-router \ --policy consistent_hash \ --vllm-pd-disaggregation \ --prefill http://PREFILL0_IP:8000 \ --decode http://DECODE0_IP:8001 --decode http://DECODE1_IP:8002 \ --intra-node-data-parallel-size 1 \ --host 0.0.0.0 --port 8010路由器端口固定为ROUTER_PORT 8000 ROUTE_SIZE。4.3 容器运行时的 RDMA 透传配置每个容器以--privileged、--nethost外加--utshost --ipchost启动并显式挂载/dev/infiniband/uverbs*与/dev/gdrdrv设备vllm.sbatch以实现 EFA 上的 GPU-direct RDMA。脚本还注入以下环境变量-e VLLM_NIXL_SIDE_CHANNEL_HOST${host_ip} \ -e VLLM_NIXL_SIDE_CHANNEL_PORT${SIDE_CHANNEL_PORT:-5600} \ -e VLLM_RPC_TIMEOUT${VLLM_RPC_TIMEOUT:-3600000} \ -e VLLM_ENGINE_READY_TIMEOUT_S${VLLM_ENGINE_READY_TIMEOUT_S:-3600}VLLM_NIXL_SIDE_CHANNEL_HOST/PORT用于 NIXL 控制面侧信道握手超时参数被放大到小时级避免多节点冷启动时误判失败。健康检查通过curl http://ip:port/health轮询最长等待 1800 秒。五、基准脚本bench.sh 与 nixlbench 微基准5.1 bench.sh封装vllm bench serve的客户端bench.sh 包装vllm bench serve透明处理镜像加载若宿主机没有vllmCLI脚本会先预解析--image/-i参数加载镜像tarball 或 ECR pull后把自己重新执行进容器bench.sh。在 Slurm 分配内命令通过srun -N1 --ntasks-per-node1分发执行。基准客户端指向路由器端点或单组配置下的直接 vLLM 端点bash bench.sh -H ROUTER_IP -p ROUTER_PORT -- \ --model /fsx/models/deepseek-ai/DeepSeek-V2-Lite \ --dataset-name random \ --random-input-len 512 --random-output-len 256 \ --num-prompts 1024实际执行的核心命令为vllm bench serve --base-url http://${HOST}:${PORT} argsbench.sh。5.2 nixlbench原始 KV 传输带宽/延迟微基准在查看端到端结果之前先用nixlbench测量 EFA 上两节点间 NIXL 原始传输带宽为 KV cache 传输开销建立上界。编排脚本 nixl.sbatch 会在 head 节点启动 etcd端口2379 SLURM_JOB_ID % 1000作为服务发现随后在各节点启动nixlbench容器。命令在多 GPUMG模式下让每节点全部 8 张 GPU 经LIBFABRIC后端做 VRAM-to-VRAM 传输salloc -N 2 bash nixl.sbatch --backend LIBFABRIC \ --initiator_seg_type VRAM --target_seg_type VRAM \ --mode MG --num_initiator_dev 8 --num_target_dev 8实测带宽/延迟结果Block Size (B)Batch SizeB/W (GB/Sec)Avg Lat. (us)P99 Tx (us)409610.6700646.147.0819211.3153926.245.01638412.5114166.547.03276814.8204236.850.06553618.7332247.556.0131072112.34195010.652.0262144123.27218811.359.0524288143.36576412.162.01048576174.81677314.077.020971521121.08656317.3105.041943041180.63139523.2146.083886081239.03762335.1247.0167772161289.50003058.0432.0335544321327.436372102.5796.0671088641349.608429192.01724.0映射到 DeepSeek-V2-Lite 的 KV cache 传输量该模型使用 MLAMulti-head Latent Attention将 KV cache 压缩为每 token 每层一个潜变量向量大小为(kv_lora_rank qk_rope_head_dim) × dtype_size (512 64) × 2 1,152 bytes。512 个输入 token × 27 层总 KV cache 约15.2 MB。TP8 时每张 GPU 只需传输约1.9 MB落入上表约 121 GB/s 的带宽区间不做张量并行时完整 15.2 MB 传输约可达 289 GB/s。这为后续 TTFT 开销的解读提供了量化基准。六、实验设置五种配置与统一 4 节点环境所有实验在 4 节点、每节点 8 GPUTP8的集群上运行 DeepSeek-V2-Lite通过vllm bench serve使用随机输入/输出数据、1024 个 prompt。五种配置基线数据并行4 节点TP8DP4。所有节点同时服务 prefill 与 decode即标准数据并行部署。Route 22 组 × 2 节点TP8每组 DP2。路由器在组间轮询每组独立处理 prefill 与 decode。Route 44 组 × 1 节点TP8无数据并行。路由器把请求分发到 4 个完全独立的节点。PD 1P3D1 个 prefill 节点 3 个 decode 节点KV cache 经 NIXL 从 prefill 传输到 decode。PD 2P2D2 个 prefill 节点 2 个 decode 节点。对应命令disaggregated-prefill-decode.rst 原文与 vllm.sbatch 参数完全对齐# Exp 1: Baseline — 4 nodes, TP8, pure DP salloc -N 4 bash vllm.sbatch \ --model /fsx/models/deepseek-ai/DeepSeek-V2-Lite \ --gpu-memory-utilization 0.9 # Exp 2: 2 groups × 2 nodes, DP2 per group, router round-robins salloc -N 4 bash vllm.sbatch --route 2 \ --model /fsx/models/deepseek-ai/DeepSeek-V2-Lite \ --gpu-memory-utilization 0.9 # Exp 3: 4 groups × 1 node, no DP, router round-robins salloc -N 4 bash vllm.sbatch --route 4 \ --model /fsx/models/deepseek-ai/DeepSeek-V2-Lite \ --gpu-memory-utilization 0.9 # Exp 4: 1 prefill 3 decode salloc -N 4 bash vllm.sbatch --prefill 1 \ --model /fsx/models/deepseek-ai/DeepSeek-V2-Lite \ --gpu-memory-utilization 0.9 # Exp 5: 2 prefill 2 decode salloc -N 4 bash vllm.sbatch --prefill 2 \ --model /fsx/models/deepseek-ai/DeepSeek-V2-Lite \ --gpu-memory-utilization 0.9评估指标为四类输出 token 吞吐、请求吞吐、首 token 延迟TTFT、token 间延迟ITL。每张图两个面板左面板固定输出长度 256、扫描输入长度prefill 主导区右面板固定输入长度 512、扫描输出长度decode 主导区用于观察工作负载从 prefill 密集转向 decode 密集时的行为差异。七、结果分析7.1 输出 token 吞吐左面板prefill 主导固定输出 256Route 4 吞吐最高——每个节点独立运行无数据并行协调开销。分离式配置PD 1P3D、PD 2P2D在较短输入下吞吐有竞争力但在长输入处劣化此时 prefill 节点成为瓶颈。右面板decode 主导固定输入 512Route 4 再次领先PD 1P3D 次之。PD 2P2D 在该区间吞吐最低——仅有的两个 decode 节点无法匹敌其他配置的 decode 容量。7.2 请求吞吐请求吞吐呈现相似格局Route 4 在所有配置中持续最高。PD 1P3D 在短输入下保持合理请求吞吐但在 4096 token 长输入处显著跌落——单个 prefill 节点饱和成为全集群的吞吐咽喉。7.3 首 token 延迟TTFTTTFT 直接决定用户可感知的等待时长。基线 DP 与 Route 2 呈现中等水平的 TTFT随输入长度增长Route 4 在所有输入长度下 TTFT 最低——没有跨节点协调。分离式配置 TTFT 更高长输入下尤甚PD 1P3D 在 4096 输入 token 时 TTFT 超过 37 秒全部 prefill 工作都汇入单一节点PD 2P2D 有所改善但仍落后于非分离配置。NIXL 上 KV cache 传输带来的额外延迟进一步推高 TTFT。decode 主导区间右面板差异较小短输出256–512 token下 PD 1P3D 比基线高 1–2 秒此时 KV cache 传输开销占比相对更大输出超过 1024 token 后分离式配置收敛到与基线相当甚至更优——基线在更重的并发 decode 负载下受 prefill/decode 争用拖累。7.4 Token 间延迟ITLITL 衡量 decode 阶段相邻生成 token 之间的间隔是分离式服务最核心的优势战场。prefill 主导区左面板PD 1P3D 在所有输入长度下 ITL 最低4096 输入 token 时均值低至约 10 ms——decode 节点被隔离出 prefill 干扰后decode 阶段得以持续运行。PD 2P2D 相对基线也有改善但因 decode 节点更少而收益减弱。基线 DP 与各 Route 配置 ITL 更高尤其在长输入处 prefill 与 decode 争抢同一批 GPU 资源。decode 主导区右面板Route 4 的 ITL 最低约 25–29 ms各节点独立服务、无跨节点协调。分离式配置中 PD 1P3D 优于 PD 2P2D3 个 vs 2 个 decode 节点ITL 保持在约 26–35 msPD 2P2D 仅 2 个 decode 节点ITL 与基线相当约 45–50 ms。输出长度增长时所有配置 ITL 均缓慢上升反映 decode 负载加重。八、讨论银弹吗结论显然不是需要先强调实验前提所有基准使用随机生成的 prompt即每个请求产生独一无二的 KV cache前缀缓存命中率为零——这是分离式服务的最坏情况每次 prefill 都必须从头计算完整 KV cache 必须全部经网络传输。在生产负载中若存在共享系统 prompt 或重复前缀prefill 节点上的前缀缓存可以大幅削减冗余计算与传输量可能改变权衡天平。即便如此结果已揭示一组尖锐的取舍使分离架构成为专用工具而非通用改进ITL 大幅获胜但吞吐取决于扩展方式分离式配置带来了数量级的 ITL 改善——PD 1P3D 在长输入下 ITL 低至约 10 msprefill 主导区比基线好最多 14 倍decode 主导区好 1.4–2.4 倍。本实验观察到的吞吐与 TTFT 劣化部分源于固定 4 节点集群的伪影把节点专用于某一角色会饿死另一角色。实践中 prefill 与 decode 池可独立伸缩——加 prefill 节点消除 prefill 瓶颈或加 decode 节点提升 token 吞吐。难点在于为给定工作负载找到合适的 prefill:decode 比例任何一侧过度供给都会增加成本而无成比例收益。prefill 瓶颈是硬约束集群规模固定时节点专用于 prefill 就减少 decode 容量反之亦然。PD 1P3D 在长输入下严重 prefill 饱和4096 token 时 TTFT 37sPD 2P2D 则因 decode 节点少而限制 decode 吞吐。NVIDIA Dynamo 等框架试图按实时需求动态伸缩 prefill/decode 池但这增加了运维复杂度。简单路由在吞吐上击败分离Route 4纯路由、无 DP、无分离通过完全消除跨节点同步在所有配置中持续获得最高吞吐prefill 主导负载下 TTFT 也最低虽然 decode 主导区 PD 1P3D 因 512 固定输入足够短、未触发 prefill 饱和而略胜。这是一个意外强劲的基线——对于 ITL 不是首要指标的负载无状态负载均衡的独立节点同时胜过数据并行与分离式配置。KV cache 传输并非免费NIXL 经 EFA 的传输为分离式配置的 TTFT 增加了可测量延迟。该开销在长 decode 序列中被摊薄但在短输出下相当明显使分离架构对短回复类负载缺乏吸引力。总结分离式 prefill/decode 的目标是通过隔离两个阶段同时优化 TTFT 与 ITL但达成这一目标并不保证。网络上的 KV cache 传输引入额外开销可能抵消 TTFT 收益——尤其当输入很长、传输量很大时。ITL 的改善因消除 decode 节点上的 prefill 干扰而稳定可见但整体服务性能强烈依赖 prefill:decode 比例、工作负载特征与网络带宽。考虑采用该架构的团队应仔细画像自己的输入/输出长度分布、延迟 SLA 与吞吐需求再决定是否值得承担这份复杂性。九、参考资料与配套资源本实验的技术栈版本与配置细节均可在当前仓库中复核实验编排与启动参数vllm.sbatch、bench.shNIXL 微基准编排nixl.sbatch镜像构建与打包Dockerfile、Makefile原始实验文档disaggregated-prefill-decode.rst实验图表docs/_static/appendix/nixl/目录下的throughput.png、req_throughput.png、ttft.png、itl.png文中涉及的外部组件NIXL、vLLM、vllm-router均为各自开源项目本文只引用当前仓库中可验证的版本与用法未对上游项目做任何未经证实的结论。赞分享文档教程开发工具【免费下载链接】pysheeetPython Cheat Sheet项目地址https://gitcode.com/gh_mirrors/py/pysheeet点击查看免费下载相关推荐AIBrix AWS NeuronTrainium2P/D 分离式推理部署指南基于 NIXL/EFA 的 Prefill/Decode 架构实战AIBrix AWS NeuronTrainium2P/D 分离式推理部署指南基于 NIXL/EFA 的 Prefill/Decode 架构实战 导读云原生大模型模型推理服务API网关LLM 网关弹性伸缩可观测性后端Blender 新手如何上手awesome-blender 免费插件、教程与 3D 资源完整指南Blender 新手如何上手awesome blender 免费插件、教程与 3D 资源完整指南 刚学 Blender 的朋友最容易卡在找资源上教程不知道文档教程draw.io 桌面版 Windows 安装三种 CPU 架构对应 3 个安装包离线画完第一张图draw.io 桌面版 Windows 安装三种 CPU 架构对应 3 个安装包离线画完第一张图 朋友在方案咨询行业客户审计卡得死在线 SaaS 一律禁桌面应用图形学创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考