大模型推理优化技术概述

大模型推理优化技术概述

    • KVcache一句话总结:
    • KV cache背景
    • KV cache 计算过程
    • PageAttention
      • 概述
      • 背景:
    • MHD、MQA、GQA注意力机制
      • MHA
      • MQA
      • GQA
    • Flash Attention

KVcache一句话总结:

KV cache其实就是通过空间换取时间的方式,通过缓存Attention中的K和V来实现推理优化。
注意力机制
公式
在这里插入图片描述

其中:

  • Q 表示查询(Query)矩阵
  • K 表示键(Key)矩阵
  • V 表示值(Value)矩阵
  • dk 是键向量的维度,用于缩放因子,防止内积后的数值过大导致梯度消失问题
  • softmax函数是用来归一化权重的

计算过程

  1. 矩阵乘法(QKT):首先,计算查询矩阵Q和键矩阵K的转置的点积。这一步是为了计算每个查询和所有键之间的相似度。
  2. 缩放(除以 dk):将上述点积的结果除以dk的值。这一步是为了控制点积的大小,防止梯度在训练过程中消失。
  3. 应用softmax函数:接着对每一行应用softmax函数,将点积的结果转换成概率形式(即注意力权重)。这些权重表示了在计算最终输出时,各个值的重要程度。
  4. 加权和(乘以 V):最后,将这些注意力权重应用于值矩阵V。通过加权求和的方式,合成最终的输出。权重较大的值会在输出中占据更主要的位置,这样模型就可以关注对当前任务更重要的信息。

KV cache背景

在探讨模型推理的效率时,我们面临一个关键问题:每次推理都输入完整的前文数据是一种资源消耗较大的做法。这种方法导致了大量的冗余计算,因为当文本长度从S增加到S+1时,对于前S个token的处理(包括Embedding映射、KQV映射、注意力权重计算、以及前馈网络(FFN)层的操作)在连续的推理过程中是重复的。这种重复是由于模型参数是固定的,每次的计算结果是一样的。
理想情况下,我们可能会考虑只输入新的token(即第S+1个token)来减少计算负担。然而,这种方法在实际应用中是行不通的。尽管最终输出似乎只由最后一个token决定,但注意力机制的实质是依赖于整个序列的,它需要利用前文中的Key和Value向量来有效载入并处理历史信息。因此,不能简单地忽略前面的文本数据。

[图片]

在每一步生成中,仅使用输入序列中的最后一个token的注意力表示,即可预测出下一个token。但模型还是并行计算了所有token的注意力表示,其中产生了大量冗余的计算(包含qkv映射,attention计算等),并且输入的长度越长,产生的冗余计算量越大。

KV cache 计算过程

b j = ∑ i = 1 n s o f t m a x ( q j ⋅ k i ) v i b^j= ∑^{n}_{i=1}softmax(q^j⋅k^i)v^i bj=i=1nsoftmax(qjki)vi

输入:中国的首都
预测:是

  1. 计算中国的首都每个token的k,v,以及对应的注意力计算结果b1,b2,b3。
  2. 使用b3预测下一个token,得到:是。
  3. 缓存[k1,k2,k3],[v1,v2,v3]

输入:中国的首都是
预测:北

  1. 计算是的,q,k,v。
  2. 更新缓存[k1,k2,k3,k4],[v1,v2,v3,v4]
  3. 计算b4,预测下一个token,得到北。

输入:中国的首都是北
预测:京

  1. 计算北的,q,k,v。
  2. 更新缓存[k1,k2,k3,k4,k5],[v1,v2,v3,v4,v5]
  3. 计算b5,预测下一个token,得到京。

统计图如下,当关闭KV-Cache时,随着文本长度从10增长到1000,推理一个token从17ms增长到426ms,推理步长越大,效率越来越低,而当开启KV-Cache时,推理一个token的耗时基本稳定维持在30ms左右,只呈现出小数点后第三位上的略微增长趋势,推理长度几乎没有对推理效率产生负面影响。
在这里插入图片描述

缺点
用KV cache做推理时的一些特点:

  • 随着prompt数量变多和序列变长,KV cache也变大,对gpu显存造成压力
  • 由于输出的序列长度无法预先知道,所以我们很难提前为KV cache量身定制存储空间
    在这里插入图片描述

PageAttention

论文地址:
https://arxiv.org/abs/2309.06180

概述

