大语言模型(LLM)中大数据的压缩存储及其重要性

在大型语言模型(LLM)中,KV Cache(键值缓存)的压缩方法及其重要性。

为什么要压缩KV Cache?

  • 计算效率:在生成文本的过程中,每个生成的token都需要与之前所有的token的键值(K和V)进行交互。如果不使用KV Cache,则每次生成新token时都需要重新计算,这将导致巨大的计算量。
  • 显存消耗:KV Cache虽然减少了计算量,但随着token数量的增加,它占用的显存也会增加。显存是有限的,因此需要对KV Cache进行压缩。

KV Cache的分类及方法

  • 生成阶段压缩:大多数方法集中在生成阶段的KV Cache压缩,以支持长文本的生成或加速计算。这些方法通常采用驱逐策略,保留重要的KV,舍弃不重要的。
  • ClusterKV:通过聚类KV Cache中的token,并使用聚类中心来判断重要性,减少计算量同时保持精度。
  • LeanKV:根据每个attention head的需要保留不同的KV,分为高精度和低精度保留,动态调整以压缩KV Cache。

输入prompt的KV Cache压缩

  • SnapKV:针对输入prompt太长导致的问题,通过识别输入中的模式来压缩KV Cache。它假设这些模式在生成过程中是一致的。
  • ZigZagKV:在SnapKV的基础上进行优化,提出不应该给每个attention head分配相同大小的显存,而应根据每个head所需的最少token数来分配。

ZigZagKV的空间分配

  • 问题:给模型的每一层分配相同大小的显存来存储KV Cache是不合理的,因为不同层的LMBA(维持attention score所需的最小KV数)差异很大。
  • 解决方案:提出了一种按比例分配显存的方法,并为每个层保留一个最小大小,以避免某些层分配到的空间过小。

效果

  • 文章最后提到,ZigZagKV在各种测试中表现最佳,特别是在大海捞针测试中。

总结

在大型语言模型中,如何通过压缩KV Cache来提高计算效率和减少显存消耗。不同的压缩方法针对不同的场景和需求,而ZigZagKV方法在保持模型性能的同时,有效地解决了显存分配的问题。

 

 

  

 

 

source:ZigZagKV,KVCache80%的压缩率可以达到近乎无损的效果

为什么要压缩?

输入Prompt和decoding阶段生成的每个token都会产生对应的K和V。每次生成一个新的token的时候,当前的需要和历史上所有的K和V进行交互得到结果,所以我们一般把已经计算出来的K和V都保存起来供后面的token使用,保存的结果就叫做KV Cache。

如果不使用KV Cache来保存历史结果,那么每一个token生成的时候都需要重新计算prompt和之前生成的tokens的K和V。显然,KV Cache减小了计算量。但是,它增加了显存的消耗。随着token的数量增多,需要越来越多的显存。而我们的显存显然不是无穷大的,这就要求我们需要做KV Cache的压缩。此外,随着KV的增多,每生成一个token的计算量也越来越大(因为需要和所有的K和V都进行计算)。这进一步增加了KV Cache压缩的需求。

KV Cache分类以及方法

KV Cache的内容来源于两个方面:

  1. 输入prompt;

  2. 生成的token。

之前的大多数文章里面的KV Cache方法都集中在处理生成阶段压缩KV Cache,以此来支持生成长文本或者在生成过程中加速计算。这一类KV Cache压缩的方法大多采取驱逐策略,保留系统认为重要的KV,舍弃那些不重要的。其中重要性的判断非常重要,大部分的系统都是对于每一层按照attention score的大小,保留top-B的结果。

前面的文章:

  • ClusterKV,接近无损的KV Cache压缩方法

  • LeanKV, 接近无损的5倍的KV Cache压缩以及2.5倍的吞吐提升

