作者:袁镱博士,腾讯公司专家工程师,负责无量系统和一念 LLM 等机器学习训练和推理框架研发。
一念LLM 取“一念三千”之意,寓意“一念之间,用大模型生成世间万象”。
Github开源地址:
简介
在业务数据的测试集(总共512条,平均输入1812 tokens,输出978 tokens)上,我们经过理论推算,如果两台H20(16卡)部署fp8满血版Deepseek,吞吐的保守上限是18000+ tokens/s。在2月底,开源vllm/sglang的吞吐1400 tokens/s和2200 tokens/s,存在巨大的优化空间。经过4个月的快速迭代后,vllm/sglang最新版都上升到6100 tokens/s左右。同一时期,一念从不支持Deepseek和分布式推理,达到当前的9084 tokens/s,发布0.6.0版本。
其中主要的性能优化来源于两个方面:
1)PP支持multi-batch并发执行,相比多机DP(数据并行)+EP(专家并行)方案,跨机通讯量降低98.3%,而且多个batch之间异步通讯大大降低了机器间网络抖动对整体性能的影响;
2)通过显存的精细化管理,留给kv-cache的可用显存增加137%,可以进行更多的请求并行执行。
PP在运营上有很多优秀的特点:
1)没有节点同构的要求,可以随意的卡数和卡型组合。
2)由于流水线并行节点之间通讯量低,且都是异步通讯,GPU机器之间的互联性能要求很低。这些特点都给到底层GPU资源调度运营更大的自由空间。PP支持multi-batch并不是一个创新,是PP在经典定义中就应该有的特性,我们在大模型推理框架ContinuousBatching,投机解码等新兴技术背景下将经典重现。在大模型推理中使用PP是针对当前硬件条件和业务需求的设计选择和优化。H20相比H100计算性能相差10+倍,英伟达B系列性能更强,而业界主流开源框架都源于美国,设计和开发重点都在英伟达最强的硬件上,从而很容易导致与我们特定情况的技术错配。我们有必要从实际的硬件条件出发,结合业务的特点,继续探索更合理的推理调度方案。
当前性能只是勉强达到保守的理论上限的50%,仍然有非常大的优化空间,我们也看到还有很多优化工作可以做。比如:目前使用的是TP+PP的方式,叠加EP+DP后还会有不错的吞吐提升;不管是计算还是通讯的算子,很多都没有充分发挥硬件性能;PD分离能够进一步降低权重和kv-cache对显存的消耗;这些技术正在开发和优化中,敬请期待后续发布。
下面会首先介绍一下一念的研发思路,然后结合现有方案的优缺点,介绍PP的multi-batch支持。
一. LLM的推理逻辑,以及一念的研发思路。
在介绍相关内容之前,我们先简单回顾一下大语言模型推理的基础逻辑,大致可以用下图来简单理解。
当一个新请求被加入后,会由调度器为新请求分配显存,并与现有请求组装成batch,交给下一步进行Forward操作。在Forward完成后,通过Sampling得到一个token的输出。如果还需要继续输出,则返回调度器进入下一个周期,重复图中2-5步,直到模型生成结束符或者到达用户设定的长度限制。
这个过程中涉及到的模块,我们大致可以分为三类:
调度与执行引擎。调度器会在请求级别管理计算和存储两种资源。在Forward中会有一个执行器来调度算子级别的计算和存储资源。不同的推理框架基于不同的设计理念,会在这些模块选择不同的方案。 算子。由于大语言模型结构相对固定,算子优化的可复用性很高。各个框架会相互借鉴算子实现,来让提升算子利用硬件的能力。 定制/探索性功能。在大模型应用中,由于模型推理过程占据了业务服务的主要耗时,业务不再满足于看到生成结果后再处理,而是希望控制token生成的过程。在整个生成过程的循环中,常见的控制点在采样前和采样后。比如:通过采样过滤功能,限制输出token的选择范围。通过结构化输出,控制输出结果的模式,以及用特定的小模型或者逻辑来执行投机解码,对特定业务场景进行推理加速。
对于一念的研发路径选择,我们基于两个基本判断:
随着模型能力的增强,模型推理占据业务逻辑的比重会越来越大。如果“模型即应用”,这个比例会趋向100%。业务特性会在推理框架中越来越多地体现出来。框架需要有对业务需求快速的响应能力。由于定制化功能与资源调度息息相关,要实现业务的快速响应并维持框架的持续迭代,对调度和定制化功能的设计和研发进度需要有足够的控制力。 开源模型算子优化上,硬件厂商和模型开发者会深度优化相关算子。比如:英伟达深度介入FlashAttention的新版本开发;华为将ATB作为一个单独模块提供出来;DeepSeek在其开源周上公布了多个DeepSeek相关的算子库,迅速被各个开源框架采纳。
所以,为了掌握调度模块的控制权,一念在立项之初,放弃了基于开源框架进行二次开发的路线,而是选择了自研调度和定制化功能模块。对于算子,采用了多来源择优的策略,这样即便开源框架迭代迅速,一念通过在算子层面借鉴,只要打平业界性能,就能在调度上保持针对业务优化的额外收益。
二. 技术介绍
由于需要开发核心模块,而开发人力有限,需求排期上以业务主要使用的中小模型上的优化为主线,导致DeepSeek-R1这样需要多机推理的大模型的支持上漏球。经过4个月的努力,一念发布0.6.0,在Deepseek满血版推理上,吞吐达到了9084 tokens/s,超过vllm/sglang最新版48%。
这个过程中,团队进行了大量细致的优化,比如:代码重构,算子调优,缓存优化等,这些都是魔鬼细节,这里就不一一讲述了。一念的整体设计可以参考之前的文章。下面主要分析大家常听到的TP/DP/EP/PD分离技术,再介绍PP实现multi batch并行推理的工作。
2.1 TP,DP,EP和PD分离
TP,DP,EP和PD分离是当前大模型推理中经常被提到的技术。我们首先看看单机情况下不同的TP/DP/EP组合有什么区别。这里以Deepseek的一层的推理为例:
我们大致可以将一层模型的推理分为Attention和FFN两个阶段,Deepseek模型在两个阶段的模型结构分别是MLA和MoE。这两个阶段都会读取大量的参数权重并进行大量计算。为了让多张GPU卡并行执行这些操作,TP(Tensor Parallelism)将一个权重tensor切分到多张GPU卡上,然后对应权重的计算也被分到了多张卡上。TP操作之后,需要将这些切片的结果通过all reduce操作合并起来。所以我们可以看到在MLA和MoE之后都有all reduce的操作。
为了便于后面描述DP,我们将Attention部分的TP叫做Attention Tensor Parallelism(ATP)。ATP4表示4张卡来执行一个Attention部分的Tensor并行操作。而TP专指MoE部分的tensor并行,TP4表示4张卡来执行MoE部分的Tensor并行操作。图a中就是ATP4+TP4的工作模式。
在Dense模型的时候,Attention和FFN的计算量差距不大。当MoE结构兴起后,FFN阶段的计算量发生了很大的变化。以前MLP的结构会处理全部的token,MoE的每个专家只会处理一部分token,专家越多,每个专家处理的token越少。比如:Deepseek v3有256个专家,每个专家只会处理batch中8/256的token。如果batch size是256,在decoding阶段的时候,一个专家只会处理8个token,会造成巨大的计算资源浪费。而batch size的增长主要受限于kv-cache的显存消耗,Deepseek的MLA结构会在ATP内的多张卡使用到相同的kv-cache数据,所以需要ATP越小,冗余的kv-cache拷贝越少。然而,MoE需要更多的卡并行计算,让batch size越大越好。于是就有了数据并行(Data Parallelism)的设计。有多份MLA的拷贝(一份Data和Tensor),每个拷贝内的ATP比较小,而DP拷贝数越多,MoE部分的TP就越大,MoE部分的batch size也越大。
DP拷贝的数量增大后,TP的值可能超过单机的卡数,就会导致另外一个问题:在TP机制下,每个专家计算输入和结果都是独立的切片数据,专家数越多,切片越多。而由于专家路由逻辑的特点,切片不是均匀的,导致融合多个专家的算子形成更高效计算的难度很大。加上共享专家机制的加入,导致算子优化的难度上升以及通讯碎片。于是有了EP(Expert Parallelism)的方案,通过将不同Expert分配到不同卡上,这样只需要将batch中的token按照专家路由的结果发送到具体Expert上,然后Expert将自己要计算的tokens收集起来,就能进行整块数据的计算。通讯成本也更低。
另外,大模型推理分为Prefilling和Decoding两个阶段,两个阶段推理的token数量有巨大的差异。一个请求在Prefilling阶段可能几K或者几十K个token同时推理,而Decoding阶段只会有一个或者几个token在推理。所以为了达到MoE阶段GPU充分利用的目标,两个阶段的batch size需求是不同的。在DeepSeek-V3的论文中,Prefilling阶段是8路DP,而Decoding阶段是80路DP。而且推理框架还会针对两种阶段会定制不同的算子,以达到更优的计算效率。另外,在Deepseek的设计中,为Decoding阶段专门定制了权重吸收的计算逻辑WA-MLA(weight-absorb MLA),而权重吸收机制有独立的一份WA-MLA的权重,如果在相同的卡上执行Prefill和Decode阶段流程,多出来的一份权重会让留给kv-cache的显存更少,直接影响吞吐。
可以看出,TP/DP/EP和PD分离的机制都是围绕一层模型的推理性能进行优化,在多机情况下,会有更好的单层耗时。然而,在需要多机部署的时候,都会导致每层计算中都有多次全局的数据交换和同步。以Deepseek-R1为例,总共61层,那么生成一个token就需要至少61*2次全局数据交换。在这种高频同步的情况下,任何一个节点的计算性能问题或者网络通讯抖动都会形成木桶短板。为了避免高频同步通讯对推理性能的影响,DP+EP方案部署对多机互联网络的性能有很高的要求,比如:同路由器高速互联。业界采用这个方案大规模部署的基本都是使用Nvidia InfiniBand网络或者能够有相近性能的互联方案。需要基础设施团队与推理平台团队紧密协同,增加了运营的复杂度。
2.2 流水线并行PP
通过分析TP/DP/EP和PD分离的技术,会有几个疑问:不管是H20还是机器间高性能互联,都是以前训练集群的硬件配置。作为推理服务,为什么一定要像小型机一样的高性能高可靠的硬件才能跑得好。互联网的服务不应该是海量和柔性的么?成本怎么降下来?
如果要打造一个皮实的系统,那么对于机型和网络这两项硬件的容忍度就必须需要提升。在可接受性能损失内,减少高频的机器间同步操作就是一个自然的选择。
沿着这个思路,很容易想到的就是一个经典的但是在大模型推理领域少有被提及的流水线并行技术。以两个节点为例,一个batch的流水线并行推理的流程如下:
从上面的示意图,我们可以看出:
1)优势是
a. 实现简单,跨机通讯小。以61层的Deepseek R1模型为例,DP/TP/EP每层都需要进行至少两次HiddenState的同步通讯,而PP只需要进行两次HiddenState的传输,那么在双机情况下,PP的传输量只有TP或DP方案的1/61。
b. 运营灵活度高。对于不同计算能力的节点,可以通过调整负载来保障整个流水线的顺利执行。比如:计算慢的节点就分配少一点的层;一般DP/EP方案的部署都要求卡数是2的倍数,而PP完全没有这个限制。
2)弱势也是非常明显的。如果只能运行一个batch,在ForwardLayer占据主要计算量的情况下,会导致GPU算力只能用起来 1/pp(pp是流水线并行节点数),造成巨大的GPU资源浪费。或者说如果batch调度不畅,也很容易形成空泡。大模型的自回归推理流程下,有状态的异步控制比较麻烦,现有框架基本都把研发重点放在了DP/EP和PD分离这些同步方案上。流水线并行的实现也都只能运行一个batch或者说支持了多batch的实际效果也不好。
经典的流水线并行,就是要通过多个batch将多个资源充分利用起来。在大模型的推理过程中,由于kv-cache的引入,大模型自回归的推理生成过程是有状态的,所以流水线并行的multi batch调度会稍微复杂一些。
在大模型训练加速的领域,早就遇到过类似的问题。现在的训练框架都会将一个大batch拆分成多个小batch的方式来执行。在多个小batch流水线执行后,GPU空闲时间就显著变少了。如下图所示:
图片来源:Efficient Large-Scale Language Model Training on GPU Clusters Using Megatron-LMEfficient Large-Scale Language Model Training on GPU Clusters Using Megatron-LM
与训练流程相比,大模型自回归的推理流程有以下特点。
1)训练流程需要有一个Pipeline flush操作来同步更新模型参数。在推理流程中,模型参数是不更新的。需要保证的只是请求的自回归流程正常。
2)训练流程中每个batch中样本使用的次数是确定的。而大模型推理过程中,由于请求进入batch的时间不同,输出长度的不同,会导致batch随时可能有请求加入和退出。如果batch之间执行时间差异大,就会导致执行时间长的batch卡住执行时间短的batch,从而让其他环节的GPU空闲。我们在压力测试中观察到这个部分的空闲可能导致整体吞吐30%的下降。
于是一念针对这两个特点有了以下的设计。
1)MultiBatch自回归流程
我们期望的执行流程如下图所示:
为了尽量不影响现有逻辑和后期DP/EP的开发,我们采用了一个相对简单的线程模型。以多线程方式执行多个batch,每个batch的调度和执行流程控制都在一个线程中完成,每个线程保证自己所负责batch的自回归流程的正确性。计算资源,通讯资源和存储资源都被池化,由多个batch线程自由竞争。
2)batch动态负载均衡
针对大模型推理中存在batch内请求随时进入和退出的问题,我们需要在原来continous batching技术的基础上,增加batch间负载均衡的策略。在每次调度过程中,负载均衡器都会尝试按照某个策略对batch的负载进行均衡。这个策略决策的主要因素是请求数,推理计算的token数,推理序列长度与算子性能之间的关系。优化目标是调整请求数,推理token数,推理序列长度,让所有batch的执行耗时均匀,同时每个batch的算子耗时最优。
3)layer offload机制
在前面的分析中,我们会发现master节点需要做调度,embedding lookup,lmhead,sampling等操作,用户的定制操作,投机采样等操作也都在master上。为了不让master节点成为流水线上的计算瓶颈,我们还提供了layer offload机制,通过将一部份层分配给worker节点,来降低master节点上推理的模型层数,从而降低master节点的负载。
2.3 性能情况
测试数据:我们采用从业务线上采集的请求作为测试集。总共512条,平均输入1812 tokens,输出978 tokens。
测试硬件:两台机器,共16张96GB版本的H20。
测试模型:Deepseek-R1 0528,权重格式:fp8
测试方法:以不同的QPS向被测试服务发送请求,采集token吞吐,TTFT,TPOT数据。
测试结果:
首先,我们看到两个框架的Token吞吐在小QPS的时候都保持一致的上升趋势。当QPS超过2之后,SGLang逐步达到饱和,吞吐也趋于稳定。从TTFT的数值上也可以看出,SGLang在QPS>2之后因为请求堆积而导致排队,首token的输出时间暴涨。与此同时,我们看到一念的吞吐还在逐渐增长,在QPS=10的时候达到了8823 tokens/s。而一念的P99 TTFT值在QPS>8之后才开始有较大的增长。如果是不考虑TTFT的批处理场景,一念到达9084 tokens/s,SGLang能到6119 tokens/s。】
如果观察TPOT的数值,我们会发现,一念的TPOT值一直高于SGLang。在低QPS的时候,我们看到一念的TPOT值相对SGLang一直有13ms的偏差。主要有两方面的原因:1)一念在当前版本使用的是TCP通讯,发送和接收方都需要在内存和显存之间拷贝数据。2)一念目前的算子性能还未打平SGLang最新版本。这两块都是明确的问题,正在优化,会在稍后的版本中更新。在QPS高的情况下,两者TPOT的差距达到了50ms左右。这里的增加量主要是由于batch size变大使得通讯量和计算量变大,导致对于单请求的TPOT指标上升;相信随着前面提到的两个问题解决,这个差距也会缩小或者消失。
2.4. PP与DP,EP,PD分离技术的关系
简单来讲,DP+EP以及PD分离的架构都能在一层模型的的多机推理上提升计算资源的利用率,从而提升整体的吞吐。而PP解决的是多层模型在多机上推理的性能问题。二者是正交的,可以和DP+EP以及PD分离技术结合使用。
目前一念发布的0.6.0版本中已经包含了上面几个技术的功能,但是性能上还不能打败当前方案。在达到团队的优化目标后会正式发布。
三. 理论分析与未来工作
在2月份,我们做了一个粗略的理论上限计算,来评估框架的优化空间。具体方法是:以模型的数学公式,计算每个数学计算逻辑所涉及到的计算量和通讯量。由于fp8权重模型的计算过程有较多算子都涉及fp16格式的数据计算,计算量和通讯量都是按fp16来估算的。然后假定算子能够发挥出硬件60%的标称最大性能,计算每个数学逻辑对应算子的计算或通讯耗时。得到一个双机16卡H20硬件的吞吐理论上限:18000+ tokens/s。当然,这个估算是非常粗略的,比如:没有考虑算子调度本身的开销,在实际推理过程中,算子越小,调度的耗时占比会明显增加。
让我们吃惊的是,2月时业界开源框架vllm和sglang的性能是大约1400+ tokens/s和2200 tokens/s,说明当时开源框架的性能优化空间巨大。后来发生的事情也证明了这一点,随着vllm v1引擎支持Deepseek和SGLang多项优化的逐步上线,两个推理框架的性能迅速提升,都在5月份达到了大约6100 tokens/s的吞吐。性能提升了2-3倍。但是我们也看到,相对理论上限,各个框架连理论上限的一半都没有达到。
一念目前只使用了TP+PP的技术,前面分析中提到的DP/EP和PD分离正在开发中,很快将正式发布。预计很快还会有30%+的性能提升。另外,在这个上面的对比中,我们使用的是fp8的满血版Deepseek。业内还有多个团队在探索低精度的推理方案。低精度推理方案能降低计算和显存的需求量,从而降低时延,提高吞吐。我们正在与相关团队沟通合作,将大家在算子方面的深度优化与一念结合起来,进一步降低业务使用大模型的成本。
推荐站内搜索:最好用的开发软件、免费开源系统、渗透测试工具云盘下载、最新渗透测试资料、最新黑客工具下载……
还没有评论,来说两句吧...