LLM:推理加速相关的结构优化

对于 LLM,加速推理并降低显存,是两个至关重要的问题。本文将从 Key-Value Cache 出发,介绍两种相关的模型结构改进。分别是 ChatGLM 系列使用的 Multi-Query Attention(MQA) 和 LLama 系列使用的 Grouped-Query Attention(GQA)。希望读完之后,能够明白“为何要做”和“如何去做”。


LLM 普遍采用 decoder-only 的结构,自回归地逐个 token 进行生成。在最基础的设置下,我们传给模型的输入顺序为(假设只生成 5 个词):

prompt -> x0 -> x1 -> x2 -> x3 -> x4 -> x5

用 transformers 库的 pytorh 代码表示为:

input_ids = tokenizer(prompt, return_tensors="pt")["input_ids"].to("cuda")  for _ in range(5):  next_logits = model(input_ids)["logits"][:, -1:]  # 取最大概率token为当前时间步输出.  next_token_id = torch.argmax(next_logits,dim=-1)  # 将prompt和历史输出拼接在一起,作为下一步的输入.  input_ids = torch.cat([input_ids, next_token_id], dim=-1)  print("shape of input_ids", input_ids.shape)

每一次推理,都使用完整的历史序列作为 model 的输入,因此 input_ids 不断增长:

shape of input_ids torch.Size([1, 21])  
shape of input_ids torch.Size([1, 22])  
shape of input_ids torch.Size([1, 23])  
shape of input_ids torch.Size([1, 24])  
shape of input_ids torch.Size([1, 25])

1. Key-Value Cache

实际上,上述的计算流程在古早 transformer 模型时代就已经被废弃了,因为重复计算实在是太多。

在 Bert 这种的 encoder 结构中,所有的序列位置是并行计算的,Query 、Key 和 Value 都是 [seq_length, hidden_size] 的矩阵。但是到了 LLM 这样的 decoder 结构中,逐个时间步进行生成,Query 退化为 [1, hidden_size] 的向量,Key 和 Value 仍然是 [seq_length, hidden_size] 的矩阵。

以 x=[robot, must, obey, orders] 为例,self-attention 的权重矩阵是一个下三角,每个 token 的后序位置会全部被 mask 住。

self-attention 权重计算

transformers 库支持对 Key-Value Cache 的使用,只要传入一个参数 use_cache=True 即可。

past_key_values = None # 即 key-value cache, 列表结构为 [num_layers, 0 for k, 1 for v, batch_size, length, hidden_dim]  
generated_tokens = [] # 记录生成结果.  
next_token_id = tokenizer(prompt, return_tensors="pt")["input_ids"].to("cuda")  for _ in range(5):  # 只传入当前 token 作为输入.  next_logits, past_key_values = model(next_token_id, past_key_values=past_key_values, use_cache=True).to_tuple()  next_logits = next_logits[:, -1:]  # 取最大概率token为当前时间步输出.  next_token_id = torch.argmax(next_logits, dim=-1)  print("shape of input_ids", next_token_id.shape)  print("length of key-value cache", len(past_key_values[0][0]))  # 只记录, 不参与后续生成.  generated_tokens.append(next_token_id.item())

在这种模式下,每次迭代只输入 next_token_id,而不是完整历史序列 input_ids。因此,model 的输入 next_token_id 在每一次迭代中保持不变,而 past_key_values 不断增长。

shape of input_ids torch.Size([1, 1])  
length of key-value cache 20  
shape of input_ids torch.Size([1, 1])  
length of key-value cache 21  
shape of input_ids torch.Size([1, 1])  
length of key-value cache 22  
shape of input_ids torch.Size([1, 1])  
length of key-value cache 23  
shape of input_ids torch.Size([1, 1])  
length of key-value cache 24

关于具体解释可以看我的另一个回答:Transformer推理性能优化技术很重要的一个就是K V cache,能否通俗分析,可以结合代码?

Key-Value Cache 是一种不影响预测结果的性能优化方法,它有两个主要优势:

  1. 比起全量计算 QK^T 退化为 qK^T 后大幅削减了FLOPs(FLoating-point OPerations),显著提升推理速度;

  2. 最大内存消耗随序列变长的增长曲线,从二次方变为线性,得到有效控制;

2. 多轮会话的存储开销

对于 LLM 应用,多轮会话的场景天然地适配 Key-Value Cache 策略。

User:礼拜天之后是星期几?  
Assistant:是星期一。  
User:那再往后呢?  
Assistant:是星期二。

如果不做缓存,就不得不在每一次 user 提问之后,把历史会话内容进行重新编码。用 model.generate() 入口做一个示例:

