作者 | Civ 编辑 | 自动驾驶之心
原文链接:https://zhuanlan.zhihu.com/p/673775476
点击下方卡片,关注“自动驾驶之心”公众号
ADAS巨卷干货,即可获取
点击进入→自动驾驶之心【大语言模型】技术交流群
本文只做学术分享,如有侵权,联系删文
端侧LLM毫无疑问会成为各手机厂商在2024年的主战场。从国内各手机厂透露的信息来看,大家几乎都把希望寄托在了芯片厂身上,自身能做的、会做的工作太少。希望苹果的工作对国内厂商们有启发、借鉴意义。
论文链接:LLM in a flash: Efficient Large Language Model Inference with Limited Memory
1. Flash Memory and DRAM
在移动端设备中(如手机),DRAM可理解为“运行时内存”,Flash Memory可理解为“存储空间”。做一个简单的类比,在PC中,DRAM对应于内存;Flash Memory对应于硬盘存储(注意:仅仅是对应于,实现方案并不一样)。
在通常的LLM推理阶段,LLM都是直接加载到DRAM中的。一个7B半精度LLM,完全加载进DRAM所需的存储空间超过14GB。考虑到目前主流手机的DRAM最高也就16GB的水平,在端侧直接使用DRAM来加载7B LLM面临巨大挑战。
图1给出了一个移动端标准的存储结构示意图。
![aef20e15678d91707999c2eb7460f74e.png](https://i-blog.csdnimg.cn/blog_migrate/8e51e1f6739c6c87fc7703491f8ad6e6.png)
Flash Memory的特点是大存储,低带宽。也就是说,Flash Memory可存储的内容多(图中的100GB),但数据传输速率低(图中的1GB/s)。而DRAM的特点是小存储,高带宽。
现在的问题是:模型大小 > DRAM,所以无法将模型全部加载进DRAM。
苹果的解决方案是将LLM放在Flash Memory中,在每次需要进行推理时,仅仅将部分必要参数加载到DRAM中。
苹果的整个方案重点解决两个问题:
如何快速识别出哪些模型参数是必要的
考虑到由Flash memory到DRAM的带宽较低,如何加快由Flash memory到DRAM的传输效率
论文中从三个不同方面做了尝试,下面分别介绍。
2. 减少数据传输量
这部分介绍论文中采用的三种降低数据传输量的方法。
2.1 方法一:Selective Persistence Strategy
对于常见的LLM而言,它的模型参数主要由Attention参数和MLP参数两部分构成,其中Attention参数占比约为1/3,MLP参数占比约为2/3。除此,还有参数量级可忽略不计的Embedding层的参数。
因为Attention参数量相对较少,所以苹果的方案是将Attention参数和Embedding层的参数直接加载到DRAM中。
这就是所谓的Selective Persistence Strategy,其意为:有选择性地把部分参数常驻在DRAM中。而这部分常驻的参数就是Attention参数和Embedding参数。原因是因为它们占比较小。
2.2 方法二:Anticipating ReLU Sparsity
这里主要借鉴了DejaVu的思路:MLP层的输出只有不到10%的值是激活状态(不为0)。一般把这种现象称为稀疏性。稀疏性越强,则非激活状态的值就越多。
所以我们也可把这句话“MLP层的输出只有不到10%的值是激活状态”简写作“MLP层的稀疏性超过90%”。
要注意,此处的稀疏性一般称为“Contextual Sparsity”。也就是说,MLP层的哪些神经元会激活,与当前的输入相关。
苹果照搬了DejaVu的方法,使用一个两层MLP来预测哪些神经元会激活。方法也很简单,假设神经元个数为4096,只需要将MLP的输出层的大小设为4096,并为每一个输出使用sigmoid来做一个二分类即可(“选择”or“不选择”)。
注意1:不同Transformer层使用的预测模型不同。
注意2:同一个Transformer层中的MLP一般有两层。它们的激活神经元始终保持相同。
在能够准确预测的前提下,每次在推理时动态加载预测为激活神经元对应的参数即可。
这里有对DejaVu详细介绍的文章:[ICML'23] DejaVu:LLM中的动态剪枝
2.3 方法三:Sliding Window
根据2.2小节中介绍的稀疏性可知,在每一次LLM进行前向推理时,它都需要使用模型预测每一个MLP层中激活神经元的编号,并将所需的神经元所对应的权重由Flash memory加载到DRAM中。
因为LLM的推理阶段是逐token进行的,这意味着在生成不同token的时候,需要加载到DRAM中的MLP的参数也不同。
用一个简单的例子来说明这个基础概念,只考虑第 层的Transformer模块。在处理当前token 时,该层使用模型预测MLP会激活的神经元编号,假设为{0, 1, 3, 5},并将其对应的参数从Flash memory加载到DRAM中,然后进行推理。
在处理下一个token 时,将 从DRAM中删除,再使用模型预测MLP会激活的神经元编号,假设为{0, 2, 3, 6},并将其对应的参数从Flash memory加载到DRAM中,然后进行推理。
注意到在我们的例子中,两次前向推理时,第 层的Transformer结构中MLP有部分被预测为激活的神经元是重叠的:{0, 3}。所以实际上在进行第二次前向推理时,没有必要把完全从DRAM中删除,而是将其中编号为{1, 5}神经元对应的参数删除,再将编号为{2, 6}的神经元对应的参数读入即可。这样可以减少I/O的总开销。
这就是Sliding Window的核心思想:保留处理过去k个token时的激活神经元所对应的参数在DRAM中,并在处理当前token时只对:1)部分多余的参数进行删除;2)缺少的参数进行加载。图2是原文中的示意图。
![af7b327108db030ccaad068ad667c26c.png](https://i-blog.csdnimg.cn/blog_migrate/5fb23bc2a6d3dd7c2e58e8d1326a0347.png)
图中上图表示在处理当前token “Was”之前,前5个token(k=5)的激活神经元(淡蓝色偏绿部分)。图中下图表示在处理当前token “Was”之时,需要新加入的神经元(蓝色部分)和需要删除的神经元(分红部分)。
Sliding Window的核心假设是LLM在处理相邻token时产生的稀疏性具有相似性。原文没有仔细分析和论证这个假设。
3 提高传输吞吐量
3.1 Bundling Columns and Rows
通常LLM中的MLP层包含两个全连层。在忽略激活函数的情况下,这两个全连层可以写为:
![a09784a128b3f65fe68f6c7b8b89adb6.png](https://i-blog.csdnimg.cn/blog_migrate/ebab7d00922b713b476d3d5e25853fbd.png)
在2.2小节中曾经提到,稀疏性预测是对MLP中两个全连层同时进行的。也就是说,如果我们预测结果是第一个全连层中0号神经元不会被激活,那么该预测结果同样也适用于第二个全连层:第二个全连层的0号神经元也不会被激活。
对于第一个全连层的参数矩阵,第i个神经元对应于它的第i列;对于第二个全连层的参数矩阵,第i个神经元对应于它的第i行。
当第i个神经元被预测为激活时,需要同时读取的第i列和的第i行。所以为了提高读取速度,可以将的每一列和的对应行拼接起来存储,如下图所示:
![9bd4f30ec950d545c152c0a3613a9637.png](https://i-blog.csdnimg.cn/blog_migrate/47b2395985551f636bfefbf74dfc78dd.png)
图3中的Up Proj指的是第一个全连层,对应于上文参数矩阵;Down Proj指第二个全连层,对应于上文参数矩阵。
这样做的好处是原本需要两次I/O,现在只需要一次了。虽然总的数据读取量并没有变,但读取大块、连续的数据会比读取大量小块、非连续数据更加高效,因此整体传输吞吐量提升了。
3.2 Bundling Based on Co-activation
这是一个原文尝试过,但被验证为无效的策略。既然原文提到了,所以这里也罗列出来。
原文中猜测某些神经元之间可能存在一些紧密联系。比如对于两个神经元a和b,当a激活时,b也会激活(或者当b激活时,a也会激活)。
因此可以通过分析来找到每个神经元的“closest friend”(与该神经元同时激活频率最高的其它某个神经元)。然后在存储Flash memory中存储时,也将它们的参数拼接存在一起。这样的读取效率更高。
但该方法之所以无效,主要原因是可能会存在某个神经元i,它是其它很多神经元的“closest friend”。这样导致的问题则是神经元i被额外传输了太多次,导致实际的I/O成本增加了。
4 Optimized Data Management in DRAM
虽然DRAM的数据读取速度比Flash memory快很多,但当需要对其中数据进行大量、高频读写时,它的时耗仍然不可忽略。在本文介绍的内容中,对DRAM的读写主要发生在对MLP层中所需神经元对应参数的删除与新增(参考图2)。
为此,论文中设计了一种特殊的数据结构来对DRAM中的数据做精细化管理。该数据结构的核心变量如下:
Matrix:按照“Bundling Columns and Rows”的方法存储激活神经元所对应的参数
bias:激活神经元所对应的bias参数
num_used:激活神经元的个数
last_k_active:过去k个token所对应的激活神经元编号
Pointer:当前行参数对应的神经元编号
![d80fd67086c18b16529175c901f26b3f.png](https://i-blog.csdnimg.cn/blog_migrate/2f59714a0872d82bed1be79472467b15.png)
![1dea7698240ecdbc25b1a5cf4712cdca.png](https://i-blog.csdnimg.cn/blog_migrate/ae4c5bae45ac914d89d7402c2f0ad563.png)
通过预分配一个足够大的空间,可以避免因反复分配而导致的额外开销。下面来说明基于该数据结构的一些操作的高效实现方法。
该矩阵中的行对应的是当前存储在DRAM中激活神经元的参数。前文提到(2.3小节),当处理新的token时,需要将不会被激活的神经元删除,并添加新的会被激活的神经元。所以最重要的两个操作是“删除”和“新增”。
当需要删除某个神经元时(如图4中左图标红部分,对应的是编号为10的神经元),只需将num_rows的数量减1,并将最后一行Copy至被删除行,结果如图4的中图所示。虚线框表示当前有效的数据。
当需要“新增”时,直接将其对应的参数由Flash memory中copy至该矩阵中即可,无需额外分配存储空间。
5. 实验结果
苹果这篇paper的主要关注点在于:让LLM在运行时内存受限的情况下能高效地跑起来。所以论文的实验主要对比了各种情况下I/O导致的时耗,如下图所示。
![d94e8a9b70504a9e7d35eb14b8eb9d2b.png](https://i-blog.csdnimg.cn/blog_migrate/2e29d3da86583f2eee2f4fa3abbd01b2.png)
图5中的实验使用的是OPT 6.7B模型,半精度。表中第一行和第二行都是基准baseline。第一行假设初始模型全部在Flash memory中,那么为了完成一次完整的推理,需要将模型全部加载一遍,整个I/O耗时2130ms。
第二行对应于假设模型有一半参数提前在DRAM中的整个加载耗时。
第三行到第五行对应于应用了Predictor(2.2小节)、Windowing(2.3小节)和Bundling(3.1小节)后对应的耗时。
效率提升非常明显。
投稿作者为『自动驾驶之心知识星球』特邀嘉宾,欢迎加入交流!
① 全网独家视频课程
BEV感知、毫米波雷达视觉融合、多传感器标定、多传感器融合、多模态3D目标检测、车道线检测、轨迹预测、在线高精地图、世界模型、点云3D目标检测、目标跟踪、Occupancy、cuda与TensorRT模型部署、大模型与自动驾驶、Nerf、语义分割、自动驾驶仿真、传感器部署、决策规划、轨迹预测等多个方向学习视频(扫码即可学习)
![4eba0efb0d1f9d41690bb28a2af2d152.png](https://i-blog.csdnimg.cn/blog_migrate/54e5362f8617bbbf0ba3ccacc39b62b9.png)
② 国内首个自动驾驶学习社区
近2400人的交流社区,涉及30+自动驾驶技术栈学习路线,想要了解更多自动驾驶感知(2D检测、分割、2D/3D车道线、BEV感知、3D目标检测、Occupancy、多传感器融合、多传感器标定、目标跟踪、光流估计)、自动驾驶定位建图(SLAM、高精地图、局部在线地图)、自动驾驶规划控制/轨迹预测等领域技术方案、AI模型部署落地实战、行业动态、岗位发布,欢迎扫描下方二维码,加入自动驾驶之心知识星球,这是一个真正有干货的地方,与领域大佬交流入门、学习、工作、跳槽上的各类难题,日常分享论文+代码+视频,期待交流!
![6f5998757a0e46cc47aed121a398d167.png](https://i-blog.csdnimg.cn/blog_migrate/868e374769654a151d7cbd41a518dc92.png)
③【自动驾驶之心】技术交流群
自动驾驶之心是首个自动驾驶开发者社区,聚焦目标检测、语义分割、全景分割、实例分割、关键点检测、车道线、目标跟踪、3D目标检测、BEV感知、多模态感知、Occupancy、多传感器融合、transformer、大模型、点云处理、端到端自动驾驶、SLAM、光流估计、深度估计、轨迹预测、高精地图、NeRF、规划控制、模型部署落地、自动驾驶仿真测试、产品经理、硬件配置、AI求职交流等方向。扫码添加汽车人助理微信邀请入群,备注:学校/公司+方向+昵称(快速入群方式)
④【自动驾驶之心】平台矩阵,欢迎联系我们!