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

LLM推理优化——KV Cache篇(百倍提速)

LLM推理优化——KV Cache篇(百倍提速)

请添加图片描述

注意:KV Cache本质上是空间换时间的技术。与计算机组成原理中的cache不同,它不涉及访存优化。

不知道大家在用LLM的时候,有没有注意到一个问题:我们在输入我们的问题之后,需要等待一段漫长的时间才能看到第一个字符的响应,而等待第一个之后,后续的响应却非常之快,这就是使用了KV Cache加速后的带来的优势。

LLM推理过程与自注意力机制

LLM的推理过程和训练过程是有所区别的,LLM在训练过程中使用因果掩码并行化训练,无需像RNN一样等待之前的结果运算结束。但是他的推理过程却类似RNN,并且有大量的重复计算。详细解释可以参照上一篇Blog:LLM的训练与推断。我们已经知道LLM推断时实际上是一种自回归模型 f θ f_\theta fθ,假设在 t t t步及其之前的输入和推断表示为 x 1 : t x_{1:t} x1:t,我们可以用公式表示它:

x 1 : t + 1 = f θ ( x 1 : t ) (1) % \begin{align} x_{1:t+1} = f_\theta(x_{1:t}) \tag{1} % \end{align} x1:t+1=fθ(x1:t)(1)

从公式1我们可以看到,即使 x 1 : t x_{1:t} x1:t已经是计算过的,但是在计算 x t + 1 x_{t+1} xt+1时却还要重复计算 x 1 : t x_{1:t} x1:t,当序列愈来愈长,这个计算代价也越来越不可接受,尤其绝大多数计算都是在做无用功(重复计算)。

基于此,我们就有一个朴素的优化思考:我们能否去除掉这些重复计算?那答案是当然可以,不然就没有这篇博客了🤣。

那么如何去除呢?如果有动态规划、搜索基础的小伙伴可能会比较眼熟,类似于常用的剪枝操作。将后续仍然需要使用的计算结果保存起来,后续使用时不必再次计算

那么来看一下具体是如何实施的,从LLM的训练与推断中我们可以知道,需要重复计算的矛盾点来自于自注意力机制,首先回顾一下它:
a t t n ( Q , K , V ) = s o f t m a x ( Q T K d k ) V attn(Q,K,V) = softmax\left(\frac{Q^TK}{\sqrt{d_k}}\right)V attn(Q,K,V)=softmax(dk QTK)V
我们可以用行列向量的形式表示第t步计算 x t x_t xt时的 ( Q T K ) t (Q^TK)_t (QTK)t
( Q T K ) t = ( q 1 T k 1 q 1 T k 2 … q 1 T k t q 2 T k 1 q 2 T k 2 … q 2 T k t ⋮ ⋮ ⋱ ⋮ q t T k 1 q t T k 2 … q t T k t ) ( Q T K ) t + 1 = ( q 1 T k 1 q 1 T k 2 … q 1 T k t q 1 T k t + 1 q 2 T k 1 q 2 T k 2 … q 2 T k t q 2 T k t + 1 ⋮ ⋮ ⋮ ⋮ q t T k 1 q t T k 2 … q t T k t q t T k t + 1 q t + 1 T k 1 q t + 1 T k 2 … q t + 1 T k t q t + 1 T k t + 1 ) \begin{align} (Q^TK)_t&= \left( \begin{array}{cccc} q^T_1k_1 & q^T_1k_2&\ldots&q^T_1k_t\\ q^T_2k_1 & q^T_2k_2&\ldots&q^T_2k_t\\ \vdots& \vdots&\ddots&\vdots\\ q^T_tk_1 & q^T_tk_2&\ldots&q^T_tk_t\\ \end{array}\right)\notag \\ (Q^TK)_{t+1}&= \left( \begin{array}{ccccc} q^T_1k_1 & q^T_1k_2&\ldots&q^T_1k_t&q^T_1k_{t+1}\\ q^T_2k_1 & q^T_2k_2&\ldots&q^T_2k_t&q^T_2k_{t+1}\\ \vdots& \vdots&\ &\vdots&\vdots\\ q^T_tk_1 & q^T_tk_2&\ldots&q^T_tk_t&q^T_tk_{t+1}\\ q^T_{t+1}k_1 & q^T_{t+1}k_2&\ldots&q^T_{t+1}k_t&q^T_{t+1}k_{t+1}\\ \end{array}\right)\notag \\ \end{align} (QTK)t(QTK)t+1= q1Tk1q2Tk1qtTk1q1Tk2q2Tk2qtTk2q1Tktq2TktqtTkt = q1Tk1q2Tk1qtTk1qt+1Tk1q1Tk2q2Tk2qtTk2qt+1Tk2 q1Tktq2TktqtTktqt+1Tktq1Tkt+1q2Tkt+1qtTkt+1qt+1Tkt+1

