Continous Batching提出于论文《Orca: A Distributed Serving System for Transformer-Based Generative Models》,因其可以实现数倍乃至数十倍的系统吞吐提升,已广泛被各大LLM推理框架采用(原名Iteration Batching,TGI和vLLM称之为Contious Batching,TensorRT-LLM称之为In-flight Batching)。
笔者曾阅读几篇关于Continous Batching的解读,始终觉得对运行机制的理解不够透彻,因而自己看论文做了这篇解说。
所谓“一图胜千言”,FriendliAI(ORCA作者单位之一)用一个动图诠释了Continous Batching的精华。
图片来源:https://friendli.ai/blog/llm-iteration-batching/
为了更好地解决Early-Finished 和 Late-Joining,ORCA提出了Iteration-level Scheduling。笔者对其做了密集注释,应该很清晰了:
ORCA版Iteration-level Scheduling的算法描述(含笔者注释,点击放大)
解决问题的关键点是:CLM(Casual Language Modeling)模型(典型如GPT系列),并不是一次推理就能生成全部的文本,而是像下图那样迭代式地调用GPU推理生成每一个Token。因此在每次GPU推理的空隙,可以插入调度操作,实现Batch样本的增删和显存的动态分配释放(这就是论文提出的核心思想:Iteration-level Scheduling)。具体而言,Early-finished 的问题通过算法描述中第13~14行的逻辑解决(还应有request出队列的逻辑,但没有描述),而Late-joining 的问题通过算法描述中第23~27行的逻辑解决。
CLM生成文本逻辑与Schedule时机
图片来源:https://www.usenix.org/conference/osdi22/presentation/yu
OCRA解决这个问题的思路没啥特别的,上图就可以说的很明白了,笔者稍微做下解读:
因为大模型推理发展迅速,比如ORCA发表时被比下去的框架现在也用上了Continous Batching,还加入了其他的优化方法(比如Paged Attention),所以实验结果有明显的时效性问题,笔者不做过多解读。感兴趣的读者可以参阅以下译文:
Continuous Batching:一种提升 LLM 部署吞吐量的利器https://zhuanlan.zhihu.com/p/657586838
作者关注过一些针对原版Continous Batching(即OCRA版)某些细节做的改进,在这里列一下:
1. 对Canceled Requests(部分请求已要求中止生成)的处理。对于这些请求应及时从Batch中剔除并释放相应显存,但ORCA版没有提及。现在流行的推理框架都应补全了这块逻辑,例如TGI中Filtering的服务逻辑包含了对Canceled Requests的清除。
2. 拆分Initiation Phase(又称Prefill)和Increment Phase(又称Decode)。OCRA版把这2个阶段合并在一起做,但其实它们的计算模式差很多,分开做能够更好地做优化(例如计算Linear时,Initiation Phase的计算Kernel更接近GEMM,Increment Phase的计算Kernel更接近GEMV)。以TGI为例,它的改动是将Initiation Phase的请求批量做完计算后,再这些请求与已在Increment Phase的请求合并做批量计算。
3.优化K/V Cache的释放机制或时机。ORCA版在请求生成结束时就立即释放其K/V Cache。在多轮对话场景中,这个机制会导致冗余计算,即“上一轮对话生成K/V Cache → 释放K/V Cache显存 → 通过本轮对话的Prompt生成 之前的K/V Cache”。这样会恶化后续几轮对话的First Token Time(产生第一个Token的时延)指标(很明显后面的Prompt会非常长,算力一下就吃满了)。阿里对这个问题做了优化工作,感兴趣可以看这里:
大模型推理优化实践:KV cache复用与投机采样https://mp.weixin.qq.com/s/M6bisR_rTHM-vyeOD9ILXA?poc_token=HMMOvWWjH4_1DyqpGrwTyfj2At3gOBfRTGZJdh2-
4. 优化时延抖动问题。Contious Batching增大了整个系统的吞吐,但可能会给单个用户的体验带来一些小问题:在自己请求的文本生成过程中,如果有新的请求进来就会一起加入生成计算中。因为BatchSize在动态变化,计算时延会有比较明显的波动——这会让用户产生LLM系统卡顿或忽快忽慢的感觉。这个小问题在产品上还是容易解决的,例如笔者留意过某些国产LLM会在一些合适的地方主动作停顿,做一下缓冲(例如生成冒号或分号后停一下,模拟人类分点讲述时的必要停顿)。技术上的解决方案也有,例如有一位大神把解决时延抖动的关键定位在Prefill阶段,通过将Prefill阶段拆分为多次完成来削弱对时延的影响,同时因为拆分对齐了某些特定维度,使算力得到更好的发挥。具体看这里:
大模型推理优化--Prefill阶段seq_q切分:https://zhuanlan.zhihu.com/p/658443665
文章来源:https://zhuanlan.zhihu.com/p/680123256
已获得作者授权
本文分享自 GiantPandaCV 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!