KV Cache的显存瓶颈与优化:从GQA到MQA的演进逻辑
KV Cache的显存瓶颈与优化从GQA到MQA的演进逻辑一、自回归生成中99%的显存被KV Cache占据在大模型的推理阶段自回归生成过程逐个token生成有一个显著的不对称性计算量随生成长度线性增长每生成一个新token所有之前的token都要参与注意力计算但KV Cache的显存占用也随长度线性增长——而且这个增长的系数非常惊人。对于LLaMA-70B模型使用FP16精度batch_size1生成长度2048时模型权重约140GBKV Cache约2.6GB每层约33MB × 80层看起来KV Cache远小于权重但如果batch_size32生成长度8192KV Cache约332GB——远超模型权重这就是长序列推理的显存墙显存不是被模型权重占满的是被KV Cache吃光的。flowchart TB A[标准 MHA: 每个头独立的 KV] -- B[KV Cache 2 × B × H × L × D] B -- C{KV Cache 优化方向} C -- D[GQA: 分组查询注意力] D -- D1[K/V 头数 查询头数 / G] D -- D2[KV Cache 缩小 G 倍] D -- D3[精度损失: 1%] C -- E[MQA: 多查询注意力] E -- E1[所有查询头共享 1 组 K/V] E -- E2[KV Cache 缩小 H 倍] E -- E3[精度损失: 1-3%] C -- F[MLA: 多头潜在注意力 DeepSeek] F -- F1[KV 压缩到低秩潜在空间] F -- F2[KV Cache 缩小 5-10x] F -- F3[需要从预训练阶段引入] style D fill:#e8f5e9 style E fill:#fff3e0 style F fill:#e1f5fe二、从Multi-Head到Multi-Query的权衡分析标准 Multi-Head Attention (MHA) 中每个注意力头有独立的 Q、K、V 投影。这意味着对于 H 个头KV Cache 需要存储 H 组 K 和 V。Multi-Query Attention (MQA) 的激进方案是所有头共享同一组 K 和 V只有 Q 保持多头。这样 KV Cache 缩小了 H 倍。Grouped-Query Attention (GQA) 是 MHA 和 MQA 之间的折中将 H 个查询头分为 G 组每组共享一组 K 和 V。当 G1 时退化为 MQA当 GH 时即为 MHA。关键问题是这个折中在精度和效率上究竟如何import torch import torch.nn as nn import torch.nn.functional as F import math from typing import Optional, Tuple class GroupedQueryAttention(nn.Module): GQA: 分组查询注意力的实现。 分组策略选择 - G1 (MQA): 极致节省显存适用于推理加速 - GH (MHA): 无节省适用于训练 - GH/8 (典型GQA): LLaMA-2 70B 使用此配置 为什么不是所有层都用相同的 G 实验表明底层靠近输入对 KV 冗余更敏感 高层可以使用更激进的 G 值更小的 G。 def __init__( self, hidden_size: int, num_heads: int, num_kv_heads: int, # K/V 头数 num_heads dropout: float 0.0 ): super().__init__() self.hidden_size hidden_size self.num_heads num_heads self.num_kv_heads num_kv_heads self.head_dim hidden_size // num_heads # GQA 的头分组比例 self.num_queries_per_kv num_heads // num_kv_heads # Q 投影每个查询头独立 self.q_proj nn.Linear(hidden_size, num_heads * self.head_dim, biasFalse) # K, V 投影仅在 num_kv_heads 个头上 self.k_proj nn.Linear(hidden_size, num_kv_heads * self.head_dim, biasFalse) self.v_proj nn.Linear(hidden_size, num_kv_heads * self.head_dim, biasFalse) self.o_proj nn.Linear(num_heads * self.head_dim, hidden_size, biasFalse) self.dropout nn.Dropout(dropout) def forward( self, hidden_states: torch.Tensor, attention_mask: Optional[torch.Tensor] None, past_key_value: Optional[Tuple[torch.Tensor]] None, ) - Tuple[torch.Tensor, Optional[Tuple[torch.Tensor]]]: bsz, seq_len, _ hidden_states.shape # 投影 q self.q_proj(hidden_states) k self.k_proj(hidden_states) v self.v_proj(hidden_states) # 重塑Q 为 [bsz, num_heads, seq_len, head_dim] q q.view(bsz, seq_len, self.num_heads, self.head_dim).transpose(1, 2) # K, V 为 [bsz, num_kv_heads, seq_len, head_dim] k k.view(bsz, seq_len, self.num_kv_heads, self.head_dim).transpose(1, 2) v v.view(bsz, seq_len, self.num_kv_heads, self.head_dim).transpose(1, 2) # 拼接历史 KV Cache if past_key_value is not None: k torch.cat([past_key_value[0], k], dim2) v torch.cat([past_key_value[1], v], dim2) # 保存当前 KV 用于下一步的 Cache current_key_value (k, v) # GQA 关键操作将 K/V 从 num_kv_heads 扩展到 num_heads # 通过在相邻组之间重复 K/V 头实现 k_expanded k.unsqueeze(1).expand( bsz, self.num_queries_per_kv, self.num_kv_heads, k.shape[2], self.head_dim ).reshape(bsz, self.num_heads, k.shape[2], self.head_dim) v_expanded v.unsqueeze(1).expand( bsz, self.num_queries_per_kv, self.num_kv_heads, v.shape[2], self.head_dim ).reshape(bsz, self.num_heads, v.shape[2], self.head_dim) # 标准缩放点积注意力 scale 1.0 / math.sqrt(self.head_dim) attn_weights torch.matmul(q, k_expanded.transpose(-2, -1)) * scale if attention_mask is not None: attn_weights attn_weights attention_mask attn_weights F.softmax(attn_weights, dim-1) attn_weights self.dropout(attn_weights) attn_output torch.matmul(attn_weights, v_expanded) # 重塑输出 attn_output attn_output.transpose(1, 2).reshape(bsz, seq_len, -1) attn_output self.o_proj(attn_output) return attn_output, current_key_value def estimate_kv_cache_size(self, batch_size: int, seq_length: int) - int: 估算给定配置下的 KV Cache 大小字节。 bytes_per_element 2 # FP16 kv_elements ( 2 # K V * batch_size * self.num_kv_heads # ← 关键这里是 num_kv_heads 而非 num_heads * seq_length * self.head_dim ) return kv_elements * bytes_per_element三、KV Cache 的其他优化方向除了 GQA/MQA 减少 KV 头数外还有几个正交的优化方向INT8/INT4 KV Cache 量化将 KV Cache 压缩到 8-bit 或 4-bit。挑战在于 KV 值的分布是动态变化的不同层、不同token位置差异大静态量化效果有限。KIVIKV-cache quantization with 2-bit在每个token位置使用独立的量化参数。滑动窗口注意力 全局token对于长文档场景大多数token只需要关注附近的token局部依赖只有少数全局token需要关注整个序列。Mistral 的 Sliding Window Attention 和 Longformer 的混合模式都属于这个类别。Token 淘汰策略EvictionStreamingLLM 的注意力汇聚点Attention Sink发现表明前几个 token 对注意力分布有不成比例的影响。据此可以设计策略保留前K个token 最近的M个token淘汰中间的不重要token。四、不同优化路线的适用场景预训练阶段GQA 需要从预训练开始就使用分组KV结构。如果在标准MHA预训练的模型上改为GQA需要额外的微调LLaMA-2采用的就是GQA从头训练。微调阶段可以在标准MHA基础上引入GQA结构并进行少量微调~1000步以快速降低推理成本。推理阶段如果无法修改模型结构可以使用KV Cache量化INT4或token淘汰策略等后处理方法。五、总结KV Cache 是长序列推理的核心瓶颈优化方向围绕减少每个token位置存储的KV量GQA 在精度损失1%和显存节省2-8x之间取得了最佳平衡是目前工业界的主流选择。MQA 提供极致的显存节省但精度损失较大适用于对显存极度受限的边缘设备。KV Cache 量化和 Token 淘汰策略与 GQA/MQA 正交可以叠加使用。优化方案的选择取决于能否修改模型结构这一前置条件。

