← 返回观点 思考

DeepInfer 深度解析:DeepSeek 如何把模型、缓存与调度一起设计成 Token 工厂

从 DeepSeek 开源代码与官方技术报告出发,拆解 CED、CSA2、SWA 有界回放、Wide-EP、DSSpark 和异步调度,核查性能口径与推理经济性,并给出构建生产级服务的扩展接口、验证门槛及选型建议。

2026-10-23思考90 分钟阅读
DeepInfer 深度解析:DeepSeek 如何把模型、缓存与调度一起设计成 Token 工厂

从 CED 与 CSA2,到 Wide-EP、SWA bounded replay、DSpark 和异步调度:一次面向 AI 基础设施架构师、产品负责人和推理服务经营者的源码级拆解。

研究口径:本文基于 2026 年 10 月 23 日可获得的官方材料,并将 DeepInfer 源码固定到提交 9bd9cf243fc53ef9afbf8f04d391d989117d6ab9。本文采用文档核验与静态源码分析,没有自行运行 GPU 性能测试;性能数字区分官方披露、基准脚本推算与本文假设,不把离线结果当作生产承诺。

先说结论:值得认真研究;收益来自共设计,生产化仍需补齐系统

DeepInfer 最重要的意义,在于把 DeepSeek 的一套工程判断公开成了可阅读、可运行、可验证的实现。当模型服务进入长上下文、多轮 Agent 和大规模 MoE 阶段,值得优化的对象已经从单个矩阵乘法、单卡每秒生成多少 Token,扩展到整个请求生命周期:有多少计算值得执行、有多少状态值得保存、哪些资源必须同步等待,以及这些决策能否转化成满足延迟约束的有效产出。

它的核心优势来自共设计。模型通过 CED 和 CSA2 减少必须生成和保留的 KV;引擎用 SWA bounded replay 接受可评估的近似状态重建,换掉昂贵的持久化和重算;Wide-EP 把 Decode 的专家权重与批量计算重新分配到大规模高速互联域;DSpark 不仅生成草稿,还把接受概率提供给调度器,让验证预算按边际收益分配;异步调度则把原本露在关键路径上的 CPU 工作藏到设备执行之后。这些机制环环相扣,彼此为对方创造前提条件。

但另一半结论同样重要:这次公开的是支撑生产系统的离线推理核心,DeepSeek 内部云服务的完整发行版还包含更多东西。仓库已经包含本地 KV 分配、状态缓存、批调度、模型执行和诸多 PD 分离扩展位置;完整的分布式 KV 服务、跨实例路由与负载均衡、E/P/D 服务编排等,仍需部署方补齐。把「内部生产系统由 DeepInfer 驱动」理解成「克隆仓库就得到同等生产服务」,会在上线阶段付出非常高的学费。[1][2]

下文先解释模型如何改变计算和状态,再进入并行、投机与异步执行,最后把基准、经济性与生产化放在同一套验收标准里。读者若主要关心选型,可以先看第十至十三节,再回到机制部分核对收益前提。

对已有大规模 DeepSeek 业务、具备高速互联和基础设施研发能力的团队,DeepInfer 是值得进入验证流水线的候选,也是理解下一代推理成本结构的一份高价值样本。对小规模、多模型、强调开箱即用的团队,它首先是架构参考和专项实验对象,而不必立即成为统一服务底座。最后的选择应该由真实请求轨迹下的服务质量、有效吞吐、容量风险和总成本决定,而不是由发布当天的一张 Pareto 图决定。

图 1:DeepInfer 公开引擎与完整生产系统的边界
图 1:DeepInfer 公开引擎与完整生产系统的边界

图 1 阅读重点:公开核心解决「把一次推理执行好」,完整服务还要解决「把请求与状态送到正确的位置,并在失败时继续工作」。图中外接组件是生产化责任边界,不代表仓库完全没有对应的底层能力。

一、从聊天服务器到 Token 工厂,瓶颈为什么变了

早期部署语言模型,典型问题是让模型装进显存、把单请求响应变快、用批处理提高利用率。如今,一个 Agent 可能反复读取工具结果、检索资料、修改代码,每轮都携带不断增长的历史。输入长度、输出长度、会话间隔和前缀复用率,开始和模型参数量一样影响成本。相同的「百万 Token」,可能是大量无法复用的首轮长输入,也可能是反复命中缓存的历史上下文,还可能是需要持续占用 Decode 资源的长输出。只报一个混合 Token 单价,会遮蔽真正的资源消耗。

Prefill 和 Decode 也不是同一种工作。Prefill 一次处理一段已知输入,通常可以形成较大的矩阵计算;Decode 必须沿着自回归依赖不断推进,每轮每个请求贡献的有效工作有限,对权重搬运、KV 读取、通信和调度空隙更加敏感。长上下文进一步增加注意力状态与访问成本。多模态场景还有独立的视觉编码工作,它的成本又受到图片尺寸、切片和 patch 数量影响。

所以「让 GPU 一直忙」本身说明不了什么。GPU 可以忙于重算本来能复用的前缀,忙于验证大概率会被拒绝的草稿,忙于为其他 rank 等待,或者忙于产出客户端已经取消、最终无法交付的内容。Token 工厂要提高的是:在指定质量与服务等级下,每单位总资源能交付多少有用结果。

DeepSeek 的部署 Q&A 把目标描述得相当具体:支持多家加速器;用普通八卡机器组织 Prefill、用 64–128 卡级别的超节点组织 Decode;让 KV 的长期复用窗口超过 72 小时。这些是采购、网络、存储与业务形态共同施加的约束,不是抽象算法指标。[2] 理解这组约束,比记住某一个优化名词更有价值。一个适合大规模 Agent 流量的解法,在低并发、低复用、小模型服务中未必有同样收益。

从这个角度看,DeepInfer 展示的是模型结构如何让调度、缓存和硬件部署变得更有利——成本问题的答案并不全在调度器。模型决定哪些状态必须存在;系统决定这些状态在哪里、何时产生、如何迁移,以及多久以后还值得保留。

二、先把发布边界看清楚:运行时、服务面与内部系统是三层东西

README 明确写出本次发布提供 offline inference,并列出了当前支持的模型 DeepSeek-V4.1-Flash,以及 NVIDIA SM100 和华为 Ascend 950 两类硬件。依赖包括 Linux、GCC 13 及以上、Python 3.12,NVIDIA 路径要求 CUDA 13,Ascend 路径要求 CANN 9.2。这是当前官方明确支持的范围;其他模型与硬件组合不能据此视为已经验证。[1]

公开运行时的内容并不少。外层的 LLM 接口负责输入、采样参数与请求生命周期,LLMEngine 把批调度、状态管理和设备执行衔接起来;C++ 侧承担序列、块管理、调度和输入元数据;Python 侧组织模型、图执行、算子后端与平台适配。README 还给出结构化输出、确定性采样、batch-invariant inference、DSpark 和 bounded replay 等配置。它不是只有几个 kernel 的展示工程。

然而,完整在线服务还包含另一类问题:请求鉴权与配额、协议转换、排队与取消、跨实例选路、故障重试、会话迁移、分布式缓存查找与传输、扩缩容、计量和可观测性。README 将 KV cache system、VE/Prefill/Decode 分离,以及 Prefill 和 Decode 的数据并行副本负载均衡列为完整服务仍需的组件。这里的「缺 KV 系统」指分布式服务层,不是没有本地 KV cache。[1]

这一区分在源码里可直接核实。deepinfer/worker/cache_engine.py 实现了 KVCacheManager、GPUCacheInterface、StateBlock 和 GPU 缓存分配;csrc/engine/block_manager.hpp 管理块资源;LLMEngine 则保留了 init_pd_split、post_schedule、do_save_kvcache、send_processed_prompts 等扩展方法。它们说明引擎考虑了生产系统的集成位置,但不能据此把尚未接入的存储、传输与路由当成已经交付的服务。[3][4]

还有一个容易混淆的边界:README 的能力表包含 balanced CP,而官方 Q&A 表述的是当前内部部署暂不使用 TP 和 CP。两者并不矛盾。前者是实现支持面,后者是某个模型、硬件和负载条件下的生产选择。架构评估应分别记录「能运行」「经过验证」「官方当前采用」三个状态,不能把它们压成一个勾选框。

三、模型与引擎的共设计:先减少必须做的工作,再加速剩下的工作

CED 把 Prefill 与 Decode 的计算图区别对待

DeepSeek-V4.1-Flash 技术报告给出的 backbone 参数量为 552B,Prefill 每 Token 激活约 8B 参数,Decode 激活约 16B。这种不对称来自 Causal Encoder-Decoder,简称 CED,而不是简单把同一个网络在两个阶段用不同精度跑一遍。[5]