大型语言模型 (LLM) 的高吞吐量服务需要一次批处理足够多的请求。然而,现有系统很困难,因为每个请求的键值缓存(KV 缓存)内存很大,并且会动态增长和收缩。如果管理效率低下,这些内存可能会因碎片和冗余重复而被严重浪费,从而限制了批处理大小。为了解决这个问题,我们提出了 PagedAttention,这是一种受操作系统中经典虚拟内存和分页技术启发的注意力算法。在此基础上,我们构建了 vLLM,这是一个 LLM 服务系统,它实现了(1)KV cache内存几乎为零的浪费,以及(2)在请求内和请求之间灵活共享 KV cache,以进一步减少内存使用。我们的评估表明,与最先进的系统(例如 FasterTransformer 和 Orca)相比,在相同延迟水平下,vLLM 将流行 LLM 的吞吐量提高了 2-4倍。对于更长的序列、更大的模型和更复杂的解码算法,这种改进更加明显。
在这里插入图片描述

背景:

  • KV cache内存的巨大需求:每个请求的KV缓存内存需求巨大,且随请求数量增加而快速增长。
  • 内存碎片化和冗余占用:现有系统的内存管理不善,导致大量内存碎片和冗余占用,限制了批处理大小。
    解决方法:
    PagedAttention通过将KVcache划分为固定大小的块进行存储,这些块可以在非连续的物理内存空间中存储,从而减少内存碎片并允许跨请求共享内存。具体步骤如下:
  • 分块存储:将请求的KVcache划分为固定大小的块,每个块包含一定数量的键值对。
  • 非连续存储:这些块可以存储在非连续的物理内存空间中,灵活分配内存。
  • 内存共享:允许跨请求共享KVcache块,提高内存利用率。
    常规KV cache存储分配
    通过下图可以看出,常规kv cache,造成了极大的显存资源浪费。
    在这里插入图片描述

单个请求
通过虚拟表进行映射,更合理的分配显存。
在这里插入图片描述

多个请求
多个请求到来的时候,充分利用显存空间
在这里插入图片描述

共享内存
对于相同的请求进行共享显存,更多应用在让大模型生成多个回答,以及使用思维树的时候。
在这里插入图片描述

MHD、MQA、GQA注意力机制

GQA论文地址:
https://arxiv.org/pdf/2305.13245

  • Llama 2 系列模型。更大的模型(70B)使用分组查询注意 (GQA) 来提高推理可扩展性。
  • Llama 3 系列模型。8 和 70B 版本均使用分组查询注意 (GQA) 来提高推理可扩展性。
  • Qwen2 等模型
    在这里插入图片描述

MHA

多头注意力机制是Transformer模型中的核心组件。在其设计中,"多头"意味着该机制并不只计算一种注意力权重,而是并行计算多种权重,每种权重都从不同的“视角”捕获输入的不同信息。

  1. hidden_state经过线性层得到q、k、v
  2. q、k、v经过split后增加一个维度:num_heads
  3. q、k计算注意力分数score
  4. softmax对注意力分数进行归一化得到注意力权重attention_probs
  5. 用注意力权重和值计算输出:output
  6. 对注意力输出进行拼接concat
import torch
from torch import nn
class MutiHeadAttention(torch.nn.Module):def __init__(self, hidden_size, num_heads):super(MutiHeadAttention, self).__init__()self.num_heads = num_headsself.head_dim = hidden_size // num_heads## 初始化Q、K、V投影矩阵self.q_linear = nn.Linear(hidden_size, hidden_size)self.k_linear = nn.Linear(hidden_size, hidden_size)self.v_linear = nn.Linear(hidden_size, hidden_size)## 输出线性层self.o_linear = nn.Linear(hidden_size, hidden_size)def forward(self, hidden_state, attention_mask=None):batch_size = hidden_state.size()[0]query = self.q_linear(hidden_state)key = self.k_linear(hidden_state)value = self.v_linear(hidden_state)query = self.split_head(query)key = self.split_head(key)value = self.split_head(value)## 计算注意力分数attention_scores = torch.matmul(query, key.transpose(-1, -2)) / torch.sqrt(torch.tensor(self.head_dim))if attention_mask != None:attention_scores += attention_mask * -1e-9## 对注意力分数进行归一化attention_probs = torch.softmax(attention_scores, dim=-1)output = torch.matmul(attention_probs, value)## 对注意力输出进行拼接output = output.transpose(-1, -2).contiguous().view(batch_size, -1, self.head_dim * self.num_heads)output = self.o_linear(output)return outputdef split_head(self, x):batch_size = x.size()[0]return x.view(batch_size, -1, self.num_heads, self.head_dim).transpose(1,2)

