Qwen大模型实践之量化
接上篇内容。
1. AutoGPTQ量化
提供了基于AutoGPTQ的量化方案,并开源了Int4和Int8量化模型。量化模型的效果损失很小,但能显著降低显存占用并提升推理速度。
以下我们提供示例说明如何使用Int4量化模型。在开始使用前,请先保证满足要求(如torch 2.0及以上,transformers版本为4.32.0及以上,等等),并安装所需安装包:
pip install auto-gptq optimum
效果测试:
# 通过程序下载Qwen/Qwen-14B-Chat-Int4模型,并将模型放到测试脚本路径下。
# Int4量化模型文件相比原模型文件小很多
(base) root@intern-studio-50014188:~/Qwen# du -sh ./Qwen-14B-Chat/
27G ./Qwen-14B-Chat/
(base) root@intern-studio-50014188:~/Qwen# du -sh ./Qwen-14B-Chat-Int4/
9.1G ./Qwen-14B-Chat-Int4/
# 修改web_demo.py,使用Qwen-14B-Chat-Int4模型。然后运行程序
(qwen) root@intern-studio-50014188:~/Qwen# python3 web_demo.py
经过测试显存占用明显降低,约10G;使用相同问答,推理速度提示较明显,包括第一个令牌时间(TTFT)和输出令牌吞吐量都提升明显,接近于可接受的水平。
附官网BF16,Int8和Int4模型在基准评测,量化模型效果损失较小,结果如下所示:
Quantization | MMLU | CEval (val) | GSM8K | Humaneval |
---|---|---|---|---|
Qwen-1.8B-Chat (BF16) | 43.3 | 55.6 | 33.7 | 26.2 |
Qwen-1.8B-Chat (Int8) | 43.1 | 55.8 | 33.0 | 27.4 |
Qwen-1.8B-Chat (Int4) | 42.9 | 52.8 | 31.2 | 25.0 |
Qwen-7B-Chat (BF16) | 55.8 | 59.7 | 50.3 | 37.2 |
Qwen-7B-Chat (Int8) | 55.4 | 59.4 | 48.3 | 34.8 |
Qwen-7B-Chat (Int4) | 55.1 | 59.2 | 49.7 | 29.9 |
Qwen-14B-Chat (BF16) | 64.6 | 69.8 | 60.1 | 43.9 |
Qwen-14B-Chat (Int8) | 63.6 | 68.6 | 60.0 | 48.2 |
Qwen-14B-Chat (Int4) | 63.3 | 69.0 | 59.8 | 45.7 |
Qwen-72B-Chat (BF16) | 74.4 | 80.1 | 76.4 | 64.6 |
Qwen-72B-Chat (Int8) | 73.5 | 80.1 | 73.5 | 62.2 |
Qwen-72B-Chat (Int4) | 73.4 | 80.1 | 75.3 | 61.6 |
2. KV cache量化
修改web_demo.py程序开启KV cache量化:
(qwen) root@intern-studio-50014188:~/Qwen# vim web_demo.py
...
model = AutoModelForCausalLM.from_pretrained(
args.checkpoint_path,
device_map=device_map,
trust_remote_code=True,
resume_download=True,
use_cache_quantization=True,
use_cache_kernel=True,
use_flash_attn=False,
).eval()
...
运行程序后,模型加载完毕,显存占用9G左右,有降低。但是问答测试过程中本机测试遇到如下问题待解决:
return forward_call(*args, **kwargs)
File "/root/.cache/huggingface/modules/transformers_modules/Qwen-14B-Chat-Int4/modeling_qwen.py", line 505, in forward
torch.ones((key.size(1), key.size(1)), dtype=torch.bool, device=key.device)
AttributeError: 'tuple' object has no attribute 'size'
User: 你好
Traceback (most recent call last):
File "/usr/local/lib/python3.8/dist-packages/gradio/queueing.py", line 527, in process_events
response = await route_utils.call_process_api(
File "/usr/local/lib/python3.8/dist-packages/gradio/route_utils.py", line 270, in call_process_api
output = await app.get_blocks().process_api(
在模型推理时,我们可以将中间结果key以及value的值量化后压缩存储,这样便可以在相同的卡上存储更多的key以及value,增加样本吞吐。
在config.json
里提供了use_cache_quantization
和use_cache_kernel
两个参数来控制是否启用KV cache量化,具体使用方法如下:
model = AutoModelForCausalLM.from_pretrained(
"Qwen/Qwen-7B-Chat",
device_map="auto",
trust_remote_code=True,
use_cache_quantization=True,
use_cache_kernel=True,
use_flash_attn=False
)
注意: 当前该功能不支持与flash attention同时开启,如果你开了KV cache量化的同时又开了flash attention(use_flash_attn=True, use_cache_quantization=True, use_cache_kernel=True),程序默认将关闭use_flash_attn。
效果方面,我们验证过Int8 KV Cache的使用对模型整体的精度指标基本无损。我们做了针对显存占用的性能测试。评测运行于单张A100-SXM4-80G GPU,模型默认使用BF16格式,默认生成1024个token,其中OOM表示内存不足。
开启了KV cache量化之后,模型在推理的时候可以开启更大的batch size (bs)。
USE KV Cache | bs=1 | bs=4 | bs=16 | bs=32 | bs=64 | bs=100 |
---|---|---|---|---|---|---|
No | 16.3GB | 24.1GB | 31.7GB | 48.7GB | oom | oom |
Yes | 15.5GB | 17.2GB | 22.3GB | 30.2GB | 48.2GB | 72.4GB |
开启了KV cache量化之后,模型在推理时可在生成更长的序列(sl,生成的token数)时,节约更多的显存。
USE KV Cache | sl=512 | sl=1024 | sl=2048 | sl=4096 | sl=8192 |
---|---|---|---|---|---|
no | 15.2GB | 16.3GB | 17.6GB | 19.5GB | 23.2GB |
yes | 15GB | 15.5GB | 15.8GB | 16.6GB | 17.6GB |
开启KV cache量化后,模型在推理时会将原始存进layer-past
的float格式的key/value转换成int8格式,同时存储量化部分的参数。
具体操作如下:
-
将key/value进行量化操作
qv,scale,zero_point=quantize_cache_v(v)
-
存入 layer_past
中:
量化格式的layer-past
:
layer_past=((q_key,key_scale,key_zero_point),
(q_value,value_scale,value_zero_point))
原始格式的layer-past
:
layer_past=(key,value)
如果需要将layer-past
中存好的key,value直接取出使用,可以使用反量化操作将Int8格式的key/value转回float格式:
v=dequantize_cache_torch(qv,scale,zero_point)
3. 推理性能测试
本机使用官网脚本测试遇到如下问题,待解决:
File "/root/Qwen/profile.py", line 45, in <module>
from auto_gptq import AutoGPTQForCausalLM
ImportError: cannot import name 'AutoGPTQForCausalLM' from partially initialized module 'auto_gptq' (most likely due to a circular import) (/usr/local/lib/python3.8/dist-packages/auto_gptq/__init__.py)
这里附官网数据和方法:
这一部分将介绍模型推理的速度和显存占用的相关数据。下文的性能测算使用 此脚本 完成。
我们测算了BF16、Int8和Int4模型在生成2048个token时的平均推理速度(tokens/s)和显存使用。结果如下所示:
Model Size | Quantization | Speed (Tokens/s) | GPU Memory Usage |
---|---|---|---|
1.8B | BF16 | 54.09 | 4.23GB |
Int8 | 55.56 | 3.48GB | |
Int4 | 71.07 | 2.91GB | |
7B | BF16 | 40.93 | 16.99GB |
Int8 | 37.47 | 11.20GB | |
Int4 | 50.09 | 8.21GB | |
14B | BF16 | 32.22 | 30.15GB |
Int8 | 29.28 | 18.81GB | |
Int4 | 38.72 | 13.01GB | |
72B | BF16 | 8.48 | 144.69GB (2xA100) |
Int8 | 9.05 | 81.27GB (2xA100) | |
Int4 | 11.32 | 48.86GB | |
72B + vLLM | BF16 | 17.60 | 2xA100 |
评测运行于单张A100-SXM4-80G GPU(除非提到使用2xA100),使用PyTorch 2.0.1、CUDA 11.8和Flash-Attention2。(72B + vLLM 使用 PyTorch 2.1.0和Cuda 11.8.)推理速度是生成2048个token的速度均值。
注意:以上Int4/Int8模型生成速度使用autogptq库给出,当前AutoModelForCausalLM.from_pretrained
载入的模型生成速度会慢大约20%。我们已经将该问题汇报给HuggingFace团队,若有解决方案将即时更新。
我们还测量了不同上下文长度、生成长度、Flash-Attention版本的推理速度和 GPU 内存使用情况。可以在 Hugging Face 或 ModelScope 上的相应的模型介绍页面找到结果。
本文由 mdnice 多平台发布