赞
踩
如何优化 LLM 模型推理中的访存密集问题呢? 我们可以使用 KV Cache 量化和 4bit Weight Only 量化(W4A16)。KV Cache 量化是指将逐 Token(Decoding)生成过程中的上下文 K 和 V 中间结果进行 INT8 量化(计算时再反量化),以降低生成过程中的显存占用。4bit Weight 量化,将 FP16 的模型权重量化为 INT4,Kernel 计算时,访存量直接降为 FP16 模型的 1/4,大幅降低了访存成本。Weight Only 是指仅量化权重,数值计算依然采用 FP16(需要将 INT4 权重反量化)。
KV Cache 量化是将已经生成序列的 KV 变成 Int8,使用过程一共包括三步:
第一步:计算 minmax。主要思路是通过计算给定输入样本在每一层不同位置处计算结果的统计情况。
对于 Attention 的 K 和 V:取每个 Head 各自维度在所有Token的最大、最小和绝对值最大值。对每一层来说,上面三组值都是 (num_heads, head_dim) 的矩阵。这里的统计结果将用于本小节的 KV Cache。
对于模型每层的输入:取对应维度的最大、最小、均值、绝对值最大和绝对值均值。每一层每个位置的输入都有对应的统计值,它们大多是 (hidden_dim, ) 的一维向量,当然在 FFN 层由于结构是先变宽后恢复,因此恢复的位置维度并不相同。这里的统计结果用于下个小节的模型参数量化,主要用在缩放环节(回顾PPT内容)。
第二步:通过 minmax 获取量化参数。主要就是利用下面这个公式,获取每一层的 K V 中心值(zp)和缩放值(scale)。
zp = (min+max) / 2
scale = (max-min) / 255
quant: q = round( (f-zp) / scale)
dequant: f = q * scale + zp
有这两个值就可以进行量化和解量化操作了。具体来说,就是对历史的 K 和 V 存储 quant 后的值,使用时在 dequant。
第三步:修改配置。也就是修改 weights/config.ini 文件,这个我们在《2.6.2 模型配置实践》中已经提到过了(KV int8 开关),只需要把 quant_policy 改为 4 即可。
接下来就可以正常运行前面的各种服务了,只不过咱们现在可是用上了 KV Cache 量化,能更省(运行时)显存了。
KV Cache 可以节约大约 20% 的显存
精度不仅没有明显下降,相反在不少任务上还有一定的提升。可能得原因是,量化会导致一定的误差,有时候这种误差可能会减少模型对训练数据的拟合,从而提高泛化性能。量化可以被视为引入轻微噪声的正则化方法。或者,也有可能量化后的模型正好对某些数据集具有更好的性能。
1.python 量化代码:
from lmdeploy import turbomind as tm # load model model_path = "/root/share/temp/model_repos/internlm-chat-7b/" tm_model = tm.TurboMind.from_pretrained(model_path, model_name='internlm-chat-20b') generator = tm_model.create_instance() # process query query = "你好啊兄嘚" prompt = tm_model.model.get_prompt(query) input_ids = tm_model.tokenizer.encode(prompt) # inference for outputs in generator.stream_infer( session_id=0, input_ids=[input_ids]): res, tokens = outputs[0] response = tm_model.tokenizer.decode(res.tolist()) print(response)
第一步:
第二步:
第三步:
W4A16中的A是指Activation,保持FP16,只对参数进行 4bit 量化。使用过程也可以看作是三步。
第一步:同 1.3.1,不再赘述。
第二步:量化权重模型。利用第一步得到的统计值对参数进行量化,具体又包括两小步:
缩放参数。主要是性能上的考虑(回顾 PPT)。
整体量化。
最后一步:转换成 TurboMind 格式。
TurboMind 相比其他框架速度优势非常显著,比 mlc-llm 快了将近 30%。
TurboMind 在不同精度和上下文长度下的显存占用情况:4bit 模型可以降低 50-60% 的显存占用,效果非常明显。
W4A16
转turboMind
服务部署和量化是没有直接关联的,量化的最主要目的是降低显存占用,主要包括两方面的显存:模型参数(W4A16)和中间过程计算结果(KV Cache)。
量化在降低显存的同时,一般还能带来性能的提升,因为更小精度的浮点数要比高精度的浮点数计算效率高,而整型要比浮点数高很多。
在各种配置下尝试,看效果能否满足需要。这一般需要在自己的数据集上进行测试。具体步骤如下。
Step1:优先尝试正常(非量化)版本,评估效果。
如果效果不行,需要尝试更大参数模型或者微调。
如果效果可以,跳到下一步。
Step2:尝试正常版本+KV Cache 量化,评估效果。
如果效果不行,回到上一步。
如果效果可以,跳到下一步。
Step3:尝试量化版本,评估效果。
如果效果不行,回到上一步。
如果效果可以,跳到下一步。
Step4:尝试量化版本+ KV Cache 量化,评估效果。
如果效果不行,回到上一步。
如果效果可以,使用方案。
精度越高,显存占用越多,推理效率越低,但一般效果较好。
Server 端推理一般用非量化版本或半精度、BF16、Int8 等精度的量化版本,比较少使用更低精度的量化版本。
端侧推理一般都使用量化版本,且大多是低精度的量化版本。这主要是因为计算资源所限。
以上是针对项目开发情况,如果是自己尝试(玩儿)的话:
如果资源足够(有GPU卡很重要),那就用非量化的正常版本。
如果没有 GPU 卡,只有 CPU(不管什么芯片),那还是尝试量化版本。
如果生成文本长度很长,显存不够,就开启 KV Cache。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。