当前位置: 首页 > news >正文

生成式AI的引擎室:深入剖析LLM内存管理与调度

在这里插入图片描述

引言

大型语言模型(LLM)推理的核心挑战

在深入探讨大型语言模型(LLM)推理的复杂优化之前,必须首先理解一个根本性事实:与许多传统计算任务不同,LLM的自回归生成本质上是受限于内存带宽(memory-bandwidth-bound) 而非计算能力(compute-bound)的工作负载。这意味着,推理速度的瓶颈通常不在于GPU的浮点运算速度,而在于将模型参数和中间状态(激活值)从高带宽内存(HBM)加载到计算核心的效率。这一关键区别是理解和设计后续所有优化策略的基石。

KV Cache的核心地位

在推理过程中,键值缓存(Key-Value Cache, KV Cache) 是GPU内存最主要的消耗者。在Transformer架构中,为生成下一个词元(token),模型需要关注所有先前词元的键(Key)和值(Value)向量。为避免在每一步生成中重复计算这些历史信息,系统会将它们缓存起来。KV Cache的大小与序列长度和批处理大小(batch size)成线性关系,随着上下文长度增加,KV Cache会迅速膨胀,成为决定服务吞吐量的最关键因素。因此,高效管理KV Cache是LLM服务系统设计的核心。

本文主旨与路线图

本文旨在深入剖析现代高性能LLM服务系统背后的内存管理与调度策略,论证当前LLM服务性能的巨大飞跃,源于一场从静态、请求级管理到动态、迭代级控制的范式转变——这一原则深刻借鉴了经典操作系统的核心思想。本文围绕三大支柱展开,系统性探讨这一演进过程:KV Cache管理、批处理策略和请求调度。我们将深入底层原理,并以相关领域的开创性学术论文为理论依据,揭示这些技术如何协同工作,共同构成驱动现代生成式AI的强大引擎。

第一部分:驯服巨兽——先进的KV Cache优化

本部分详细剖析用于管理LLM推理内存中最大、最动态的组件(KV Cache)的各项技术,从物理布局优化、数据表示,到长上下文管理策略,层层递进,揭示如何驯服这头内存巨兽。

1.1 PagedAttention:为LLM设计的虚拟内存

内存碎片化问题

在vLLM团队提出PagedAttention之前,LLM服务系统管理KV Cache时普遍面临严重的内存效率问题。传统深度学习框架要求张量在内存中连续存储,导致两种主要内存浪费形式:

  • 内部碎片(Internal Fragmentation):系统通常按请求可能达到的最大序列长度(如2048个词元)预分配连续内存块,但实际生成的序列长度往往远小于最大值,未使用空间无法被其他请求利用,造成浪费。
  • 外部碎片(External Fragmentation):不同请求的序列长度不同,分配/释放大小不一的内存块后,GPU内存会形成“碎片化”状态——即使总可用内存充足,也可能因无足够大的连续空间无法服务新请求。

性能剖析显示,这种浪费极为惊人:在部分现有系统中,仅20%-40%的已分配KV Cache内存被实际用于存储词元状态,其余均被碎片化吞噬。这种低效内存管理直接限制系统支持的最大批处理大小,严重制约整体服务吞吐量。

PagedAttention解决方案

为解决这一难题,vLLM论文作者从经典操作系统的虚拟内存和分页(paging)技术中汲取灵感,提出PagedAttention算法,核心思想是将KV Cache的管理方式从连续内存分配转变为非连续的分页式管理:

  • 逻辑块与物理块:将每个序列的KV Cache分割成若干固定大小的“逻辑块”,通过“页表”映射到GPU内存中不一定连续的“物理块”。这种设计将序列的逻辑布局与其物理内存存储布局解耦,类似操作系统将进程虚拟地址空间映射到物理RAM。
  • 解决碎片化:所有物理块大小相同且较小,彻底消除外部碎片(任何空闲物理块可分配给任意请求的逻辑块);通过按需分配物理块(仅当前块填满时分配新块),最小化内部碎片(浪费最多不超过一个块的大小)。
  • 实现高效内存共享:非连续布局是高效内存共享的关键。例如,并行采样(parallel sampling)或束搜索(beam search)中,多个候选序列常共享相同前缀(prompt),借助PagedAttention,这些序列可共享对应共同前缀的物理块,仅为发散的新词元分配新物理块(类似操作系统“写时复制”(copy-on-write)),也为第三部分的“请求复用(前缀共享)”奠定基础。