MQA

多查询注意力(MQA)可能导致质量下降和训练不稳定,并且训练针对质量和推理优化的单独模型可能不可行。此外,虽然一些语言模型已经使用了多查询注意力,如PaLM但许多语言模型没有,包括公开可用的语言模型,如T5和LLaM.

  1. hidden_state经过线性层得到q、k、v
  2. q、k、v经过split后增加一个维度:num_heads(q = num_heads,k=1,v=1)。相当于多个query,即多查询。
  3. q、k计算注意力分数score
  4. softmax对注意力分数进行归一化得到注意力权重attention_probs
  5. 使用注意力权重和值计算输出:output
  6. 对注意力输出进行拼接concat
import torch
from torch import nn
class MutiQueryAttention(torch.nn.Module):def __init__(self, hidden_size, num_heads):super(MutiQueryAttention, self).__init__()self.num_heads = num_headsself.head_dim = hidden_size // num_heads## 初始化Q、K、V投影矩阵self.q_linear = nn.Linear(hidden_size, hidden_size)self.k_linear = nn.Linear(hidden_size, self.head_dim) ###self.v_linear = nn.Linear(hidden_size, self.head_dim) ##### 输出线性层self.o_linear = nn.Linear(hidden_size, hidden_size)def forward(self, hidden_state, attention_mask=None):batch_size = hidden_state.size()[0]query = self.q_linear(hidden_state)key = self.k_linear(hidden_state)value = self.v_linear(hidden_state)query = self.split_head(query)key = self.split_head(key, 1)value = self.split_head(value, 1)## 计算注意力分数attention_scores = torch.matmul(query, key.transpose(-1, -2)) / torch.sqrt(torch.tensor(self.head_dim))if attention_mask != None:attention_scores += attention_mask * -1e-9## 对注意力分数进行归一化attention_probs = torch.softmax(attention_scores, dim=-1)output = torch.matmul(attention_probs, value)output = output.transpose(-1, -2).contiguous().view(batch_size, -1, self.head_dim * self.num_heads)output = self.o_linear(output)return outputdef split_head(self, x, head_num=None):batch_size = x.size()[0]if head_num == None:return x.view(batch_size, -1, self.num_heads, self.head_dim).transpose(1,2)else:return x.view(batch_size, -1, head_num, self.head_dim).transpose(1,2)

GQA

引入分组查询注意力 (GQA),这是多 头语言模型的泛化。查询注意力,它使用多于一个,少于查询头数量的键值头。经过训练的GQA 实现了接近多头注意力 的质量,并且速度与 MQA 相当。

  1. hidden_state经过线性层得到q、k、v
  2. q、k、v经过split后增加一个维度:num_heads(q = num_heads,k=group_num,v=group_num)。相当于把多头分组了,比如原先有10个头,那就是10个query,分成5组,每组2个query,1个value,1个key。
  3. q、k计算注意力分数score
  4. softmax对注意力分数进行归一化得到注意力权重attention_probs
  5. 使用注意力权重和值计算输出:output
  6. 对注意力输出进行拼接concat
import torch
from torch import nn
class MutiGroupAttention(torch.nn.Module):def __init__(self, hidden_size, num_heads, group_num):super(MutiGroupAttention, self).__init__()self.num_heads = num_headsself.head_dim = hidden_size // num_headsself.group_num = group_num## 初始化Q、K、V投影矩阵self.q_linear = nn.Linear(hidden_size, hidden_size)self.k_linear = nn.Linear(hidden_size, self.group_num * self.head_dim)self.v_linear = nn.Linear(hidden_size, self.group_num * self.head_dim)## 输出线性层self.o_linear = nn.Linear(hidden_size, hidden_size)def forward(self, hidden_state, attention_mask=None):batch_size = hidden_state.size()[0]query = self.q_linear(hidden_state)key = self.k_linear(hidden_state)value = self.v_linear(hidden_state)query = self.split_head(query)key = self.split_head(key, self.group_num)value = self.split_head(value, self.group_num)## 计算注意力分数attention_scores = torch.matmul(query, key.transpose(-1, -2)) / torch.sqrt(torch.tensor(self.head_dim))if attention_mask != None:attention_scores += attention_mask * -1e-9## 对注意力分数进行归一化attention_probs = torch.softmax(attention_scores, dim=-1)output = torch.matmul(attention_probs, value)output = output.transpose(-1, -2).contiguous().view(batch_size, -1, self.head_dim * self.num_heads)output = self.o_linear(output)return outputdef split_head(self, x, group_num=None):batch_size,seq_len = x.size()[:2]if group_num == None:return x.view(batch_size, -1, self.num_heads, self.head_dim).transpose(1,2)else:x = x.view(batch_size, -1, group_num, self.head_dim).transpose(1,2)x = x[:, :, None, :, :].expand(batch_size, group_num, self.num_heads // group_num, seq_len, self.head_dim).reshape(batch_size, self.num_heads // group_num * group_num, seq_len, self.head_dim)return x