这里的 Encoder 和 Decoder 不能照搬传统机器翻译模型的理解:Encoder 仍是因果计算;它也不是系统 E/P/D 分离中的 E(后者指视觉编码器)。CED 是模型内部计算拓扑,Prefill/Decode 分离是服务部署拓扑,两者可以组合,却是两回事。CED 的前半部分是因果编码层,后半部分的全局 KV 不再由各自逐层处理完整前缀后生成,而是从最后一个 Encoder 层的隐藏状态投影获得。对于完整历史,Decoder 部分所需的全局记忆可以通过这个更短的路径建立。于是 Prefill 不必在全部层上执行完整的逐 Token 计算。

为什么 Decode 仍需要更完整的路径?因为生成当前 Token 的隐藏状态和输出,仍要经过相应的深层处理;而且各层的局部滑动窗口状态保持自己的逐层依赖。CED 减少的是历史输入建立状态时的重复工作,并不是让后半个模型从生成过程里消失。把它理解为「Prefill 少算大量历史,Decode 保留生成能力」,比理解为「把模型砍成一半」更准确。

对于输入占比高、频繁调用工具的 Agent,这个结构有直接价值。一次工具调用后,系统需要吸收新增输入,而此前的历史还可能很长。模型若能让历史状态建立更便宜,缓存命中和未命中两种场景都更容易控制 TTFT。不过收益依赖输入规模:输入已经很短,或整个请求主要成本来自漫长输出时,Prefill 的优化不可能按同样比例降低端到端成本。

CSA2 把全局记忆的重复存储和重复索引拆开

仅减少 Prefill 计算还不够。长上下文服务会受到 KV 容量、加载带宽和存储成本的多重限制。CSA2,也就是 Compressed Sparse Attention 2,把跨层共享细分成 Full、Reindex、Reuse 三种模式。Full 层生成全局 KV 并做索引;Reindex 层共享前面已有的全局 KV,但使用自己的查询重新选择相关项;Reuse 层连选出的 Top-K 索引也复用。与此同时,各层保留自己的全局 Q 与局部 SWA KV。[5]

这个设计的关键是承认:不同层未必都需要重新创造一份历史记忆,也未必都需要重新判断该读哪些历史。把「保存记忆」和「选择记忆」分别共享,可以比一刀切复用更灵活地分配计算。它也让注意力后端不再是完全同质的逐层结构。实现者必须理解一个层是生产者、重新索引者还是消费者,否则缓存布局、生命期和算子调用都可能出错。

为了把三种模式的边界说清楚,可以用一张紧凑的职责表:

CSA2 模式 全局 KV / indexer K Top-K 选择 本层仍独立计算什么
Full 新生成 本层新选择 主查询、局部 SWA、注意力输出
Reindex 复用已有状态 本层重新选择 主查询、局部 SWA、注意力输出
Reuse 复用已有状态 复用已有选择 主查询、局部 SWA、注意力输出

V4.1 使用的是纯 CSA2,不是 V4 的 CSA/HCA 混合。40 个 backbone 层中,前 20 层是因果 Encoder,后 20 层是 Decoder;按报告配置,主要全局 KV 来源只有四处,而不是每层一份。复用也不是复制上一层输出:当前层仍会用自己的查询处理选出的记忆。这保留了层间表达变化,同时削减重复状态。[5][11]

把 890 B/token 算出来,才能知道到底省了什么

主 KV 的每个条目有 512 个四比特数,数据占 256 B,加上每 16 个数一个一字节 scale,共 288 B;indexer K 的每个条目有 128 个四比特数,数据占 64 B,加上每 32 个数一个 scale,共 68 B。三份 Encoder 全局缓存每两个原始 Token 生成一条,另一份 Decoder 全局缓存每个 Token 一条,于是理想全局 KV 量可以复核为:

(3/2+1)×(288+68)=890 B/原始 Token。

这个数字同时包含三种优化:共享决定有几份,序列压缩决定每份有几条,数值格式决定每条多少字节。对 1,048,576 个 Token,只算这些全局 KV 的理想容量是 890 MiB;它不是完整显存占用,更不能据此宣称单卡可以运行模型。权重、Engram、SWA、草稿状态、临时工作区、页元数据、通信缓冲区和图执行内存都在这张小账单之外。[5][23]

还要区分存储精度与计算精度,也不能把「使用 FP4」理解成所有张量都变成四比特:主 KV 的 FP4 主要为了节省状态,注意力计算前会反量化,并非整条注意力路径都在做 FP4 矩阵乘法;Q&A 对 main KV、indexer KV 和 routed-expert weights 分别描述了量化格式;SWA 使用 MXFP8 格式,每层每个缓存位置占 528 B,包含 512 B 数据与 16 B 缩放因子,总量还需计入保存层数和窗口长度。系统收益取决于数据、scale、对齐、索引与元数据的总大小,以及它们的读写模式,不是只看理想比特数;直接拿芯片公布的 FP4 峰值算力除以模型 FLOPs,预测不了这条混合精度、稀疏且受访存影响的路径。[2]

稀疏注意力之后,找到相关历史本身也有成本

全局注意力分支最多读取选中的 512 项,此外还有独立的局部 SWA 窗口;这也不代表找出这 512 项没有成本。如果每个索引层仍扫完整历史,长上下文的索引开销会重新成为瓶颈。V4.1 一方面用 Reuse 层避免重复索引,另一方面让 Decoder 首个 Full 层扫描历史时形成候选池:最多取 2,048 个八位置块,形成至多 16,384 个候选位置,后续 Reindex 层再从候选池中选择各自的 Top-512。[5]

16,384 是检索范围,512 才是最终主注意力选择量,二者不能混用。候选池也不是整段会话永久不变的摘要,而是随查询产生的共享信息。这种层次化索引把后续检索限制在有界集合中,但最初的全局扫描仍随历史增长。因此,更准确的结论是「把长上下文的主要开销增长压低」,而不是「整个 Decode 变成与上下文无关的 O(1)」。它也带来质量边界:早期候选集合遗漏的重要历史,后续层可能无法重新找回,需要在远距离证据、稀有引用和多步工具任务上专门评估。

图 2:CED 与 CSA2 的模型—引擎共设计
图 2:CED 与 CSA2 的模型—引擎共设计

图 2 阅读重点:模型内部 CED 不等于服务层 P/D 分离;跨层 KV 复用、索引复用和有界 Decoder 重放分别削减不同工作。890 B/token 只描述全局 KV,不是完整设备内存。

官方报告称,相对 DeepSeek-V4-Flash,在同样序列长度下 V4.1-Flash 的运行时 KV 约为四分之一,持久化 KV 约为八分之一。它们是模型架构、精度和缓存策略共同作用后的相对口径,不是 DeepInfer 对任意模型都能提供的通用压缩比。[5] 同样,Decode FLOPs 随上下文增长较缓,不代表端到端延迟完全不随上下文增长:索引、访存、缓存加载和排队仍然可能变化。

不只注意力与 MoE:条件记忆和残差路径也有系统账单

Engram 与 Single-Pass mHC 是这套共设计的另外两个组成部分。Engram 用输入 Token 的 n-gram 哈希寻址条件记忆表,再将查得内容投影并门控融合到隐藏状态。公开运行时把表分片放在专门的并行组,处理跨 rank 查找;其地址由输入决定,为预取与计算重叠创造了条件。但大规模条件记忆带来的容量和通信不能从部署预算中消失,也不能仅用「每 Token 激活参数」衡量。[5][24]

Single-Pass mHC 与 Mega-mHC 则提醒我们,残差及混合路径中的激活搬运同样值得优化。这里并非只把原计算图的几个 kernel 合在一起:Single-Pass mHC 先改变输入混合系数的依赖,使用前一块的系数消除原先的等待,再由 Mega-mHC 融合残差更新、系数计算、输入混合与预归一化。官方报告称,融合后的 Mega-mHC 相对原有四 kernel 实现把这一路径的激活内存流量减半;这不是整模型显存、总耗时或所有内存访问都减半。[5] 当矩阵计算和注意力已经高度优化,这些原先不起眼的反复读写、归一化与启动成本,会变成新的瓶颈。完整性能需要沿整条执行轨迹找空隙,只盯最大算子是不够的。

共设计也意味着可迁移性有边界

这些收益之所以可观,恰恰因为模型在训练和结构层面为系统创造了条件。给一个未经相同设计的普通 Transformer 接上 DeepInfer,并不会自动得到半量 Prefill 或同样的缓存压缩。SWA bounded replay 对质量的影响也由模型结构、训练适配和任务分布共同决定,不是对任何模型都成立的数学恒等式。

因此,研究 DeepInfer 有两种不同目的。一种是部署当前模型,应该尽可能复现它验证过的完整组合;另一种是吸收架构思想,用于自研模型或其他服务系统。后者需要重新验证精度、调度与成本,不应只迁移配置名。这也正是模型团队与系统团队需要提前协作的原因:模型一旦发布,许多成本边界已经写进它的计算图。

四、SWA bounded replay:一次有质量边界的「少存一点、少算一点」

