
新智元报道
编辑:Aeneas 好困
近日,来自 SGLang、英伟达等机构的联合团队发了一篇万字技术报告:短短 4 个月,他们就让 DeepSeek-R1 在 H100 上的性能提升了 26 倍,吞吐量已非常接近 DeepSeek 官博数据!
DeepSeek 的含金量还在上升。
就在最近,Hugging Face 联创、首席科学家 Thomas Wolf 表示——DeepSeek 的出现,是开源 AI 领域的 ChatGPT 时刻!
用他的话说,「正如 ChatGPT 让全世界认识到 AI 的存在,DeepSeek 则让全世界意识到,原来还有着这样一个充满活力的开源社区。」
DeepSeek-R1 的性能已经媲美甚至超越美国最顶尖的闭源 AI 模型,对于全球 AI 圈来说,这件事的意义都极其深远。
与此同时,来自 SGLang、英伟达等机构的数十人联合团队,也在 DeepSeek 上整了个大活。
在短短 4 个月内,他们利用最新的 SGLang 推理优化,直接让 DeepSeek-R1 在 H100 上的性能提升了 26 倍!
这是怎么做到的?
团队发布了长篇博文,详细展示了这一过程。
文章地址:https://lmsys.org/blog/2025-05-05-large-scale-ep/
在 96 块 H100 GPU 上优化部署 DeepSeek
要知道,DeepSeek 模型因为庞大的参数,以及多头潜注意力(MLA)和专家混合机制(MoE)等独特架构,如果想要大规模部署,就必须使用更先进的系统。
为此,团队先是对 SGLang 进行了全面升级,完整支持了 PD 分离、大规模 EP、DeepEP、DeepGEMM 及 EPLB 等功能。
然后凭借这些新特性,成功地在 12 个节点共 96 块 GPU 的集群上,复现了 DeepSeek 的推理系统。
最终,在处理 2000 个 token 的输入序列时,实现了每个节点每秒 52.3k 输入 token 和 22.3k 输出 token 的吞吐量。
方案运行在 Atlas Cloud 的 12 个节点上,每个节点均配备 8 块 H100 GPU
团队表示,这应该是首个吞吐量接近 DeepSeek 官方数据的开源实现。
在本地环境下部署此方案,成本可降至 0.20 美元/1M 输出 token,约为 DeepSeek Chat API 官方定价的五分之一。
相较于使用相同资源的原始张量并行策略,此优化方案可将输出吞吐量提升高达 5 倍。
接下来,团队深入探讨了他们的并行设计、优化方法以及最终成果。
并行设计
高效的并行化设计,对于控制 DeepSeek 架构的计算复杂度和内存需求至关重要。
针对以下关键组件,团队都给出了优化方案:注意力层、稠密前馈网络(FFN)、稀疏 FFN 以及语言模型(LM)的头部。
每个组件都采用了专门设计的并行化策略,以提升可扩展性、内存效率和整体性能。
注意力层
DeepSeek 采用了多头潜注意力机制(MLA),从而能够有效地对输入序列中的复杂依赖关系进行建模。
为了优化这一机制,团队实现了 DP attention,这是一种数据并行策略,目的是消除跨设备的 KV 缓存冗余,从而显著降低内存开销。
在 SGLang v0.4 版本中引入的该方法,现已扩展至支持混合数据并行和张量并行,为高效处理小批量数据提供了更大的灵活性。
稠密 FFN
即便 DeepSeek-V3 仅使用了三个稠密 FFN 层,其计算过程仍然可能显著增加峰值内存占用,若不加以谨慎管理,极易导致系统崩溃。
为了解决这个问题,团队选择采用数据并行(DP)策略,而非张量并行(TP),主要是考虑到 DP 的以下优势。
· 更强的可扩展性
当中间层维度为 18,432 时,较高的 TP 度(例如 TP32)会导致数据被低效地分割成小单元片段(例如 576 个单元),而这些单元无法被 128 整除。
128,就是现代 GPU(如 H100)常见的对齐边界。
这种未对齐的情况,会严重阻碍计算效率和内存利用率。
相比之下,DP 能够避免数据碎片化,从而提供更具可扩展性的解决方案,确保跨设备的工作负载均衡分配。
· 优化的内存效率
传统观念认为,TP 可以随着 worker size 的增加而降低内存使用量,但这种优势在 DP attention 的应用场景下会逐渐减弱。
在纯 TP 设置中,单层 Transformer 模型的内存需求与 DP size 的关系如下:
其中,是每个设备(DP rank)上隐藏状态的大小,是模型参数的数量,k是一个系数,表示来自 CUDA Graph 复制的额外内存开销。
通过假设 DP=TP,当时,此内存的使用函数达到最小值。
DeepSeek-V3 使用 18,432 的中间大小。在 prefill 阶段,CUDA Graph 通常被禁用,因此k=0。
但是,每个设备的 token 大小很容易超过2,048,导致最佳 TP 大小为 3 或更小。
在解码阶段,一个实际的配置可能使用每个设备 128 个 token,并设置k=3。在这种情况下,内存最佳的 TP 大小为6。
在这两个阶段,较低的 TP 度可以最大限度地减少每个设备的内存使用量。
因此,与仅依赖 TP 相比,DP 可以提供更节省内存的扩展方法。
·最小化的通信开销
在纯 TP 模式下,每个 FFN 层都需要执行两次 all-reduce 操作,从而导致巨大的通信开销。
通过采用 DP 策略,团队将该过程优化为:在先前的 attention 层之后执行一次 reduce-scatter 操作,并在下一个 attention 层之前执行一次 all-gather 操作,从而将通信成本降低 50%。
更进一步,如果 attention 计算也采用纯 DP 模式,那么设备间的通信将被完全消除,进而显著提升整体效率。
DP 稠密 FFN 与 DP attention 的集成方案如下图左侧所示。用户可以通过设置--moe-dense-tp-size=1 来启用。
稀疏 FFN
在 DeepSeek-V3 的 MoE 架构中,稀疏 FFN 需要处理大量的专家权重,进而造成显著的内存瓶颈。
为了缓解这一问题,团队采用了专家并行(EP)策略,将专家权重分散到多个设备上。
这种方法能够有效地扩展内存容量,不过,它在维持高性能的同时,也带来了一些新的挑战,比如不规则的全互联通信以及工作负载不均衡等。
团队利用 DeepEP 框架实现的 EP 方案
LM 头
LM 头(LM Head)负责计算大型词汇表上的输出概率,这是一项资源稠密型的操作,传统方案是采用词汇表并行技术,从 TP 组中聚合 token logits。
为了进一步提升可扩展性和效率,团队采用了数据并行(DP)策略,与处理稠密 FFN 的方法保持一致。
这种做法不仅可以降低内存开销,还能简化跨设备的通信过程,从而提供了更加精简的解决方案。
预填充和解码分离
LLM 的推理过程主要包含两个不同的阶段:预填充(prefill)和解码(decode)。
预填充阶段属于计算密集型,需要处理完整的输入序列;而解码阶段则属于内存密集型,主要负责管理用于生成 token 的 KV 缓存。
传统方案通常在一个统一的引擎中处理这两个阶段,然而,这种预填充和解码 batch 的混合调度方式会引入效率问题。
为了解决这些挑战,团队在 SGLang 中引入了预填充和解码(PD)分离技术。
如下图所示,SGLang 会通过预填充服务器和解码服务器的协同工作,实现两个阶段的交错执行。
接收到输入请求后,系统的工作流程如下:
-
预填充服务器和解码服务器通过握手配对,各自作为本地发送者和接收者。
-
解码服务器预先分配 KV 缓存,并通知预填充服务器启动模型前向传递,计算 KV 缓存。
-
完成计算后,数据将被传输至解码服务器,由该服务器负责进行迭代式的 token 生成。
这种分离机制确保了每个阶段都能在最佳状态下运行,从而最大限度地利用 GPU 资源。
并且,为了进一步提升性能,团队的实现方案还包含以下特性。
-
非阻塞传输:数据发送和接收操作在后台线程中执行,从而保证调度器的事件循环不会被中断。
-
基于 RDMA 的传输:远程直接内存访问(RDMA)技术利用队列对(Queue Pairs)进行连接管理,并利用分散-聚集元素(Scatter-Gather Elements, SGE)实现非连续内存块的高效传输。
-
灵活的API集成:SGLang 提供了高度可定制的 API,能够与 Mooncake 和 NIXL 等高性能 RDMA 库无缝集成,从而简化了数据传输流程。
大规模专家并行性
基于 DeepEP 的专家并行
由 DeepSeek 团队开发的 DeepEP 提供了一系列优化过的通信内核,可以有效降低延迟并提升吞吐量,高效地将 token 路由到多个 GPU 上。
DeepEP 有两种专门设计的调度模式,以满足不同的工作负载需求。
-
标准调度模式(Normal Dispatch):主要针对处理较长的输入序列进行优化,例如预填充阶段,其首要目标是最大化计算吞吐量。 但会生成与 CUDA Graph 不兼容的符号形状,从而降低其在解码阶段的效率,因为在解码阶段,内核启动开销会成为一个显著的瓶颈。
-
低延迟调度模式(Low-Latency Dispatch):专门为解码阶段生成输出 token 而设计,其核心目标是最小化延迟,从而确保实时性能。尽管它支持 CUDA Graph,但需要预先分配固定大小的内存。如果实际内存需求超过了预分配的容量,则会触发运行时错误。
在 SGLang 中,DeepEP 的集成提供了一种自动模式,能够根据当前的工作负载,动态地在上述两种调度模式之间进行选择。
与此同时,通过利用 PD 分离技术,使得在 DP attention 机制下,预填充阶段能够采用标准调度模式(Normal Dispatch),而解码阶段则能够采用低延迟调度模式(Low-Latency Dispatch)。
这种集成方式能够根据每个阶段的具体需求来调整调度模式,从而优化资源利用率,并提升整体性能。
DeepGEMM 集成
由 DeepSeek 团队开发的 DeepGEMM,则被用于优化 MoE 模型中的计算过程。
DeepGEMM 提供了两个经过专门设计的函数,用于处理与 MoE 相关的矩阵乘法运算(分组 GEMM),每个函数都针对推理过程的不同阶段进行了定制。
-
分组GEMM(连续布局):这种内核专门为动态输入形状而设计,使其成为 MoE 推理预填充阶段的理想选择。 它可以处理来自不同专家的输入数据,这些数据以连续的方式连接在一起,从而灵活地处理各种输入尺寸的变化。
-
分组 GEMM(掩码布局):这种内核假定输入形状是固定的,并使用掩码张量来仅计算输入的有效部分。 由于它与 CUDA Graph 兼容(可优化内核启动过程),因此特别适合于需要显著降低开销的解码阶段。
DeepGEMM 与 DeepEP 的调度模式可以实现无缝集成:
-
对于与预填充阶段的标准调度模式配合使用的连续布局内核,需要执行一个额外的步骤。团队参考了 LightLLM 项目,并实现了一个自定义的 Triton 内核来实现高效的置换。确保了从标准调度模式输出的数据能够被正确地重新排列,从而实现与连续 GEMM 内核的平滑集成。
-
掩码布局内核与 DeepEP 的低延迟调度模式能够实现无缝对接,因为两者都针对解码阶段进行了专门优化,并且都支持 CUDA Graph。
SGLang 集成了 DeepGEMM,用于在张量并行模式下进行 MoE 计算。通过在 SGLang 中设置环境变量 SGL_ENABLE_JIT_DEEPGEMM 为1,即可激活该内核,从而为非 MoE 操作提供更高的计算效率。
双 batch 重叠
在多节点环境下,有限的通信带宽可能会显著增加整体延迟。
为了应对这一挑战,团队遵循 DeepSeek 的系统设计理念,实现了双 batch 重叠(TBO)技术。
TBO 将单个 batch 拆分为两个 micro-batch,从而允许计算和通信过程相互重叠,同时,通过将有效 batch 大小减半,也降低了峰值内存的使用量。
为了创建更易于维护和重用的代码库,团队采用了一个由操作和 yield 点构成的抽象层。
这种方法可以让用户像处理单个 micro-batch 一样编写代码,同时通过策略性地插入 yield 点来暂停执行,从而允许其他 micro-batch 继续进行。
如此一来,不仅消除了代码重复,减少了对变量后缀的需求,并且还能有效地管理某些执行在层末尾完成而其他执行尚未完成的情况。
此外,抽象层还能轻松地适应不同的重叠区域选择,或者未来的增强功能,例如三 batch 重叠,而只需要进行极少的代码修改。
operations = [ self._forward_attn, YieldOperation (), # Pause execution for other micro-batches self._forward_dispatch, self._forward_mlp, YieldOperation (), # Another pause point self._forward_combine, ] # Process a single micro-batch without duplicating code def _forward_attn (self, state): state.hidden_states = self.self_attn (state.hidden_states, ...)
团队优化了预填充阶段的启动顺序,以避免通过 DeepEP 中的调度操作阻塞 CPU,即使用的是其异步模式。
具体来说:
-
在 GPU 从其他 rank 接收到元数据,从而能够正确分配大小合适的张量之前,调度操作会阻塞 CPU。
-
不正确的实施方式会导致在此期间计算流处于空闲状态,因为没有计算任务被提交给 GPU。
为了实现优化,团队优先将计算任务提交给 GPU,然后再启动可能导致 CPU 阻塞的通信操作。这样可以确保 GPU 在通信期间保持活跃状态。
如下图所示,通过采用正确的启动顺序,TBO 可以避免由 CPU 阻塞操作引起的性能瓶颈。
专家并行负载均衡器
为了解决由专家并行(EP)引起的各个 GPU 工作负载分布不均匀的问题,DeepSeek 开发了专家并行负载均衡器(Expert Parallelism Load Balancer, EPLB)。
EPLB 以专家分布的统计信息作为输入,计算出专家的最佳排列方式,从而最大限度地减少不平衡现象。
用户可以分配冗余专家(例如,增加 32 个专家),这些冗余专家与原有的 256 个专家组合在一起,形成一个包含 288 个专家的资源池。
借助这个资源池,EPLB 能够策略性地放置或复制专家——例如,多次复制最常用的专家,或者将使用频率适中的专家与在单个 GPU 上很少使用的专家组合在一起。
除了平衡工作负载之外,EPLB 还在并行设计方面提供了更大的灵活性。如果使用最初的 256 个专家,并行规模只能被限制为 2 的幂次方。而 EPLB 通过使用 288 个专家,能够实现更多样化的配置,例如将并行规模设置为 12 或 72。
在下图中,团队展示了系统规模和 EPLB 算法对不平衡问题的影响。
他们将 GPU 的平衡度,定义为 GPU 中 MoE 层的平均计算时间与最大计算时间之比,并使用 GPU 处理的 token 数量来估计其计算时间。
从图中可以看出,当系统随着节点数量的增加而扩展时,GPU 的利用率会降低,而启用 EPLB 则可以显著提高了 GPU 的利用率。
EPLB 在实际服务中的应用
为了使 EPLB 能够有效发挥作用,输入数据的分布必须与实际服务的工作负载高度吻合。通过以下两种策略,可以增强这种吻合度:
-
增加batch 大小:更大的 batch 可以减少专家使用过程中的随机波动,从而提高负载均衡的效果。这一目标可以通过扩展集群规模或者采用多 token 预测(MTP)等技术来实现。
-
定期进行重新平衡:定期更新专家的排列方式可以利用时间局部性原理,但这需要高效地重新加载专家模型。因此,需要尽可能降低专家模型重新加载操作的成本。
即使采用了 EPLB,一定程度的不平衡现象仍然难以避免,未来仍需进一步优化。
重新平衡的具体实施方案
SGLang 通过三个阶段的重新平衡操作,来确保既高效又不会造成中断,进而在权重更新期间维持系统的性能。
-
系统加载阶段:可以选择从磁盘预加载权重数据到主内存中,以加快重新平衡的速度;也可以选择将权重数据保存在磁盘上,并使用内存映射(memory mapping, mmap)技术,从而减少内存的占用量。
-
重新平衡准备阶段:所需的权重数据会在后台异步传输到设备内存中,利用空闲的 DMA 硬件引擎,从而避免中断正在进行的 GPU 操作。
-
重新平衡执行阶段:通过设备到设备的数据复制来更新权重数据。还可以通过物理内存重绑定等技术来进一步优化这一步骤。
评估
为了突出使用的先进优化技术带来的吞吐量提升,团队使用 DeepSeek-V3 模型,在一个包含 12 个节点的集群上,对 SGLang 的不同配置进行了端到端性能评估。
他们比较了以下四种不同的配置:
-
SGLang(采用 TP16x6)
-
SGLang(采用 PD 分离)
-
SGLang(采用 PD 分离和模拟 MTP)
-
DeepSeek 的结果
为了适应不同的工作负载需求,团队分别独立地评估了预填充阶段和解码阶段的性能。
评估结果总结如下:
· 预填充阶段:在 4 个节点的配置下,对于 prompt 长度分别为 1K、2K 和 4K 的情况,系统所实现的单节点吞吐量分别为每秒 57,674、54,543 和 50,302 个 token。
如下图所示,与 TP16 基线相比,这种配置实现了高达 3.3 倍的性能提升。
在假设工作负载完全平衡的前提下,此系统的吞吐量与 DeepSeek 官方数据之间的差距在 5.6% 以内。
· 解码阶段:在 9 个节点的配置下进行评估,对于 2K 的输入,系统实现的单节点吞吐量为 22,282 个 token/秒,这意味着与 TP16 基线相比,性能提升了 5.2 倍。
在模拟 MTP 条件下,对于 4K 的输入,系统仍然能够保持每节点 17,373 个 token/秒的高吞吐量,仅比 DeepSeek 官方性能分析数据低 6.6%。
接着,团队将 SGLang 的性能与 DeepSeek 的推理系统进行对比,力求使实验设置尽可能贴近 DeepSeek 的生产环境。
对于预填充阶段,团队测试了一个场景,在该场景中,每个设备处理 16,384 个 token,输入长度为4,096。
考虑到 DeepSeek 的专家分布存在不确定性,他们评估了两种情况:一种是采用默认的专家分布,另一种是模拟理想状态下的 EPLB,并将后者的结果作为性能上限。
评估结果如下所示:
DeepSeek 的性能分析数据显示,其所报告的吞吐量大约是其生产环境的两倍。
在默认的专家不平衡情况下,SGLang 的性能比 DeepSeek 的性能分析数据慢 20%;而在模拟的理想 EPLB 情况下,这个差距缩小到了6%。
对于解码阶段,结果如下所示:
在使用 DeepSeek 一半数量的节点的情况下,搭载模拟 MTP 的 SGLang 仅比 DeepSeek 的性能分析数据略慢。
在更高的 batch 大小设置下(256 个序列,2,000 个输入长度),SGLang 实现了每节点每秒 22,282 个 token 的处理速度,充分展现了其强大的可扩展性。
下图详细分析了预填充阶段各个内核的执行时间。
如下图所示,SGLang 的解码内核分析结果与 DeepSeek 的结果非常接近:
可以看出,SGLang 的解码性能在很大程度上与 DeepSeek 的性能相一致。
因此,下一步的工作重点,就是预填充阶段的优化了。
局限性与未来工作
总的来说,项目在吞吐量上有着显著的提升,但仍然存在一些局限性以及需要增强的领域:
-
延迟优化:目前因为专注于提升吞吐量,导致首 token 时间(TTFT)达到2-5 秒,token 间延迟(ITL)大约 100 毫秒。之后还需要进一步优化,来满足实时使用场景的需求。
-
序列长度约束:由于使用了 96 个 GPU,因此序列长度被限制在较短的范围内。 扩展 GPU 资源将支持更长的序列,这对于特定应用至关重要。
-
多 token 预测(MTP)集成:SGLang 支持 MTP,但缺乏与 DP 注意力的完全集成,降低了混合并行配置的效率。
-
专家并行负载均衡(EPLB)分布:本次实验使用了专家并行负载均衡器(EPLB)的同分布数据,这可能无法反映真实场景中的数据变动。之后还需要研究出现分布偏移时的性能表现。
-
灵活的张量并行(TP)规模:对于 DeepSeek-V3 而言,稠密 FFN 的内存最优 TP 规模较小,但大于1。目前 SGLang 仅支持纯 TP 或 DP,导致内存利用率不高。之后还需要支持更灵活的 TP 选项。
-
Blackwell 支持:目前的实现仅支持 NVIDIA Hopper 架构。团队正在努力将兼容性扩展到下一代 Blackwell 架构。
参考资料: