LMDeploy量化部署
基于Cuda12.2-conda镜像,在30% A100下实现。
使用LMDeploy进行模型部署的显存占用计算
如果一个模型是7B,若使用16位精度存储,那么权重参数占用显存计算如下:
对于一个7B(70亿)参数的模型,每个参数使用16位浮点数(等于 2个 Byte)表示,则模型的权重大小约为:
7×10^9 parameters×2 Bytes/parameter=14GB
70亿个参数×每个参数占用2个字节/1024/1024/1024=14GB
lmdeploy默认设置cache-max-entry-count为0.8,即kv cache占用剩余显存的80%
若1.8B的16精度模型,那么权重占显存3.6G,若采用30%的A100,那么总显存24G,剩余显存为24-3.6G,KV缓存默认占16.32G,权重+缓存=19.92G
创建虚拟环境
conda create -n lmdeploy2 python=3.10 -y
conda activate lmdeploy2
conda install pytorch==2.1.2 torchvision==0.16.2 torchaudio==2.1.2 pytorch-cuda=12.1 -c pytorch -c nvidia -y
pip install timm==1.0.8 openai==1.40.3 lmdeploy[all]==0.5.3
链接模型
mkdir /root/models
ln -s /root/share/new_models/Shanghai_AI_Laboratory/internlm2_5-1_8b-chat /root/models
启动对话
lmdeploy chat /root/models/internlm2_5-1_8b-chat
权重+缓存=19.92G,其他约占1G:
LMDeploy支持的模型压缩技术
KV-CACHE设置
lmdeploy chat /root/models/internlm2_5-1_8b-chat --cache-max-entry-count 0.4
观测显存占用情况,可以看到减少了约8GB的显存。
设置在线 kv cache int4/int8 量化
自 v0.4.0 起,LMDeploy 支持在线 kv cache int4/int8 量化,量化方式为 per-head per-token 的非对称量化。此外,通过 LMDeploy 应用 kv 量化非常简单,只需要设定 quant_policy 和cache-max-entry-count参数。目前,LMDeploy 规定 quant_policy=4 表示 kv int4 量化,quant_policy=8 表示 kv int8 量化。
lmdeploy serve api_server \
/root/models/internlm2_5-1_8b-chat \
--model-format hf \
--quant-policy 4 \
--cache-max-entry-count 0.4\
--server-name 0.0.0.0 \
--server-port 23333 \
--tp 1
W4A16 模型量化和部署
准确说,模型量化是一种优化技术,旨在减少机器学习模型的大小并提高其推理速度。量化通过将模型的权重和激活从高精度(如16位浮点数)转换为低精度(如8位整数、4位整数、甚至二值网络)来实现。
那么标题中的W4A16又是什么意思呢?
- W4:这通常表示权重量化为4位整数(int4)。这意味着模型中的权重参数将从它们原始的浮点表示(例如FP32、BF16或FP16,Internlm2.5精度为BF16)转换为4位的整数表示。这样做可以显著减少模型的大小。
- A16:这表示激活(或输入/输出)仍然保持在16位浮点数(例如FP16或BF16)。激活是在神经网络中传播的数据,通常在每层运算之后产生。
因此,W4A16的量化配置意味着:
- 权重被量化为4位整数。
- 激活保持为16位浮点数。
让我们回到LMDeploy,在最新的版本中,LMDeploy使用的是AWQ算法,能够实现模型的4bit权重量化。输入以下指令,执行量化工作。
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
有可能会出现加载calibrate数据集出现NoneType问题:
Loading calibrate dataset ...
Traceback (most recent call last):
File "/root/.conda/envs/lmdeploy2/bin/lmdeploy", line 8, in <module>
sys.exit(run())
File "/root/.conda/envs/lmdeploy2/lib/python3.10/site-packages/lmdeploy/cli/entrypoint.py", line 36, in run
args.run(args)
File "/root/.conda/envs/lmdeploy2/lib/python3.10/site-packages/lmdeploy/cli/lite.py", line 139, in auto_awq
auto_awq(**kwargs)
File "/root/.conda/envs/lmdeploy2/lib/python3.10/site-packages/lmdeploy/lite/apis/auto_awq.py", line 80, in auto_awq
vl_model, model, tokenizer, work_dir = calibrate(model,
File "/root/.conda/envs/lmdeploy2/lib/python3.10/site-packages/lmdeploy/lite/apis/calibrate.py", line 216, in calibrate
calib_loader, _ = get_calib_loaders(calib_dataset,
File "/root/.conda/envs/lmdeploy2/lib/python3.10/site-packages/lmdeploy/lite/utils/calib_dataloader.py", line 302, in get_calib_loaders
return get_ptb(tokenizer, nsamples, seed, seqlen)
File "/root/.conda/envs/lmdeploy2/lib/python3.10/site-packages/lmdeploy/lite/utils/calib_dataloader.py", line 58, in get_ptb
traindata = load_dataset('ptb_text_only', 'penn_treebank', split='train')
File "/root/.conda/envs/lmdeploy2/lib/python3.10/site-packages/datasets/load.py", line 2074, in load_dataset
builder_instance = load_dataset_builder(
File "/root/.conda/envs/lmdeploy2/lib/python3.10/site-packages/datasets/load.py", line 1832, in load_dataset_builder
builder_instance: DatasetBuilder = builder_cls(
TypeError: 'NoneType' object is not callable
解决:需要将datasets降版本:
pip install datasets==2.20.0
优化结果
优化前的:
执行量化后的模型,对比下显存占用
lmdeploy chat /root/models/internlm2_5-1_8b-chat-w4a16-4bit/ --model-format awq
貌似应该是11G左右,但实际占用20G,估计还是KV缓存问题(估计受激活保持16影响)
与量化后的模型对话
加上KV缓存,占用11G:
W4A16 量化+ KV cache+KV cache 量化
同时启用量化后的模型、设定kv cache占用和kv cache int4量化。
lmdeploy serve api_server \
/root/models/internlm2_5-1_8b-chat-w4a16-4bit/ \
--model-format awq \
--quant-policy 4 \
--cache-max-entry-count 0.4\
--server-name 0.0.0.0 \
--server-port 23333 \
--tp 1