为什么局部窗口也会形成昂贵的恢复问题

滑动窗口注意力看起来很便宜:每个位置只读最近 W 个 Token,状态大小不随总上下文线性增长。但多层叠加后,某一层最近窗口里的隐藏状态,仍受更早层、更远位置影响。若要求精确重建深层 SWA 状态,恢复范围会沿层数展开,重算一个窗口并不天然够用。

在 V4.1 的 Decoder 场景中,Q&A 对比了精确恢复所需的最近 2,560 个 Token 与 bounded replay 使用的最近约 128 个 Token。后者只在重放段内部允许 SWA 访问:若从位置 s 开始重放,位置 i 只读取从 max(s, i−127) 到 i 的局部键。它主动截断了重放段之外的局部依赖,因此重建的是近似状态。[2]

这项方法的价值不止「快一些」。如果一次 SWA cache miss 必须引发昂贵的长段恢复,系统就只能花大量存储预算保证状态不丢;当 miss 的代价降到有界、可预测的小段重放,SWA 便可以留在较便宜的短期内存层,过期后放心回收——存储和计算之间的经济边界被改写了。

Encoder 与 Decoder 的重放解决不同问题

Encoder bounded replay 面向「全局 block KV 已命中,但 SWA 状态没找到」的情况。系统复用命中的全局 KV,额外重放命中前缀尾部的一小段,把局部 SWA 状态补起来,再与未命中的输入后缀一起继续执行。重放段用于恢复 SWA,不应重算或覆盖已经复用的全局 block KV。这既节省计算,也避免覆盖已命中的全局 KV;但未命中后缀新生成的全局 KV 和 SWA 仍会受到近似状态影响,不同命中边界下并不数学等价。[2] 直接论述见技术报告第 20 页。

Decoder bounded replay 则帮助 CED 真正兑现 Prefill 节省。完整历史的 Decoder 全局 KV 已经能从 Encoder 输出投影获得,剩下需要补的是 Decoder 各层的局部 SWA 状态。于是只让尾部窗口经过 Decoder,得到后续 Decode 所需的局部状态。这部分重建结果用于当前生成,不进入前缀持久缓存。

因此,bounded replay 既是缓存 miss 的兜底机制,也是模型计算图优化的组成部分。前者让长期缓存可以少保存一种昂贵状态,后者让 Prefill 可以少执行大段 Decoder。两条路径相互关联,却不应该混称为同一个「缓存压缩开关」。

128、134 和 140 为什么同时出现

官方解释机制时使用 128-token 窗口;Q&A 中 SWA 状态槽与前缀命中上界涉及 128 加 6 个位置;README 推荐的 Decoder 保留长度则是 DEEPINFER_YOCO_PREFILL_KEEP_TOKENS=140。这些数字承担不同职责:窗口宽度描述注意力依赖,额外位置服务于投机回退和环形状态边界,保留后缀是具体实现的安全配置。[1][2]

不能因为原理图写着 128,就把生产配置机械改成 128。保留长度至少要覆盖窗口与最大回退需求,并匹配草稿长度和状态实现。修改相关参数后,应同时检查跨 128 边界的存储点、草稿拒绝后的回退、分块 Prefill 的最后一块、恢复后的第一个 Decode step,以及请求取消时的状态回收。

仓库还提供 mask 和 compact 两种实现的等价性验证。mask 可以在原有布局中屏蔽不需要的部分,compact 则把实际执行的数据压紧,减少无用工作。examples/yoco/yoco_equiv.py 的 L1 比较元数据、可见键和存储槽;L2 在固定 teacher-forcing 轨迹下比较 logprob 与 Top-K,并可检查草稿置信度。[6] 这验证的是两种截断实现是否一致,不是在证明有界重放和完整历史计算数学等价。后者本来就是近似,必须另做任务质量评估。

五、缓存成为独立基础设施:为什么不能只画一条 HBM→DRAM→SSD 箭头

普通的多级缓存图常把 HBM、主机内存、SSD 画成从热到冷的同一条链。DeepSeek 的公开部署设计更有针对性:正在计算的 block KV 与状态位于设备内存;SWA 的短期可复用状态位于生产机器的主机内存;长期 paged block KV 位于独立 3FS 存储集群。不同内容有不同生命周期,不必经过完全相同的层级。[2]

全局 KV 值得持久保存,因为很长时间之后仍可能被多个请求复用。SWA 更像会话推进过程中的局部工作状态,一旦用户进入下一轮或会话结束,旧状态价值迅速下降。官方技术报告据此把 SWA 放在短期主机内存池,把全局 KV 留在长期存储,并依靠 bounded replay 处理 SWA 缺失。这里优化的是状态的「未来复用价值」,而非缓存总量。[5]

独立存储还有路由层面的收益。若前缀只存在少数 Prefill 节点,调度器必须在「去有缓存的地方」和「去空闲的地方」之间做选择;共享存储让任意 Prefill 节点都能读取命中前缀,降低缓存亲和性与负载均衡之间的冲突。它同时把计算节点故障与长期缓存丢失解耦,让存储扩容不必跟随计算资源同比例变化。[2]

代价也很明确:本来只在本地内存完成的命中,现在可能引入目录查询、网络读取、主机共享内存和 HBM 导入,系统必须有足够好的尾延迟和重叠能力。Q&A 将匹配、读取和 swap-in 分开描述:匹配只查询元数据,但命中长度影响路由,不能完全藏到后面;KV 拉取在独立进程中异步进行;主机到设备按层导入,目标是与计算重叠。内部 NVIDIA 路径还使用 GDR,通过 RDMA NIC 进行细粒度缓存块传输,避免占用 SM。[2]

一个命中率漂亮但恢复很慢的缓存系统,可能反而恶化首 Token 延迟。部署方需要同时测量命中长度、命中字节、元数据查询 p99、首层就绪时间、全部状态就绪时间、I/O 与计算重叠率、拉取失败后的重算代价。单一「缓存命中请求占比」无法回答节省了多少计算。

Q&A 披露的内部规模很大:约 100 PiB SSD 容量、每 GPU 约 14.4 TB 的逻辑缓存量,以及 Agent 三天、chatbot 七天的 TTL。推荐存储节点使用 20 块 30.73 TB SSD,具备至少 40 GB/s 读取和 5 GB/s 写入能力。[2] 这些是参考部署的工程参数,不是安装 DeepInfer 的硬性门槛。TTL、物理冗余和缓存容量应该从自己的复用曲线反推,否则复制容量只会复制账单,不一定复制命中率。

同时,不应把这些缓存能力理解为「Decode 一直从 SSD 逐 Token 读取 KV」。Q&A 明确说内部 Decode 没启用 KV offload:正在服务的请求所需状态仍在设备侧,Decode 产生的 KV 写入持久存储,是为了未来请求复用。长期存储与当前生成关键路径,是两种不同用途。

图 3:全局 KV 与 SWA 状态的不同生命周期
图 3:全局 KV 与 SWA 状态的不同生命周期

图 3 阅读重点:长期 block KV 与短期 SWA 分开管理;SWA 缺失可以重放恢复,长期全局 KV 命中不必因此全部作废。图中异步读取与按层加载描述官方内部设计,公开仓库仍需接入外部存储服务。

六、Attention DP、Wide-EP 与 EPLB:重新安排等待

一张请求表,两种并行视角

对 MoE 模型而言,Attention 和专家计算需要的并行方式未必相同。DeepSeek 的部署让 Attention 按请求进行数据并行:每个 rank 服务自己的请求,维护相应 KV;到了 MoE 阶段,再按路由结果把 Token 发送到负责对应专家的设备。于是同一组设备既是 Attention 的 DP 副本,也是 MoE 的 EP 成员。[2]

为什么要让 Decode 使用很宽的 EP?Decode 每个请求每步只贡献少量 Token,单个专家如果只看到很小的批量,矩阵计算难以充分利用设备,同时需要反复读取大量专家权重。在每 rank 并发相近、总流量随域规模增加的情况下,把更多请求集中到一个专家并行域,可以提高专家实际处理的批量,并把专家权重分摊到更多设备,降低每卡每步的专家权重搬运压力。若总流量固定而且很小,更大的域不会凭空创造有用工作,反而可能增加通信和闲置。

但收益成立的前提不止「有 64 张卡」。Token 必须跨 rank dispatch,再经 combine 回到原请求的路径;专家计算又要等待同步域中最慢的成员。如果网络延迟高、有效带宽不足,或某些专家特别热门,放大的可能是通信和等待。官方 Decode 基准在同一 scale-up domain 内运行,这个物理边界应该和 EP64 的数字一起阅读,不能外推成普通以太网连接的 64 卡集群必然有同样效果。[1]

Prefill 的选择则不同。大块输入本身就提供较大的计算批量,继续扩大 EP 未必值得额外通信。Q&A 因而建议 Prefill 用 HBM 允许的尽量小的 EP/DP,示例为 EP2–8;Decode 用可用硬件支持的更宽 EP/DP,示例为 EP64–128。两个阶段在找各自不同的计算通信平衡点,并不冲突。[2]

