论文地址-《Efficient Memory Management for Large Language Model Serving with PagedAttention》
代码地址- Github
摘要
- 问题背景
- 为LLM提供高吞吐量服务需要一次批处理足够多的请求。然而,现有的系统很难做到这一点,因为每个请求所需的KV缓存非常大,而且会动态增长和缩小。
- 如果管理效率低下,这些内存可能会因碎片和冗余重复而被大量浪费,从而限制了批量大小。
- 本文贡献
- 为了解决这个问题,作者提出了 PagedAttention,这是一种受操作系统中经典虚拟内存和分页技术启发的注意力算法
- 在此基础上,作者构建了一个 LLM 服务系统 vLLM,该系统可实现:
- KV 缓存内存的近乎零浪费;
- 在请求内和请求间灵活共享 KV 缓存,以进一步降低内存使用率
1 介绍
- LLM 的核心是一个自回归Transformer模型。该模型根据输入(prompt)和它迄今为止生成的输出token的先前序列,一次生成一个词(token)。这种顺序生成过程使工作负载受内存限制,无法充分利用 GPU 的计算能力,限制了服务吞吐量。
- 批量处理多个请求可以提高吞吐量。不过,要批量处理多个请求,就必须有效管理每个请求的内存空间。
- 例如,图 1(左)展示了在配备 40GB 内存的英伟达 A100 GPU 上处理 13B 参数 LLM 的内存分布情况。大约 65% 的内存分配给了模型权重,这些权重在服务过程中保持静态。近 30% 的内存用于存储请求的动态状态,对于 Transformers 来说,这些状态包括与注意力机制相关的键和值张量,通常称为 KV 缓存。其他的是一些激活。
- 由于模型权重是恒定的,而激活只占用 GPU 内存的一小部分,因此 KV 缓存的管理方式对于决定最大批次大小至关重要。

- 现有工作
- 在本文中,作者发现现有的 LLM 服务系统无法高效地管理 KV 缓存。这主要是因为它们将请求的 KV 缓存存储在连续的内存空间中,而大多数深度学习框架都要求将张量存储在连续的内存中。
- 然而,与传统深度学习工作负载中的张量不同,KV 缓存具有独特的特性:它会随着模型生成新token的时间动态增长和收缩,而且其生命周期和长度并不是事先已知的。这些特点使得现有系统的方法在两个方面明显效率低下:
- 现有系统存在内部和外部内存碎片问题。
- 为了在连续空间中存储请求的KV缓存,它们预先分配了一块具有请求最大长度的连续内存,这会导致严重的内部碎片,因为请求的实际长度可能比最大长度短很多。
- 此外,即使事先知道实际长度,预分配的效率仍然很低:由于整个分块在请求生命周期内被保留,其他较短的请求就无法使用当前未使用的分块。
- 此外,由于每个请求的预分配大小都可能不同,外部内存碎片也可能非常严重。事实上,图 2 中的分析结果表明,在现有系统中,只有 20.4% - 38.2% 的 KV 缓存内存用于存储实际的token状态。
- 现有系统无法利用内存共享的机会
- LLM 服务通常使用高级解码算法,如并行采样和beam搜索,可为每个请求生成多个输出。在这些情况下,请求由多个序列组成,这些序列可以部分共享其 KV 缓存。然而,现有系统无法实现内存共享,因为序列的 KV 缓存存储在不同的连续空间中。
- 现有系统存在内部和外部内存碎片问题。

