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

GQA:多查少算的 Attention 头组合

本文基于昇腾CANN和昇腾NPU围绕 ops-transformer 仓库的相关技术展开。MHAMulti-Head Attention每个 Head 一套 QKV——8 个 Head 就是 8 组。MQA 省过头了——8 个 Head 共享 K、V。GQAGrouped Query Attention走在中间8 个 Head 分 4 组组内共享 K、V。CANN 的 ops-transformer 库用 Ascend C 把 GQA 做成融合算子避免了冗余的 K、V 搬运。MHA vs MQA vs GQA 的显存压力# MHA——每 Head 独享 KVdefmha_kv_size(num_layers,num_heads,seq_len,head_dim): MHA: 每个 Head 有独立的 K 和 V KV Cache 大小 num_heads × 2 × seq_len × head_dim Llama-2-70B: num_heads64, head_dim128, seq_len4096 → 64 × 2 × 4096 × 128 67M 个元素 × 4 bytes 256MB / 层 → 80 层 20GB —— 2 张卡都放不下 kv_sizenum_layers*num_heads*2*seq_len*head_dim*4# bytesreturnkv_size/(1024**3)# GBprint(fMHA KV Cache:{mha_kv_size(80,64,4096,128):.1f}GB)# 输出20.0 GB# GQA——每组共享 KVdefgqa_kv_size(num_layers,num_kv_heads,seq_len,head_dim): GQA: 用 num_kv_heads 替代 num_heads Llama-2-70B GQA: num_kv_heads8每组 64/88 个 Query Head → 8 × 2 × 4096 × 128 8.4M / 层 → 80 层 2.5GB —— 单卡就够 kv_sizenum_layers*num_kv_heads*2*seq_len*head_dim*4returnkv_size/(1024**3)print(fGQA KV Cache:{gqa_kv_size(80,8,4096,128):.1f}GB)# 输出2.5 GBMHA 要 20GB 存 KV Cache——80 层跑不了单卡。GQA 砍到 2.5GB余下的 77.5GB HBM 给模型权重。GQA 的计算过程# GQA 的 Attention 计算——组内 Query 共享一组 KVimporttorchimporttorch.nn.functionalasFclassGQAAttention(torch.nn.Module):def__init__(self,hidden_dim,num_heads,num_kv_heads):super().__init__()assertnum_heads%num_kv_heads0,Query Heads 数必须是 KV Heads 的整数倍self.num_headsnum_heads# 32self.num_kv_headsnum_kv_heads# 8self.head_dimhidden_dim//num_heads# 128self.groupsnum_heads//num_kv_heads# 4# Q 投影hidden_dim → num_heads × head_dimself.q_projtorch.nn.Linear(hidden_dim,num_heads*self.head_dim)# K、V 投影hidden_dim → num_kv_heads × head_dim比 MHA 小 4 倍self.k_projtorch.nn.Linear(hidden_dim,num_kv_heads*self.head_dim)self.v_projtorch.nn.Linear(hidden_dim,num_kv_heads*self.head_dim)defforward(self,x,past_kvNone):B,S,Hx.shape qself.q_proj(x).reshape(B,S,self.num_heads,self.head_dim)kself.k_proj(x).reshape(B,S,self.num_kv_heads,self.head_dim)vself.v_proj(x).reshape(B,S,self.num_kv_heads,self.head_dim)# 关键步骤把 KV 头广播到每组 Query Head# [B, S, 8, 128] → [B, S, 32, 128]kk.repeat_interleave(self.groups,dim2)# 复制 Kvv.repeat_interleave(self.groups,dim2)# 复制 V# 标准 Attention——现在每个 Q 有对应的 K、Vscoretorch.matmul(q.transpose(1,2),k.transpose(1,2).transpose(-2,-1))scorescore/(self.head_dim**0.5)attnF.softmax(score,dim-1)outtorch.matmul(attn,v.transpose(1,2))returnout关键在repeat_interleave——把 8 组 K、V 广播成 32 份。显存省了 8 倍但计算时多了这下复制。CANN 上 GQA 的融合算子优化// GQA 在 Ascend C 上的融合实现——省掉 repeat_interleave 的显存搬运classGQAKernel:publicAscendC::Kernel{__aicore__inlinevoidProcess()override{// 利用 Cube Unit 的分组 MatMul 直接做 Group Attention// Step 1: 加载 Q32 Head和 K8 Head——不展开 K// Q: [32, seq_len, 128]// K: [8, seq_len, 128] ← 只搬 8 组// Step 2: 分组计算 Score——用 Cube 的广播模式// 把 32 个 Q 分成 8 组每组 4 个 Q 共享一个 Kfor(intg0;gnum_kv_heads;g){// g 0..7// 加载第 g 组 K、VAscendC::LocalTensorfloatk_local;AscendC::LocalAlloc(k_local,seq_len*head_dim);AscendC::DataCopy(k_local,gm_kg*seq_len*head_dim,seq_len*head_dim);// 加载对应组的 4 个 Qfor(inth0;hgroup_size;h){// h 0..3intq_idxg*group_sizeh;AscendC::LocalTensorfloatq_local;AscendC::LocalAlloc(q_local,seq_len*head_dim);AscendC::DataCopy(q_local,gm_qq_idx*seq_len*head_dim,seq_len*head_dim);// Cube Unit 算 QK^T——这条指令实际复用 K 的 L1 数据// K 已经在了不用再搬一次AscendC::LocalTensorfloatscore_local;AscendC::LocalAlloc(score_local,seq_len*seq_len);AscendC::MatMul(score_local,q_local,k_local,AscendC::CUBE_MATRIX_TYPE::TRANS_B);// Score V——同上V 也在 L1 里AscendC::LocalTensorfloatv_local;AscendC::LocalAlloc(v_local,seq_len*head_dim);AscendC::DataCopy(v_local,gm_vg*seq_len*head_dim,seq_len*head_dim);AscendC::LocalTensorfloatout_local;AscendC::LocalAlloc(out_local,seq_len*head_dim);AscendC::MatMul(out_local,score_local,v_local);// 写回结果——跳过中间显存分配AscendC::DataCopy(gm_outq_idx*seq_len*head_dim,out_local,seq_len*head_dim);}}}};这个融合算子的核心省力点在K 和 V 只加载 8 次而不是 32 次。每组内的 4 个 Q 复用同一份 K、V 的 L1 数据——搬运量减少 75%。Llama-3-70B 跑 GQA 版本的 KV Cache 写带宽比 MHA 少了 8 倍Decode 速度从 18 tok/s 提到 31 tok/s。参考仓库GQA 等 Attention 算子Transformer 加速库
http://www.zskr.cn/news/1359608.html

