5.LMDeploy 量化部署 LLM 实践

视频链接:LMDeploy 量化部署 LLM-VLM 实践_哔哩哔哩_bilibili

项目链接:https://github.com/InternLM/Tutorial/blob/camp2/lmdeploy/README.md

5.0 LMDeploy介绍

5.0.1 模型部署面临的挑战

计算密集(compute-bound): 指推理过程中,绝大部分时间消耗在数值计算上;针对计算密集型场景,可以通过使用更快的硬件计算单元来提升计算速度。

访存密集(memory-bound): 指推理过程中,绝大部分时间消耗在数据读取上;针对访存密集型场景,一般通过减少访存次数、提高计算访存比或降低访存量来优化。

常见的 LLM 模型由于 Decoder Only 架构的特性,实际推理时大多数的时间都消耗在了逐 Token 生成阶段(Decoding 阶段),是典型的访存密集型场景。

(1)大模型前向推理计算量大,部署困难。

20B的小模型计算一个token需要进行406亿次浮点数计算,175B的大模型计算千万亿次。对比A100显卡性能,每秒77万亿。

前向推理计算量 = 2*参数量 + 2*模型层数*记忆长度*注意力输出的维度,浮点数运算数量

(2)内存开销大

加载:20B模型加载占40G+显存,175B模型需要350G+显存。

推理:参数KV,FP16 + BATCH_SIZE=16 + INPUT_TOKENS=512 + OUTPUT_TOKENS=32 ——>10G+缓存。

A100 最大80G显存

(3)访存瓶颈

BATCH_SIZE=1 + INPUT_TOKENS=1000 + OUTPUT_TOKENS=250 = 计算量是6.83万亿次

6.83TFLOPs+中间结果+写入 = 访存32.62T。

4090的FP16计算性能是每秒82.58万亿次,6.83/82.58<<10%。但显存带宽1008G/S每秒一万亿个字节数,6.83万亿/1万亿=6秒,大部分时间是浪费到传输数据。

5.0.2 模型部署方法

(1)模型剪枝

用不到的参数剪掉

(2)知识蒸馏

不是所有参数有用,间接训练一个没有冗余参数的小模型:先训练一个大模型(“教师”模型),通过模型迁移获得小模型(“学生”模型)

(3)量化

改变表示格式:浮点数转换成整数或其他离散格式。模型参数默认是存储成32位浮点数,占4个字节。减小存储位数可以尽可能多的传输数据,即使还要反量化,这也只是增加了计算量,却没有达到访存瓶颈。

5.0.3 LMDeploy

轻量化部署工具,高效推理引擎TurboMind、W4A16量化(AWQ,FP16->INT4,压缩到1/4)、服务化部署

5.1 搭建环境

开发机和conda环境创建:10%A100,镜像Cuda12.2-conda

激活环境和安装包LMDeploy

studio-conda -t lmdeploy -o pytorch-2.1.2
conda activate lmdeploy

pip install lmdeploy[all]==0.3.0

5.2 与模型对话:Transformer库 v.s. LMDeploy

Transformer库直接运行HF格式模型,LMDeploy要将HF格式模型转换为TurboMind格式的模型。

5.2.1 Transformer库

创建软链接,下载文件夹/root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b的模型

与模型对话,创建对话文件pipeline_transformer.py。对话文件代码见项目链接2.3节。

# 创建软链接
ln -s /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b /root/

#创建对话文件pipeline_transformer.py
touch /root/pipeline_transformer.py

# 运行
python /root/pipeline_transformer.py

实验结果:大概八分钟完成实验

5.2.2 LMDeploy

LMDeploy与模型进行对话的指令:

# 指令格式lmdeploy chat [HF格式模型路径/TurboMind格式模型路径]
lmdeploy chat /root/internlm2-chat-1_8b

实验结果:大概两分钟完成实验

5.3 LMDeploy模型量化(lite)

量化是一种以参数或计算中间结果精度下降换空间节省(以及同时带来的性能提升)的策略。

KV8量化W4A16量化:

KV8量化是指将逐 Token(Decoding)生成过程中的上下文 K 和 V 中间结果进行 INT8 量化(计算时再反量化),以降低生成过程中的显存占用。代价是模型推理速度降低

W4A16 量化,将 FP16 的模型权重量化为 INT4,Kernel 计算时,访存量直接降为 FP16 模型的 1/4,大幅降低了访存成本。Weight Only 是指仅量化权重,数值计算依然采用 FP16(需要将 INT4 权重反量化)。

5.3.1 设置最大KV Cache缓存大小——KV8量化对比实验

KV Cache:

一种缓存技术,通过存储键值对的形式来复用计算结果,以达到提高性能和降低内存消耗的目的。在大规模训练和推理中,KV Cache可以显著减少重复计算量,从而提升模型的推理速度。理想情况下,KV Cache全部存储于显存,以加快访存速度。当显存空间不足时,也可以将KV Cache放在内存,通过缓存管理器控制将当前需要使用的数据放入显存。