介绍了两种效果都不错的KVCache压缩方法。其中ClusterKV的重要观察点是对于一个q重要的所有token对应的K之间的cos距离都比较小。另外就是KV Cache里面某个token的重要性是动态变化的。基于这两个观察,ClusterKV把KV Cache里面的token进行聚类,使用聚类的中心来做重要性判断,如果一个类被判断为重要那么就把这一个类里面所有的token都拿来做计算,这样既减少了计算量还保持了精度。而KVCache并不常驻显存,这样就可以减少显存使用。这篇文章的方法其实是显著不同于大多数采用驱逐策略的方法,因为每个KV都没有完全被驱逐,都是可重入的。

LeanKV也是一篇做得非常细致的文章。核心观察是每一层的每个attention head需要保留的重要KV不一样,并且具有稀疏性。基于这个观察,它不以layer为单位,而是以attention head为单位,去保留对应的重要KV。保留的KV又会分为高精度保留、低精度保留。每次新生成了KV的时候,每个attention head会去计算是否保留新的K和V,如果保留,是否需要驱逐之前的。用这种动态的方法,达到压缩KV又保持精度的效果。

另外一类文章,以SnapKV为代表,研究的是另外一个问题:输入太长,压缩输入prompt的KV Cache。这里的压缩并不是要让生成的token很长,而是不压缩的话可能输入就已经把显存撑爆。或者即便显存还可以,每一步计算也会因为需要交互的token太多而非常慢。所以压缩输入的KV解决的是这两个问题。

ZigZagKV其实是在SnapKV上继续做优化,也就是说,它也是输入prompt的KV Cache压缩算法。它的核心改进点在于不应该给每个attention head分配同样多的显存,而应该根据每个head可以保留绝大部分信息需要的token数来进行分配(SnapKV给所有的layer的head是平均分配的)。

ZigZagKV的一些新的观察

我们首先定义MBA(MinimumBudget size required to maintain 90% of the totalAttention score),其实就是维持90%的attention score需要的最小KV数:

其中,是的第i个元素。是当前KV Cache里面的token数量。

由于每个attention head都可以计算出一个MBA值,我们把一层里面所有的attention head的MBA的均值叫做LMBA(LayerMinimumBudget size to maintainAttention score):

LMBA越高也就意味着需要更多的token来维持精度,也就意味着需要分配更多的显存来存储KV Cache。

我们分别计算了Mistral和LLaMA在WikiMQA数据集上的LMBA,结果如下:

图片

可以看出,不同的模型的对应层的LMBA差距比较大;同一个模型不同层的LMBA差距也很大。

刚才我们分析是基于保持attention score,我们再以输出的相似性这个维度分析一下需要保留多少的KV才能让输出类似。我们定义LMBO(Layer-wiseMinimumBudget forOutput):

其中是用所有的KV得到的输出,是用一部分得到的结果。

图片

我们再次发现,同一个模型不同层在保持输出基本一致的限制下需要的KV数量差距很大。

基于上面的两个观察,我们得出的结论就是给模型的每一层分配同样大小显存来存储KV Cache是不合理的

ZigZagKV空间分配

为每一层分配多大的空间存储KV Cache是合理的呢?

一个直观的想法就是按照比例来分配,大层多份,小的少分。

上面公式里面的就是每一层按照LMBA计算得到的比例,B是单层的Budget,是模型的L层总共的budget,是第层分到的大小。

这么分其实有一个问题,就是如果某一层的LMBA特别大的时候可能导致某些层分配到的空间特别小,也就意味着这些层基本无法保存任何KV。一个层基本没有KV Cache,效果自然保证不了。所以,我们给每个层保留一个最小大小,分配公式改为

这就是ZigZagKV的主要改进点。ZigZagKV和SnapKV都假设给prompt的KV Cache空间是,SanpKV给每一层均匀分配B空间。而ZigZagKV自适应地分配空间。

解决了每一层KV Cache的空间分配问题,还有一个问题就是要保存那些K和V。这里需要先介绍SnapKV。

SnapKV