# 第一轮会话.  
prompt = system_prompt + "Question: Please write a function in Python that transforms bytes to Giga bytes.\n\nAnswer: Here"  
model_inputs = tokenizer(prompt, return_tensors='pt')  
# 无生成历史.  
generation_output = model.generate(**model_inputs, max_new_tokens=60, return_dict_in_generate=True)  
decoded_output = tokenizer.batch_decode(generation_output.sequences)[0]  # 第二轮会话.   
prompt = decoded_output + "\nQuestion: How can I modify the function above to return Mega bytes instead?\n\nAnswer: Here"  
model_inputs = tokenizer(prompt, return_tensors='pt')  
# 传入 past_key_values.  
generation_output = model.generate(  **model_inputs,  past_key_values=generation_output.past_key_values,  max_new_tokens=60,  return_dict_in_generate=True  
)

但是,由于 Key-Value Cache 将全部层、全部 attention 头、全部时间步的 K 和 V 都缓存起来,对于一个支持 超长上下文的 LLM 来说,整体的存储开销是非常惊人的。以 Chinese-LLaMA-2-7B-16K 为例:

2 * config.max_position_embeddings * config.num_hidden_layers * config.hidden_size  = 2 * 16384 * 32 * 4096  = 4,294,967,296

将近 43 亿个浮点数!如果用半精度 float16,相当于 8G;即使是最狠的 4-bit 量化,也得占 2G 的显存。这还只是一个轻量化的 LLaMA-7B。

因此,有必要设置针对性的优化方案,削减 K 和 V 对应的存储空间以降低缓存容量。这就是 Multi-Query Attention(MQA) 和 Grouped-Query Attention(GQA)的出发点。

3. Multi-Query Attention(MQA)

MQA:《Fast Transformer Decoding: One Write-Head is All You Need》

“Multi-Query”即只有 Query 进行分头,Key 和 Value 变换为单头维度,在各个注意力头之间共享同一组 KV 映射。即削减了 FLOPs,也降低了 Cache,并且压缩了频繁矩阵拼接的 I/O 耗时。

# query 正常分头.  
self.head_dim = self.embed_dim // self.num_heads  
# key 和 value 使用单头.  
self.kv_heads = 1 if self.multi_query else self.num_heads  
# key 和 value 降维.  
self.kv_dim = self.kv_heads * self.head_dim  # K,Q,V 映射矩阵,embed_dim(Q) + kv_dim(K) + kv_dim(V)  
self.c_attn = nn.Linear(self.embed_dim, self.embed_dim + 2 * self.kv_dim)  
# 从 hidden_states 映射为 query \ key \ value.  
query, key_value = self.c_attn(hidden_states).split((self.embed_dim, 2 * self.kv_dim), dim=2)  
key, value = key_value.split((self.head_dim, self.head_dim), dim=-1)

MQA 在 2019 年就已经发表,目前用在 Falcon、PaLM、MPT、BLOOM 等 LLM 上。

4. Grouped-Query Attention(GQA)

GQA:《GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints》

GQA 是 Google 在 2023 年提出的,作者认为 MQA 砍得太狠了,影响了模型效果。于是改用一种温和策略,对Key 和 Value 先分头,再分组(2或4或8),同一组内共享 KV 矩阵。

GQA(中间)与 MQA(右边)

论文的对比实验用的是 “Uptraining” 的方法。即,把原始的多头 Key 和 Value 做平均池化,模拟“单头”(MQA)和“多组”(GQA),然后再继续预训练 a=0.05 的原预训练步数。

MQA与GQA效果对比

原版 MHA 的指标是 47.2,MQA 有所衰减为 46.4,GQA-8 回升到 47.1,接近无损了。并且,推理速度上 GQA 并没有明确落后于 MQA。

推理速度对比

在大模型时代,我们如何有效的去学习大模型?

现如今大模型岗位需求越来越大,但是相关岗位人才难求,薪资持续走高,AI运营薪资平均值约18457元,AI工程师薪资平均值约37336元,大模型算法薪资平均值约39607元。
在这里插入图片描述

掌握大模型技术你还能拥有更多可能性

• 成为一名全栈大模型工程师,包括Prompt,LangChain,LoRA等技术开发、运营、产品等方向全栈工程;

• 能够拥有模型二次训练和微调能力,带领大家完成智能对话、文生图等热门应用;

• 薪资上浮10%-20%,覆盖更多高薪岗位,这是一个高需求、高待遇的热门方向和领域;

• 更优质的项目可以为未来创新创业提供基石。

可能大家都想学习AI大模型技术,也_想通过这项技能真正达到升职加薪,就业或是副业的目的,但是不知道该如何开始学习,因为网上的资料太多太杂乱了,如果不能系统的学习就相当于是白学。为了让大家少走弯路,少碰壁,这里我直接把都打包整理好,希望能够真正帮助到大家_。

