这一章节主要考察量化部署推理的时候内存占用知识,以及如何通过量化等方案来减小模型部署显存占用;
1. 模型显存占用构成:
推理需要的内存主要有三部分:加载模型、激活和KV-cache,量化通过降低大型语言模型 (LLM) 的参数精度(例如从 16 位到 4 位)来减小其大小。
模型存储规模:参数量 * 格式,BP
然而KV-cache 所占用的内存大小不可忽视,KV-cache用以存储模型的中间计算结果,让自回归生成时直接查询,以减少生成时间。以7B 模型10000Token为例,
10000 个词元的输入时,我们需要多少内存来存储 KV 缓存。存储一个词元的 KV 缓存所需的内存大致为 2 * 2 * 层数 * 键值抽头数 * 每抽头的维度
,其中第一个 2
表示键和值,第二个 2
是我们需要的字节数 (假设模型加载精度为 float16
)。因此,如果上下文长度为 10000 词元,仅键值缓存所需的内存我们就要:
2 * 2 * 32 * 32 * 128 * 10000 ≈ 5GB
该内存需求几乎是半精度模型参数所需内存的三分之一。相当高;
2. 模型进行 W4A16 量化+ KV cache+KV cache 量化
采用了50%的A100, 显存空间为40GB
采用了 1.8B 模型,BF16格式,那么模型参数占用的是3.6 GB
root/models/internlm2_5-1_8b-chat
在KV- cache当中,由于设置的 cache-max-entry-count 数为0.8,既 40-3.6 = 36.4 * 0.8 = 29.12GB, 结合激活层0.8GB 左右,总共显存为: 33.6GB 左右,我们看看实际显存占用:
非常接近
下面进行W4A16 量化
lmdeploy lite auto_awq \
/root/models/internlm2_5-1_8b-chat \
--calib-dataset 'ptb' \
--calib-samples 128 \
--calib-seqlen 2048 \
--w-bits 4 \
--w-group-size 128 \
--batch-size 1 \
--search-scale False \
--work-dir /root/models/internlm2_5-1_8b-chat-w4a16-4bit
具体命令解释:
lmdeploy lite auto_awq
:lite
这是LMDeploy的命令,用于启动量化过程,而auto_awq
代表自动权重量化(auto-weight-quantization)。/root/models/internlm2_5-7b-chat
: 模型文件的路径。--calib-dataset 'ptb'
: 这个参数指定了一个校准数据集,这里使用的是’ptb’(Penn Treebank,一个常用的语言模型数据集)。--calib-samples 128
: 这指定了用于校准的样本数量—128个样本--calib-seqlen 2048
: 这指定了校准过程中使用的序列长度—2048--w-bits 4
: 这表示权重(weights)的位数将被量化为4位。--work-dir /root/models/internlm2_5-7b-chat-w4a16-4bit
: 这是工作目录的路径,用于存储量化后的模型和中间结果。
模型量化后,从3.6GB 减小到1.5GB
有个问题是为什么不是4倍缩减呢,是因为量化过程中表示激活(或输入/输出)仍然保持在16位浮点数(例如FP16或BF16)。激活是在神经网络中传播的数据,通常在每层运算之后产生。因而不是整数倍减少;
3. 量化后的模型推理:
使用结合W4A16量化与kv cache量化的internlm2_5-1_8b-chat
模型封装本地API并与大模型进行一次对话,具体不再赘述,cache-max-entry-count 设置为 0.4,那么我们看看显存占用多少呢?
可以推算,KV-cache实际应该是(40-1.5)* 0.4 = 15.4GB, 模型参数1.5GB ,激活大概0.5GB 总共是17.4GB, 与显示数值相同;
4. 与Function call 功能结合;
采用了和Open AI相同的 tool 调用形式,具体格式逻辑如下:
最终结果看似很完美,然而看看后台却很失望
可以看到是采用了openAI的 response 格式要求,在这个中间我们发现了一个不好的地方;
由于计算(3+5)*2 其实是两次逻辑操作,如果一个足够智能的agent,自行控制流程,并进行下一次输入中间计算的参数,然而不行的是,我们发现是写死的,过程是写死的,'3+5={func1_out}',这种方式平添了人工。
哎,还是不够智能哈。