如果我们输入的prompt有16K,那么如果存储对应的所有KV无论对于显存还是计算都有极大的压力。那显然,我们需要压缩prompt生成的KV。为了压缩输入KV,SnapKV有一个非常重要的观察:

Pattern can be identified before generation and is consistent during generation

什么意思呢?其实就是说,输入里面哪些重要可以使用输入prompt本身就可以决定。

作者把输入128个token为单位划分window,取靠近尾部的20个window来做计算。prompt前面的部分叫做prefix, 20个窗口叫做observation window。对于prefix里面的任意一个token,假设叫做。我们取20个window里面的某一个window,假设叫。的每一个元素和都会有交互,因为在的元素前面。那么,的每个元素和都会计算出一个attention score。这样,对于窗口,会有128个attention score。取这128个attention score的均值作为的重要性值。

这样,对于窗口,prefix的每个token都可以计算出重要性值。注意,我们计算的时候是按照attention head为单位计算的。计算完之后就可以得到。其中是attention head的数量;是一个窗口内token的数量,这里其实就是128;是prompt除了观察的20个窗口的token之外其他的token的总数。

对于每个attention head,prefix里面每个token和窗口内的每个token都有一个attention score,把它们取平均得到最后的score。这是一个的矩阵。然后每个head可以根据平均score选出重要的topK个token。

也可以根据设定的K值选出topK重要的token,其中,代表压缩率。

在生成一个token的时候,对于当前step的q,它和prefix里面的所有token都会有交互。对于模型的每一层,可以计算出的attention score。我们设定一个阈值,我们认为大于这个阈值的attention score对应的token对于当前生成的token来说都是重要的。以此来选择出生成阶段prefix中的重要token。

我们比较窗口选择出来的重要token和生成阶段选择出来的重要token的重叠率,也就是论文所说的Hit Rate

用数学公式表达就是:

其中。公式稍微有点复杂,更多还是看我的描述吧,文字容易懂点。

通过比较20个窗口选择的重要token和生成阶段实际选择出来的重要token,我们发现最后一个窗口选择出来的和生成阶段选择的是高度重合的。也就意味着,Pattern can be identified before generation

在生成了若干个token之后,我们把生成的token也像输入一样分成4个窗口,每个窗口包含128个token。然后使用这四个窗口去选择prefix中的重要token。最后发现,选择出来的和prompt里面最后一个窗口选择的是高度吻合的。

图片

这也就是开始所说的Pattern is consistent during generation.

SnapKV基于这两个观察,放心地用prompt里面最后一个窗口来压缩输入prompt的KV Cache。实际上,作者也观察到只使用上面直接用窗口选择的内容,会造成生成的信息不全。所以,实际上的操作是在计算完均值矩阵之后,对每一行都使用1D Pooling操作。其思想很简单,比如第5个token很重要,那么它相邻的4和6我们也应该选进来,不然5的上下文不全。而要选到4和6最简单的就是pool一下,可以简单理解为跟高斯模糊一个性质。

最后选择的token就是pool之后的topK,再机上最后一个窗口里面所有的token。

ZigZagKV的token选择

SnapKV里面token的选择跟上面的SnapKV非常类似。只不过每个head的配额少了,在相同压缩率的情况下topK的K对于每个head是变化的。所以对每个head按照配额大小计算好K,其它的都跟上面的方法一致。

效果

大海捞针测试,ZigZagKV最好:

图片

其它一些细分测试里面,ZigZag也是最好的。

参考文献

[1].ClusterKV,接近无损的KV Cache压缩方法

[2].LeanKV, 接近无损的5倍的KV Cache压缩以及2.5倍的吞吐提升

[3]. ZigZagKV: Dynamic KV Cache Compression for Long-context Modeling based on Layer Uncertainty

[4]. SnapKV: LLM Knows What You are Looking for Before Generation

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

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

相关文章

Springboot关于格式化记录