一、AGI大模型系统学习路线

很多人学习大模型的时候没有方向,东学一点西学一点,像只无头苍蝇乱撞,下面是我整理好的一套完整的学习路线,希望能够帮助到你们学习AI大模型。

在这里插入图片描述

第一阶段: 从大模型系统设计入手,讲解大模型的主要方法;

第二阶段: 在通过大模型提示词工程从Prompts角度入手更好发挥模型的作用;

第三阶段: 大模型平台应用开发借助阿里云PAI平台构建电商领域虚拟试衣系统;

第四阶段: 大模型知识库应用开发以LangChain框架为例,构建物流行业咨询智能问答系统;

第五阶段: 大模型微调开发借助以大健康、新零售、新媒体领域构建适合当前领域大模型;

第六阶段: 以SD多模态大模型为主,搭建了文生图小程序案例;

第七阶段: 以大模型平台应用与开发为主,通过星火大模型,文心大模型等成熟大模型构建大模型行业应用。

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

在这里插入图片描述

三、AI大模型经典PDF书籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

在这里插入图片描述

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

四、AI大模型各大场景实战案例

在这里插入图片描述

结语

【一一AGI大模型学习 所有资源获取处(无偿领取)一一】
所有资料 ⚡️ ,朋友们如果有需要全套 《LLM大模型入门+进阶学习资源包》,扫码获取~

👉[CSDN大礼包🎁:全网最全《LLM大模型入门+进阶学习资源包》免费分享(安全链接,放心点击)]()👈

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/52999.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++学习, 函数返回指针

C 允许函数返回指针&#xff0c;需要声明返回指针的函数。 声明函数返回指针方式&#xff1a; type *Function() { } 程序示例&#xff1a; #include <iostream> #include <ctime> #include <cstdlib> using namespace std; int *getRandom( ) { static…

前端与后端的身份认证

这里写目录标题 前端与后端的身份认证Web开发模式服务端渲染的Web开发模式前后端分离的Web开发模式根据场景选择开发模式 身份认证为什么需要身份认证不同开发模式下的身份认证 Session认证机制HTTP协议下的无状态性如何突破HTTP无状态的限制CookieCookie的几大特性&#xff1a…

ET算法【动态规划】

线性dp&#xff1a;dp[i][j] 由 dp[i - 1][j] 通过加减乘除等线性运算得到 状压dp&#xff1a;dp[i][j] 表示一个用二进制数表示的子集来反映当前状态&#xff0c;如7 &#xff08;111&#xff09;&#xff08;选了三个&#xff09; 期望dp&#xff1a;dp[i][j] 表示期望或者…

yolo8 目标检测、鉴黄

省流 看前必读 别浪费时间 &#xff1a;本文只是一个记录&#xff0c;防止自己下次被改需求时浪费时间&#xff0c;在这里就随意的写了一下文章记录整个步骤&#xff0c;但是文章想必肯定没有对应的教程讲的详细&#xff0c;该文章只适合想要快速按照步骤完成一个简单的 demo 的…

学习之git

github 创建远程仓库 代码推送 Push 代码拉取 Pull 代码克隆 Clone SSH免密登录 Idea集成GitHubGitee码云 码云创建远程仓库 Idea集成Gitee码云 码云连接Github进行代码的复制和迁移GitLab gitlab服务器的搭建和部署 Idea集成GitLabgit概述 一切皆本地 版本控制工具 集中…

win10配置adb环境变量

初始状态&#xff1a; 最简单的配置方案&#xff0c;直接复制adb所在路径&#xff1a; 粘贴进来确定即可&#xff1a; 然后打开 cmd 查看已经配置成功了&#xff1a;

【c++】cout打印char * 或者char[]的细节详解

目录 char* 类型 1.打印指向的字符串 2.打印指针指向的地址 问题描述 解决方法 char型数组 1. 想要输出字符串 2. 想输出字符数组的地址 printf 和cout 的对比 1.打印首字符 2.打印字符串 3.打印字符串首地址 &#x1f497;感谢阅读&#xff01;&#x1f497; char*…

用powermock编写单元测试

1、pom文件引入jar包 <!-- 单元测试 start --> <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope> </dependency> <dependency>&…

基于ZYNQ SOC的软件无线电处理平台

板载SOC实时处理器&#xff1a;XC7Z020-2CLG484I板载2片AD9361射频收发芯片&#xff0c;兼容AD80305具有1路千兆以太网口具有1个USB串口、1个USB OTG、1个SD卡ADC/DAC采集位宽&#xff1a;12位2路TX、2路RX&#xff0c;可实现全双工或者半双工 基于Xilinx ZYNQ SOC的软件无线电…