Flash Attention

论文地址:
https://arxiv.org/abs/2205.14135
本质上是通过重计算。把矩阵计算中的QKV进行拆分,复制到SRAM中,进行计算,再取出来。
在这里插入图片描述

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

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

相关文章

QTday5 2024-06-19

作业要求&#xff1a; 1.思维导图 2.整理代码&#xff1a;TCP服务器 作业1&#xff1a;思维导图 作业2&#xff1a;整理代码 运行代码&#xff1a; widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpServer> #include <QList>…

边学边赛拿冠军!北邮学子勇夺昇腾AI原生创新算子挑战赛金奖

导读 如何从零开始学习算子开发&#xff1f;昇腾AI原生创新算子挑战赛冠军“法宝”大揭秘。 “0xCCCCCCCC团队夺冠&#xff01;” 2024年5月9日&#xff0c;在首届昇腾AI原生创新算子挑战赛S1赛季决赛现场&#xff0c;来自北京邮电大学0xCCCCCCCC团队的孙明志和梁昊骞以总分第…

金蝶BI方案与奥威BI:智能、高效的数据分析组合

在当今数据驱动的时代&#xff0c;企业对于快速、准确、全面的数据分析需求日益增长。金蝶BI方案和奥威BI SaaS平台正是为满足这一需求而精心打造的智能数据分析工具。 方案见效快 金蝶BI方案以其高效的数据处理能力&#xff0c;能够快速地将海量数据转化为有价值的信息。通过…

uniapp 微信小程序自定义分享图片

场景&#xff1a;微信小程序用户&#xff0c;点击小程序里商品的分享按钮时&#xff0c;想要不同的商品展示不用的分享内容&#xff0c;比如分享图片上展示商品的图片、价格等信息。分享的UI图如下&#xff1a; 实现方法&#xff1a; 1. 分享按钮&#xff1a;<button open-…

计算机顶级会议和顶级期刊

顶级会议 国际计算机设计会议&#xff08;ICCD&#xff09;&#xff1a;由国际电气与电子工程师协会&#xff08;IEEE&#xff09;主办&#xff0c;是计算机体系结构领域的国际顶级会议之一&#xff0c;已经成功举办四十余届。 NeurIPS&#xff1a;全称神经信息处理系统大会&a…

电感(线圈)具有哪些基本特性

首先&#xff0c;电感&#xff08;线圈&#xff09;具有以下基本特性&#xff0c;称之为“电感的感性电抗” ?①直流基本上直接流过。 ?②对于交流&#xff0c;起到类似电阻的作用。 ?③频率越高越难通过。 下面是表示电感的频率和阻抗特性的示意图。 在理想电感器中&#…

centos7安装FTP服务器

目录 实验背景 一、配置yum源 1、本地yum 2、阿里云yum 二、安装vsftpd 1、安装vsftp服务 2、启动服务并设置开机自启动 3、开放防火墙和SELinux 三、创建用户和FTP目录 1、创建文件目录并配置权限 2、创建ftp组以及用户 四、修改vsftpd.conf文件 1、备份 vsftpd.c…

C/C++ vector模拟实现

模拟实现&#xff1a; 框架 namespace yx {template<class T>class vector{public:typedef T* iterator;private:iterator _start;iterator _finish;iterator _end_of_storage;}; } 这里我们声明定义不分离 reverse() 新开一个空间&#xff0c;拷贝数据&#xff0c;然…

HTML星空特效

目录 写在前面 完整代码 代码分析 运行效果 系列文章 写在后面 写在前面 100行代码实现HTML星空特效。 完整代码 全部代码如下。 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"&g…

【Redis】基于Redission实现分布式锁(代码实现)