相关新闻

PC企业微信逆向工程实战:从黑盒到白盒的深度解析

PC企业微信逆向工程实战:从黑盒到白盒的深度解析

1. 项目概述:从“黑盒”到“白盒”的探索之旅在软件开发和信息安全领域,“逆向工程”一直是一个充满神秘色彩又极具挑战性的词汇。它不像正向开发那样,从需求到设计再到编码,一步步构建出可见的功能。逆向更像是一场侦探游戏&…

2026/7/9 20:19:28阅读更多 →
YOLOv8电梯内电动车识别检测系统(项目源码+YOLO数据集+模型权重+UI界面+python+深度学习+环境配置+目标检测)

YOLOv8电梯内电动车识别检测系统(项目源码+YOLO数据集+模型权重+UI界面+python+深度学习+环境配置+目标检测)

摘要 本系统基于YOLOv8(You Only Look Once version 8)目标检测算法,设计并实现了一套完整的电梯内电动车识别检测系统。YOLOv8作为Ultralytics团队于2023年推出的最新一代实时目标检测模型,在检测精度、推理速度和模型轻量化方面…

2026/7/9 20:19:28阅读更多 →
文本翻译API能力边界详解:19种语言互译与请求实战

文本翻译API能力边界详解:19种语言互译与请求实战

