【InternLM 实战营第二期笔记+作业05】LMDeploy量化部署LLM&VLM实践

第五次课程官方操作文档:https://github.com/InternLM/Tutorial/blob/camp2/lmdeploy/README.md

第五次课程官方录播课程:

LMDeploy 量化部署 LLM-VLM 实践_哔哩哔哩_bilibili

一、模型部署

1定义:

  • 在软件工程中,部署通常指的是将开发完毕的软件投入使用的过程。
  • 在人工智能领域,模型部署是实现深度学习算法落地应用的关键步骤。简单来说,模型部署就是将训练好的深度学习模型在特定环境中运行的过程

2场景:

  • 服务器端:CPU部署,单GPU/TPU/NPU部署,多卡/集群部署…
  • 移动端/边缘端:移动机器人,手机.…

3大模型部署面临的挑战:

1.大模型参数量巨大,前向推理时需要进行大量计算。

根据InternLM2技术报告[1]提供的模型参数数据,以及OpenAl团队提供的计算量估算方法[2],20B模型每生成1个token,就要进行约406亿次浮点运算:照此计算,若生成128个token,就要进行5.2万亿次运算
20B算是大模型里的“小”模型了,若模型参数规模达到175B(GPT-3),Batch-Size(BS)再大一点,每次推理计算量将达到干万亿量级,
以NVIDIA A100为例,单张理论FP16运算性能为每秒77.97 TFLOPS[3](77万亿),性能捉紧。

[1] Cai Z, Cao M, Chen H, et al. InternLM2 Technical Report[J]. arXiv preprint arXiv:2403.17297, 2024.

[2] Kaplan J, McCandlish S, Henighan T, et al. Scaling laws for neural language models[J]. arXiv preprint arXiv:2001.08361, 2020

[3] https://www.topcpu.net/

大模型前向推理所需计算量计算公式[2]:

大模型前向推理所需计算量估算(InternLM2为例)[1]:

2.内存开销巨大

  • 以FP16为例,20B模型仅加载参数就需40G+显存175B模型(如GPT-3)更是需要350G+显存。
  • 大模型在推理过程中,为避免重复计算,会将计算注意力(Attention)得到的KV进行缓存。根据InternLM2技术报告[1]提供的模型参数数据,以及KV Cache空间估算方法[2],以FP16为例,在batch-size为16、输入512 tokens、输出32 tokens的情境下,仅20B模型就会产生10.3GB的缓存。
  • 目前,以NVIDIA RTX 4060消费级显卡为例(参考零售价¥2399B[3]),单卡显存仅有8GB;NVIDIA A100单卡显存仅有80GB。

[1] Cai Z, Cao M, Chen H, et al. InternLM2 Technical Report[J]. arXiv preprint arXiv:2403.17297, 2024.
[2] https://zhuanlan.zhihu.com/p/624740065
[3] https://www.nvidia.cn/geforce/graphics-cards/40-series/rtx-4060-4060ti/

KV Cache显存占用估算公式[2]:

前向推理KV Cache空间估算(InternLM2为例)[1]:

3.访存瓶颈、动态请求

4大模型部署方法:

1.模型剪枝(pruning):

2.知识蒸馏(Knowledge Distillation,KD):

3.模型量化(Quantization):

二、LMDeploy介绍

1LMDeploy简介:

LMDeploy 由 MMDeploy 和 MMRazor 团队联合开发是涵盖了 LLM 任务的全套轻量化、部署和服务解决方案。核心功能包括高效推理、可靠量化、便捷服务和有状态推理。

  • 高效的推理:LMDeploy开发了Continuous Batch,Blocked K/ Cache,动态拆分和融合,张量并行,高效的计算kernel等重要特性。InternLM2推理性能是vLLM的 1.8 倍。
  • 可靠的量化:LMDeploy支持权重量化和k/量化。4bit模型推理效率是FP16下的2.4倍。量化模型的可靠性已通过OpenCompass评测得到充分验证。
  • 便捷的服务:通过请求分发服务,LMDeploy 支持多模型在多机、多卡上的推理服务
  • 有状态推理:通过缓存多轮对话过程中Attention的k/,记住对话历史,从而避免重复处理历史会话。显著提升长文本多轮对话场景中的效率。

2LMDeploy核心功能:

1.模型高效推理

参考命令:lmdeploy chat -h

turbomind是lmdeploy团队开发的一款关于LLM推理的高效推理引擎,包括:llama结构模型的支持,continuous batch推理模式和可扩展的KV缓存管理器。

2.模型量化压缩

参考命令:lmdeploy lite -h

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

3.服务化部署

参考命令:Imdeploy serve -h