- 为了解决上述限制,作者提出了分页注意力算法(PagedAttention),这种注意力算法的灵感来自操作系统(OS)对内存碎片和共享的解决方案:具有分页功能的虚拟内存。
- PagedAttention 将请求的 KV 缓存划分为多个区块,每个区块可包含固定数量token的注意键和值。在 PagedAttention 中,KV 缓存块不一定存储在连续的空间中。
- 作者可以像在操作系统的虚拟内存中一样,以更灵活的方式管理 KV 缓存:作者可以把块看作页,把token看作字节,把请求看作进程。 这种设计通过使用相对较小的区块并按需分配,缓解了内部碎片问题。
- 此外,由于所有块的大小相同,它还消除了外部碎片。
- 最后,它还能在块的粒度、与同一请求相关的不同序列甚至不同请求之间共享内存。
2 背景
略
3 LLM服务中的内存挑战
- 虽然细粒度批处理减少了计算的浪费,并能以更灵活的方式对请求进行批处理,但可以批处理在一起的请求数量仍然受到 GPU 内存容量的限制,特别是分配用于存储 KV 缓存的空间。换句话说,服务系统的吞吐量受内存限制。要克服这种内存限制,需要解决内存管理中的以下难题:
- 大型 KV 缓存。KV 缓存的大小会随着请求数量的增加而快速增长。
- 复杂的解码算法。LLM 服务提供了一系列解码算法供用户选择,每种算法对内存管理复杂度的影响各不相同。例如,当用户从单个输入prompt中请求多个随机样本时,prompt部分的 KV 缓存可以共享,以尽量减少内存使用。另一方面,自回归生成阶段的 KV 缓存应保持非共享状态,因为不同的样本结果及其对上下文和位置的依赖性各不相同。
- 未知输入和输出长度的调度。 向 LLM 服务发出的请求在输入和输出长度上具有可变性。这就要求内存管理系统能够适应各种prompt长度。此外,随着解码时请求输出长度的增加,其 KV 缓存所需的内存也会随之增加,可能会耗尽用于接收请求或正在生成的现有prompt的可用内存,系统需要做出调度决策。
3.1 现有系统的内存管理
- 由于当前深度学习框架中的大多数运算符都要求将张量存储在连续的内存中,因此之前的 LLM 服务系统也会将一个请求的 KV 缓存存储为跨不同位置的连续张量。由于 LLM 的输出长度不可预测,它们会根据请求的最大可能序列长度为请求静态分配一块内存,而不管请求的实际输入或最终输出长度。
- 下图展示了两个请求:最大序列长度为2048的请求A和最大序列长度为12的请求B。现有系统中的分块预分配方案有三个主要的内存浪费来源:为未来token预留、为潜在最大序列长度超额配置造成的内部碎片,以及来自内存分配器的外部碎片。

- 虽然有人提出了压缩 [54] 作为碎片化的潜在解决方案,但由于 KV 缓存容量巨大,在对性能敏感的 LLM 服务系统中执行压缩是不切实际的。即使进行了压缩,为每个请求预分配的块空间也会阻止现有内存管理系统中解码算法所特有的内存共享。
4 方法
- 在这项工作中,作者开发了一种新的注意力算法 PagedAttention,并构建了一个 LLM 服务引擎 vLLM,以应对第 3 节中概述的挑战。
- vLLM 采用集中式调度器来协调分布式 GPU 工作站的执行。
- KV 缓存管理器通过 PagedAttention 以分页方式有效管理 KV 缓存。
- 具体来说,KV 缓存管理器通过集中式调度程序发送的指令来管理 GPU Worker 上的物理 KV 缓存内存。
4.1 PagedAttention
- PagedAttention
- 与传统的注意力算法不同,PagedAttention 允许在非连续的内存空间中存储连续的键和值。
- 具体来说,PagedAttention将每个序列的KV缓存划分为KV块,每个块包含固定数量token的k和v,这个数量称为块大小。
- 使用 K_j = (k_{( j -1)B+1}, ..., k_{jB}) 和 V_j = (v_{( j -1)B+1}, ., v_{jB}) 表示key块和value块 。式 4 中的注意力计算可以转化为下面的块级计算
- 其中A_{ij}=(a_{i,(j-1)B+1},...,a_{i,jB}) 是第 j 个KV块的注意力得分行向量
- 在注意力计算过程中,PagedAttention 内核会分别识别和获取不同的 KV 块。
- 作者在图 5 中展示了一个 PagedAttention 的例子:键和值向量分布在三个块中,而这三个块在物理内存上并不连续。
- 每次,内核将查询token("forth")的查询向量 q_i 与块中的键向量 K_j(例如,块 0 的键向量为 "Four score and seven")相乘,计算出注意力分数 A_{ij} ,然后将 A_{ij} 与块中的值向量 V_j 相乘,得出最终的注意力输出 o_i 。

4.2 KV缓存管理
- vLLM内存管理器背后的关键理念类似于操作系统中的虚拟内存。操作系统将内存划分为固定大小的页面,并将用户程序的逻辑页面映射到物理页面。连续的逻辑页可以对应非连续的物理内存页,允许用户程序像访问连续内存一样访问内存。
- 此外,物理内存空间无需提前完全预留,操作系统可根据需要动态分配物理页。
- vLLM 利用虚拟内存背后的理念来管理 LLM 服务中的 KV 缓存。通过 PagedAttention,作者将 KV 缓存组织为固定大小的 KV 块,就像虚拟内存中的页面一样。
- 请求的 KV 缓存表示为一系列逻辑 KV 块,随着新token及其 KV 缓存的生成从左到右依次填充。
- 最后一个 KV 块未填满的位置将保留给后代。在 GPU 工作站上,块引擎会分配一块连续的 GPU DRAM 并将其划分为物理 KV 块。
- KV 块管理器还维护块表--每个请求的逻辑和物理 KV 块之间的映射。每个块表条目都记录了逻辑块对应的物理块以及已填充位置的数量。
- 将逻辑 KV 块和物理 KV 块分开,可以让 vLLM 动态增加 KV 缓存内存,而无需提前为所有位置预留内存,从而消除了现有系统中的大部分内存浪费现象
4.3 使用 PagedAttention 和 vLLM 解码
-
接下来,作者将通过图6所示的示例,演示vLLM如何在单个输入序列的解码过程中执行PagedAttention并管理内存:
-
与操作系统的虚拟内存一样,vLLM 最初并不需要为可能生成的最大序列长度预留内存。相反,它只保留必要的 KV 块,以容纳在prompt计算过程中生成的 KV 缓存。
- 在本例中,prompt有 7 个token,因此 vLLM 会将前 2 个逻辑 KV 块(0 和 1)映射到 2 个物理 KV 块(分别为 7 和 1)。
- 在预填充步骤中,vLLM 采用传统的自注意算法生成prompt符和第一个输出token的 KV 缓存。然后,vLLM 会将前 4 个token的 KV 缓存存储在逻辑块 0 中,将后 3 个token存储在逻辑块 1 中。剩余的槽位将保留给后续的自回归生成阶段。
-
在第一个自回归解码步骤中,vLLM 在物理块 7 和物理块 1 上使用分页保留算法生成新token。 由于最后一个逻辑块中仍有一个空位,新生成的 KV 缓存将被存储在该逻辑块中,并更新块表的 #filled 记录。
-
在第二个解码步骤中,由于最后一个逻辑块已满,vLLM 将新生成的 KV 缓存存储到一个新的逻辑块中;vLLM 为其分配一个新的物理块(物理块 3),并将此映射存储到块表中。
-