系统级影响

最终,PagedAttention实现近乎零的内存浪费,使系统能支持更大批处理大小,吞吐量相较于FasterTransformer和Orca等先进系统提升2-4倍。

1.2 榨干每一比特:KV Cache量化艺术

动机

如果说PagedAttention优化了内存的物理布局,那么量化(Quantization) 则通过降低存储数据的精度优化内存占用空间,这项技术对长上下文场景尤为重要——此类场景中KV Cache大小会异常庞大。

后训练量化(PTQ)的核心思想

将模型权重或KV Cache从标准16位浮点数(FP16/BF16)压缩到更低位宽(如8位、4位)是精细工作,多种后训练量化(Post-Training Quantization, PTQ)方法的核心思想不同,但目标一致:在尽可能保持模型精度的前提下,最大化压缩率。

量化方法核心原理如何处理重要权重关键权衡
GPTQ利用近似的二阶(Hessian)信息,逐个量化权重,并更新剩余未量化权重以补偿量化误差通过误差补偿间接保护,使整体输出误差最小化计算密集,量化过程需数个GPU小时,但精度极高
AWQ认为一小部分权重对模型性能至关重要,其重要性由激活值的幅度而非权重本身大小决定对与高激活值相对应的权重通道进行缩放(scale up),减小相对量化误差需要小的校准数据集统计激活值分布
SpQR明确识别并分离会导致巨大量化误差的“离群值”权重将离群值权重以高精度(如FP16)稀疏存储,其余大部分权重压缩至3-4位引入稀疏计算的复杂性,需专门推理内核处理混合精度
KV Cache的FP8量化实践

在实际应用中(尤其是NVIDIA的TensorRT-LLM等高性能推理引擎),FP8量化被广泛应用于KV Cache:

  • 机制:数据写入KV Cache时,从FP16/BF16量化为8位浮点格式(如E4M3);后续注意力计算需读取这些值时,动态“逆量化”(de-quantize)回高精度格式。
  • 性能增益:最直接好处是内存占用减半,与FP16相比,FP8 KV Cache可在相同内存预算下支持两倍的上下文长度或批处理大小。
  • 硬件加速:现代GPU(如Hopper和Ada架构)上,启用use_fp8_context_fmha等选项后,注意力计算可直接在FP8精度下执行,既节省内存,又带来直接计算加速,充分利用硬件最新特性。

1.3 有限预算下的无限上下文:驱逐与重计算

“无限”数据流的挑战

随着应用场景对上下文长度要求越来越高,处理“无限长”输入流成为新挑战。简单的滑动窗口注意力机制(丢弃KV Cache中最旧词元)会导致灾难性性能下降——模型会丢失关键初始上下文信息。

“注意力池”现象

StreamingLLM论文作者揭示关键发现:在自回归模型中,无论语义内容如何,模型总是将不成比例的注意力分数分配给序列最开始的几个词元。这些初始词元像“注意力池”(Attention Sink),稳定汇聚大量注意力;当这些初始词元从KV Cache中驱逐时,模型性能会急剧下降。

StreamingLLM的驱逐策略

基于这一发现,StreamingLLM提出简单而深刻的KV Cache驱逐策略:不再是简单的先进先出(FIFO)队列,而是始终在缓存中保留最开始的几个“注意力池”词元(如前4个词元),同时对其余序列应用滑动窗口。

无需微调即可工作的原因

这种方法无需任何模型微调就能奏效,因为它保留了模型在预训练阶段学到的结构性偏好。即使上下文窗口不断滑动,模型内部状态也能保持稳定,使其能泛化到数百万词元长度的序列,而KV Cache大小固定。与基于重计算的滑动窗口方法相比,这种策略带来高达22倍的速度提升。

1.4 第一部分深层关联