EPLB 平衡的是每一步最慢的设备

把 384 个专家平均分给若干 GPU,并不意味着负载平均。模型路由会随任务、语言、上下文和生成阶段变化。有的专家可能持续热门,有的只在特定时刻集中出现。同步执行里,平均 GPU 很空并不能弥补某个 rank 极忙,因为下一步仍然受慢者牵制。

EPLB 将模型语义上的 logical expert 与部署中的 physical expert 副本分开。热点专家可以有多个物理副本,再将这些副本分配到各 GPU 的固定槽位。公开 policy.py 的重要之处,是利用历史逐步负载优化设备分配,目标贴近「各步最慢 rank 的负载之和」,而不是只把整个统计窗口的 Token 总数分平均。两个专家若在不同时间变热,放到同一卡可能相对合理;若总是同时变热,平均统计相同也可能制造尖峰。[7]

Q&A 给出不同阶段的起始参数:Prefill 从每 GPU 四个冗余专家、100 步统计窗口、1,000 步重分配开始;Decode 从每 GPU 一个冗余专家、1,000 步统计窗口、10,000 步重分配开始。这里的「起始」很重要,最终物理专家数还有整除和容量约束。它们反映 Prefill 和 Decode 的时间尺度、热点变化及搬迁成本不同,并不是建议把参数复制到所有流量上。[2]

EPLB 也有成本:冗余专家占 HBM,权重重分布占用通信和执行时间,过于频繁的调整可能追逐噪声,过于迟钝则错过负载变化。生产监控不能只记录平均专家 Token 数,还应记录最慢/平均 rank 比值、重分配事件、权重搬迁耗时和调整前后的尾延迟。对高频切换的多租户业务,还要检查不同任务混合是否使统计窗口失去代表性。

Mega-MoE 的融合,依赖拓扑和布局契约

Mega-MoE 将通信与专家计算路径做更深的融合,减少中间张量搬运、kernel 启动和阶段间空隙。公开代码不是在任何环境都无条件走融合路径:启用条件涉及 EP 组是否位于物理 scale-up 域,以及支持的精度组合;其他情况仍有 dispatch、grouped GEMM、combine 的明确路径。[8]

这也是阅读推理框架代码时容易忽略的一点。高性能往往不是一个函数更聪明,而是上游 gate 直接把索引与权重写到约定的通信缓冲区,输入以预定格式出现,下游 kernel 不再重复整理。改变其中任何一层的数据布局,都可能使融合收益消失。架构师要管理的是一整套跨模块契约;单独替换一个算子,换不来这份收益。

Wide-EP 还扩大故障域。Q&A 表明,同一个大 EP 实例里的单 GPU 失败会使整个通信实例不可用;内部系统依靠冗余容量和请求级重路由,并在重启时按健康 GPU 重新确定 EP 大小。[2] 因此更宽的 EP 既可能提高稳态效率,也可能提高故障发生时的受影响请求数。采购方案必须把有效吞吐和故障恢复一起评估。

官方所说的「64 张 Prefill 加 64 张 Decode 是最小高效部署单元」,应放回其推荐 EP64、实际 P:D 约 1:1 的负载背景。Q&A 同时说 1P+1D 可部署。前者是特定业务与效率目标下的参考配置,不是软件最低硬件要求,更不是每家企业开始试验都必须采购 128 卡的结论。

图 4:Attention DP、Wide-EP 与热点专家副本
图 4:Attention DP、Wide-EP 与热点专家副本

图 4 阅读重点:Attention 保留请求局部性,MoE 在高速互联域内交换 Token;EPLB 通过物理副本与放置降低慢 rank 拖累。更宽的 EP 必须与通信条件、负载平衡和故障域一起判断。

七、DSpark:验证预算比草稿更稀缺

为什么生成更多草稿,可能让系统更慢

投机解码用一个较便宜的草稿路径先提出多个候选 Token,再让目标模型批量验证,希望用一次较重的前向推进多个位置。它的收益取决于草稿成本、接受长度和验证成本的关系。一个请求能提出五个 Token,不代表验证全部五个就是最优:靠后的候选更容易因为前面某处被拒绝而失去价值,验证它们却仍会占用计算。

DSpark 为这个问题增加了两类信息。第一,草稿采用半自回归结构:三层草稿 Transformer 为五个位置并行产生基础信息,再由轻量 Markov head 建模候选之间的依赖。第二,Confidence Head 估计每个位置的条件接受概率,让调度器能预测某段草稿转化成输出的收益。[5][9]

这里的概率不是「置信度高,所以无需目标模型验证」——Confidence 只决定值得把验证预算花在哪些前缀上,最终接受或拒绝仍由投机采样校验处理。它也不允许随意跳过中间位置:请求沿前缀推进,后面的候选要有收益,前面的候选必须先存活。

从固定长度改成边际收益分配

若第 i 个请求第 j 个候选的条件接受概率是 p(i,j),验证到第 k 个位置时,草稿带来的期望增量可以直观写成各前缀存活概率的和:p(i,1),再加 p(i,1)×p(i,2),依次累加。系统还要加上目标路径本来产生的推进量。优化目标是整个 batch 的期望有效输出除以 step 时间;候选总数最多、平均接受率最高、某个请求单独走得最远,都只是代理指标。

这几个目标可能冲突。只挑非常容易接受的第一个草稿,接受率会很漂亮,却可能没有充分利用硬件;所有请求固定验证五个,batch 足够大,却可能浪费在低收益后缀;为一个请求追求最长推进,又可能损害其他请求的交互性。DSpark 将置信度和硬件吞吐曲线结合,寻找当前负载下更合适的总验证预算,再把预算分给各请求。

公开代码让这个说法落到了实处。csrc/engine/mtp_varlen.hpp 使用启动时的 Decode 性能曲线,并加入运行时 forward 与 sampler 耗时估计,比较不同图尺寸下的期望收益/时间;估计并不把一次离线 profile 当成永久正确,运行时会用实际执行反馈修正,因为上下文长度和请求组合会改变运行时间。[9]

它与异步调度有一条必须维持的时序约束

异步执行时,CPU 制定下一轮调度计划时,最新一轮 Confidence 可能尚未返回。若为获得它强行同步,就会丢掉调度重叠收益。DeepInfer 的处理是让 CPU 先决定总预算,再让 GPU 用更新的信息修正各请求验证长度。源码进一步区分不同轮次的置信度用于 batch 预算和请求长度,避免未来位置的信息不恰当地影响较早候选的验证选择。[9]

这解释了为什么 DSpark 不能孤立地理解成「多了一个预测头」。它连接草稿模型、采样语义、运行时性能模型、图尺寸、请求映射和 CPU/GPU 时序。修改调度算法时,如果只看统计吞吐而不保留这些约束,可能在看似更快的同时引入选择偏差或状态错误。

官方 Q&A 给出的动态与固定五候选比较也很克制:在约每 rank 60 个并发请求的运行点,估算吞吐从 13,730 提升到 14,466 Token/s/rank,约为 5.4%;在 16 并发时则为 −1.5%,96 并发时为 +11.0%。[2] 它说明节省无效验证在较高负载下更有价值,也说明动态策略不是所有运行点都获胜。不能把「生产点约 4%–7%」改写成任意环境必得的加速,更不能与另一篇论文、另一种模型或另一版草稿的提升比例混乘。

此外,接受率会随任务漂移。代码、自然语言、结构化 JSON、长推理和多语言的草稿质量未必相同。上线时应按任务桶观察预计与实际接受长度是否校准,并把预算算法误差、采样耗时、草稿耗时和尾延迟一起记录。过期的吞吐曲线与过度自信的预测,都可能让优化器稳定地选择错误运行点。

图 5:按置信度分配投机验证预算
图 5:按置信度分配投机验证预算

图 5 阅读重点:预算优先给期望收益更高的候选前缀,灰色后缀可以不验证;绿色「预测值得验证」不等于已经被目标模型接受。优化目标是系统有效输出/时间,而非草稿长度。

八、异步调度:把 CPU 空隙藏起来,也把生命周期问题暴露出来

同步推理循环通常按 schedule、forward、sample、同步、post-process 的顺序执行,再开始下一步。当设备完成采样、CPU 读取结果并整理下一批时,GPU 可能没有可执行工作。随着 kernel 更快,曾经不显眼的 Python、C++ 元数据整理和对象管理,反而更容易成为每步的固定税。

DeepInfer 所称的 zero-overhead batch scheduler,「zero-overhead」的合理读法是把这份税尽量藏起来,而非 CPU 工作消失。公开 Worker 逻辑先发射当前前向,在设备运行期间处理上一轮结果,再发射当前采样;CPU 与 GPU 以流水方式推进。滞后的序列长度和请求映射,由设备端元数据修正路径补齐,避免每步为了最新结果做一次完整同步。[10]