- 总体而言,对于每次解码迭代,vLLM 首先会选择一组候选序列进行批处理(详见第 4.5 节),并为新需要的逻辑块分配物理块。然后,vLLM 将当前迭代的所有输入token(即prompt阶段请求的所有token和生成阶段请求的最新token)连接起来,作为一个序列并将其输入 LLM。
- 在LLM的计算过程中,vLLM使用PagedAttention内核访问以前以逻辑KV块形式存储的KV缓存,并将新生成的KV缓存保存到物理KV块中。在一个KV块中存储多个token(块大小 > 1)可使 PagedAttention 内核在更多位置上并行处理 KV 缓存,从而提高硬件利用率并减少延迟。
- 在LLM的计算过程中,vLLM使用PagedAttention内核访问以前以逻辑KV块形式存储的KV缓存,并将新生成的KV缓存保存到物理KV块中。在一个KV块中存储多个token(块大小 > 1)可使 PagedAttention 内核在更多位置上并行处理 KV 缓存,从而提高硬件利用率并减少延迟。
4.4 应用于其他解码场景
- 在许多成功的 LLM 应用中,LLM 服务必须提供更复杂的解码场景,这些场景会表现出复杂的访问模式和更多的内存共享机会。在本节中,作者将展示 vLLM 对它们的普遍适用性。
- Parallel sampling并行采样
- 在并行采样中,一个请求包括多个采样,共享同一个输入prompt,这样就可以共享prompt的 KV 缓存。通过 PagedAttention 和分页内存管理,vLLM 可以轻松实现这种共享并节省内存。
- 图 8 显示了两个输出的并行解码示例。
- 由于两个输出共享相同的prompt,因此作者在prompt阶段只为一个prompt状态副本保留空间;两个序列的prompt逻辑块被映射到相同的物理块:两个序列的逻辑块 0 和 1 分别映射到物理块 7 和 1。由于一个物理块可以映射到多个逻辑块,作者为每个物理块引入了一个引用计数。在这种情况下,物理块 7 和 1 的引用计数都是 2。
- 在生成阶段,这两个输出采样不同的输出token,需要分别存储到 KV 缓存中。vLLM 在块粒度上为需要通过多个序列进行修改的物理块实现了一种 “copy-on-write"机制,这与操作系统虚拟内存中的 "copy-on-write "技术(例如,在分叉进程时)类似。

- 总之,vLLM 可以在多个输出样本之间共享用于存储prompt的 KV 缓存的大部分空间,但最后一个逻辑块除外,该逻辑块由copy-on-write机制管理。
- Beam search束搜索
- 在解码过程中,波束搜索通过考虑所有可能的token来扩展波束中的每个候选序列,使用 LLM 计算它们各自的概率,并从 k - |V | 个候选序列中保留最有可能的前 k 个序列,其中 |V| 是词汇量。
- 与并行解码不同,波束搜索不仅能共享初始prompt块,还能共享不同候选块中的其他块,而且共享模式会随着解码进程的推进而动态变化,这与操作系统中由复合分叉创建的进程树类似。
- 图 9 显示了 vLLM 如何在 k = 4 的波束搜索示例中管理 KV 块。
- 在虚线所示的迭代之前,每个候选序列都使用了 4 个完整的逻辑块。
- 所有Beam候选人共享第一个区块 0(即prompt)。候选人 3 从第二个区块开始偏离其他区块。候选者 0-2 共享前 3 个区块,并在第 4 个区块出现偏离。在随后的迭代中,前 4 位可能的候选者都来自候选者 1 和 2。由于最初的候选块 0 和 3 不再是最热门的候选块,因此它们的逻辑块被释放,相应物理块的引用计数被减少。
- 然后,vLLM 分配新的物理块(块 9-12)来存储来自新候选者的新 KV 缓存。现在,所有候选者共享第 0、1、3 个区块;候选者 0 和 1 共享第 6 个区块,候选者 2 和 3 进一步共享第 7 个区块。
- 共享前缀
- 通常,LLM 用户提供任务的(长)描述,包括指令和示例输入和输出,也称为系统提示符 [36]。描述与实际任务输入连接在一起,以形成请求的提示。例如图 10 的例子
- 此外,可以通过提示工程进一步调整共享前缀,以提高下游任务的准确性。
- 对于这种类型的应用程序,许多用户提示共享一个前缀,因此 LLM 服务提供商可以提前存储前缀的 KV 缓存,以减少在前缀上花费的冗余计算。

