AREX Feed Article
vLLM 发布 EPD 分离推理升级:官方基准显示 DeepSeek V4.1 Flash 多页文档 P90 TTFT 降 44%~47%、每 GPU 吞吐升 6.6%~9.5%
北京时间 2026 年 11 月 11 日 18 时许,vLLM 项目在官方 X 账号 上宣布其 EPD(encoder/prefill/decode,编码/预填充/解码)分离部署完成一轮升级,并同日在 vllm.ai 发布工程博客 。帖文给出的自报成绩是:在 GB200 上以 DeepSeek V4.1 Flash 运行多页文档基准、并发 64~128 时,P90 TTFT(首 token 生成延迟的第 90 百分位)降低 44%~47%;计入全部 4 张 encoder GPU 后,每 GPU token 吞吐提升 6.6%~9.5%。
这批基准数字与工程描述均为 vLLM 项目单方发布口径。博客把本轮工作归为五项改动:只传元数据的请求让下游免于重复预处理媒体、encoder 专属执行路径、经 Mooncake 与 NIXL 的远程嵌入传输、Mooncake Store 支撑的跨 encoder 输出复用,以及与 vLLM Router、SMG、llm-d 的编排集成。核心能力已包含在 vLLM v0.32.0 中;DeepSeek V4.1 Flash 的元数据支持目前在 main 分支,经 提供。博客也写明了成绩的边界:并发 16 时,EPD 的每 GPU 吞吐反而低于基线。
更多图像不该逼着扩容整个语言模型层
多模态推理在语言模型开工前多一道编码工序:图像、视频帧和音频要先转成 embeddings(嵌入向量),语言模型才能使用。这道工序的负载随媒体大小、模态和请求组合波动,还可能与 prefill、decode 的负载脱节。EPD 把三段拆成独立部署的 vLLM 实例,支持两种模式:E+PD,单独的 encoder 加一个合一的 prefill/decode 实例;E/P/D,三段全部分开。图像密集的负载可以只加 encoder 容量,响应偏长的负载反向调整,encoder 计算也从服务语言模型的 GPU 上挪走。
vLLM 自 2025 年 12 月的起支持 encoder 分离,本轮是对这条线的持续改进。帖文把这条路线的佐证记给 DeepInfer,称其已验证 EPD 分离部署的价值,其自身也以这种部署方式在各阶段间灵活分配资源。据 vLLM 博客的转述,DeepSeek 的 描述了带独立部署视觉 encoder 的 E/P/D 架构;据该问答自述,DeepInfer 是 DeepSeek 开源的面向大规模云服务的推理框架,支撑着 V4.1 Flash 背后的推理服务,单个集群目前每天服务 155 万亿 token。
官方基准:并发 64~128 收益明显,并发 16 反而更慢
博客的 DeepSeek V4.1 Flash 实验在 GB200 上进行:512 道 MP-DocVQA 验证题,每题含 4~6 页原始文档页,请求平均 4,905 个输入 token、5.2 个输出 token,每个并发档跑三遍,缓存与 CUDA Graph 开启。对比两侧的资源并不对称:PD 基线用 4 卡做 prefill、4 卡做 decode,共 8 卡;EPD 保持同样的 P/D 配置——TP=1、DP=4、专家并行,GPU 常驻的 Engram 表按 DP 秩分片(DEP4)——另加 4 个单卡 encoder 实例,共 12 卡。EPD 的嵌入走 Mooncake GPU RDMA,两套部署的 KV 传输都用 NIXL,代码都在 main 提交 5314c58281 加 DeepSeek 元数据扩展上。
结果分两段。并发 64~128 时,EPD 的输入加输出每 GPU 吞吐比 8 卡 PD 基线高 6.6%~9.5%,分母计入全部 12 张卡、包括 encoder;P90 TTFT 低 44%~47%。并发 16 时 EPD 每 GPU 吞吐反而更低,并发 32 大致打平。博客自己给出的判断是:收益取决于负载与资源配置,而不是分离本身。图注注明了口径:吞吐按输入加输出 token 除以总耗时和全部在役 GPU 计算,P90 汇集每个并发档全部 1,536 个请求。
元数据代替原图:下游不再重复拉取、解码、切块
传 embeddings 只完成交接的一半。下游实例还要重建多模态输入布局:占位符长度、图像网格、特征长度,以及把这些位置与传入 embeddings 对应起来的标识。博客指出,直白的 EPD 实现会把原始媒体继续转给 P/PD,消费端可能重新抓取、解码、缩放、归一化乃至切块——这些工作 encoder 已经做过一遍。
元数据请求的做法,是把下游媒体项换成一个引用,内含 encoder 侧已经算好的结构信息,消费端据此重建占位符;embeddings 仍经 EC 连接器走数据通道,文本提示与生成设置不变。图像用 image_grid_thw 这类网格信息,视频用 video_embeds 引用与 encoder 发布的时间戳(Qwen3-VL 的 video_grid_thw 会影响提示的 token 布局),音频用 token 数与特征长度。结构字段还能以数字 JSON 数组表示,省掉 PyTorch 张量序列化与 base64 转换。
音频评测演示了这套交接的价值:MMAU test-mini 上 1,000 个样本跑两遍,Qwen3-Omni-30B-A3B-Instruct、BF16、TP=1、1E+1PD 拓扑、Mooncake TCP、并发 64,元数据转发把吞吐从 62.21 提到 73.13 请求/秒,平均延迟从 980 毫秒降到 853 毫秒;准确率从 75.90% 变为 75.65%,博客称这一差异有待调查。博客特别注明:这组对比衡量的是 EPD 内部两条音频输入路径,不是 EPD 对比同置部署。
DeepSeek V4.1 的图像元数据支持由 PR #62802 引入,该 PR 的验证记录自报:GB200、2E(各 TP=1)加 PD(TP=2)、Mooncake RDMA、并发 96 下 512 道 MUIRBench 题,元数据路径把每 GPU 吞吐从 4,411 提到 4,905 token/秒(+11.19%),端到端 P90 延迟降 6.68%,准确率下降 0.20 个百分点。
encoder 只跑编码,嵌入经 Mooncake 与 NIXL 跨机传输
encoder 实例不跑语言模型、不维护语言模型的 KV cache(键值缓存)、不采样 token。Model Runner V2 用专属的 MMEncoderModelRunner 隔离 encoder 执行:GPU 完成不再依赖 token 采样判断,避免 encoder 还在算时缓冲区被提前复用;配套改动包括生产者专属 EC 实例自动进入 encoder-only 模式、encoder-only 步骤跳过 token 采样,以及可选的 ViT CUDA Graph 捕获。
启动开销也被单独处理:encoder-only 加载在能安全分类权重布局时跳过纯语言模型 checkpoint 分片。在一个剪枝过的 Kimi-K3 checkpoint 上,encoder 只读 96 个分片中的 2 个,权重加载从 683 秒降到 0.31 秒。GPU 预处理与 NVDEC 硬件解码用来加速媒体处理:一项 30 帧 MMVU 评测中,三次运行各自在独立的 4 卡 GB200 节点上(Qwen3.5-35B-A3B,1E+3PD 拓扑,并发 64),端到端吞吐提升约 94%~115%;encoder 变快之后,瓶颈转移到了 PD 层。
跨节点部署需要网络传输,两条远程路径已经合入:NIXL 加 CPU EC,在注册的 CPU mmap 区域之间共享 CPU 卸载的 encoder 输出;Mooncake EC 经 Mooncake TransferEngine 交付,支持 TCP 与 RDMA 两种配置。传输缓冲区可能要在编码之前分配,而 encoder 输出宽度因模态和架构而异——被测的 Qwen3-Omni checkpoint 视觉输出宽 8,192(含 DeepStack 信息)、音频输出宽 2,048。EC 生产者现在在初始化时按模态测量输出宽度,并把实际形状随传输协议携带;NIXL EC 协议版本随之更新,要求生产者与消费者一起升级。
失败处理也因元数据请求而变得关键:只拿元数据的消费端没有原始媒体可回退。现在,远程编码迟迟不到且本地恢复不可用时,消费端把受影响请求标记为不可用,而不是走可能终止 EngineCore 的不安全回退路径;NIXL 设置失败后的共享内存释放等资源生命周期修复同步落地。
跨 encoder 缓存:受控实验里 512 次重复编码降到 0
实例本地的缓存有个盲区:一张图在 E0 上编过,负载均衡、扩缩或恢复后可能被路由到 E1;E1 本地没有缓存,就会重复一次另一个实例已完成的前向。Mooncake Store 补上这层共享:本地未命中时 encoder 查共享 Store,命中就直接取 embedding,未命中走正常编码并异步发布输出;发给所选 P 实例仍走 Mooncake P2P。共享复用会校验输入身份、模型身份和输出张量契约,初始支持图像、Model Runner V2、encoder TP=1,不支持动态 LoRA。
一项给出了上限参考:六张 H20、InternVL3_5-38B-HF、2E+4PD 拓扑、同节点 Mooncake TCP。缓存预热后,把图像在两个 encoder 之间重新指派、制造本地未命中;在含 512 张图的 128 个请求中,共享复用把重复图像编码从 512 次降到 0 次,TTFT p50 从 1.209 秒降到 0.819 秒,p90 从 1.656 秒降到 0.891 秒,TPOT 基本不变。博客随即提醒:这是单次运行、且每张图都被重指派的最好情形;生产环境能省多少,取决于输出复用频率与 Store 的内存、I/O 成本之比;发布是异步的,并发的冷请求仍可能重复计算。
Router、SMG、llm-d 补上调度层,回复区继续追问
编码变快、缓存命中变多之后,调度本身可能成为瓶颈。Python EPD 代理换上更快的 JSON 编解码,最终响应字节(含流式响应)直接转发而不解码再编码;元数据请求本身也减少了下游媒体流量。集成层面,vLLM Router 支持 HTTP E+PD 与 E/P/D 部署、元数据转发、多图分发到多个 encoder 以及数据并行的 P/PD 消费者,encoder 与消费者数量可以独立配置;SMG 经 gRPC 支持 E/P/D,提供 Python 与 Rust 两种 servicer,还能把单个纯图像请求里的多张图分给多个 E worker,并对分给同一 encoder 的图做批处理,两者集成均基于各自仓库的 main 分支;llm-d 在 Kubernetes 上运行 vLLM EPD,每个角色是独立的 pod 层,encoder 可以独立扩缩并使用不同硬件,llm-d Router(Endpoint Picker)负责挑选 encoder pod,路由 sidecar 或 Coordinator 把编码请求分发出去并行处理多图,embeddings 经 NIXL EC 连接器抵达消费端,纯文本请求直接跳过编码。博客提到 llm-d 团队与 vLLM 社区合作提供了经过验证的 Kubernetes 原生部署路径,并致谢来自 Inferact、InferMatrix 团队与 IBM 的贡献者。
帖子下的回复也在给这套方案出题。X 用户 Ethan Lin 认为,把 encoder GPU 计入吞吐分母是「诚实的报告方式」——分离式的演示常把这个成本藏起来——他追问的是短多模态提示下这种拆分何时不再划算;X 用户 Bharat Sharma(其资料自述为 WattOps 创始人)则认为这种拆分正适合 computer-use agents(操作电脑的智能体),真正的考验是回合之间的工具暂停:如果 KV 与 encoder 缓存在代理等待工具时被逐出,每一轮都得重新编码截图、重新预填充整段历史,只有缓存在这段暂停里保得住,分离部署才有回报。
路线图上还留着一个未解的协调问题:在 E 优先的流水线里,P 还没发现它的 KV cache 已覆盖某个多模态出现、或本地已有可复用 embedding 时,encoder 可能已经把前向算完了。一项正在探索如何让 P 端的需求反过来抑制上游不必要的编码,而设计要在省下的计算与额外的查找、协调、冷请求延迟之间找平衡。下一步还包括观测性、更多传输与缓存后端、前端集成与更清晰的上游错误传播——运营者需要分清计算 embedding、读取缓存输出和远程传输各花多少时间。缓存能否在工具调用的间隙里保住,是回复区留下的开放问题;让 P 端需求反过来抑制上游多余编码的设计,则还停在博客路线图上的那项讨论里。