第 4 章 第 4 章 卷积神经网络-datawhale ai夏令营

独热向量 y ′ 的长度决 定了模型可以识别出多少不同种类的东西。我们希望 y ′ 和 yˆ 的交叉熵越小越好。 为了避免过拟合&#xff0c;在做图像识别的时候&#xff0c;考虑到图像本身的特性&#xff0c;并不一定 需要全连接&#xff0c;即不需要每个神经元跟输入的每个维度都…

Python中排序算法之插入排序

1 插入排序算法原理 插入排序算法与《Python中排序算法之选择排序》中提到的选择排序算法类似&#xff0c;也是将要排序的数列分为两个子数列&#xff08;红色框数列和绿色框数列&#xff09;&#xff0c;不同之处在于插入排序算法从绿色框子数列中逐个选择数字&#xff0c;之…

单片机内存区域划分

目录 一、C 语言内存分区1、栈区2、堆区3、全局区&#xff08;静态区&#xff09;4、常量区5、代码区6、总结 二、单片机存储分配1、存储器1.1 RAM1.2 ROM1.3 Flash Memory1.4 不同数据的存放位置 2、程序占用内存大小 一、C 语言内存分区 C 语言在内存中一共分为如下几个区域…

【生日视频制作】农村大马路绿色墙体广告标语喷漆AE模板修改文字软件生成器教程特效素材【AE模板】

生日视频制作教程农村大马路墙体广告标语喷漆AE模板改文字素材 怎么如何做的【生日视频制作】农村大马路绿色墙体广告标语喷漆AE模板修改文字软件生成器教程特效素材【AE模板】 生日视频制作步骤&#xff1a; 安装AE软件 下载AE模板 把AE模板导入AE软件 修改图片或文字 渲染出…

【最新消息】211高校,拟撤销测绘工程专业

近日&#xff0c;中国石油大学&#xff08;北京&#xff09;教务处发布《关于公示2024年度拟撤销本科专业的通知》&#xff0c;拟撤销音乐学、建筑学、测绘工程等9个本科专业。 通知内容如下&#xff1a; 根据《教育部高等教育司关于开展2024年度普通高等学校本科专业设置工作的…

【STM32】IIC

超级常见的外设通信方式&#xff0c;一般叫做I方C。 大部分图片来源&#xff1a;正点原子HAL库课程 专栏目录&#xff1a;记录自己的嵌入式学习之路-CSDN博客 目录 1 基本概念 1.1 总线结构 1.2 IIC协议 1.3 软件模拟IIC逻辑 2 AT24C02 2.1 设备地址与…

一次VUE3 使用axios调用萤石云OpenAPI踩坑经历

通过调用萤石云的获取设备列表功能&#xff0c;我们可以根据 ACCESS_TOKEN 获取该用户下的设备列表。 Python 调用接口 根据接口文档[1]&#xff0c;使用Python&#xff0c;很轻松就能获取到该列表&#xff0c;代码如下&#xff08;该代码用于拼接生成vue代码&#xff0c;这是…

Codeforces Round 969 (Div. 2) 题ABC详细题解,包含(C++,Python语言描述)

前言&#xff1a; 首先让我们恭喜tourist创造历史 他是第一&#xff0c;他又是第一&#xff0c;他总是第一&#xff0c;第一个codefores上4000分的&#xff0c;创造一个新的段位:Tourist&#xff0c;他的名字就是一个新的段位&#xff0c;他就是最高的山&#xff0c;最长的河 本…

访问win10共享文件夹:用户或密码不正确 以及 未授予用户在此计算机上的请求登录类型

因为安装的是神州网信政府版&#xff0c;该版本通常包含更严格的安全策略和访问控制&#xff0c;设置了共享文件夹后&#xff0c;访问共享文件夹时出现错误。 1、首先报错&#xff1a;用户或密码不正确 将》网络访问&#xff1a;本地账户的共享和安全模型&#xff0c;修改为&a…

开源通用验证码识别OCR —— DdddOcr 源码赏析(二)

文章目录 前言DdddOcr分类识别调用识别功能classification 函数源码classification 函数源码解读1. 分类功能不支持目标检测2. 转换为Image对象3. 根据模型配置调整图片尺寸和色彩模式4. 图像数据转换为浮点数据并归一化5. 图像数据预处理6. 运行模型&#xff0c;返回预测结果 …

Python测试之测试覆盖率统计

本篇承接上一篇 Python测试框架之—— pytest介绍与示例&#xff0c;在此基础上介绍如何基于pytest进行测试的覆盖率统计。 要在使用 pytest 进行测试时检测代码覆盖率&#xff0c;可以使用 pytest-cov 插件。这个插件是基于 coverage.py&#xff0c;它能帮助你了解哪些代码部…