从式子中可以看到,在计算 ( Q T K ) t + 1 (Q^TK)_{t+1} (QTK)t+1时,前t行t列已经被计算过,我们只需要计算最后一行并且保存即可。由 q t + 1 T k 1 , q t + 1 T k 2 , … , q t + 1 T k t , q t + 1 T k t + 1 q^T_{t+1}k_1, q^T_{t+1}k_2,\ldots,q^T_{t+1}k_t,q^T_{t+1}k_{t+1} qt+1Tk1,qt+1Tk2,,qt+1Tkt,qt+1Tkt+1可知,我们还需要知道之前每次计算出的 k k k值,所以在保存每行值之外,也应当保存 k 1 , k 2 , … , k t + 1 k_1, k_2,\ldots,k_{t+1} k1,k2,,kt+1的值。

这里可能会有疑惑,最后一列用了之前的 q 1 , q 2 , … , q t q_1,q_2, \ldots,q_t q1,q2,,qt,为什么不保存 q q q的值。实际上, Q T K Q^TK QTK矩阵会经过一个掩码操作,他最后得到是一个下三角矩阵,我们不必再次计算,直接补0即可。

保存 V V V值亦是同理。

保存 K , V K,V K,V是不是KV Cache名称的由来呢?

相关文章:

LLM推理优化——KV Cache篇(百倍提速)

LLM推理优化——KV Cache篇(百倍提速) 注意:KV Cache本质上是空间换时间的技术。与计算机组成原理中的cache不同,它不涉及访存优化。 不知道大家在用LLM的时候,有没有注意到一个问题:我们在输入我们的问题…...

Linux进程--system

...

[Office] Word 特殊字符

0 打开“特殊字符集” 依次选择:Insert -> Symbol -> More Symbol 1 带圈编号 字体Font选择Wingdings...

联想电脑怎么重装系统_联想电脑U盘重装win10详细图文教程

联想电脑怎么重装系统?在当今科技发展迅猛的时代,联想电脑已经成为了人们生活中不可或缺的一部分。然而,随着时间的推移,我们可能会遇到一些问题,例如系统崩溃或者需要更换操作系统。这时,使用U盘来重新安装…...

前端开发者必备:揭秘谷歌F12调试的隐藏技巧!

前言 使用断点(breakpoint)是调试 JavaScript 代码的一种非常有效的方式。通过在代码的关键位置设置断点,可以阻止页面的状态变化,从而方便地检查和修改页面的当前状态。 1. 使用 setTimeout 配合 debugger 和 console.log setTi…...

vivado IP_REPO_PATHS

此属性允许您创建自定义IP目录,以与Vivado Design Suite一起使用。 IP_REPO_PATHS属性定义了一个或多个目录的路径,这些目录包含 第三方或用户定义的IP。指定的目录和任何子目录是 搜索要添加到Vivado Design Suite IP目录以用于设计的IP定义 进入或与IP…...

前端代码混淆加密(使用Terser、WebpackObfuscator)

零、相关技术及版本号 "vue": "2.6.12", "vue/cli-service": "4.4.6", "javascript-obfuscator": "^4.1.1", "terser-webpack-plugin": "^4.2.3", "vue-template-compiler": &quo…...

【复读EffectiveC++24】条款24:若所有参数皆需类型转换,请为此采用non-member函数

条款24:若所有参数皆需类型转换,请为此采用non-member函数 一、问题引入 举个例子,如果你设计一个表示有理数的类,允许从整型到有理数的隐式转换应该是合理的。在C内置类型中,从int转换到double也是再合理不过的了&a…...

Mac应用快速启动器:Alfred 5 for Mac 激活版

Alfred 5 是一款专为 macOS 系统设计的效率提升工具。这款软件以其快速启动和高效操作功能著称,通过使用快捷键来呼出输入界面,用户可以快速完成各种任务。 最新版本 Alfred 5.5 引入了一些新功能。其中包括整合了 ChatGPT 和 DALL-E,这意味…...

oracle语法介绍

