TAG:BladeLLM 的纯异步推理架构

作者:张子鹏 PAI引擎团队

随着 GQA/MLA/MoE 等模型结构不断发展,大语言模型的推理逐步解除了显存限制,逐渐向着高并发、高吞吐的方向发展。推理引擎的运行时开销也变得不可忽视。主流 LLM 推理框架的运行时开销大致来自:

  1. Python 性能:考虑用户易用性和开发效率,业界主流框架都采用 Python 为主要开发语言、C++实现模型和算子的方式。Python 一直存在让人诟病的 GIL 问题,框架中很多的代码无法有效并行。这导致在高并发场景,Python 执行速度成为了显著的瓶颈。

  2. 通信开销:为了规避Python GIL的限制来提升框架的并行度,即使是在单机内,主流框架通常都会引入多进程的设计。此外大模型推理也逐渐扩展至分布式推理,系统模块可能存在多个 Prefill、Decode 实例。系统在运行过程中,不同的模块、实例间需要频繁进行交互。而进程间的通信、消息的序列化和反序列化也不可避免的成为了瓶颈。

  3. 同步执行逻辑:主流的推理框架都会采用分页的 KV Cache 管理,执行流程是严格按照 KV Cache Block分配、模型计算、KV Cache Block更新的迭代式的过程。目前业界主流框架都是基本按照同步的设计,各个组件的开销不能被掩盖,当并发变大后累计的开销可能会达到模型计算的量级。

近期,大模型推理社区(vLLM,SGLang 等)普遍开始关注框架运行时开销,提出了多步调度、异步输出处理、独立 API Server 进程等工作,来分摊或掩盖部分开销。

在我们的实际业务场景中,也观察到高额的框架开销严重限制了系统吞吐,特别是在高并发(>1k)场景下,运行时开销已经接近或高于 GPU 运行时间,导致资源严重浪费和性能下降。为此,BladeLLM 设计并实现了基于 Python 的纯异步 LLM 推理架构 -- TAG (Totally Asynchronous Generator) ,以最大程度提高 GPU 利用率,提升引擎性能。

LLM 推理引擎简介

一个典型的 LLM 推理引擎可以分为以下组件:

  • API Server:负责请求接收和响应;

  • Scheduler:负责请求调度、KV Cache Block 分配等;

  • Model Runner:主要负责模型计算和采样;

  • Decoder:负责将采样得到的 Token ID 转化为字符形式输出。

以下是一个完全同步的推理引擎的 timeline 示意图:

社区现状

针对运行时开销逐渐变大的问题,社区也在逐渐优化中,提出了包括异步输出处理、多步调度等方案来尽可能掩盖或分摊运行时开销。

以目前最新的 vLLM 0.6.0 为例,开启 MultiStepScheduling 和异步输出处理优化后,整体的 timeline 大致可以表示为:

可以发现,开启优化后, Model Runner 在连续 N 个 step 之间,可以不和 Scheduler 进行同步和交互,连续进行多次 forward,从而保证了该段时间内 GPU 利用率变高。SGLang 也提供了类似功能。

然而我们仍然可以观察到, 这样的调度方式存在以下问题:

  1. 连续 N 个 step 结束之后,Model Runner 还是会处于等待状态,直到 Scheduler 调度新的一轮请求。所以MultiStepScheduling 只能平摊、但不能完全消除 Scheduler 的开销。而随着并发增大,Scheduler 和 Decoder 等环节开销变大,Model Runner 的等待时间仍然会增加。

  2. Model Runner 需要多个 step 后再进行返回,而这中间,用户是不能接收到这些新生成的 token。所以从用户视角,TTFT 和 ITL 会显著上升,影响用户体验。

纯异步 LLM 推理引擎 TAG

异步Scheduler

目前看来,社区推理引擎关键问题在于调度和 Model Runner 执行存在同步关系。以 vLLM 为例,这个同步关系主要来源于: Scheduler 进行调度时,会为每个请求分配 KV Cache Block,而分配决策依赖于每个请求的 Token;而当前 step 调度所需要的 Token需要等待上一步Model Runner 运行结果返回给 Scheduler ,从而形成了依赖,导致 Scheduler 和 Model Runner 执行需要同步串行进行。