这种重叠为什么有用?假设 GPU 一步执行需要时间 G,CPU 整理需要时间 C,同步串行的关键路径近似 G+C;若两者能正确重叠,理想情况下接近 max(G,C),但还存在不可隐藏的依赖和启动成本。它对小步长 Decode 尤其重要,因为固定 CPU 开销在短 step 中占比更高。反过来,若 schema 编译、网络回调、内存拷贝或跨 rank 协调拖慢 CPU,C 超过可隐藏窗口,设备空隙仍会回来。

代价是时间上的「现在」变复杂了。CPU 认为某个请求已结束时,设备可能仍在读取上一步的元数据;一个状态块已经从逻辑队列移除,并不等于可以立刻复用;新 batch 中相同位置的元素,也不一定是旧 batch 的同一条请求。源码的 DeferredRelease、块引用计数、pin/unpin 和事件同步,正是在维护这些不变量。[3][10]

这一点直接决定生产接入是否安全。LLMEngine.step() 明确说明返回的 RequestOutput 由对象池管理,下一次 step 会回收;如果要跨步保留,必须 clone。HTTP/SSE 服务若把内部对象直接塞进异步发送队列,慢客户端还没读完,引擎就可能复用内存。正确做法是在边界复制稳定的输出事件,再由独立网络层发送,并限制发送队列大小。吞吐优化不能建立在客户端永远足够快的假设上。

请求取消、超时和滚动关闭也需要覆盖在途状态。源码提供 flush_inflight_reqs 处理 ZOS 流水中的未落账输出,这应该进入引擎排空流程,而不是仅仅停止调用 step。测试应主动在 Prefill、验证、采样和输出发送之间取消请求,验证不会多计费、重复输出、提前释放或泄露资源。

图 6:同步循环与异步 CPU/GPU 流水对比
图 6:同步循环与异步 CPU/GPU 流水对比

图 6 阅读重点:重叠的是可并行的 CPU 调度、旧结果处理与设备执行;依赖没有消失,只是通过更严格的状态和缓冲区生命周期管理被移出了关键路径。

九、从源码读懂实现:沿一条请求走,不要从算子目录开始迷路

理解这个仓库,最有效的方法是先走通请求路径,再进入热点。examples/offline_inference.py 展示启动、模型配置和输出检查;deepinfer/entrypoints/llm.py 的 LLM.generate 将请求加入引擎,循环执行 step,并在结束时排空在途结果。这是可理解的离线入口,但不是把整个函数包进一个 HTTP handler 就能获得的在线服务。[3]

第二站是 deepinfer/engine/llm_engine.py。它负责 worker 初始化、cache 初始化、请求接收、调度后处理和扩展钩子。顺着 step 中的 self.scheduler.schedule(),进入 csrc/engine/scheduler.hpp,可以看到序列如何组批、状态如何分配、分块 Prefill 如何推进。再看 csrc/engine/input_metadata,才能理解逻辑请求如何变成设备可消费的索引、长度和缓存加载计划。[4]

第三站是 deepinfer/worker/worker.py 和 model_runner.py,这里连接异步时序、图执行、模型 forward、采样与性能反馈。之后再去 deepinfer/model_executor/models/v4_modules 阅读共享层拓扑、YOCO、注意力和 MoE,才能看出一个消费者层为什么没有生产者层的全部工作。cross_layer.py 对共享关系的校验,正是防止复用逻辑读到尚未写入的状态。[11]

第四站才是具体 kernel。FlashMLA、DeepGEMM、DeepEP、TileKernels、DeepSelect 与仓库中的 TileLang 算子承担不同职责:注意力、矩阵计算、专家通信、细粒度融合、索引选择和运行时元数据处理。examples/benchmark.py 可用于生成 trace,先从真实 trace 找出时间花在哪里,再决定是否值得阅读某个 kernel。不要因为某个模块名字最响,就假定它在自己的运行点上一定是瓶颈。[1][12]

有一个必须保持的源码阅读纪律:文档描述的现网实现,不等于每一段都已经在开源 scheduler 中出现。例如 Q&A 的 Prefill 调度描述使用每步时间预算、拟合二次成本函数,并根据已有前缀长度求可处理的 chunk;固定提交中的开源调度路径,能直接核验的是按 max_num_batched_tokens 等约束截断。[2][4] 前者是重要的生产设计启示,后者才是本次可直接改造和运行的代码证据。把两者区分开,才能正确估计二次开发工作量。

双硬件支持同样应该沿实现看。platform.py 为 NVIDIA 选择 CUDA/NCCL,为 Ascend 选择对应 TileLang 后端和 HCCL,并处理设备 API、主机内存固定及 scale 类型等差异;相应 kernel 也有平台实现。它证明有真实适配,而不是证明两种硬件具有同样的成熟度、性能和数值行为。README 对 batch-invariant 与确定性采样限定 NVIDIA,部署验收应尊重这个支持范围。[13]

十、如何读官方性能图:同一个「Token/s」,可能代表三种不同东西

Prefill 图测的是 step,不是用户等待的全部时间

官方 Prefill 图使用四张 SM100 GPU,EP4DP4、384+32 个专家、131,072 Token 上下文和 140-token Decoder bounded replay。纵轴是每 GPU 的未缓存输入吞吐;横轴是每次 Prefill step 的平均时间。[14]

图 7:Prefill 未缓存输入吞吐与单步延迟
图 7:Prefill 未缓存输入吞吐与单步延迟

来源:DeepInfer 官方仓库固定提交。四卡、128K 上下文、140-token bounded replay;横轴是 Prefill step,不是 TTFT。本文未复测,未从图片制造精确点数据。

横轴不是完整请求的 TTFT。视请求类型与部署方式,首 Token 返回前还可能经历排队、缓存恢复、视觉编码、分块 Prefill 和跨阶段传输等环节。如果一个长输入需要多个 step,把图上的单 step 毫秒数直接写成「128K 首 Token 延迟」,就是换了指标定义。

未缓存输入吞吐也不等于全部逻辑输入吞吐。缓存命中可以让服务看起来每秒处理了非常多的历史 Token,但其中大部分没有重新进行 Prefill。对算力规划应关心实际新增计算,对业务计量可能关心逻辑输入,两者都可以有价值,但必须分账。

Decode 图包含一个明确的接受率换算

官方 Decode 图使用同一 scale-up 域内的 64 张 SM100,EP64DP64、384+64 专家、131,072 上下文、固定 nextn=3,并按 75% 接受率换算得到 τ=3.25。plot_pareto.py 的代码直接写明 τ=1+nextn×a,并将实测 steps/s 同时乘到每用户速度与每 GPU 吞吐上。[14][15]

这张图既不是动态 DSpark 验证长度的实测,也不是线上成功交付、可计费 Token 的统计:它是固定长度运行点的设备执行测量,加上显式接受率假设后的输出速度估计。脚本甚至拒绝把开启变长验证的数据再套用这个公式,因为那会重复计算接受率。

公式中的 a 也要理解准确。若它表示所有提出草稿中最终被接受的经验比例,固定 k 个草稿可以用 k×a 表示平均接受数;若把它理解为每个位置相同的独立条件通过概率,期望前缀长度一般应累加 a、a²、a³,而不是简单 k×a。引用图表时,沿用作者声明的换算口径即可,不应偷偷把同一个「75%」换成另一种概率定义。

图上的并发标签是每 DP rank 的请求数。EP64DP64、CP=1 时,64 requests/rank 对应整个组 4,096 个并发请求,而不是全系统只有 64 个。这解释了曲线为何同时展示高吞吐和交互性下降:让更多请求共享一个 step,可以提高总产出,却会拉长每个人等待下一批 Token 的时间。不同点并没有天然的好坏,是否可用由业务 SLO 决定。

图 8:固定三候选、接受率换算的 Decode 曲线
图 8:固定三候选、接受率换算的 Decode 曲线

来源:DeepInfer 官方仓库固定提交。EP64DP64、128K 上下文、nextn=3,按 75% 接受率取 τ=3.25;不代表变长 DSpark 或实际计费 Token 测量。原图标签与当前默认 1017 checkpoint 的完整对应关系,仍需原始运行记录确认。

测试脚本刻意构造了理想稳态,必须知道它排除了什么

benchmark.py 使用随机非特殊 Token 作为输入,建立前缀后复用并产生后续请求;它强制开启负载平衡路径,相关参数会影响 gate 的随机/均衡路由。计时还区分热身和稳态,部分与负载统计刷新重叠的区间不进入「干净」窗口。[12] 这有利于隔离引擎计算能力,但并不代表真实任务的专家热点、EOS、取消和到达过程。

没有找到与官方图逐点对应的原始 JSONL,就不应从 PNG 目测读出小数位,再包装成精确测量表。本文保留图示的配置与趋势,不杜撰原始数据,也不据此宣布相对其他框架的速度名次。官方 Wide-EP 图可以支持「在给定条件下 EP64 的曲线优于 EP8」,却不能单独证明固定总预算、固定流量和相同故障冗余下的成本更低。[14]

