注意力变体与内存效率

注意力变体与内存效率

💡 原文英文,约2800词,阅读约需11分钟。
📝

内容提要

推理时注意力架构由训练好的检查点固定,不能随意替换。多头注意力为每个查询头存储键值,内存占用最大;分组查询注意力和多查询注意力通过共享键值头显著缩小KV缓存;滑动窗口注意力只保留最近令牌,使局部层缓存有界;多头潜在注意力则压缩键值表示。推理引擎只能调整缓存布局、精度和内核,无法改变逻辑注意力行为。因此应根据检查点估算每令牌缓存字节,进而推算服务容量。

🔎

延伸解读

检查点决定注意力架构,推理时不可替换

文章强调,推理引擎无法改变模型训练时确定的注意力变体。MHA、GQA、MQA、滑动窗口和MLA都是检查点的一部分,替换它们会改变模型行为,甚至需要重新训练才能恢复质量。因此,部署前应通过配置对象检查层数、KV头数、头维度、滑动窗口等字段,并注意某些字段可能被其他开关禁用。

KV缓存是持久内存,决定最大并发

注意力内存分为持久KV缓存和临时工作区。KV缓存随活跃请求数和缓存令牌数增长,通常决定最大并发;临时内存只在单次前向传播中使用。文章给出每令牌缓存字节的估算公式,并指出对于等长请求,缓存总量与批大小和序列长度成正比。实际部署时需从加速器内存中扣除权重、工作区等开销,再推算容量。

不同变体以不同方式降低缓存成本

MHA为每个查询头存储键值,缓存最大;GQA和MQA通过共享KV头减少缓存,例如32个查询头配8个KV头可将KV缓存和投影参数减少为四分之一。滑动窗口只保留最近W个令牌,使局部层缓存有界,但混合模型中的全局层仍随上下文增长。MLA压缩KV表示,但需要专用内核避免展开中间张量,且不能简单套用MHA公式估算。

运行时优化不改变逻辑注意力行为

FlashAttention、分页注意力、缓存量化、卸载和内核融合等运行时技术,改变的是内存使用方式或物理布局,而非逻辑注意力行为。例如,FlashAttention减少临时注意力内存和内存流量,但不改变持久KV缓存或KV头数;分页注意力改善分配和共享,但不减少逻辑缓存值。因此,选择检查点时应记录每令牌KV字节、层模式、最大并发和内核支持情况。

❓

Q&A

为什么说推理时不能随意替换模型的注意力变体?

因为检查点已经固定了注意力架构,包括查询头与键值头的数量、局部注意力模式、潜在维度等。替换变体(如将MHA改为GQA)会改变模型行为,可能需要额外训练才能恢复质量;将全注意力改为滑动窗口会丢弃模型期望的上下文。推理引擎只能调整缓存布局、精度和内核,无法改变逻辑注意力行为。

多头注意力(MHA)、分组查询注意力(GQA)和多查询注意力(MQA)在KV缓存上有什么区别?

MHA为每个查询头存储独立的键值头,KV缓存最大;GQA让多个查询头共享一个键值头,减少KV缓存和键值投影参数;MQA让所有查询头共享一个键值头,KV缓存最小。例如32个查询头时,MHA有32个键值头,GQA有8个(减少4倍),MQA有1个(减少32倍)。

滑动窗口注意力如何限制KV缓存大小?

滑动窗口注意力只保留最近W个令牌的键值,超出窗口的令牌不再需要缓存。因此每层的缓存可以实现为容量为W的环形缓冲区,即使总对话更长,该层的内存也有界。但代价是丢失对远处令牌的直接访问,模型必须为此训练或适配。混合模型交替使用局部和全局层,全局层仍保留完整上下文,因此总缓存不会完全有界,但增长速率降低。

多头潜在注意力(MLA)如何减少KV缓存?

MLA将键值表示压缩为更小的潜在向量,而不是为每个头存储完整的键和值。解码时从压缩状态推导出头特定信息,从而减少缓存读取量,但增加投影计算。这种权衡在解码受内存带宽限制时有利。MLA不是通用压缩包装器,其投影和位置处理是训练架构的一部分,需要专用内核来避免展开大型中间张量。

推理运行时可以改变注意力的哪些方面?

推理运行时可以改变物理内存管理和执行方式,例如使用FlashAttention减少临时内存和内存流量、使用分页注意力改善分配和共享、改变缓存精度、卸载缓存、共享前缀、内核融合等。但这些技术不改变逻辑注意力行为(如哪些令牌可以关注哪些令牌、键值头数量、缓存表示),后者由检查点决定。

如何从KV缓存大小估算模型的 serving 容量?

首先计算每个令牌的KV缓存字节数:2 × 层数 × 键值头数 × 头维度 × 每个元素字节数。然后乘以上下文长度得到每个请求的缓存字节数。最后用缓存预算(加速器内存减去模型权重、工作区、通信缓冲和安全余量)除以每个请求的字节数,得到等长请求的最大数量。实际容量受块舍入、碎片、分配器元数据和不均匀请求长度影响,因此结果是理论上限。

🏷️

标签

➡️

继续阅读