vLLM并发加速
论文:Efficient Memory Management for Large Language Model Serving with PagedAttention
链接:https://dl.acm.org/doi/pdf/10.1145/3600006.3613165
随着LLM模型能力的逐步提升,相关的业务应用也在井喷式增长。作为一个商业服务,必须承受高用户量的并发,vLLM的出现很好解决了这个需求。
LLM服务吞吐量的挑战
大模型服务有以下几个特点:
- 高吞吐量的服务需要批量处理足够多的请求。
- kv缓存巨大,并且会动态增长和收缩。
KV cache
LLM权重的特点如下,大部分参数在服务期间保持静态,近30%的内存用于存储请求的动态状态,这些状态在模型结构中属于注意力机制中的key和value组成的张量组,通常被称为kv cache。
在标准的自注意力计算中,对于序列中的每个元素,模型都需要计算其与序列中所有其他元素的注意力权重,并根据这些权重聚合信息。这个过程涉及大量的计算,尤其是当序列很长时,计算量会呈平方级增长。KV缓存是一种优化方法,它通过缓存已经计算过的键(Key, K)和值(Value, V)对,来减少重复计算。具体来说,当模型处理序列中的下一个元素时,它只需要计算新的查询(Query, Q)与之前缓存的键值对之间的注意力权重,而不需要重新计算整个序列的键值对。这样可以显著减少计算量,提高处理长序列时的效率。
LLM的原理
LLM的生成原理为根据上文生成下文,学习大量数据的生成规律。在生成每一个token时,需要不断对前文(先前的序列)做注意力。对于每个请求,都会重复这个昂贵的过程,直到模型输出终止令牌。这种顺序生成过程使工作负载被内存绑定,没有充分利用GPU的计算能力,并限制了服务吞吐量。
现有深度学习框架的限制
大多数深度学习框架要求张量存储在连续的内存中。而KV 缓存随时间动态增长的特性使其在两个方面效率低下:
- 预先分配了具有请求最大长度的连续内存块(例如2048个令牌)。这可能会导致严重的内部碎片化,因为请求的实际长度可能比其最大长度短得多。此外,即使实际长度是先验的,预分配仍然效率低下:由于整个块在请求的生命周期内被保留,其他较短的请求无法利用当前未使用的块的任何部分。
- 现有的LLM使用的均为并行采样等高级算法,请求通常由多个序列组成,而连续存储决定了其不能共享权重。
LLM的批处理挑战
虽然批次足够大的时候,可以提高LLM的计算利用率(请求共享模型权重,能摊销)。 但是LLM的批次请求受两个点限制:
- 请求长度不一会产生等待导致的排队延迟,
- 对长度不一的序列使用填充策略平衡长度会造成很大的内存和计算浪费。
vLLM的作者沿用了先前提出的蜂窝批处理
和迭代级调度
。这些技术在迭代级别工作。每次迭代后,已完成的请求将从批处理中删除,并添加新的请求。因此,可以在等待单次迭代后处理新请求,而不是等待整个批次完成。此外,使用特殊的GPU内核,这些技术无需填充输入和输出。通过减少排队延迟和填充效率低下,细粒度的配料机制显著增加了LLM服务的吞吐量。
LLM中的内存挑战
从GPU制造的成本来说,计算能力的增长时很快的,但GPU的内存的增长却很缓慢。对于大模型的巨大参数量,内存已经成为主要的瓶颈。
-
缓存共享的挑战: 大模型的输入输出缓存主要分为两个部分,输入请求的提示词KV缓存(在作者的实验中占用12%的内存),它时可以共享的,可以减少内存使用量。另一部分是自动回归模型阶段生成的KV缓存,由于不同的样本结果对其上下文和位置的依赖,该阶段的KV缓存应保持不共享的状态。KV缓存共享的程度取决于特定的解码算法。
-
输入输出内存的调度: 调度未知的输入和输出长度。对LLM服务的请求在输入和输出长度上表现出可变性。这需要内存管理系统来适应广泛的提示长度。此外,随着请求的输出长度在解码时增加,其KV缓存所需的内存也会扩展,并可能耗尽传入请求的可用内存或现有提示的持续生成。系统需要做出调度决策,例如从GPU内存中删除或交换一些请求的KV缓存。
现有系统中的内存管理
现有深度学习框架(Pytorch等)的特点:
- 张量存储在连续内存中,一个请求的KV缓存被存储为跨越不同位置的连续张量。
- LLM的输出长度不可预测,无论请求的实际输入或最终输出长度如何,他们根据请求的最大可能序列长度静态地为请求分配一块内存。
vLLM框架
作者开发了一个LLM的服务引擎vLLM应对一般深度学习框架推理LLM出现的挑战。vLLM采用集中式调度器来协调分布式GPU线程执行,KV缓存管理器通过PagedAttention启用,以分页方式有效管理KV缓存。
PageAttention
PagedAttention允许在非连续的内存空间中存储连续的键和值。具体来说,PagedAttention将每个序列的KV缓存划分为KV块,每个块包含固定数量令牌的密钥和值向量,将其表示为KV块大小(B)。
如下图:键(k)和值(v)向量分布在三个块上,这三个块在物理内存上不毗连。这中管理策略使得内存碎片较小,可以分配更大的需要连续内存的大对象,防止出现总内存足够,而因为内存碎片无法分配大的连续内存的情况。
总之,PagedAttention算法允许KV块存储在非连续的物理内存中,从而在vLLM中实现更灵活的分页内存管理。
KV缓存管理器
最后修改于 2024-04-23
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。