BladeLLM 团队针对这一场景,重新分析了该依赖关系,发现:

  1. Scheduler 在调度和分配 KV Cache Block 时,需要的信息只是每个请求 Token 的长度l,与 Token ID 具体的值无关;

  2. Model Runner 每执行一次,能够新生成 Token 数的上界(p)都是确定的:对普通的 step,生成 Token 数为 1; 如果使用了投机采样算法,每步生成 Token 数至多为 gamma + 1,其中 gamma 为 draft model 采样步数;

  3. 因此,第i步调度时,只需要在第i-1步 调度的 Token 数(l_{i-1})基础上,额外预留上一步最多生成的 Token 数,即可以满足 worker 运行逻辑,而不会导致 KV Cache Block 不足;

  4. 在 Model Runner 实际运行完成后,如果实际生成的 Token 数( g_i )小于p ,则更新 scheduler 状态,下次调度只需要再预留n-m个 token 的 KV Cache。这个状态的更新是异步的,所以调度第 i 个 step 时,会比实际所需 token 多预留\sum_{j=i-t}^i({n_j-m_j})个 token 的 KV Cache,其中 t 为异步调度的最大步数。在我们的实际使用中, t 取 2 即可达到完全异步的效果,因此,额外预留 token 数较小,不会影响整体 cache 容量。

TAG 架构

在消除了 Scheduler 和 ModelRunner 之间的同步点后,我们发现,整个推理系统可以完全异步起来,因此我们提出 TAG (Totally Asynchronous Generator) 的架构设计:

图中,所有组件之间的消息传递都是异步完成的。整体流程分为:

  1. WebServer 接受用户请求,经过 Tokenizer 后,将请求添加到 Scheduler 的请求队列中;同时,并行从 Detokenizer 中接收 response,返回给用户;

  2. Update Loop 主要负责处理 Model Runner 的返回消息队列,包括:

  • 给 Scheduler 更新请求之前步执行实际生成 token 数,减少 token cache 浪费;

  • detokenize,并将生成 token 结果传给 WebServer ;

  • 判停,及时删除结束的请求;

  • 完成上述步骤后,释放信号量,让 Scheduler 进行下一次调度。

3. Scheduler 和 Update Loop 通过 Python 协程的方式进行并行,又通过信号量控制 Scheduler 最大调度步数;因此,Scheduler 的循环为:获取信号量 -> 预分配最大 token cache -> 调度结果发送给 Model Runner。

4. 由于 Scheduler 会同时有多次调度结果发送到 Model Runner,所以 Model Runner 能够不间断的获取请求,运行模型,而不会出现闲置。Model Runner 进程内部运行也是完全异步的,包括接收并反序列化请求->调用模型->序列化结果并返回三个部分,使得调用模型的过程不会中断。

TAG 的 Timeline 可以表示为:

跨进程通讯框架

Scheduler 和 ModelRunner 采用的是 CPU/GPU 多进程分离的设计,这种多进程的架构不可避免的会引入通信带来的包括序列化和反序列化、消息传输一系列开销,引擎在早期的通信选型调研过包括:RPC、消息队列、Socket、管道等多种方式。

  • 以 gRPC 为典型代表的 RPC 应用场景最为广泛,支持多种协议,跨机通信,缺点是 gRPC 框架的性能开销不可忽略,对于频繁的小包通信的效率不是最优的。

  • 消息队列的通信方式在消息较小的时候性能尚可,但随着消息变大,性能下降比较严重。

  • 共享内存通过虚拟地址的方式,将同一块物理内存映射到多个进程中,使得共享内存传输大块的数据是效率最高。

因此结合上述考虑后,各组件间的通信采用了 Unix Domain Socket 配合共享内存的方式,在线上常见的50~100 并发以内的时候,进程间通信的开销在 1ms 以内,避免了引擎引入过大额外的开销。

性能测试

我们对比了 TAG 和 vLLM(0.6.0)和 SGLang(0.3.0)在不同并发(64/256/512)下的 QPS 和 TBT,结果如下:

注:

  1. 由于主要测试 runtime 开销,所以数据集输入长度固定位 10,输出长度为 20-500 的正态分布,并设置 ignore_eos=True;

  2. vLLM 开启 multi step scheduling 后,TBT 会显著高于 SGLang 和 BladeLLM-TAG;

由这两个图可以发现,TAG 由于完全掩盖了 Worker 进程外的所有开销,所以相比社区方案能做到更低延迟、更高吞吐,支持更高并发。

总结展望