图 9:EP8 与 EP64 的工作点比较
图 9:EP8 与 EP64 的工作点比较

来源:DeepInfer 官方仓库固定提交。组规模和冗余专家数不同,图中曲线不是固定总流量、固定总预算的成本实验。

正确的复现过程应分两步。先固定仓库提交、子模块、checkpoint revision、工具链、驱动、设备型号与拓扑,在 profiler 关闭时复现官方 sweep,并保存所有原始结果,而非只保留最好的一张图。再换成真实或具有代表性的业务输入,使用正常专家路由、真实 EOS、实际采样参数和缓存生命周期,分别比较无投机、固定长度与动态验证。

后一个阶段应使用开环到达负载,或者保留真实到达时间。只用固定闭环并发,客户端会因为响应变慢而自动少发请求,可能掩盖服务器过载。要观察的是随着 offered load 增加,TTFT、Token 间隔 p95/p99、错误率和队列长度何时失控,以及这个边界之前能交付多少满足 SLO 的结果。投机输出还可能呈现「成批突然到达」的节奏,平均 Token/s 不足以描述流式体验。

最终,至少保留两种时间口径:一份是用于解释 kernel 和调度上限的干净稳态,一份是包含缓存读取、EPLB 重排、GC、扩缩容、故障与重试的完整服务窗口。前者帮助找瓶颈,后者才能支撑采购与成本决策。

十一、放到当前推理生态里,DeepInfer 到底在与谁竞争

把 DeepInfer 描述成「全面替代 vLLM 的更快引擎」并不准确。README 本身明确说明其早期主要基于 vLLM,并受到 SGLang 与 TensorRT-LLM 启发。[1] 缓存、专家并行、投机解码和调度重叠,也并非其他项目没有的能力。值得比较的是优化边界、服务交付程度、模型与硬件支持,以及部署方愿意承担多少集成责任。

对象 当前应如何定位 对选型最有价值的差异
DeepInfer 围绕 DeepSeek 模型与目标硬件深度共设计的公开推理核心 专用计算图、缓存语义和调度协同;完整在线服务需补齐
vLLM 面向广泛模型和硬件的推理与服务生态 通用接入、兼容 API、工具链及连接器;具体高级功能组合需逐项验证
SGLang 面向 LLM、多模态、Agent/RL 工作负载的运行时与服务生态 前缀复用、HiCache、PD 和网关能力适合纳入系统方案比较
TensorRT-LLM NVIDIA 平台上的深度优化推理栈 硬件特性、并行、内存与服务路径的整合;按当前版本核对支持矩阵
NVIDIA Dynamo 分布式推理服务与控制层,不是同层 kernel 引擎 路由、规划、状态传输与部署编排;可与引擎互补,不能直接做同层速度排名

这张表描述的是定位,不是任何模型、量化、硬件、PD 和投机功能任意组合都已打通的承诺。本文也没有在相同 V4.1 权重和相同硬件上做跨框架实测,因而不提供速度排行榜。表中的通用能力也不代表各框架已完整支持这个 V4.1 checkpoint 的全部特性。[16][17][18][19]

缓存是一个适合深入比较的切面。SGLang HiCache 将 GPU、实例主机内存和后端存储组织成层级,L1/L2 仍是实例私有,跨实例共享由实际 L3 后端决定;DeepSeek 的公开生产设计则把长期全局 KV 放到专用共享存储,以降低前缀亲和路由与算力均衡之间的冲突。[2][17] 两者比较的是「让计算靠近已有缓存」与「让共享缓存支持自由调度」的取舍。一个依赖网络与存储能力,一个更在意局部性与路由,不存在脱离负载的普遍赢家。

PD 分离也是如此。vLLM 当前官方文档仍把分离 Prefill 标为实验能力,并提醒分离本身不是吞吐提升的保证。[16] 它可能改善 TTFT 与 Decode 尾延迟的相互干扰,也能让两个池独立调优;同时会增加传输、独立池闲置、部署颗粒度和控制面复杂度。DeepInfer 的模型压缩、Wide-EP 与分离部署应该分别归因,而不是把所有收益都算在「拆成两台机器」头上。

对 TensorRT-LLM 的比较尤其要避免过期印象。截至本次核验,官方 latest 迁移文档已说明 TensorRT engine backend 移除,PyTorch 是唯一执行后端,不再要求独立的 checkpoint 转换和引擎构建步骤。因此不应继续用「静态预编译 TensorRT 对动态 Python」概括当前差异。[18] 需要核验的是目标模型的执行路径、量化支持、图与并行策略,以及服务层如何暴露这些能力。

Dynamo 则代表另一个维度:把不同引擎组织成可扩缩的分布式服务。它与 DeepInfer 更可能形成「控制面加执行核心」的组合,谈不上谁替代谁。但本次没有核验到官方即插即用的 DeepInfer backend,任何接入建议都应被当作需要实现和测试的工程项目,而不是已交付功能。[19]

十二、把性能变成钱:先定义什么才算工厂的有效产出

38 美元/GPU·小时是收入,不是成本

官方 Q&A 自报单集群每天服务 155 万亿 Token,并在谷价口径下实现每 GPU·小时 38 美元收入。[2] 这个数字可以帮助理解其规模化经营目标,却不能拿来推导 GPU 租赁成本、毛利率或第三方部署的利润。它还涉及输入、缓存命中输入、输出、价格和流量混合,不能把全部逻辑 Token 都理解为现场新生成的 Decode Token。

推理成本的分子应覆盖完整资源,而不只是忙碌的 Decode GPU。Prefill、视觉编码、草稿路径、存储、网络、CPU、主机内存、备用容量、冷启动与闲置,以及运维和研发摊销都可能重要。自有硬件应考虑折旧、资金和能源;云租赁报价若已经包含电力,再单独叠加同一部分就是重复计费。

分母同样需要定义。本文建议把成功交付、去重、满足事先约定质量和时延条件的输出作为有效 Token。被拒绝的草稿、padding、验证中间量、取消后未交付内容和重试重复输出,不进入分母;为它们花掉的成本仍留在分子。若完整服务每小时成本为 C,每秒有效输出为 G,则每百万有效输出成本为:

成本/百万有效输出=C×1,000,000÷(3,600×G)。

这是一种评估口径,不是仓库原生指标。质量最好按任务验收,不必假装每个线上 Token 都能独立判断正确;应同时报告每成功任务成本,避免通过让模型回答更长来做大 Token 分母。对长输入短输出应用,还应报告未缓存输入成本与每请求成本,否则纯输出指标容易误导。

一个峰值更高、实际成本却更高的透明例子

以下全部是假设算例,不是 DeepInfer 实测,也不是任何 GPU 的市场报价。只看一个 Decode 资源池,设每 GPU·小时成本为 4 美元、质量相同、满足时延要求的输出占比为 95%。有效利用系数表示在整个付费窗口内兑现了多少特定基准工作点的产能,它不是 GPU 面板上的 SM busy 百分比。

假设场景 基准输出能力/卡 有效利用系数 SLO 内输出/卡 美元/百万有效输出
A:基线 1,000 Token/s 60% 570 Token/s 1.95
B:提速且利用不变 1,500 Token/s 60% 855 Token/s 1.30
C:提速但闲置增加 1,500 Token/s 30% 427.5 Token/s 2.60
图 10:假设算例 利用率如何改变每百万有效输出成本
图 10:假设算例 利用率如何改变每百万有效输出成本

图中全部参数是透明假设,不是 DeepInfer 基准或 GPU 报价;只计算示例 Decode 资源池,不包含完整服务的其他成本。

从 A 到 B,单位成本下降约三分之一;从 A 到 C,峰值仍提高 50%,单位成本却上升约三分之一。造成这种反转的可能原因包括 EP 分组过大、需求不足、独立资源池无法互相借用,或者缩容颗粒度太粗。更快的核心提供了选择空间,但只有释放机器、缩短付费时间、减少能耗或承接更多达标需求,才能兑现经济收益。

如果已经从完整窗口直接测得 G,就不要再乘一次利用率或接受率。那些因子只用于从局部基准估计完整产出的模型;真实交付日志已经包含相应损失,再扣一次会把成本夸大。

Prefill 和 Decode 是串联产能,最慢的一段决定工厂出货

设业务每产生一个输出 Token,平均需要处理 ρ 个未缓存输入 Token;Prefill 池有 Np 张卡,每卡有效未缓存输入吞吐为 Qp,Decode 池有 Nd 张卡,每卡有效输出吞吐为 Qd。忽略其他瓶颈时,全系统原始输出能力不超过 min(Np×Qp/ρ,Nd×Qd)。视觉、存储和网络还可能进一步压低这个上限。