适用场景分析 文本翻译是现代国际化应用的基石。无论是多语言内容平台(如新闻网站、电商商品描述)、即时通讯工具的多语言实时翻译、还是游戏本地化,都需要稳定高效的翻译接口。该API支持19种语言互译,其中包括粤语和文言文等特殊…

2026/7/9 20:14:28阅读更多 →
Cocos Creator热更新实战:从原理到避坑的完整解决方案

Cocos Creator热更新实战:从原理到避坑的完整解决方案

1. 项目概述:为什么热更新是Cocos项目开发的“刚需”?做Cocos Creator项目,尤其是手游,最怕什么?怕的不是代码写不出来,而是版本发出去之后,发现一个致命Bug,或者想紧急加个活动。这…

2026/7/9 21:29:37阅读更多 →
从《愚者之夜》到实战:Blender与UE5创建混合生物数字角色全流程

从《愚者之夜》到实战:Blender与UE5创建混合生物数字角色全流程

🚀 30款热门AI模型一站整合,DeepSeek/GLM/Qwen 随心用,限时 5 折。 👉 点击领海量免费额度 如果你最近在关注AI动画、数字人或者3D建模领域,可能会发现一个趋势:技术正在以前所未有的速度,将…

2026/7/9 21:29:37阅读更多 →
iOS个人开发者APP备案:无服务器、纯本地应用3个解决方案实测

iOS个人开发者APP备案:无服务器、纯本地应用3个解决方案实测

iOS个人开发者APP备案实战指南:无服务器应用的3种合规路径去年夏天在App Store提交一款离线笔记工具时,突然收到苹果要求补充ICP备案号的邮件。作为纯本地应用开发者,我翻遍工信部官网却发现个人根本无法直接备案——这个看似简单的流程背后藏…