提供API接口,快捷服务化部署,将LLM封装为HTTP API服务,支持Triton扩展。

3LMDeploy性能表现:

4LMDeploy推理视觉多模态大模型:

新版本的Imdeploy支持了对多模态大模型llava的支持,可以pipeline便捷运行

5LMDeploy更多支持模型:

三、实践——安装、部署、量化

1环境部署

1.1创建开发机

注意这节课选的是cuda12.2

1.2创建conda环境

1.3安装lmdeploy

2LMDeploy模型对话

2.1huggingface与turbomind

HuggingFace

HuggingFace是一个高速发展的社区,包括Meta、Google、Microsoft、Amazon在内的超过5000家组织机构在为HuggingFace开源社区贡献代码、数据集和模型。可以认为是一个针对深度学习模型和数据集的在线托管社区,如果你有数据集或者模型想对外分享,网盘又不太方便,就不妨托管在HuggingFace。

托管在HuggingFace社区的模型通常采用HuggingFace格式存储,简写为HF格式

但是HuggingFace社区的服务器在国外,国内访问不太方便。国内可以使用阿里巴巴的MindScope社区,或者上海AI Lab搭建的OpenXLab社区,上面托管的模型也通常采用HF格式

TurboMind

TurboMind是LMDeploy团队开发的一款关于LLM推理的高效推理引擎,它的主要功能包括:LLaMa 结构模型的支持,continuous batch 推理模式和可扩展的 KV 缓存管理器。

TurboMind推理引擎仅支持推理TurboMind格式的模型。因此,TurboMind在推理HF格式的模型时,会首先自动将HF格式模型转换为TurboMind格式的模型。该过程在新版本的LMDeploy中是自动进行的,无需用户操作。(先进)

几个容易迷惑的点:

  • TurboMind与LMDeploy的关系:LMDeploy是涵盖了LLM 任务全套轻量化、部署和服务解决方案的集成功能包,TurboMind是LMDeploy的一个推理引擎,是一个子模块。LMDeploy也可以使用pytorch作为推理引擎。
  • TurboMind与TurboMind模型的关系:TurboMind是推理引擎的名字,TurboMind模型是一种模型存储格式,TurboMind引擎只能推理TurboMind格式的模型。

2.2下载模型

开发机的共享目录中准备好了预训练模型,先看下

ls /root/share/new_models/Shanghai_AI_Laboratory/

进home目录,教程把模型要放在这

cd ~

 建软连接节省空间

ln -s /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b /root/
# 这是复制的办法cp -r /root/share/new_models/Shanghai_AI_Laboratory/internlm2-chat-1_8b /root/

然后由openxlab平台下载模型,因为我上一步已经从共享目录里下载了,这步不用管了

2.3使用transformer库(huggingface官方库)运行模型

Transformer库是Huggingface社区推出的用于运行HF模型的官方库。我们已经下载好了InternLM2-Chat-1.8B的HF模型。下面我们先用Transformer来直接运行InternLM2-Chat-1.8B模型,后面对比一下LMDeploy的使用感受。

VScode模式下新建terminal

在终端中输入如下指令,新建pipeline_transformer.py

touch /root/pipeline_transformer.py

将以下内容复制粘贴进入pipeline_transformer.py,ctrls保存

import torch
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()

inp = "hello"
print("[INPUT]", inp)
response, history = model.chat(tokenizer, inp, history=[])
print("[OUTPUT]", response)

inp = "please provide three suggestions about time management"
print("[INPUT]", inp)
response, history = model.chat(tokenizer, inp, history=history)
print("[OUTPUT]", response)

激活环境,运行代码

conda activate lmdeploy
python /root/pipeline_transformer.py

 感受下目前的加载进度,我的比老师演示慢好多

2.4使用LMDeploy与模型对话

激活环境

conda activate lmdeploy

使用LMDeploy与模型进行对话的通用命令格式为:

lmdeploy chat [HF格式模型路径/TurboMind格式模型路径]

例如,运行下载的1.8B模型,确实快了很多

lmdeploy chat /root/internlm2-chat-1_8b

有关LMDeploy的chat功能的更多参数可通过-h命令查看。

lmdeploy chat -h

 3LMDeploy模型量化(lite)

本部分内容主要介绍如何对模型进行量化。主要包括 KV8量化和W4A16量化。总的来说,量化是一种以参数或计算中间结果精度下降换空间节省(以及同时带来的性能提升)的策略。

正式介绍 LMDeploy 量化方案前,需要先介绍两个概念:

  • 计算密集(compute-bound): 指推理过程中,绝大部分时间消耗在数值计算上;针对计算密集型场景,可以通过使用更快的硬件计算单元来提升计算速度。
  • 访存密集(memory-bound): 指推理过程中,绝大部分时间消耗在数据读取上;针对访存密集型场景,一般通过减少访存次数、提高计算访存比或降低访存量来优化。

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