目录 基于Redission实现分布式锁解决商品秒杀超卖的场景&#xff1a; 1.引入依赖&#xff1a; 2.加上redis的配置&#xff1a; 3.添加配置类&#xff1a; 4.编写代码实现&#xff1a; 5.模拟服务器分布式集群的情况&#xff1a; 1.右键点击Copy Configuration 2.点击Modi…

怎么投资中证全指证券公司指数?

中证全指证券公司指数的代码是399975&#xff0c;有50只成分股&#xff0c;几乎包含了市场上所有主要的证券公司&#xff0c;算是指数基金中投资证券行业的不二选择。 根据天天基金的数据显示&#xff0c;市面上有31只跟踪该指数的基金&#xff0c;规模最大的是南方中证全指证…

【Java面试】二十二、JVM篇(下):JVM参数调优与排查

文章目录 1、JVM的参数在哪里设置2、常见的JVM调优参数有哪些3、常见的JVM调优工具有哪些4、Java内存泄漏的排查思路5、CPU飙高的排查思路 1、JVM的参数在哪里设置 war包部署&#xff0c;在tomcat中设置&#xff0c;修改TOMCAT_HOME/bin/catalina.sh 文件 jar包启动&#xff0…

jpg格式图片无法打开可以修复吗?有哪些方法?

JPG的图片打不开怎么办呢&#xff1f;当JPG图片打不开的时候&#xff0c;我们需要先了解下具体的原因&#xff0c;是因为格式不支持&#xff0c;还是因为图片文件损坏。不同的原因&#xff0c;解决的方法也会不同&#xff0c;比如图片损坏&#xff0c;我们就需要对图片修复处理…

web爬虫笔记:js逆向案例九(某多多 anti_content参数)补环境流程

web爬虫笔记:js逆向案例九(某多多 anti_content参数)补环境流程 一、目标网站:aHR0cHM6Ly9tb2JpbGUueWFuZ2tlZHVvLmNvbS8= 二、接口分析 1、快速定位加密位置(通过搜索/cells/hub/v3快速定位到加密js文件) 2、通过分析可知&#

双系统下,如何隐藏另一个系统分区?

前言 最近有小伙伴在公众号下留言&#xff1a; 小伙伴说&#xff1a;“双系统时&#xff0c;非当前系统的系统盘能不能屏蔽&#xff1f;&#xff01;比如Win7的系统盘在Win10系统时&#xff0c;盘符成了D盘&#xff0c;安装应用软件时&#xff0c;有些文件就到了D盘&#xff0…

DuDuTalk:智能电子录音工牌在销售场景的应用价值

在快速变化的市场环境中&#xff0c;销售团队面临着日益激烈的竞争和不断变化的客户需求。为了提升销售效率、优化客户体验并加强团队协作&#xff0c;越来越多的企业开始采用智能电子录音工牌作为销售场景中的关键工具。本文将从多个方面探讨智能电子录音工牌在销售场景中的应…

一图读懂腾讯云EdgeOne Open Edge平台

为了鼓励更多开发者参与、共同构建和改进边缘应用&#xff0c;腾讯云EdgeOne面向广大开发者&#xff0c;打造了技术开放共创平台——OpenEdge&#xff0c;该平台是国内首个全免费的边缘应用平台&#xff0c;不仅进一步开放了腾讯云遍布世界各地的边缘节点能力&#xff0c;还可以…

Ollama(docker)+ Open Webui(docker)+Comfyui

Windows 系统可以安装docker desktop 相对比较好用一点&#xff0c;其他的应该也可以 比如rancher desktop podman desktop 安装需要windows WSL 安装ollama docker docker run -d --gpusall -v D:\ollama:/root/.ollama -p 11434:11434 --name ollama ollama/ollama 这里…

微服务必备容器化技术

文章目录 docker介绍与安装及上手应用什么是容器化技术&#xff1f;为什么需要学习docker&#xff1f;如何理解dockerdocker下载与安装docker的基础组成docker体验 dockerfile介绍并创建go-zero环境容器docker的基础组成从容器构建属于go环境的容器基于dockerfile构建go容器镜像…

最新技术:跨境电商源码,应对多国市场需求,让您轻松开展全球业务!

随着全球化进程的不断推进&#xff0c;跨境电商已成为企业拓展国际市场的重要途径。为了满足不同国家和地区消费者不断增长的需求&#xff0c;跨境电商源码应运而生&#xff0c;为企业提供了便捷高效的全球化业务发展方案。 一、全球化运营的关键 跨境电商源码的核心功能在于…