2026/7/9 21:29:37阅读更多 →
基于STM32单片机智能厨房安全控制天然气甲烷检测火焰火灾报警321(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_

基于STM32单片机智能厨房安全控制天然气甲烷检测火焰火灾报警321(设计源文件+万字报告+讲解)(支持资料、图片参考_相关定制)_

基于STM32单片机智能厨房安全控制天然气甲烷检测火焰火灾报警321(设计源文件万字报告讲解)(支持资料、图片参考_相关定制)_ 版本1:火焰水泵声光报警自动/手动模式火焰传感器检测当前厨房是否发生明火按键一:自动模式 按键二&a…

2026/7/9 21:29:37阅读更多 →
Unity DOTS多人游戏47ms延迟突增:Netcode指令调度与Ghost同步优化实战

Unity DOTS多人游戏47ms延迟突增:Netcode指令调度与Ghost同步优化实战

1. 项目概述:当DOTS 2.0遇上Netcode for Entities 最近在折腾一个基于Unity DOTS 2.0架构的多人对战项目,核心网络同步方案用的是Netcode for Entities。项目上线前进行跨服压力测试时,我们遇到了一个非常棘手的问题:在特定场景下…

2026/7/9 21:29:37阅读更多 →
for循环和while循环——我终于让程序能重复做一件事了

for循环和while循环——我终于让程序能重复做一件事了

一、while循环&#xff1a;不知道要重复多少次的时候 while循环的意思是&#xff1a;当条件成立时&#xff0c;一直重复执行某段代码。 先看一个最简单的例子&#xff1a; count 0 while count < 5: print(f"第{count 1}次循环") count count 1 运行结果&…

2026/7/9 21:24:37阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述&#xff1a;从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目&#xff0c;叫 skills4/skills &#xff0c;它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景&#xff1a;一个旨在展示或教授某种技能的仓库&#xff0c;本身却成了安…

2026/7/9 5:56:19阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示&#xff1a;因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战&#xff1a;从“黑箱预测”到“可信推理”2026年6月&#xff0c;第7届机器学习与趋势国际会议&#xff08;MLT 2026&#xff09;将在悉尼召开。会议议程中&#xff0c;“因果与可解释机器学习…

2026/7/9 9:45:20阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时&#xff0c;通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中&#xff0c;是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/9 2:47:07阅读更多 →
Three.js 着色器光效教程

Three.js 着色器光效教程

着色器光效 Shader Light ▶ 在线运行案例 案例合集&#xff1a; 三维可视化功能案例&#xff08;threehub.cn&#xff09;开源仓库github地址&#xff1a; https://github.com/z2586300277/three-cesium-examples400个案例代码: 网盘链接 你将学到什么 ShaderMaterial 自…

2026/7/9 0:04:37阅读更多 →
如何5分钟掌握CS2智能库存管理:开源工具CASEMOVE终极指南

如何5分钟掌握CS2智能库存管理:开源工具CASEMOVE终极指南

如何5分钟掌握CS2智能库存管理&#xff1a;开源工具CASEMOVE终极指南 【免费下载链接】casemove A dedicated desktop app that enables you to move items in and out of storage units in CS2. 项目地址: https://gitcode.com/gh_mirrors/ca/casemove 还在为CS2存储单…

2026/7/9 0:04:37阅读更多 →
GBase 8a vs MySQL 8.0:ALTER TABLE语法与限制的5点关键差异对比

GBase 8a vs MySQL 8.0:ALTER TABLE语法与限制的5点关键差异对比

GBase 8a与MySQL 8.0&#xff1a;ALTER TABLE语法差异深度解析与实战指南1. 两种数据库的ALTER TABLE能力全景对比在数据库架构设计和运维过程中&#xff0c;表结构变更&#xff08;DDL操作&#xff09;是不可避免的需求。GBase 8a作为国产分析型数据库代表&#xff0c;与开源M…

2026/7/9 0:04:37阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时&#xff0c;发现推理速度只有可怜的 1-2 FPS&#xff0c;而别人的演示视频却能跑到 30 FPS 以上&#xff0c;那么问题很可能不在模型本身&#xff0c;而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后&#xff0c;会直接使用官方示例…

2026/7/9 9:45:20阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一&#xff1a;为什么你需要了解 Coze 和 Dify&#xff1f;如果你对 AI 应用开发感兴趣&#xff0c;但一看到“大模型”、“智能体”、“工作流”这些词就头疼&#xff0c;觉得门槛太高&#xff0c;那这篇文章就是为你准备的。很多开发者&#xff0c;包括我自己&#…

2026/7/9 15:50:44阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会&#xff1a;配图一直是个让人头疼的问题。2026年&#xff0c;AI生图工具已经非常成熟了&#xff0c;但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1&#xff1a;速度之王2026年6月11日&#xff0c…

2026/7/9 14:14:17阅读更多 →