赞
踩
9 月 20 日,上海人工智能实验室推出了书生·浦语大模型(InternLM)200 亿参数版本 InternLM-20B。它具备优异的综合性能,以不足三分之一的参数量,测评成绩达到了 Llama2-70B 的水平。
200 亿参数,大约占 40G 显存。意味着,要能推理起来 InternLM-20B,不得不租用价格高昂的 A100 服务器。有没有经济一些的方法呢?答案是有的。那就是低比特量化和推理。
LMDeploy 支持对 LLM 模型进行 4bit 量化,权重的显存开销直接降低到 1/4。只需 16G 的显存即可推理 20B 的模型。而且推理速度相比较 FP16,提升 2 倍以上。一块 3090 显卡就能妥妥玩转 InternLM-20B 模型推理。是不是非常 amazing?
接下来,请跟随本文,一览在 3090 下使用 LMDeploy 部署 InternLM-20B 模型量化、推理全流程。
https://github.com/InternLM/lmdeploy
(欢迎使用,文末点击阅读原文可直达)
4bit 权重量化
使用方法
LMDeploy 已经在 HuggingFace 和 ModelScope 上传了量化后的 internlm-chat-20b 模型,大家可以直接下载,并参考下文“4bit 模型推理服务”章节部署模型。
或者使用如下命令,从零开始,把 InternLM-20B 模型权重量化为 4bit。
- # 下载 internlm-chat-20b 模型到本地
- git-lfs install
- git clone --depth=1 https://huggingface.co/internlm/internlm-chat-20b
- # 安装 lmdeploy
- pip install 'lmdeploy>=0.0.13'
- # 校准
- lmdeploy lite calibrate --model-path ./internlm-chat-20b --work-dir ./internlm-chat-20b-4bit
- # 量化权重
- lmdeploy lite auto_awq --model-path ./internlm-chat-20b --work-dir ./internlm-chat-20b-4bit
量化原理
正式介绍 LMDeploy 量化方案前,需要先介绍两个概念:
计算密集(compute-bound): 指推理过程中,绝大部分的时间是消耗在数值计算上;针对计算密集场景,可以通过使用更快的硬件计算单元来提升计算速度,比如量化为 W8A8 使用 INT8 Tensor Core 来加速计算。
访存密集(memory-bound): 指推理过程中,绝大部分的时间是消耗在数据读取上;针对访存密集型场景,一般是通过减少访存次数、提高计算访存比或降低访存量来优化。
常见的 LLM 模型由于 Decoder Only 架构的特性,实际推理时大多数的时间都消耗在了逐 Token 生成阶段(Decoding 阶段),是典型的访存密集型场景。如下图所示,A100 的 FP16 峰值算力为 312 TFLOPS,只有在 Batch Size 达到 128 这个量级时,计算才成为推理的瓶颈,但由于 LLM 模型本身就很大,推理时还会产生 KV Cache,会占用很多显存,还有一些其他的因素影响(如 Dynamic Batch),实际推理时很难做到 128 这么大的 Batch Size。
那么,如何通过量化来优化 LLM 模型推理中的访存密集问题呢?答案是 4bit Weight Only 量化(W4A16)。
4bit Weight 量化,将 FP16 的模型权重量化为 INT4,Kernel 计算时,访存量直接降为 FP16 模型的 1/4,大幅降低了访存成本,提高了 Decoding 的速度。加速的同时还节省了显存,同样的设备能够支持更大的模型以及更长的对话长度,可谓一举多得。
介绍了 4bit 量化的底层逻辑,那 Weight Only 又是什么呢?刚刚提到了计算密集场景,可以通过 W8A8 量化,使用 INT8 Tensor Core 来加速数值计算,Weight Only 在数值计算部分,是没有进行优化的,在计算时,会先把 4bit 的权重,反量化回 FP16(在 Kernel 内部进行,从 Global Memory 读取时仍是 4bit),依旧使用的是 FP16 的计算单元。
LMDeploy 中使用 AWQ 算法进行 4bit Weight Only 量化。AWQ 是 MIT 韩松团队提出的算法,主要针对 LLM 推理中经常出现的 "Outlier" 进行优化,相较于比较火的 GPTQ 算法,AWQ 算法能够更好更快地获得量化后的模型,AWQ Kernel 的推理速度也会比 GPTQ Kernel 更快一些,ps:LMDeploy 中的 AWQ Kernel 比官方开源的 Kernel 还要快。
对 AWQ 或 GPTQ 算法原理感兴趣的同学,欢迎来 LMDeploy Discussion 与开发者交流讨论,我们未来也会对 AWQ & GPTQ 算法进行详细解读~
https://github.com/InternLM/lmdeploy/discussions
4bit 模型推理
不管是直接下载量化模型,还是从零量化,走到这里,我们手边应该已经有了 internlm-chat-20b 的量化模型,它位于文件夹 internlm-chat-20b-4bit 中。
模型转换
在推理之前,首先要使用命令 lmdeploy convert 把模型转成 LMDeploy 所要求的模型格式。下面我们来认识下这个命令。通过 lmdeploy convert --help,可以看到命令的详细说明。比较重要的参数:
- SYNOPSIS
- lmdeploy convert MODEL_NAME MODEL_PATH <flags>
-
-
- POSITIONAL ARGUMENTS
- MODEL_NAME
- The name of the to-be-deployed model, such as llama-7b, llama-13b, vicuna-7b and etc.
- MODEL_PATH
- The directory path of the model
-
-
- FLAGS
- -m, --model_format=MODEL_FORMAT
- Type: Optional[str]
- Default: None
- The format of the model, fb or hf. 'fb' stands for META's llama format, and 'hf' means huggingface format.
- -d, --dst_path=DST_PATH
- Type: str
- Default: './workspace'
- The destination path that saves outputs.
- --tp=TP
- Type: int
- Default: 1
- The number of GPUs used for tensor parallelism, which should be 2^n.
- -g, --group_size=GROUP_SIZE
- Type: int
- Default: 0
- A parameter used in AWQ to quantize fp16 weights to 4 bits.
其中:
model_name 是模型的简称,用来索引模型的对话模板。关于对话模板的介绍,请参考 LMDeploy GitHub 文档
model_format 表示输入的模型格式。对于量化模型,填写 awq
group_size 为模型量化时使用的 group_size 大小。因为 LMDeploy 的推理引擎 TurboMind 只支持了 group_size=128,所以目前固定填写 128
tp 指模型推理时用的显卡数。LMDeploy 会根据这个参数对模型权重进行切分,推理时,加载到不同的显卡上,做张量并行计算
那么,internlm-chat-20b-4bit 的转换命令是:
- lmdeploy convert \
- --model-name internlm-chat \
- --model-path ./internlm-chat-20b-4bit \
- --model-format awq \
- --group-size 128 \
- --tp 1
完成后,转换结果存放在默认路径 ./workspace 下。
与模型对话
转好模型后,可以在控制台启动一条命令,简单与模型对话,感受下对话是否正确:
lmdeploy chat turbomind ./workspace
也可以启动 gradio,通过更友好的 WebUI 界面和模型聊天:
lmdeploy serve gradio ./workspace
打开浏览器,输入 gradio server 地址,就可以啦!
推理性能
LMDeploy 提供多种测量推理性能的方式:
静态推理能力:在固定 batch、输入、输出 token 个数的前提下,测量 token 的生成速度(tokens/s)。
执行 profile_generation.py 脚本,可得到不同输入组合下的 token 生成吞吐量,以及显存开销。比如:
- python profile_generation.py
- --model-path ./workspace \
- --concurrency 1 2 \
- --prompt-tokens 64 512 \
- --completion-tokens 512 512
在 3090 下的测试结果是:
动态推理能力:测量在不定长请求时的吞吐量(req/s)。这个指标可以通过 profile_throughput.py 脚本得到:
- # 下载对话数据
- wget https://huggingface.co/datasets/anon8231489123/ShareGPT_Vicuna_unfiltered/resolve/main/ShareGPT_V3_unfiltered_cleaned_split.json
- # 执行测试脚本
- python3 profile_throughput.py ShareGPT_V3_unfiltered_cleaned_split.json ./workspace --concurrency 4
在 3090 下的测试结果是:
- Throughput requests: 0.92 req/s, 55.17 req/min
- Throughput tokens: 396.52 tokens/s
- Throughput tokens(output only):189.46 tokens/s
我们注意到,在 LMDeploy 的 GitHub issues 里和社群中,被频繁提到的一个问题是:怎么来调整推理的 batch 大小。答案在转换之后的模型配置文件中,也就是 workspace/triton_models/weights/config.ini。
在 config.ini 中有 3 个重要参数,和推理性能以及显存开销密切相关。
- max_batch_size = 32
- cache_max_entry_count = 48
- session_len = 2056
max_batch_size 控制 LMDeploy 在推理时,batch 的最大值。它必须严格小于或者等于cache_max_entry_count 。
cache_max_entry_count 表示被缓存的对话序列个数。一个对话序列表示一个用户的持续性聊天记录,包含多轮对话。
session_len 为对话序列的最大长度,也是 context window 的大小。值越大,对话序列的 K/V cache 占用显存就越多。
当显存不足时,可以调节这三个参数,来降低推理阶段的显存开销。
搭建推理服务
仅用一条简单的命令,就能启动推理服务。
lmdeploy serve api_server ./workspace
api_server 提供了兼容 openai 服务接口的 RESTful API。在浏览器中输入 http://{server_ip}:23333,就可以通过 swagger UI 阅读、测试每个 API 了。如下图所示,前 3 个 API 和 openai 接口一致,最后一个为 LMDeploy 专有交互模式推理接口。这个接口会把用户对话历史缓存在服务侧,从而避免每次对话都要重复对历史记录进行 context decoding,有助于提高推理效率。
我们后续会带来更详细的关于 api_server 的应用和技术解读,请大家持续关注。
结语
LMDeploy 4bit 推理目前支持的显卡架构是 Ampere 和 Ada Lovelace,也就是 30 系列、40 系列、A10、A100 等显卡。
而在即将发布的 v0.1 版本,LMDeploy 的推理引擎 TurboMind 会支持在图灵架构显卡上的 4bit 模型推理,大家可以在自己的 20 系列游戏卡上愉快地和 InternLM-20B 玩耍了。
除此之外,v0.1 版本还有更多硬核 feature 与大家见面,欢迎关注 https://github.com/InternLM/lmdeploy,动态资讯第一时间掌握!
大模型能成为你的私人医生么?中文医疗大模型评估基准CMB现已加入OpenCompass
(欢迎扫码加入群聊)
点击下方“阅读原文”直达 LMDeploy,欢迎使用
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。