模型在运行时,占用的显存可大致分为三部分:模型参数本身占用的显存、KV Cache占用的显存,以及中间运算结果占用的显存。即三部分共分A100的80G。LMDeploy的KV Cache管理器可以通过设置--cache-max-entry-count参数,控制KV缓存占用剩余显存的最大比例。默认的比例为0.8。

下面通过几个例子,来看一下调整--cache-max-entry-count参数的效果。

# 0.8
lmdeploy chat /root/internlm2-chat-1_8b

# 0.5
lmdeploy chat /root/internlm2-chat-1_8b --cache-max-entry-count 0.5

# 0.01
lmdeploy chat /root/internlm2-chat-1_8b --cache-max-entry-count 0.01

(1)不加该参数(默认0.8),运行1.8B模型

显存占用7856M/8182M=96.02%。

(2)--cache-max-entry-count 0.5

6608M/8182M=80.76%

(3)--cache-max-entry-count 0.01

模型本身和中间结果占用显存,4560M/8182M=55.63%

5.3.2 使用W4A16量化

命令:

# 安装依赖库
pip install einops==0.7.0

# lite量化 auto_awq自动量化方法 模型 ptb数据集 采样率128
lmdeploy lite auto_awq \              
   /root/internlm2-chat-1_8b \
  --calib-dataset 'ptb' \
  --calib-samples 128 \
  --calib-seqlen 1024 \
  --w-bits 4 \
  --w-group-size 128 \
  --work-dir /root/internlm2-chat-1_8b-4bit

7432M

0.01:2472M

5.4 LMDeploy服务(serve)

(1)运行命令行客户端

lmdeploy serve api_server \
    /root/internlm2-chat-1_8b \
    --model-format hf \
    --quant-policy 0 \
    --server-name 0.0.0.0 \
    --server-port 23333 \
    --tp 1

(2) 网页客户端连接API服务器

lmdeploy serve gradio http://localhost:23333 \
    --server-name 0.0.0.0 \
    --server-port 6006

ssh -CNg -L 6006:127.0.0.1:6006 root@ssh.intern-ai.org.cn -p <你的ssh端口号>

访问地址http://127.0.0.1:6006

5.5 Python代码集成

(1)代码集成运行模型

conda activate lmdeploy
touch /root/pipeline.py


# pipeline.py
from lmdeploy import pipeline

pipe = pipeline('/root/internlm2-chat-1_8b')
response = pipe(['Hi, pls intro yourself', '上海是'])
print(response)

# 运行
python /root/pipeline.py

(2)代码集成实现量化

touch /root/pipeline_kv.py

# pipeline_kv.py
from lmdeploy import pipeline, TurbomindEngineConfig

# 调低 k/v cache内存占比调整为总显存的 20%
backend_config = TurbomindEngineConfig(cache_max_entry_count=0.2)

pipe = pipeline('/root/internlm2-chat-1_8b',
                backend_config=backend_config)
response = pipe(['Hi, pls intro yourself', '上海是'])
print(response)

5.6 使用LMDeploy运行视觉多模态大模型llava

(1)代码

# 激活环境
conda activate lmdeploy

# 安装包
pip install git+https://github.com/haotian-liu/LLaVA.git@4e2277a060da264c4f21b364c867cc622c945874

# 创建文件
touch /root/pipeline_llava.py

# pipeline_llava.py
from lmdeploy.vl import load_image
from lmdeploy import pipeline, TurbomindEngineConfig

backend_config = TurbomindEngineConfig(session_len=8192) # 图片分辨率较高时请调高session_len
# pipe = pipeline('liuhaotian/llava-v1.6-vicuna-7b', backend_config=backend_config) 非开发机运行此命令
pipe = pipeline('/share/new_models/liuhaotian/llava-v1.6-vicuna-7b', backend_config=backend_config)

image = load_image('https://raw.githubusercontent.com/open-mmlab/mmdeploy/main/tests/data/tiger.jpeg')
response = pipe(('describe this image', image))
print(response)

# 运行
python /root/pipeline_llava.py

(2)网页端

5.7 定量比较LMDeploy与Transformer库的推理速度差异

Transformer库推理Internlm2-chat-1.8b的速度,新建python文件benchmark_transformer.py,填入以下内容,再运行。

import torch
import datetime
from transformers import AutoTokenizer, AutoModelForCausalLM

tokenizer = AutoTokenizer.from_pretrained("/root/internlm2-chat-1_8b", trust_remote_code=True)

# Set `torch_dtype=torch.float16` to load model in float16, otherwise it will be loaded as float32 and cause OOM Error.
model = AutoModelForCausalLM.from_pretrained("/root/internlm2-chat-1_8b", torch_dtype=torch.float16, trust_remote_code=True).cuda()
model = model.eval()