- 在 vLLM 中,这可以通过 LLM 服务提供商为一组预定义的共享前缀保留一组物理块来方便地实现,就像作系统处理跨进程共享库的方式一样。具有共享前缀的用户输入提示可以简单地将其逻辑块映射到缓存的物理块。prompt 阶段计算只需要在用户的任务输入上执行。
- 混合解码方法
- vLLM 有助于同时处理具有不同解码首选项的请求,这是现有系统无法高效完成的。
- 这是因为 vLLM 通过一个将逻辑块转换为物理块的公共映射层隐藏了不同序列之间的复杂内存共享。LLM 及其执行内核只能看到每个序列的物理区块 ID 列表,不需要处理跨序列的共享模式。与现有系统相比,这种方法拓宽了具有不同采样要求的请求的批处理机会,最终提高了系统的整体吞吐量。
- 这是因为 vLLM 通过一个将逻辑块转换为物理块的公共映射层隐藏了不同序列之间的复杂内存共享。LLM 及其执行内核只能看到每个序列的物理区块 ID 列表,不需要处理跨序列的共享模式。与现有系统相比,这种方法拓宽了具有不同采样要求的请求的批处理机会,最终提高了系统的整体吞吐量。
4.5 调度和抢占
-
当请求流量超过系统容量时,vLLM 必须优先处理一部分请求。在 vLLM 中,作者对所有请求都采用了先到先服务(FCFS)调度策略,以确保公平性并防止饥饿。 当 vLLM 需要抢占请求时,它会确保最早到达的请求先得到服务,最晚到达的请求先被抢占。
-
LLM 服务面临着一个独特的挑战:LLM 的输入prompt在长度上可能会有很大差异,而由此产生的输出长度并不是先验已知的 ,它取决于输入prompt和模型。随着请求数量及其输出的增长,vLLM 可能会耗尽 GPU 的物理块来存储新生成的 KV 缓存。
- 在这个过程中,vLLM 需要回答两个经典问题:(1) 应驱逐哪些区块?(2) 如果再次需要,如何恢复被驱逐的区块?
- 对于第一个问题
- 作者知道一个序列中的所有区块都会一起被访问,因此作者采用了全有或全无的驱逐策略,即要么驱逐序列中的所有区块,要么一个都不驱逐。
- 此外,一个请求中的多个序列(例如,一个波束搜索请求中的波束候选序列)将作为一个序列组进行联合调度。 由于这些序列之间可能共享内存,因此一个序列组内的序列总是一起抢占或重新调度。
- 对于第二个问题
- 作者采用了交换Swapping和重计算Recomputation两种技术
-
交换
- 在作者的案例中,作者将被驱逐的块复制到 CPU 内存中。如图 4 所示,除了 GPU 块分配器,vLLM 还包括一个 CPU 块分配器,用于管理交换到 CPU RAM 的物理块。
- 一旦抢占一个序列并驱逐其区块,vLLM 就会停止接受新请求,直到所有被抢占的序列都完成为止。一旦请求完成,其数据块就会从内存中释放出来,而被抢占序列的数据块则会被带回来继续处理该序列。
-
重计算
- 在这种情况下,作者只需在重新安排抢占序列时重新计算 KV 缓存。需要注意的是,重新计算的延迟可能比原始延迟低很多,因为解码时生成的token可以与原始用户prompt串联成一个新的prompt--其所有位置的 KV 缓存可以在一次prompt阶段迭代中生成。
- 在这种情况下,作者只需在重新安排抢占序列时重新计算 KV 缓存。需要注意的是,重新计算的延迟可能比原始延迟低很多,因为解码时生成的token可以与原始用户prompt串联成一个新的prompt--其所有位置的 KV 缓存可以在一次prompt阶段迭代中生成。
4.6 分布式执行
-
vLLM 通过支持 Transformers 上广泛使用的 Megatron-LM 风格张量模型并行策略[47],在分布式设置中非常有效。该策略采用 SPMD(单程序多数据)执行计划,其中线性层被划分来执行分块矩阵乘法,而GPU则通过all-reduce运算不断同步中间结果。
- 具体来说,注意力算子在注意力头维度上进行拆分,每个 SPMD 进程负责多头注意力中的一个注意力头子集。
-
作者注意到,即使在模型并行执行的情况下,每个模型分片仍会处理相同的输入token集,因此需要在相同的位置使用 KV 缓存。
- 因此,如图 4 所示,vLLM 在集中式调度器中设置了一个 KV 缓存管理器。不同的 GPU 工作站共享管理器以及逻辑块到物理块的映射。这种通用映射允许 GPU 工作站使用调度器为每个输入请求提供的物理块来执行模型。
- 虽然每个 GPU 工作站都有相同的物理块 ID,但工作站只存储其相应注意头的 KV 缓存的一部分。