我们设计并实现了一个纯异步的 LLM 推理引擎 TAG,解决了推理引擎各组件的同步依赖,最大程度的提高 GPU 利用率,提升服务吞吐,降低请求延迟。内部测试中,在满足 SLO 的情况下,Decode 实例能够同时支持上千并发,而 runtime overhead 不会成为性能瓶颈。后续,我们将聚焦于 Model Runner 内的运行开销,致力于打造更极致优化的 LLM 推理引擎。

招聘

阿里云人工智能平台PAI长期开放推理优化方向的研究型实习生、校招和社招岗位。团队致力于从模型和系统两方面对大语言模型推理进行协同优化,工作内容覆盖模型压缩、高性能算子、推理框架和运行时、分布式等工作。

欢迎投递简历:xiafei.qiuxf@alibaba-inc.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/425451.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

黑马十天精通MySQL知识点

一. MySQL概述 安装使用 MySQL安装完成之后,在系统启动时,会自动启动MySQL服务,无需手动启动。 也可以手动的通过指令启动停止,以管理员身份运行cmd,进入命令行执行如下指令: 1 、 net start mysql80…

Excel图片批量插入单元格排版处理插件【图片大师】

为了方便大家在图片的插入排版的重复工作中解放出来,最近发布了一款批量插入图片的插件,欢迎大家下载,免费试用。 这是图片的文件夹: 主要功能如下: 1,匹配单元格名称的多张图批量插入到一个单元格 该功能支持设置图…

学LabVIEW编程,看编程书有些看不懂怎么办?

自学LabVIEW编程时,如果发现编程书籍内容难以理解,可以尝试以下几种方式来提高学习效果: 1. 从基础入手,逐步深入: LabVIEW是一种基于图形化编程的工具,不同于传统的编程语言,因此从基础概念开…

尤雨溪推荐的拖拽插件,支持Vue2/Vue3 VueDraggablePlus

大家好,我是「前端实验室」爱分享的了不起~ 今天在网上看到尤雨溪推荐的这款拖拽组件,试了一下非常不错,这里推荐给大家。 说到拖拽工具库,非大名鼎鼎的的 Sortablejs 莫属。它是前端领域比较知名的,且功能强大的工具。但我们直接使用Sortablejs的情况很少,一般都是使用…

【Redis】之Geo

概述 Geo就是Geolocation的简写形式,代表地理坐标。在Redis中,构造了能够存储地址坐标信息的一种数据结构,帮助我们根据经纬度来检索数据。 命令行操作方法 GEOADD 可以用来添加一个或者多个地理坐标。 GEODIST 返回一个key中两个成员之…

【专题】2024跨境出海供应链洞察-更先进供应链报告合集PDF分享(附原数据表)

原文链接:https://tecdat.cn/?p37665 当前,全球化商业浪潮促使跨境电商行业飞速发展,产业带与跨境电商接轨、平台半托管模式涌现、社交电商带来红利机会以及海外仓不断扩张,这使得产业带外贸工厂、内贸工厂、传统进出口企业和品…

自制一键杀死端口进程程序# tomcat 如何杀死tomcat进程

直接cmd 窗口执行如下命令即可 netstat -ano | findstr :8080 taskkill /F /PID <PID>简简单单的两个指令,总是记不住,也懒的记, 每次端口冲突的时候, 都是直接查百度,很苦逼, 如果有一个程序,直接输入端口号,点击按钮直接杀死进程,岂不爽歪歪. 跟我一起制作一个屠猫的…

【D3.js in Action 3 精译_022】3.2 使用 D3 完成数据准备工作

当前内容所在位置 第一部分 D3.js 基础知识 第一章 D3.js 简介&#xff08;已完结&#xff09; 1.1 何为 D3.js&#xff1f;1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践&#xff08;上&#xff09;1.3 数据可视化最佳实践&#xff08;下&#xff09;1.4 本章小结 第二章…

【网络原理】❤️Tcp 常用机制❤️ —— 延时应答,捎带应答, 面向字节流, 异常情况处理。保姆式详解 , 建议收藏 !!!

本篇会加入个人的所谓鱼式疯言 ❤️❤️❤️鱼式疯言:❤️❤️❤️此疯言非彼疯言 而是理解过并总结出来通俗易懂的大白话, 小编会尽可能的在每个概念后插入鱼式疯言,帮助大家理解的. &#x1f92d;&#x1f92d;&#x1f92d;可能说的不是那么严谨.但小编初心是能让更多人…