本部分讨论的技术并非孤立存在,而是构成多层次的内存优化策略栈

  • PagedAttention在最底层优化缓存的物理布局,解决碎片化并为共享奠定基础;
  • 量化技术在每个物理块内部优化数据表示,通过降低精度压缩空间;
  • StreamingLLM的驱逐策略在时间维度上优化块的生命周期管理,决定哪些信息应长久保留。

顶级推理服务系统(如vLLM或TensorRT-LLM)会将三者结合:用PagedAttention进行内存布局,支持对页内数据进行FP8量化,实现循环KV Cache(一种驱逐策略)。这表明,实现极致性能需要对内存进行全方位、系统性的管理。

这种从底层物理布局到上层逻辑管理的优化思路,与经典操作系统设计哲学不谋而合:PagedAttention对虚拟内存的借鉴,是在GPU与AI这一全新硬件和应用领域对操作系统核心原则的重新实现——逻辑块到物理块的映射即页表,固定大小的块即页,写时复制机制与操作系统处理进程间共享内存的方式一致。这揭示深刻趋势:随着AI工作负载日益并发和动态,其资源管理挑战正与操作系统几十年来解决的经典问题趋同,解决方案也呈现惊人一致性。

第二部分:并行的力量——演进的批处理策略

本部分追溯批处理(batching)策略的演进历程,展示每一种新策略如何解决前任的低效问题,最终形成当前最适合LLM迭代式生成特性的先进技术。

2.1 早期探索:静态与动态批处理

静态批处理(Static Batching)

最基础的批处理形式:服务器等待固定数量的请求到达,将它们捆绑成一个批次处理。

  • 缺点:若请求到达速率不稳定,会导致极高延迟和低下GPU利用率——GPU会长时间空闲等待批次填满,在处理流水线中形成“GPU气泡”(GPU bubbles)。
动态批处理(Dynamic Batching / In-flight Batching)

为改善静态批处理的延迟问题而提出:服务器动态将收到的请求组合成批次,当批次大小达上限或等待超时(如100毫秒)后,立即开始处理。

  • 对LLM的局限性:这种模型对处理时间相近的请求(如图像分类)有效,但LLM生成的输出序列长度可变。动态批处理中,整个批次必须等待其中最长序列生成完毕后才能结束——短序列早早完成后,其占用的GPU资源会一直空闲,直到批次中“慢”请求完成。这是请求层面的队头阻塞(Head-of-Line Blocking),导致严重资源浪费。

2.2 突破性进展:持续批处理

概念转变:迭代级调度

真正的突破来自一次概念转变:将调度的粒度从请求(request)级别降低到单个词元生成步骤(iteration) 级别。这一思想最早在Orca论文中被系统性提出,称为“迭代级调度”(iteration-level scheduling)。

机制

系统不再等待整个批次的请求全部完成,相反,在每个时间步,为批次中所有正在处理的请求各生成一个词元。一旦某个请求完成生成(输出终止符EOS),其在批次中占用的位置会立即释放,由等待队列中的新请求填补。

解决队头阻塞

这种机制彻底解决动态批处理中的队头阻塞问题——只要请求队列中有等待处理的请求,GPU就能保持持续繁忙状态,最大化资源利用率。

在vLLM中的实现

这一策略是vLLM系统的核心基石之一,在vLLM中被称为“持续批处理”(Continuous Batching)。其高效实现严重依赖PagedAttention提供的灵活内存管理能力,使系统可动态在批次中添加/移除请求,无需重新分配大块连续内存。正是这两项技术的结合,使vLLM实现业界领先的吞吐量。

2.3 批处理策略对比表

批处理策略调度粒度GPU利用率吞吐量延迟影响队头阻塞风险
静态批处理请求批次低至中严重
动态批处理请求批次中至高较高中等(因序列长度不一)
持续批处理迭代/词元非常高最高低(摊销后)已消除

2.4 第二部分深层关联

持续批处理虽极大提升效率,但未完全解决LLM推理中的所有调度挑战——LLM推理过程包含两个截然不同的阶段:

  1. 预填充(prefill)阶段:计算密集型,用于并行处理输入提示;
  2. 解码(decode)阶段:内存带宽密集型,用于逐个生成输出词元。