- 在每个步骤中,调度程序首先为批次中的每个请求准备输入token ID 的消息,以及每个请求的块表。
- 接下来,调度程序会向 GPU 工作站广播该控制信息。
- 然后,GPU 工作站开始执行输入token ID 的模型。在注意层,GPU 工作站根据控制信息中的块表读取 KV 缓存。
- 在执行过程中,GPU 工作站利用allreduce通信原语同步中间结果,而无需调度程序的协调。
- 最后,GPU 工作站会将此次迭代的采样token发送回调度器。总之,GPU 工作站无需同步内存管理,因为它们只需在每次解码迭代开始时接收所有内存管理信息以及步骤输入。
5 实施
5.1 内核级优化
- 由于 PagedAttention 引入了现有系统无法有效支持的内存访问模式,作者开发了几种 GPU 内核对其进行优化。
- Fused reshape and block write
- 在每个Transformer层中,新的 KV 缓存被分割成块,重塑为针对块读取优化的内存布局,然后保存在块表指定的位置。为尽量减少内核启动开销,作者将它们融合到一个内核中。
- Fusing block read and attention
- 作者调整了 FasterTransformer [31] 中的注意力内核,以便根据块表读取 KV 缓存,并即时执行注意力操作。为确保对内存的集中访问,作者为读取每个块分配了一个 GPU warp。此外,作者还在请求批次中添加了对可变序列长度的支持。
- Fused block copy
- 由写入时复制机制发出的块复制操作可能会在不连续的块上运行。如果作者使用 cudaMemcpyAsync 应用程序接口,这可能会导致大量小数据移动的调用。为了减少开销,作者实施了一个内核,将不同区块的复制操作批量合并到一个内核启动中。
- 由写入时复制机制发出的块复制操作可能会在不连续的块上运行。如果作者使用 cudaMemcpyAsync 应用程序接口,这可能会导致大量小数据移动的调用。为了减少开销,作者实施了一个内核,将不同区块的复制操作批量合并到一个内核启动中。
- Fused reshape and block write
5.2 支持多种编程算法
- vLLM 使用三种关键方法实现各种解码算法:fork、append 和 free。
- fork 方法从现有序列创建新序列。append 方法将新token附加到序列中。最后,free 方法删除序列。
- 例如,在并行采样中,vLLM 使用 fork 方法从单个输入序列创建多个输出序列。然后,它在每次迭代中使用 append 向这些序列添加新token,并使用 free 删除满足停止条件的序列。相同的策略也适用于 vLLM 的Beam搜索和前缀共享。作者相信,结合这些方法也可以支持未来的解码算法。
6 评估
6.1 实验设置
- 模型和服务器配置:OPT-13B、OPT-66B OPT-175B LLaMA-13B,在 Google Cloud Platform 上使用带有 NVIDIA A100 GPU 的 A2 实例
- 负载:基于 ShareGPT [51] 和 Alpaca [50] 数据集合成工作负载,其中包含真实 LLM 服务的输入和输出文本。由于这些数据集不包含时间戳,因此作者使用具有不同请求速率的泊松分布来生成请求到达时间。
- 基线:FasterTransformer&Orca
- 关键指标:吞吐量
6.2 基本采样
- 作者通过基本抽样(每个请求一个样本)在三个模型和两个数据集上评估 vLLM 的性能。