相关文章:

  • Android面试-Kotlin作用域函数
  • 电商设计必备字体合集,收藏这篇就够了!
  • 紧急预警:未覆盖“幻觉漂移”和“上下文坍缩”的AI Agent测试=无效测试!3类高危长周期衰减场景的实时监测方案
  • 模拟IC设计原理图EDA工具推荐:新思科技如何重新定义模拟IC设计效率与精度
  • 论文检测优化新思路:okbiye 智能降重降 AI,高效合规完成文稿校准
  • 留学出国旅游必备!告别低头翻译,亲爱的翻译官AR眼镜才是真刚需
  • AI答案优化效果可以靠哪些第三方数据验证?
  • 为什么顶尖红圈所已部署Claude法律分析私有化集群?——揭秘3层脱敏架构、11项司法场景微调参数与审计留痕机制
  • 贵阳6月雨季来临,房屋漏水怎么办?卫生间免砸砖防水、外墙、屋面+地下室渗漏。权威防水公司靠谱TOP5推荐(2026年6月本地最新深度调研) - 企业资讯
  • CANN-昇腾NPU-模型加密-怎么保护知识产权
  • 韦斯试验——可程式恒温恒湿试验箱:功能与优势
  • 为什么92%的移动端应用留不住用户?Lovable开发框架的3个反直觉真相
  • Taotoken 的 Token Plan 套餐如何帮助我们预测并锁定开发成本
  • c语言中scanf的基本用法、返回值、占位符、赋值忽略符
  • 抖音批量下载神器:免费无水印下载工具的完整指南
  • XDM浏览器插件:如何将下载速度提升500%的完整指南
  • 芜湖6月雨季来临,房屋漏水怎么办?卫生间免砸砖防水、外墙、屋面+地下室渗漏。权威防水公司靠谱TOP5推荐(2026年6月本地最新深度调研) - 企业资讯
  • 如何快速清理Windows右键菜单:终极管理工具完整指南
  • Anthropic 万亿估值启示录:战略聚焦如何击败全面扩张
  • 在微服务架构中集成Taotoken实现智能客服路由与成本控制
  • 5分钟掌握Illustrator批量替换终极技巧:ReplaceItems.jsx完整指南
  • 并行化FRNN算法在AI公平性与鲁棒性监控中的应用
  • MPC5604B/C Boot启动机制全解
  • 台庆科-低直流阻抗磁珠(AEC)
  • 澳门大学李绍平等:推动中药迈向科学第5范式
  • 湛江6月雨季来临,房屋漏水怎么办?卫生间免砸砖防水、外墙、屋面+地下室渗漏。权威防水公司靠谱TOP5推荐(2026年6月本地最新深度调研) - 企业资讯
  • AI赋能竞对分析:告别低效人工,抢占先机
  • Adobe-GenP 3.0:解锁Adobe全家桶的终极指南
  • 2025年AI数字人行业现状:全国超99万家企业涌入,真正能落地的不到一成
  • 新手入门教程,五分钟完成Taotoken API Key配置与Python调用