Oracle数据库是关系型数据库管理系统之一,其SQL语法遵循标准的SQL规范,但也有一些自己的扩展。以下是一些Oracle SQL语法的基本示例: 1.选择数据: SELECT * FROM my_table; 1.插入数据: INSERT INTO my_table (colum…...

Python IDLE修改JetBrains Mono字体教程

自己在使用Python IDLE过程中发现原生字体不好看,不美观。尤其是对于部分字符,l打印不美观,区别不明显。于是诞生了换字体的想法。 教程简单,快速,3-5分钟不到即可完成。 目录 选型 下载安装 使用 选型 考虑到代码…...

CCF编程能力等级认证GESP—C++1级—20240629

CCF编程能力等级认证GESP—C1级—20240629 单选题(每题 2 分,共 30 分)判断题(每题 2 分,共 20 分)编程题 (每题 25 分,共 50 分)休息时间立方数 单选题(每题 2 分,共 30…...

继HBM之后, 内存领域新宠MCR DIMM闪亮登场!

随着人工智能(AI)和大数据的迅速发展,新型DRAM正迎来新的发展机遇。在服务器需求的推动下,MCRDIMM作为内存行业的新宠儿,正逐步登上历史舞台。 扩展阅读:MCR DIMM如何解决内存带宽瓶颈? MCR DIM…...

谷粒商城实战笔记-75-商品服务-API-品牌管理-品牌分类关联与级联更新

文章目录 一,引入Mybatis Plus分页插件二,品牌列表的模糊查询三,增加品牌测试数据四,开发后台品牌关联分类接口1,接口product/categorybrandrelation/catelog/list2,接口product/categorybrandrelation/sav…...

Java中的equals()与==的区别与用法

1. 区别 “”操作符用于比较两个对象的地址是否相等。.equals() 方法用于比较两个对象的内容是否相等。 Object 类的 .equals() 方法默认采用的是“”操作符进行比较。假如子类没有重写该方法的话,那么“”操作符和 .equals() 方法的功效就完全一样——比较两个对…...

【ai】 2005年 rule based expert system学习笔记1

PPT 是2005年的? Negnevitsky, Pearson Education 使用两种推理引擎的选择 backward chaining(逆向链接)推理过程 backward chaining(逆向链接)推理过程的GPT解释 这幅图展示了一个基于规则的专家系统如何通过backward chaining(逆向链接)推理过程来达到最终的推理目标…...

AI写作|去除了AI味道,我还花2分钟动手制作了一个coze智能体

本文背景: AI写出来的东西,机器味太浓? AI生成的文章内容质量不稳定、因为依赖于已有的数据和模式,AI可能很难创作出具有深度见解或独创性的内容 AI还无法完全理解复杂的上下文关系,导致生成的内容与用户期望的上下文不…...

数据集相关类代码回顾理解 | utils.make_grid\list comprehension\np.transpose

目录 utils.make_grid list comprehension np.transpose utils.make_grid x_gridutils.make_grid(x_grid, nrow4, padding2) make_grid 函数来自torchvision的utils模块,用于图像数据可视化,将一批图像排列成一个网格。 x_grid:四维图像…...

React前端面试每日一试 3.状态(State)和属性(Props)的区别是什么?

加粗样式先简单介绍一下Props和State的特点 Props(属性) Props(Properties)是React组件间传递数据的一种方式。它们是从父组件传递给子组件的只读数据,子组件不能修改这些数据。Props主要用于配置组件,使…...

射灯怎么安装才好看,射灯安装防踩坑

射灯安装的5个尺寸,不懂容易踩坑      你得选好角度,算好安装距离      为了防止我们花了钱却装不出效果      1,射灯是可以调角度的,一般选24度和36度就行      像小的装饰画可以选24度,大的装饰画选36度      也就是重点照明选24,洗墙和打造小山丘36度  …...

docker详细操作--未完待续

docker介绍 docker官网: Docker:加速容器应用程序开发 harbor官网:Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台,用于将应用程序及其依赖项(如库、运行时环…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器:https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

2021-03-15 iview一些问题

1.iview 在使用tree组件时,发现没有set类的方法,只有get,那么要改变tree值,只能遍历treeData,递归修改treeData的checked,发现无法更改,原因在于check模式下,子元素的勾选状态跟父节…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘&#xf…...

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析

Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...

使用SSE解决获取状态不一致问题

使用SSE解决获取状态不一致问题 1. 问题描述2. SSE介绍2.1 SSE 的工作原理2.2 SSE 的事件格式规范2.3 SSE与其他技术对比2.4 SSE 的优缺点 3. 实战代码 1. 问题描述 目前做的一个功能是上传多个文件,这个上传文件是整体功能的一部分,文件在上传的过程中…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例

目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...

Matlab实现任意伪彩色图像可视化显示

Matlab实现任意伪彩色图像可视化显示 1、灰度原始图像2、RGB彩色原始图像 在科研研究中,如何展示好看的实验结果图像非常重要!!! 1、灰度原始图像 灰度图像每个像素点只有一个数值,代表该点的​​亮度(或…...

密码学基础——SM4算法

博客主页:christine-rr-CSDN博客 ​​​​专栏主页:密码学 📌 【今日更新】📌 对称密码算法——SM4 目录 一、国密SM系列算法概述 二、SM4算法 2.1算法背景 2.2算法特点 2.3 基本部件 2.3.1 S盒 2.3.2 非线性变换 ​编辑…...