那么,如何优化 LLM 模型推理中的访存密集问题呢? 我们可以使用KV8量化和W4A16量化。KV8量化是指将逐 Token(Decoding)生成过程中的上下文 K 和 V 中间结果进行 INT8 量化(计算时再反量化),以降低生成过程中的显存占用。W4A16 量化,将 FP16 的模型权重量化为 INT4,Kernel 计算时,访存量直接降为 FP16 模型的 1/4,大幅降低了访存成本。Weight Only 是指仅量化权重,数值计算依然采用 FP16(需要将 INT4 权重反量化)。

3.1 设置最大KV Cache缓存大小

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

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

下面通过几个例子,来看一下调整--cache-max-entry-count参数的效果。首先保持不加该参数(默认0.8),运行1.8B模型。

lmdeploy chat /root/internlm2-chat-1_8b

从默认的0.8改到0.5

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

3.2 使用W4A16量化

LMDeploy使用AWQ算法,实现模型4bit权重量化。推理引擎TurboMind提供了非常高效的4bit推理cuda kernel,性能是FP16的2.4倍以上。它支持以下NVIDIA显卡:

  • 图灵架构(sm75):20系列、T4
  • 安培架构(sm80,sm86):30系列、A10、A16、A30、A100
  • Ada Lovelace架构(sm90):40 系列

运行前,首先安装一个依赖库。

pip install einops==0.7.0

模型量化

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

1.lmdeploy lite auto_awq:

  • lmdeploy: 可能是用于部署语言模型的工具的命令。
  • lite: 可能表示一个轻量级的版本或配置。
  • auto_awq: 可能是自动权重量化(Automatic Weight Quantization)的策略或方法。

2.--calib-dataset 'ptb':

  • --calib-dataset: 用于指定校准(calibration)数据集的参数。
  • 'ptb': 可能是数据集的名字或别名。在量化过程中,校准数据集用于确定量化参数,以确保量化后的模型具有与原始浮点模型相似的性能。

3.--calib-samples 128:

  • 指定用于校准的样本数量。

4.--calib-seqlen 1024:

  • 在处理序列数据时(如文本),这指定了序列的最大长度或截断长度。

5.--w-bits 4:

  • 这指定了权重量化的位数。在这里,权重将被量化为4位定点数。

6.--w-group-size 128:

  • 这可能指定了量化分组的大小。在某些量化策略中,权重不是单独量化的,而是被分组并一起量化以减少性能损失。

 运行时间较长,请耐心等待。量化工作结束后,新的HF模型被保存到internlm2-chat-1_8b-4bit目录。

下面使用Chat功能运行W4A16量化后的模型。

lmdeploy chat /root/internlm2-chat-1_8b-4bit --model-format awq

降了一些

再叠kv cache=0.01的双重buff

lmdeploy chat /root/internlm2-chat-1_8b-4bit --model-format awq --cache-max-entry-count 0.01

降了很多

4LMDeploy服务(serve)

在第二章和第三章,我们都是在本地直接推理大模型,这种方式成为本地部署。在生产环境下,我们有时会将大模型封装为API接口服务,供客户端访问。

4.1启动API

启动API服务器,推理internlm2-chat-1_8b模型:

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

其中,model-format是huggingface文件、quant-policy不使用量化,

这些参数是与第三章中一致的;server-name和server-port表示API服务器的服务IP与服务端口;tp参数表示并行数量(GPU数量)。

通过运行以上指令,我们成功启动了API服务器,请勿关闭该窗口,后面我们要新建客户端连接该服务。

可以通过运行一下指令,查看更多参数及使用方法:

lmdeploy serve api_server -h

也可以查看帮助

lmdeploy serve api_server -h

还可以本地cmd打开

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

http://127.0.0.1:23333

http://{host}:23333

 

4.2命令行客户端连接API服务器

在“4.1”中,我们在终端里新开了一个API服务器。

本节中,我们要新建一个命令行客户端去连接API服务器。首先通过VS Code新建一个终端

激活,再命令运行客户端:

lmdeploy serve api_client http://localhost:23333

目前的架构是这样的:

4.3网页客户端连接API服务器

继续在刚才的页面输入指令,把gradio作为前端,启动网页客户端

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

回到平台,按ctrlc退出

5python代码集成

5.1python代码集成运行1.8B模型

激活环境,新建python源代码文件pipeline.py

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)