这说明 P:D 资源比应该跟随未缓存输入/输出比、两个阶段的效率和并行颗粒度变化,而不是永远 1:1。缓存命中提高,会减少 Prefill 新计算量,却不会自动缩短 Decode 需要访问的历史上下文;长输出增加,则会把瓶颈推向 Decode。不同业务在同一个模型上,也可能需要完全不同的资源配比。

再给一个仅用于说明瓶颈的假设:64P+64D,每卡 4 美元/小时,其他成本 128 美元/小时,总计 640 美元/小时;Prefill 基准为每卡 10,000 未缓存输入 Token/s、有效利用 50%,Decode 为每卡 1,000 输出 Token/s、有效利用 75%,ρ=10。Prefill 折合输出能力为 32,000 Token/s,Decode 为 48,000 Token/s,系统受 Prefill 限制。若再按 95% 的有效交付比例计算,每百万有效输出约 5.85 美元。

此时仅把 Decode 提速 50%,总交付量和这项单位成本都不变。反而先将 Prefill 能力翻倍,瓶颈才转向 Decode,算例成本降至约 3.90 美元。这个模型没有模拟排队与突发,也不是推荐采购配置;它只是说明,不能用一个阶段的速度提升直接乘到全系统成本上。

缓存、投机和迁移,都有自己的盈亏平衡点

长期保留某个前缀是否值得,可以比较它未来预计被复用的次数乘以避免的 Prefill 成本,与写入、占用、匹配、读取、网络和恢复成本。保留越久,新增命中可能越来越少,而容量继续被占用。相同请求级命中率,命中 1K 与命中 100K 所节省的计算也完全不同。更有用的指标是「每单位存储成本避免了多少计算」,缓存容量本身说明不了问题。

投机解码是否值得,则比较一个完整投机周期的成本除以实际提交长度,与非投机基线的单 Token 成本。草稿若使用额外设备,必须一并计入;接受率高也不必然盈利,因为生成和验证的总时间可能更长。动态预算的价值在于不同运行点都可以调整。

迁移也有固定成本。若一次性集成与迁移支出为 F,新旧系统在相同质量和服务等级下的单位成本差为 Δc,那么回本量约为 F/Δc。假设迁移花费 5 万美元,每百万有效输出节省 0.5 美元,就需要约 1,000 亿有效输出 Token 才覆盖这笔固定支出,尚未计入并行运维与风险。这个纯假设提醒企业:规模足够大时,小比例优化非常值钱;规模不够时,工程简洁和可靠上线可能更值钱。

图 11:从离线吞吐到 SLO goodput,再到完整成本
图 11:从离线吞吐到 SLO goodput,再到完整成本

图 11 阅读重点:峰值性能必须经过真实负载、接受、交付、质量和时延约束,才形成可用于成本核算的产出。已实测的完整 goodput 不应重复乘接受率或利用率。

十三、如何把它扩展成生产引擎:从接缝处建设,而不是重写 forward

下面是一条基于公开代码提出的工程路线,不是 DeepSeek 官方路线图,也不是承诺若干周即可完成的项目排期。原则很简单:先获得可核验的单引擎可靠性,再扩大状态与故障的作用范围;先守住正确性和资源所有权,再追求跨节点复用和极限吞吐。

第一层 在线适配器,要成为真正的生命周期边界

最先需要补的是服务适配器,而非另一套模型执行器。它应围绕 add_request、step、abort_request 和输出排空组织长期运行的引擎循环,让外部请求异步进入、取消和退出;网络线程不应直接阻塞模型 step,也不应把同步 LLM.generate 逐请求包装成所谓在线连续批服务。[3]

输入侧需要认证、租户额度、请求大小限制、截止时间、过载拒绝与可观察的等待队列。输出侧需要稳定事件、背压、客户端断开处理和去重。一个请求取消之后,已排队但未执行、正在设备执行、已采样但未发送、已发送但尚未完成计量,是不同状态,必须定义清楚各自的资源释放和记账责任。

DeepSeek Recipe 可以承担 Chat Completions、Responses、Messages 等协议与统一内部会话表示之间的转换,以及模板编码和流式输出解析。但它的 README 明确把推理、工具执行和 HTTP transport 留给调用者,不能把它称为完整 API server。[20] 它对特殊 Token 的处理很有价值:模板插入的控制 Token 与用户输入中长得一样的普通文字区别编码,输出也按真正的 Token ID 识别控制边界。这能减少控制 Token 注入,却不等于解决所有语义层面的提示注入或工具安全问题。

结构化输出也应在这一层建立资源边界。DeepInfer 使用 grammar 编译与采样掩码约束输出,而不只是最后检查 JSON。相应编译缓存必须设限,schema 大小、复杂度、编译时间和租户配额也要控制,否则一个看似正常的功能就可能变成 CPU、内存与延迟的攻击面。格式合法更不等于业务内容正确,工具名称、参数权限和业务校验仍属于应用责任。[21]

第二层 把缓存当成有版本、有权限、有所有权的数据服务

建议定义一个显式的 CacheManager 契约,包含 match、fetch、commit、abort 等操作。这些名称是本文建议,不是已经存在的公共 API。match 返回可复用前缀与状态可用性;fetch 异步获取兼容的数据;commit 只发布已完成、完整可读的缓存;abort 回收未完成写入和租约。外部 I/O 可以接在 post_schedule、do_save_kvcache、Prefill 保存钩子等已有位置,避免把阻塞存储调用塞进每层 forward。[3]

缓存键不能只有文本哈希。它至少需要绑定权重 revision、tokenizer 与模板版本、精度和布局版本、完整前缀身份,以及多模态输入或 embedding 身份;还要包含授权命名空间。不同模型版本生成的同一段文本状态可能不兼容,不同租户的可见内容也不应因前缀相同而自动共享。跨租户复用若有业务需求,必须先有明确的公开内容与权限策略。

缓存传输必须校验完整性,记录源和目的的布局协商,并以 lease 或引用计数保护仍在使用的块。模型滚动升级时,新旧布局并存不能靠「看起来维度一样」判断兼容。存储超时或元数据指向失效对象时,系统应有可控回退:安全地重新计算,或者在资源不足时明确拒绝,而不是加载部分状态继续生成。

block KV 与 SWA 状态还要分开承诺。全局前缀命中不等于 SWA 同时可用,SWA 缺失应按设计进入 bounded replay;恢复过程不应覆盖长期已有的 global KV。把这两类状态包装成一个不透明缓存文件,会让失效策略、传输优化和质量诊断都变困难。

第三层 P/D 传输需要一个协议,不是一段 copy

当单引擎服务稳定后,再评估 E/P/D 分离的收益。建议设置独立 TransferManager,明确 export、import、ack 和取消语义。Prefill 完成后,Decode 何时获得请求所有权?源端什么时候可以释放 KV?目的端导入一半时失败,重试会不会重复生成?用户取消发生在传输途中,谁负责回收两边状态?这些问题必须由协议回答,而不是依赖正常路径的执行顺序。

请求 ID 加执行 epoch 可以帮助区分旧尝试和新尝试。对同一个请求的晚到数据、晚到输出和完成通知,接收方应能判断是否过期;仅有 request ID 不足以避免重试后的混淆。对于已经流式发出的工具调用,重试尤其不能导致下游重复执行。模型服务输出去重与工具副作用去重,是两个相连但不同的责任边界。

传输还要考虑不同 P/D EP 配置下的布局兼容。计算池的并行尺寸不相同,并不意味着缓存可以直接按同一缓冲区布局复制。可以重叠的按层加载、需要提前完成的元数据,以及必须保留到验证结束的状态,都应进入显式事件协议和测试。

第四层 控制面调度的是成本和截止时间,不只是请求数

Prefill 路由应该知道未缓存输入量和已有上下文,Decode 路由应该同时考虑并发数与总 KV 长度。两个请求都叫「一条请求」,不代表占用同样资源。官方内部 Prefill 按上下文桶分配资源、Decode 同时平衡请求数与 KV 长度,是这类资源估计的具体例子。[2]

但是,负载模型也必须经过业务校准。过度追求集群总吞吐,可能长期推迟大请求;过度优待短请求,又可能让需要长上下文的高价值任务饿死。生产调度需要截止时间、租户公平性和过载策略,明确哪些 SLO 优先,而不只是复刻一个吞吐最大化公式。

扩缩容应分别观察视觉、Prefill、Decode 和存储,不把一个层的指标当作全系统需求。缩容前必须 drain,在途长请求可以迁移或等待,但应设定资源和时间边界;Wide-EP 的最小颗粒度和备用容量,则会决定理想弹性能够兑现多少。若考虑引入 Dynamo 等控制面,需要先实现适配器、事件与指标协议,不能假定工具会自动理解 DeepInfer 的 StateBlock 和投机状态。

第五层 验收以失败路径为中心,而不是只跑一次成功样例

仓库已有序列、采样、状态缓存、专家重排、batch invariance、离线长输入和分布式相关测试,也有模型评测与 YOCO 等价性脚本。合理做法是在这些基础上扩展,而不是把项目描述成完全没有测试。[6][22]