# warmup
inp = "hello"
for i in range(5):
    print("Warm up...[{}/5]".format(i+1))
    response, history = model.chat(tokenizer, inp, history=[])

# test speed
inp = "请介绍一下你自己。"
times = 10
total_words = 0
start_time = datetime.datetime.now()
for i in range(times):
    response, history = model.chat(tokenizer, inp, history=history)
    total_words += len(response)
end_time = datetime.datetime.now()

delta_time = end_time - start_time
delta_time = delta_time.seconds + delta_time.microseconds / 1000000.0
speed = total_words / delta_time
print("Speed: {:.3f} words/s".format(speed))

测试LMDeploy的推理速度,新建python文件benchmark_lmdeploy.py,填入以下内容,运行。

import datetime
from lmdeploy import pipeline

pipe = pipeline('/root/internlm2-chat-1_8b')

# warmup
inp = "hello"
for i in range(5):
    print("Warm up...[{}/5]".format(i+1))
    response = pipe([inp])

# test speed
inp = "请介绍一下你自己。"
times = 10
total_words = 0
start_time = datetime.datetime.now()
for i in range(times):
    response = pipe([inp])
    total_words += len(response[0].text)
end_time = datetime.datetime.now()

delta_time = end_time - start_time
delta_time = delta_time.seconds + delta_time.microseconds / 1000000.0
speed = total_words / delta_time
print("Speed: {:.3f} words/s".format(speed))

实验结果如下:Transformer库的推理速度约为78.675 words/s,注意单位是words/s,不是token/s,word和token在数量上可以近似认为成线性关系。LMDeploy的推理速度约为473.690 words/s,是Transformer库的6倍。

​​​​​​​

### 量化部署技术介绍及应用 #### 什么是量化部署量化部署是一种通过减少模型参数表示的比特数来降低存储需求和计算复杂度的技术。这种技术能够显著减小模型大小并加速推理过程,同时尽可能保留原始模型的准确性[^2]。 #### 常见的量化方法 常见的量化方法包括但不限于线性量化、非线性量化以及混合精度量化。其中,线性量化是最常用的方法之一,它可以将权重压缩到较低位宽的数据类型,例如8位浮点数(FP8)、8位整数(INT8)、4位整数(INT4)甚至2位整数(INT2)。这些低精度数据类型的使用可以极大地节省内存占用,并提升计算效率。 #### 工具支持 为了简化开发者的操作流程,许多开源项目提供了专门用于量化的工具包。例如,`Optimum-Quantao` 是 PyTorch 的一个扩展,专注于大语言模型 (LLM) 的高效量化处理。该工具不仅实现了多种标准量化方案的支持,还引入了量化感知训练(QAT, Quantization-Aware Training),从而进一步改善经过量化的模型质量。 另外,在实际工程实践中也有其他成熟的解决方案可供选择,比如 `LMDeploy` 提供了一个名为 “lite” 的子模块来进行模型轻量化工作流管理;而针对特定的大规模预训练模型如 ChatGLM2,则有详细的指导文档描述如何完成从环境搭建到最终服务上线的一系列步骤][^[^35]。 #### 应用场景分析 当前阶段下,由于资源受限或者实时响应的要求等原因,使得在移动终端或者其他嵌入式平台上运行复杂的深度学习算法变得尤为重要起来。因此,借助于先进的量化技术和配套软件栈的帮助,越来越多的企业和个人开发者都能够成功地将自己的研究成果转化为可落地的产品形态。具体来说: 1. **边缘计算领域** 随着物联网设备数量激增,对于能够在本地执行简单任务的小型AI应用程序的需求日益增长。此时运用合适的量化策略便显得尤为关键——既满足即时决策所需的速度条件又兼顾功耗方面的考量因素[^4]。 2. **云计算环境中** 即使是在拥有强大算力支撑的数据中心内部署大型神经网络结构时,合理安排不同层次间的通信开销同样不可忽视。通过对某些部分实施不同程度上的近似运算代替精确求解方式,可以在不明显牺牲整体表现的前提下有效缓解带宽瓶颈问题。 ```python import torch from optimum.quantization import OptimumQuantizer model = ... # 加载未量化的原生模型实例 quantizer = OptimumQuantizer(bits=4) # 执行静态或动态量化转换逻辑 quantized_model = quantizer.apply_quantization(model=model) ``` 以上代码片段展示了利用 Python 编程语言配合相关 API 接口快速实现基本功能的过程概览。 #### 展望未来发展趋势 展望未来几年内可能出现的新变化趋势方面,预计会有更加智能化自动调优机制被研发出来以便更好地适应多样性的业务诉求特征。与此同时,伴随着新型专用硬件架构设计思路逐渐成熟定型之后也将极大促进整个行业的快速发展进程。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值