[数据集][目标检测]无人机识别检测数据集VOC+YOLO格式6986张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6986 标注数量(xml文件个数)&#xff1a;6986 标注数量(txt文件个数)&#xff1a;6986 标注…

‌内网穿透技术‌总结

内网穿透是一种网络技术&#xff0c;通过它可以使外部网络用户访问内部网络中的设备和服务。一般情况下&#xff0c;内网是无法直接访问的&#xff0c;因为它位于一个封闭的局域网中&#xff0c;无法从外部访问。而通过内网穿透&#xff0c;可以将内部网络中的设备和服务暴露在…

数据稀缺条件下的时间序列微分:符号回归(Symbolic Regression)方法介绍与Python示例

时间序列概况在日常生活和专业研究中都很常见。简而言之,时间序列概况是一系列连续的数据点 y(0), y(1), …, y(t) ,其中时间 t 的点依赖于时间 t-1 的前一个点(或更早的时间点)。 在许多应用中,研究者致力于预测时间序列概况的未来行为。存在各种建模方法。这些模型通常基于过…

Unity让摄像机跟随物体的方法(不借助父子关系)

在Unity中&#xff0c;不使用子对象的方式让相机跟随物体移动&#xff0c;我们通过编写脚本来实现。下面放一个从工程中摘出来的的C#脚本示例&#xff0c;用于将相机绑定到一个Target对象上并跟随其移动&#xff1a; using UnityEngine; public class FollowCamera : MonoBeh…

DPDK基础入门(十):虚拟化

I/O虚拟化 全虚拟化&#xff1a;宿主机截获客户机对I/O设备的访问请求&#xff0c;然后通过软件模拟真实的硬件。这种方式对客户机而言非常透明&#xff0c;无需考虑底层硬件的情况&#xff0c;不需要修改操作系统。 半虚拟化&#xff1a;通过前端驱动/后端驱动模拟实现I/O虚拟…

【STM32】CAN总线基础入门

CAN总线基础入门 一、CAN简介二、主流通信协议对比三、CAN物理层1、CAN硬件电路2、CAN电平标准3、CAN收发器 – TJA1050&#xff08;高速CAN&#xff09;4、CAN物理层特性 四、帧格式1、CAN总线帧格式2、数据帧&#xff13;、数据帧各部分用途简介&#xff14;、数据帧的发展历…

大模型参数高效微调技术原理综述(八)-MAM Adapter、UniPELT

MAM Adapter 背景 近年来提出了多种参数高效的迁移学习方法&#xff0c;这些方法仅微调少量&#xff08;额外&#xff09;参数即可获得强大的性能。虽然有效&#xff0c;但人们对为什么有效的关键要素以及各种高效微调方法之间的联系知之甚少。 下图展示了不同的微调方法&am…

小米,B站网络安全岗位笔试题目+答案

《网安面试指南》http://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247484339&idx1&sn356300f169de74e7a778b04bfbbbd0ab&chksmc0e47aeff793f3f9a5f7abcfa57695e8944e52bca2de2c7a3eb1aecb3c1e6b9cb6abe509d51f&scene21#wechat_redirect 《Java代码审…

坚持的力量--完成向CSDN迁移500篇技术文章阶段小记-以此自勉

前言&#xff1a;本文为迁移前的博客中的文章《坚持的力量-写给第1000篇文章笔记》发表于 publish:May 14, 2021 -Friday&#xff0c;作为原个人博客中累计写满1000篇文章的总结和鼓励。因在向CSDN迁移文章的过程中进行了一些文章合并等调整&#xff0c;总文数大量下降&#xf…

ACM模式下算法题输入输出攻略【C++】

文章目录 [TOC] 1. 核心代码模式与ACM模式1.1 ACM模式介绍1.2 注意事项 2. C常用的输入输出方法2.1 输入2.1.1 cin注意事项2.1.2 getline()注意事项2.1.3 getchar()注意事项 2.2 输出 3. 案例3.1 一维数组输入3.1.1 固定长度的一维数组3.1.2 不固定长度的一维数组 3.2 二维数组…

使用ddns-go实现自动配置IPv6的DDNS

正文共&#xff1a;888 字 17 图&#xff0c;预估阅读时间&#xff1a;1 分钟 前面说到通过PPPoE拨号获取到的IPv6地址没有发生变化&#xff08;企业路由器配置IPv6家用宽带的PPPoE拨号示例&#xff09;&#xff0c;结果说完就打脸了。中间家里停了一次电&#xff0c;路由器重新…