代码解读:\

  • 第1行,引入lmdeploy的pipeline模块 \
  • 第3行,从目录“./internlm2-chat-1_8b”加载HF模型 \
  • 第4行,运行pipeline,这里采用了批处理的方式,用一个列表包含两个输入,lmdeploy同时推理两个输入,产生两个输出结果,结果返回给response \
  • 第5行,输出response

运行

python /root/pipeline.py

 5.2向TurboMind后端传递参数

在第3章,我们通过向lmdeploy传递附加参数,实现模型的量化推理,及设置KV Cache最大占用比例。在Python代码中,可以通过创建TurbomindEngineConfig,向lmdeploy传递参数。

以设置KV Cache占用比例为例,新建python文件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)

运行代码

6扩展部分

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

激活环境,安装llava依赖库

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

新建pipeline_llava.py

touch /root/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)

代码解读: \

  • 第1行引入用于载入图片的load_image函数,第2行引入了lmdeploy的pipeline模块, \
  • 第5行创建了pipeline实例 \
  • 第7行从github下载了一张关于老虎的图片
  • 第8行运行pipeline,输入提示词“describe this image”,和图片,结果返回至response \
  • 第9行输出response

 四、进阶作业

1.设置KV Cache最大占用比例为0.4,开启W4A16量化,以命令行方式与模型对话。

激活lmdeploy环境,输入命令

lmdeploy chat /root/internlm2-chat-1_8b-4bit --model-format awq --cache-max-entry-count 0.4

此时内存

2.以API Server方式启动 lmdeploy,开启 W4A16量化,调整KV Cache的占用比例为0.4,分别使用命令行客户端与Gradio网页客户端与模型对话。

这一步折腾了非常久,感谢助教帮我重装了conda环境(配SSH打开URL可能得科学上网)

和视频教学文档里唯一不一样的一步是:

lmdeploy serve api_server \
    /root/internlm2-chat-1_8b-4bit \
    --model-format awq \
    --cache-max-entry-count 0.4 \
    --quant-policy 0 \
    --server-name 0.0.0.0 \
    --server-port 23333 \
    --tp 1

ctrlc退出两个terminal

3.使用W4A16量化,调整KV Cache的占用比例为0.4,使用Python代码集成的方式运行internlm2-chat-1.8b模型。

与视频教程不同的一步是

打开pipeline.py输入以下内容:

from lmdeploy import pipeline

pipe = pipeline('//root/internlm2-chat-1_8b-4bit')
#4bit版就是已经量化好的模型
response = pipe(['Hi, pls intro yourself', '我要上春山'])
print(response)

向TurboMind后端传递参数,与教程不同的一步是,打开pipeline_kv.py输入以下内容:

from lmdeploy import pipeline, TurbomindEngineConfig

# 调低 k/v cache内存占比调整为总显存的 40%
backend_config = TurbomindEngineConfig(cache_max_entry_count=0.4)
#这儿也换成4bit版
pipe = pipeline('/root/internlm2-chat-1_8b-4bit',
                backend_config=backend_config)
response = pipe(['Hi, pls intro yourself', '上海是'])
print(response)

4.使用 LMDeploy 运行视觉多模态大模型 llava gradio demo。

将开发机配置换到30%

命令行运行

gradio运行

import gradio as gr
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)

def model(image, text):
    if image is None:
        return [(text, "请上传一张图片。")]
    else:
        response = pipe((text, image)).text
        return [(text, response)]

demo = gr.Interface(fn=model, inputs=[gr.Image(type="pil"), gr.Textbox()], outputs=gr.Chatbot())
demo.launch()   

五、总结

1.前面课程的xtuner、rag都是为了让大模型如何更好地生成答案。本节课的内容是:大模型的参数量和计算量都是非常巨大的,部署侧的算力是否足够,如何在有限的资源里去加载大模型。大模型的部署方法包括:模型剪枝 ( Pruning )、知识蒸馏(knowledge distillation)、量化( Quantization )等手段,来减轻机器学习过程的负担。

2.对此,LMDeploy是涵盖了 LLM 任务的全套轻量化、部署和服务的集成功能包。核心功能包括模型高效推理、模型量化压缩和便捷服务部署。

3.TurboMindLMDeploy 团队开发的一款关于 LLM 推理的高效推理引擎,是一个子模块。(LMDeploy 也可以使用 pytorch 作为推理引擎)

4.值得关注的是,LMDeploy针对 LLaMa 模型写了一个高度优化的实现,LMdeploy也支持市面上常见的大模型部署。并且推理HF类型的模型时,可以自动转化为TurboMind类型的模型。

5.LMDeploy 模型量化包括KV8 量化和 W4A16量化,通过进阶部分显示,使用量化方法可以非常显著地降低显存。

  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值