一个简单的持续批处理调度器,若将需要大量计算的长prefill请求与许多轻量的decode请求混合在同一个批次中,仍会造成新的不平衡。

为应对这一“prefill-decode性能差异”带来的挑战,更先进的调度策略应运而生(如Sarathi论文提出的方法):

  • 分块预填充(chunked-prefills):将长的prefill操作分解为多个更小、计算量更可预测的块;
  • 解码最大化批处理(decode-maximal batching):智能构建混合批次——将一个prefill块(足以饱和计算单元)与尽可能多的decode步骤(计算开销小,可“搭便车”)组合在一起。

这代表批处理技术的下一个前沿:不仅是持续处理,更是对具有不同计算特性的异构任务进行智能组合,实现全局最优。

第三部分:指挥家的节拍棒——智能请求调度

本部分探讨更高级别的调度逻辑,它决定哪些请求应被执行、如何最高效地执行,这些技术超越简单排队机制,实现复杂的服务等级保障和计算复用。

3.1 超越先进先出(FIFO)

在真实生产环境中,用户需求和业务优先级各不相同,简单的先进先出(FIFO)队列远远不够——无法为紧急任务提供优先处理,也无法保证服务公平性。

3.2 请求优先级与抢占

机制

更先进的调度器可为进入系统的请求分配不同优先级。当高优先级请求到达,而系统正在处理由低优先级请求组成的满载批次时,调度器可执行抢占(preemption) 操作。

在vLLM中的实现

被抢占的低优先级请求的状态(即其KV Cache)会被保存,系统先处理高优先级请求;待高优先级请求完成后,被抢占的请求会被重新换回(swap back in)并恢复生成。这一功能的实现同样得益于PagedAttention——KV Cache的物理块是非连续的,保存和恢复请求状态高效,无需处理大块连续内存的拷贝。

影响

这种机制使服务系统能提供差异化的服务质量(QoS),为付费用户或关键业务满足严格的延迟服务等级协议(SLA)。

3.3 共享即是关怀:请求复用与前缀共享

复用的机会

在许多LLM应用中,大量请求会共享一个共同的前缀——例如,聊天机器人应用中的系统提示(system prompt)、少样本学习(few-shot learning)中的示例、检索增强生成(RAG)中的上下文文档。

朴素方法 vs. 优化方法
  • 朴素方法:对每个请求重复计算共享前缀的prefill过程,浪费大量计算资源;
  • 优化方法:识别共享前缀,仅计算一次其对应的KV Cache,后续所有使用相同前缀的请求可直接复用这个已缓存的状态,跳过大部分prefill计算。
关键技术
  • PagedAttention:实现高效前缀共享的基础技术——共享前缀的KV Cache物理块可同时映射到多个不同请求的逻辑地址空间,无需任何数据复制;
  • Hydragen - 硬件感知的注意力前缀计算:将这一优化推向极致。Hydragen指出,即使内存是共享的,标准注意力机制在计算时仍会为批次中的每个序列重复读取前缀的KV Cache。因此,Hydragen将注意力计算分解为前缀部分和后缀部分,将所有请求对前缀的注意力计算合并成一个单一的、大规模的矩阵-矩阵乘法操作,充分利用NVIDIA GPU上的Tensor Cores等高效硬件单元。这一转变将内存带宽受限的操作转换为计算受限的操作,在具有长共享前缀的工作负载下,相比vLLM实现高达32倍的吞吐量提升。

3.4 第三部分深层关联

前缀共享等技术正在模糊推理系统与应用逻辑之间的界限——服务系统不再是仅运行模型的“黑盒”,开始能感知接收到的提示的结构(如识别共享前缀)。这种“应用感知”能力,开启了传统通用方法无法企及的优化空间。未来的系统可能会更智能(如理解对话树或文档结构),执行更高级的缓存和计算复用。

从宏观视角看,系统中的各种“缓存”机制正在形成统一体系:

  • KV Cache是过去计算结果的缓存;
  • 前缀共享是输入提示状态的缓存;
  • 新兴技术(如Lookahead Decoding中的“n-gram池”)是对未来可能序列的缓存。