数值正确性应分层验证。batch-invariant 关注不同组批组合下的模型计算;确定性采样还需要固定随机流和配置,README 给出 NVIDIA 下 DEEPINFER_BATCH_INVARIANT=1、关闭 MTP varlen 并设置固定 seq_seed 的路径。它们都不自动证明不同缓存命中点、近似恢复方式或不同硬件的输出完全一致。[1]

更值得注意的是,LLMEngine.step 源码明确标注,开启 YOCO 截断时允许抢占造成结果变化。因此生产验收应覆盖「抢占前后」「缓存缺失恢复前后」「冷缓存与热缓存」的任务质量,而不能仅以 batch invariance 测试通过作为全部语义稳定性的证明。[3] 对事实检索、证据引用、长程序编辑等任务,少量平均分差异也可能掩盖具体失败模式。

以下表格把路线压缩成可执行的验收关口。它不是要求每个团队都做完全部功能,而是要求团队在进入下一层之前,知道自己增加了什么风险。

建设阶段 必须证明的结果 典型压力或故障注入
固定版本与基线 目标硬件上输出、质量与计时口径可复现 精度/配置切换、长上下文、不同组批
单引擎在线服务 取消、背压、计量、排空正确 慢 SSE 客户端、断连、超时、重复请求
分布式缓存 不串租户、不混版本、失败可回退 错误键、残缺对象、目录陈旧、存储抖动
E/P/D 分离 状态所有权与重试语义明确 半途断链、晚到 ack、目的端重启
集群调度与弹性 SLO 内有效吞吐可持续 突发、长短混合、热点专家、缩容长尾
生产经营验收 全部资源计入后仍有成本收益 GPU 故障、缓存 miss 风暴、滚动升级

每个阶段都应保留 p50/p95/p99、错误率、取消率、真实提交 Token、缓存命中长度、状态加载时间、投机验证与接受数,以及最慢 rank/平均 rank 的比值。故障请求花掉的时间和资源不能从成本样本中删除。只有在这些条件下仍然更便宜、更稳定,专用优化才转化成了生产能力。

图 12:从离线核心到生产平台的扩展与验收关口
图 12:从离线核心到生产平台的扩展与验收关口

图 12 阅读重点:接口集成、缓存正确性、传输协议和控制面是递增的风险边界;路线为本文工程建议,不是官方已实现清单或发布日期承诺。

十四、未来看什么:下一步竞争可能不在单个 kernel

DeepSeek 已明确表示,未来模型的推理代码与后续性能工作会继续在 DeepInfer 开放。[2] 这是一项方向声明,不包含完整 KV store、负载均衡器或其他集成组件的具体开源时间。基于现有设计,值得跟踪的演进方向可以更具体,但必须标为分析而不是承诺。

第一,模型会继续把系统成本写入结构与训练。CED、跨层 KV 共享、层次化索引和训练适配的 bounded replay,说明模型设计已不只是降低每 Token FLOPs,还要考虑状态保留、跨机器搬运和长时间复用。未来优化可能更直接地围绕「某个历史状态在多久之后还值得读」展开,但减少状态不能绕过任务质量验证。

第二,调度将更多利用模型产生的信息。DSpark 的 Confidence 是一个例子:模型不仅产生文本,还提供可以指导资源分配的信号。下一步值得研究的是如何把置信度、截止时间、上下文成本与租户服务等级共同纳入预算,同时避免让追求总吞吐的算法牺牲少数困难请求。优化器越聪明,校准、可解释性和回退策略越重要。

第三,多硬件支持将从「可以运行」转向「具有共同语义和独立可验证的性能」。不同设备的算子、通信、内存和数值路径不同,过度追求一份抽象抹平所有差异,可能损失效率;完全分叉又会增加维护成本。DeepInfer 的平台层与专用 kernel 组合,提供了观察这一平衡的实际样本。

第四,Wide-EP 的弹性与故障恢复可能成为规模化经营的关键。大域让稳态更高效,也让低负载碎片和单点故障更昂贵。如果未来能更平滑地改变并行尺寸、迁移请求与重分布专家,收益可能不亚于继续把某个 kernel 缩短几个百分点。但这些能力牵涉状态、拓扑和正确性,不是修改一个 EP 参数即可完成。

第五,专用引擎与通用生态不必互相排斥。通用框架提供模型广度、接口和集成经验,专用实现验证更激进的共设计;有效思想可以反向进入公共组件。DeepInfer 最有长期影响力的部分,可能是它证明了哪些接口应该开放、哪些状态可以分离、哪些近似值得纳入训练,而不只是某一代模型的最快执行路径。

结论:该不该用,取决于你准备承担哪一段价值链

如果你运营的是大规模 Token 工厂,核心业务高度集中于 DeepSeek、拥有合适的 scale-up 互联,并能建设缓存、路由和故障处理,DeepInfer 值得成为严肃的生产候选。正确起点不是承诺复制官方收入,而是固定业务质量和 SLO,验证共设计带来的节省是否足以覆盖新增存储、网络、冗余与工程成本。值得追求的目标是更低的每成功任务成本和更可预测的交付,而不只是更高的离线 Token/s。

如果你建设的是企业多模型平台,流量较小、需求多变、团队更重视上线速度,通用框架往往提供更合适的默认落点。可以将 DeepInfer 用作专项模型池或性能实验,不必为了某个模型的峰值,把全部服务迁入更专用、更需自建的体系。低负载效率、版本维护与可替换性,也是实实在在的成本优势。

如果你是基础设施供应商,机会则主要不在「再写一遍 forward」,而在把这类高效核心产品化:版本化缓存、兼容传输、可靠流式接口、SLO 调度、多硬件验收、故障恢复与可审计计量。公开核心与完整生产系统之间的距离,不只是缺失功能列表,而是一套可以形成产品壁垒的系统工程。

DeepInfer 给出的最重要启示,是把模型结构、计算精度、缓存生命周期、通信拓扑、投机预算和服务经营放进同一张设计图。先减少不值得执行的工作,再高效完成必须执行的工作,最后证明它确实转化成用户收到的好结果。这是从推理引擎走向 Token 工厂的完整路径。

来源与复核说明

文中的 DeepInfer 代码链接均固定到 9bd9cf243fc53ef9afbf8f04d391d989117d6ab9,避免后续主分支修改改变本文结论。模型报告与其他框架文档按 2026 年 10 月 23 日核验;非固定版本页面可能继续变化。官方生产规模、收入、TTL 与性能披露属于作者方自报,本文没有独立复测。成本算例及自制示意图为分析工具,不是观测数据。

  1. DeepInfer README:公开范围、支持平台与配置。
  2. DeepSeek V4.1 Flash Inference Deployment Q&A。
  3. LLMEngine:请求生命周期、扩展钩子与异步资源管理。相关入口:LLM.generate;本地缓存:CacheEngine / StateBlock;块生命周期:BlockManager。
  4. C++ Scheduler:公开调度与分块 Prefill 路径。
  5. DeepSeek-V4.1-Flash Technical Report。本文重点参考 §2.2–2.4、§3.2、参数配置与局限性讨论;模型信息可交叉核对官方模型卡。
  6. YOCO mask/compact 等价性测试说明。
  7. EPLB policy:物理专家副本与负载放置。
  8. MoE/MLP:Mega-MoE 启用条件与融合路径。
  9. MTPVarlen:验证预算、性能曲线与运行时估计。相关实现:草稿与 Confidence、GPU 预算分配。
  10. Worker:异步 forward、采样与后处理时序。相关实现:ZOS 元数据修正。
  11. SharedLayerTopology:跨层 KV 与索引共享关系。
  12. benchmark.py:输入、路由与计时口径。
  13. Platform:GPU/NPU 平台适配。
  14. 官方性能图:Prefill、Decode 与 Wide-EP。原图:Prefill、Decode、Wide-EP。
  15. plot_pareto.py:吞吐与接受率换算。复现入口:run_sweep.sh。
  16. vLLM:分离 Prefill 的边界与连接器。通用能力另见 vLLM 官方仓库。
  17. SGLang HiCache:缓存层级与共享边界。另见 SGLang 官方仓库与 PD disaggregation。
  18. TensorRT-LLM:当前后端迁移说明。迁移声明交叉核对官方源码文档,功能须另核对模型支持矩阵。
  19. NVIDIA Dynamo:分布式推理运行时架构。
  20. DeepSeek Recipe:协议、编码与流式解析边界。
  21. Structured output compiler:编译与缓存配置。运行时约束见 Sampler。
  22. DeepInfer 测试目录。另见 评测说明与离线示例说明。
  23. KV 格式定义:FP4 main KV、indexer 与 SWA。
  24. Engram runtime:哈希、分片查找与门控融合。mHC 对应代码见 mhc_modeling.py;结构性说明以技术报告为准。