6.3 并行采样和束搜索
- 作者使用两种流行的采样方法评估了 PagedAttention 中内存共享的有效性:并行采样和束搜索。


6.4 共享前缀
- 作者探讨了 vLLM 在不同输入prompt之间共享前缀的情况下的有效性。
- 对于该模型,作者使用了多语言的LLaMA-13B [52]。对于工作负载,作者使用 WMT16 [4] 英语到德语翻译数据集,并合成两个前缀,其中包括一条指令和一些翻译示例。

6.5 Chatbot
- 作者使用 ShareGPT 数据集合成聊天历史和用户查询。由于 OPT-13B 模型的上下文长度有限,作者将prompt剪切到最后 1024 个token,并让模型最多生成 1024 个token。
- 与三个 Orca 基线相比,vLLM 可以维持高 2× 的请求率。由于 ShareGPT 数据集包含许多长对话,因此大多数请求的输入prompt都有 1024 个token。

7 消融研究
7.1 内核 Microbenchmark
- 在 PagedAttention 中,动态块映射(dynamic block mapping)会影响涉及存储的 KV 缓存的 GPU 操作性能,即块的读/写操作和注意力计算。与现有系统相比,作者的 GPU 核心在访问块表、执行额外分支和处理可变序列长度方面增加了额外的开销。
- 如图18a所示,这导致与高度优化的 FasterTransformer 实现相比,注意力核的延迟增加了 20% 到 26%。作者认为这个开销很小,因为它只影响注意力操作,而不影响模型中的其他操作,如 Linear。

7.2 块大小的影响
- 块大小的选择可能会对 vLLM 的性能产生重大影响。
- 在图 18b 中,作者使用 ShareGPT 和 Alpaca 跟踪在固定请求速率下进行基本采样,评估了不同区块大小的 vLLM 的性能。在 ShareGPT 跟踪中,从 16 到 128 的块大小可实现最佳性能。在 Alpaca 跟踪中,虽然块大小 16 和 32 运行良好,但较大的块大小会显著降低性能,因为序列变得比块大小短。在实践中,作者发现块大小 16 足够大,可以有效地利用 GPU,并且足够小,可以避免在大多数工作负载中出现严重的内部碎片。因此,vLLM 将其默认块大小设置为 16。
7.3 比较 Recomputation 和 Swapping
- vLLM 支持重新计算和交换作为其恢复机制。为了了解这两种方法之间的权衡,作者评估了它们的端到端性能,并对它们的开销进行了微基准测试。
- 如图 19 所示
- 作者的结果表明,对于较小的区块大小,交换会产生过多的开销。这是因为小块大小通常会导致 CPU 和 GPU 之间进行大量小数据传输,从而限制了有效的 PCIe 带宽。相比之下,重新计算的开销在不同区块大小上保持不变,因为重新计算不使用 KV 区块。因此,当区块大小较小时,重新计算效率更高,而当区块大小较大时,交换效率更高,尽管重新计算开销永远不会高于交换延迟的 20%。对于 16 到 64 的中等块大小,这两种方法表现出相当的端到端性能。

8 讨论
- 将虚拟内存和分页技术应用于其他 GPU 工作负载
- 应用虚拟内存和分页方面特定于 LLM 的优化
9 相关工作
- 通用模型服务系统
- transformers专用服务系统
- 与 Orca 的比较
- 内存优化
10 总结
本文提出了 PagedAttention,一种新的注意力算法,允许将注意力键和值存储在非连续的分页内存中,并提出了 vLLM,这是一种高吞吐量的 LLM 服务系统,由 PagedAttention 实现高效的内存管理。受作系统的启发,作者演示了如何调整已建立的技术,例如虚拟内存和写入时复制,以有效地管理 KV 缓存并处理 LLM 服务中的各种解码算法。作者的实验表明,与最先进的系统相比,vLLM 的吞吐量提高了 2-4×。