它们都是备忘录(memoization)思想的体现,旨在通过牺牲一定内存换取计算量的减少,统一原则是利用各种形式的“冗余”——过去计算的冗余(KV Cache)、未来预测的冗余(Lookahead)、输入提示的冗余(前缀共享)。一个最优的服务系统,可看作类似现代CPU的多级缓存层级结构。

结论

核心主题的综合

本文深入探讨了驱动现代大型语言模型(LLM)高性能服务的核心技术。分析表明,LLM服务性能的巨大飞跃并非源于单一“银弹”,而是来自一系列相互关联、协同工作的系统级创新的有机整合。其核心论点可归结为:当前最先进的LLM服务系统,是通过将操作系统级别的内存管理原则(以PagedAttention为代表)、精细到迭代层面的执行控制(以持续批处理为代表)以及智能化的、感知应用上下文的调度逻辑(以前缀共享和抢占为代表) 相结合而实现的。

一体化的系统视角

这些技术并非孤立的优化技巧,而是构成紧密耦合的整体:

  • PagedAttention的非连续内存管理是基石,不仅解决内存碎片化顽疾,更关键的是为持续批处理的动态请求管理和前缀共享的高效内存复用提供可能性;
  • 持续批处理最大化这一高效内存系统的利用率,确保GPU资源始终处于高负荷运转状态;
  • 更高级的调度策略(如优先级抢占和前缀共享)确保这个强大的推理引擎能被精确导向最重要的任务,并以最经济的方式完成计算。

未来展望

展望未来,LLM服务系统的演进将继续深化这些核心主题,预计将出现更多挑战和研究方向:

  • 为同时处理推理和微调等异构工作负载设计的协同调度器;
  • 能与推测解码(speculative decoding)等新兴解码算法深度结合的调度策略;
  • 更紧密集成的软硬件协同设计,将调度逻辑进一步下沉到硬件层面,实现前所未有的效率和性能。

LLM的“引擎室”正在变得越来越复杂和智能,而其发展的核心驱动力,将继续是这些对内存和调度的不懈优化。

http://www.dtcms.com/a/353737.html

相关文章:

  • 【解锁Photonics for AI:系统学习光学神经网络与超表面设计,成就下一代光芯片工程师】
  • python - js的引入方式、注释变量、数据类型、强制转换、自动类型转换、js运算符、分支结构、函数
  • Nginx单端口代理多个前后端服务的完整配置指南
  • 【雅思019】Canceling an appointment
  • 数据结构——算法设计的基本思想(穷举、递归、分治等)
  • 【自用】JavaSE--junit单元测试、反射、注解、动态代理
  • FreeRTOS 常见面试题与核心知识点详解
  • Redis数据持久化——RDB快照和Aof日志追加
  • 8.28 模拟
  • 从易用性的角度来看,哪个ETL平台比较好用?
  • MySQL-数据类型
  • Clerk 用户认证系统集成文档
  • 关于virtual camera
  • UE5 PCG 笔记(三) Height To Density 节点
  • UE5 查找组件
  • UE5多人MOBA+GAS 55、基于 Python 协调器与 EOS 的会话编排
  • 嵌入式Linux自学不走弯路!670+讲课程!系统学习路线:入门+应用+ARM+驱动+移植+项目 (STM32MP157开发板)
  • 快速入门PowerDesigner-Database
  • 软件开发整体介绍和Swagger介绍和使用步骤
  • Dubbo加标签方式
  • Ubuntu 22.04 插入光驱后磁盘满启动故障clean, ...files, ...blocks
  • Proxmox VE 中启用 CentOS 虚拟机的串口终端(xterm.js 控制台)
  • MAX系列FPGA型号对比及低功耗特性分析
  • 服务器类型与TCP并发服务器构建(SELECT)
  • 冬天的思念
  • 数模笔记day01(数据预处理、K-means聚类、遗传算法、概率密度分布)
  • SqlHelper类库的使用方法
  • 关于DTO、DO、BO、VO
  • Linux系统性能优化全攻略:从CPU到网络的全方位监控与诊断
  • [实战] 半导体工厂生产网络项目案例分享