日期格式化 返回前端日期需要格式化 <dependency><groupId>com.fasterxml.jackson.core</groupId><artifactId>jackson-databind</artifactId><version>2.9.2</version> </dependency>JsonFormat(pattern "yyyy-MM-dd…

条款19 对共享资源使用std::shared_ptr

目录 一、std::shared_ptr 二、std::shared_ptr性能问题 三、control block的生成时机 四、std::shared_ptr可能存在的问题 五、使用this指针作为std::shared_ptr构造函数实参 六、std::shared_ptr不支持数组 一、std::shared_ptr<T> shared_ptr的内存模型如下图&…

Linux第99步_Linux之点亮LCD

主要学习如何在Linux开发板点亮屏&#xff0c;以及modetest命令的实现。 很多人踩坑&#xff0c;我也是一样。关键是踩坑后还是实现不了&#xff0c;这样的人确实很多&#xff0c;从群里可以知道。也许其他人没有遇到这个问题&#xff0c;我想是他运气好。 1、修改设备树 1)、…

攻破 kioprix level 4 靶机

又又又来了... 法一、 基本步骤 1.确认主机ip&#xff0c;扫描端口确定服务和版本 2.访问网站&#xff0c;扫描目录&#xff0c;查找敏感信息 3.利用敏感信息和SQL注入进入网站 4.ssh服务连接主机 5.shell逃逸并查找敏感信息&#xff08;与数据库等相关&#xff09; 6.m…

Qt自定义步骤引导按钮

1. 步骤引导按钮 实际在开发项目过程中&#xff0c;由一些流程比较繁琐&#xff0c;为了给客户更好的交互体验&#xff0c;往往需要使用step1->step2这种引导对话框或者引导按钮来引导用户一步步进行设置&#xff1b;话不多说&#xff0c;先上效果 2. 实现原理 实现起来…

解决nuxt3下载慢下载报错问题

在下载nuxt3时总是下不下来&#xff0c;最后还报错了。即使改成国内镜像源也不行。 解决方法&#xff1a; 直接去github上下载 https://github.com/nuxt/starter/tree/v3 解压后得到如下目录&#xff1a; 手动修改项目名和文件夹名 安装依赖 npm install可能会比较慢或下不…

ShenNiusModularity项目源码学习(6:访问控制)

ShenNius.Admin.API项目中的控制器类的函数如果需要访问控制&#xff0c;主要是调用ShenNius.Infrastructure项目下的AuthorityAttribute特性类实现的。AuthorityAttribute继承自ActionFilterAttribute抽象类&#xff0c;后者用于在调用控制器操作函数前后自定义处理逻辑&#…

【连续学习之SSL算法】2018年论文Selfless sequential learning

1 介绍 年份&#xff1a;2018 期刊&#xff1a; arXiv preprint Aljundi R, Rohrbach M, Tuytelaars T. Selfless sequential learning[J]. arXiv preprint arXiv:1806.05421, 2018. 本文提出了一种名为SLNID&#xff08;Sparse coding through Local Neural Inhibition and…

《鸿蒙HarmonyOS应用开发从入门到精通(第2版)》学习笔记——HarmonyOS技术理念

1.2 技术理念 在万物智联时代重要机遇期&#xff0c;HarmonyOS结合移动生态发展的趋势&#xff0c;提出了三大技术理念&#xff08;如下图3-1所示&#xff09;&#xff1a;一次开发&#xff0c;多端部署&#xff1b;可分可合&#xff0c;自由流转&#xff1b;统一生态&#xf…

基于springboot校园招聘系统源码和论文

可做计算机毕业设计JAVA、PHP、爬虫、APP、小程序、C#、C、python、数据可视化、大数据、文案 使用旧方法对校园招聘系统的信息进行系统化管理已经不再让人们信赖了&#xff0c;把现在的网络信息技术运用在校园招聘系统的管理上面可以解决许多信息管理上面的难题&#xff0c;比…

【小程序】自定义组件的data、methods、properties

目录 自定义组件 - 数据、方法和属性 1. data 数据 2. methods 方法 3. properties 属性 4. data 和 properties 的区别 5. 使用 setData 修改 properties 的值 自定义组件 - 数据、方法和属性 1. data 数据 在小程序组件中&#xff0c;用于组件模板渲染的私有数据&…

Python 敲电子木鱼,见机甲佛祖,修赛博真经

Python 敲电子木鱼&#xff0c;见机甲佛祖&#xff0c;修赛博真经 相关资源文件已经打包成EXE文件&#xff0c;可下载相关资源压缩包后双击直接运行程序&#xff0c;且文章末尾已附上相关源码&#xff0c;以供大家学习交流&#xff0c;博主主页还有更多Python相关程序案例&…

acitvemq AMQP:因为消息映射策略配置导致的MQTT接收JMS消息乱码问题 x-opt-jms-dest x-opt-jms-msg-type

使用ActiveMQ&#xff08;5.14.5&#xff09;作消息系统服务的场景下&#xff0c; 当我用Apache Qpid Proton发送消息(使用AMQP协议)发送JMS消息&#xff0c;用Paho MQTT接收消息的时候&#xff0c; 收到的消息前面总是有一串乱码&#xff0c;大概就是这样&#xff1a; 4Sp?AS…

viva-bus 航空机票网站 Akamai3 分析

声明: 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 有相关问题请第一时间头像私信联系我删…

pyQT + OpenCV相关练习

一、设计思路 1、思路分析与设计 本段代码是一个使用 PyQt6 和 OpenCV 创建的图像处理应用程序。其主要功能是通过一个图形界面让用户对图片进行基本的图像处理操作&#xff0c;如灰度化、翻转、旋转、亮度与对比度调整&#xff0c;以及一些滤镜效果&#xff08;模糊、锐化、边…

【数据库初阶】Linux中库的基础操作

&#x1f389;博主首页&#xff1a; 有趣的中国人 &#x1f389;专栏首页&#xff1a; 数据库初阶 &#x1f389;其它专栏&#xff1a; C初阶 | C进阶 | 初阶数据结构 亲爱的小伙伴们&#xff0c;大家好&#xff01;在这篇文章中&#xff0c;我们将深入浅出地为大家讲解 Linux…

Element Plus 日期时间选择器大于当天时间置灰

效果&#xff1a; 实现思路&#xff1a; 点击官方链接的日期时间选择器的属性查看&#xff0c;发现disabled-date属性 一个用来判断该日期是否被禁用的函数&#xff0c;接受一个 Date 对象作为参数。 应该返回一个 Boolean 值&#xff0c;即用函数返回布尔值。 前言 JavaScrip…

线性直流电流

电阻网络的等效 等效是指被化简的电阻网络与等效电阻具有相同的 u-i 关系 (即端口方程)&#xff0c;从而用等效电阻代替电阻网络之后&#xff0c;不 改变其余部分的电压和电流。 串联等效&#xff1a; 并联等效&#xff1a; 星角变换 若这两个三端网络是等效的&#xff0c;从任…

Java与SQL Server数据库连接的实践与要点

本文还有配套的精品资源&#xff0c;点击获取 简介&#xff1a;Java和SQL Server数据库交互是企业级应用开发中的重要环节。本文详细探讨了使用Java通过JDBC连接到SQL Server数据库的过程&#xff0c;包括加载驱动、建立连接、执行SQL语句、处理异常、资源管理、事务处理和连…

【Halcon】例程讲解:基于形状匹配与OCR的多图像处理(附图像、程序下载链接)

1. 开发需求 在参考图像中定义感兴趣区域&#xff08;ROI&#xff09;&#xff0c;用于形状匹配和文本识别。通过形状匹配找到图像中的目标对象位置。对齐多幅输入图像&#xff0c;使其与参考图像保持一致。在对齐后的图像上进行OCR识别&#xff0c;提取文本和数字信息。以循环…