LMDeploy 量化部署 LLM&VLM 實(shí)踐
一苔悦、理論基礎(chǔ)
大模型部署面臨的挑戰(zhàn):
-
計(jì)算量巨大
-
內(nèi)存開銷巨大
訪存瓶頸:硬件計(jì)算速度遠(yuǎn)快于顯存帶寬
動(dòng)態(tài)請(qǐng)求:請(qǐng)求量不確定蟋座,請(qǐng)求時(shí)間不確定诸狭,Token逐個(gè)生成驯遇,生成數(shù)量不確定双吆。
大模型部署方法
模型剪枝
知識(shí)蒸餾 Distillation
先訓(xùn)練一個(gè)參數(shù)量大的教師網(wǎng)絡(luò),再用它訓(xùn)練一個(gè)參數(shù)量較小的學(xué)生網(wǎng)絡(luò)。
量化
僅在存儲(chǔ)時(shí)量化降低精度,計(jì)算時(shí)還要進(jìn)行反量化。
二淳蔼、運(yùn)行實(shí)戰(zhàn)
2.1 環(huán)境部署
安裝虛擬環(huán)境 lmdeploy
隨后激活環(huán)境
2.2 LMDeploy 模型對(duì)話(chat)
- HuggingFace:托管在 HuggingFace 社區(qū)的模型通常采用 HuggingFace 格式存儲(chǔ),簡(jiǎn)寫為HF格式泡仗。
- 國(guó)內(nèi)的阿里巴巴 MindScope 社區(qū)與上海AILab的 OpenXLab社區(qū),上面托管的模型通常也是HF格式
- TurboMind:LMDeploy 團(tuán)隊(duì)開發(fā)的一款關(guān)于LLM推理的高效引擎,僅支持 TurboMind 格式的模型。因此會(huì)自動(dòng)把HF 格式轉(zhuǎn)換為 TurboMind 格式。
- TurboMind與LMDeploy的關(guān)系:LMDeploy是涵蓋了LLM 任務(wù)全套輕量化颖系、部署和服務(wù)解決方案的集成功能包,TurboMind是LMDeploy的一個(gè)推理引擎,是一個(gè)子模塊不傅。LMDeploy也可以使用pytorch作為推理引擎。
- TurboMind與TurboMind模型的關(guān)系:TurboMind是推理引擎的名字称龙,TurboMind模型是一種模型存儲(chǔ)格式,TurboMind引擎只能推理TurboMind格式的模型。
-
下載模型:使用軟拷貝,拷貝到根目錄
模型 - 使用Transformer庫(kù)運(yùn)行模型
編寫 pipeline_transoformer.py 文件
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.
# 加載模型,設(shè)置為評(píng)估模式
model = AutoModelForCausalLM.from_pretrained("/root/internlm2-chat-1_8b", torch_dtype=torch.float16, trust_remote_code=True).cuda()
model = model.eval()
# 用戶輸入文本"hello",通過model.chat函數(shù)使用模型和tokenizer生成回應(yīng)。
# 這里假設(shè)model.chat是一個(gè)擴(kuò)展或自定義的方法震檩,用于處理交互式聊天。
# history=[]表示當(dāng)前沒有歷史對(duì)話記錄霜旧。
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)
- 運(yùn)行代碼
python /root/pipeline_transformer.py
成功輸出回答,運(yùn)行時(shí)間兩分鐘掷倔。
- 使用 LMDeploy 與模型對(duì)話
lmdeploy chat /root/internlm2-chat-1_8b
加載模型成功,僅用時(shí)1分鐘
用它來(lái)講故事
答案輸出速度非常快
2.3 LMDeploy 模型量化(lite)
2.3.1 概念
量化是一種以參數(shù)或計(jì)算中間結(jié)果精度下降換取空間節(jié)省(以及同時(shí)帶來(lái)的性能提升)的策略。
- 計(jì)算密集:推理時(shí),絕大部分時(shí)間消耗在數(shù)值計(jì)算上该面。可以通過使用更快的硬件計(jì)算單元來(lái)提升計(jì)算速度。
- 訪存密集:推理時(shí)牵触,絕大部分時(shí)間消耗在數(shù)據(jù)讀取上《ず梗可以通過減少訪存次數(shù)酒来、提高計(jì)算訪存比或降低訪存量來(lái)優(yōu)化伟墙。
常見的 LLM 模型由于 Decoder Only 架構(gòu)的特性远荠,實(shí)際推理時(shí)大多數(shù)的時(shí)間都消耗在了逐 Token 生成階段(Decoding 階段),是典型的訪存密集型場(chǎng)景。
- KV8量化:將逐 Token(Decoding)生成過程中的上下文 K 和 V 中間結(jié)果進(jìn)行 INT8 量化(計(jì)算時(shí)再反量化)浦妄,以降低生成過程中的顯存占用剂娄。
- W4A16量化:將 FP16 的模型權(quán)重量化為 INT4徘铝,Kernel 計(jì)算時(shí)怕午,訪存量直接降為 FP16 模型的 1/4,大幅降低了訪存成本兆蕉。
- WeightOnly:指僅量化權(quán)重半醉,數(shù)值計(jì)算依然采用 FP16(需要將 INT4 權(quán)重反量化)呆奕。
2.3.2 設(shè)置最大KV Cache緩存大小
KV Cache是一種緩存技術(shù),通過存儲(chǔ)鍵值對(duì)的形式來(lái)復(fù)用計(jì)算結(jié)果,以達(dá)到提高性能和降低內(nèi)存消耗的目的。在大規(guī)模訓(xùn)練和推理中方咆,KV Cache可以顯著減少重復(fù)計(jì)算量,從而提升模型的推理速度妓肢。理想情況下,KV Cache全部存儲(chǔ)于顯存,以加快訪存速度操禀。當(dāng)顯存空間不足時(shí)耿焊,也可以將KV Cache放在內(nèi)存器腋,通過緩存管理器控制將當(dāng)前需要使用的數(shù)據(jù)放入顯存诊县。
模型在運(yùn)行時(shí),占用的顯存可大致分為三部分:模型參數(shù)本身占用的顯存、KV Cache占用的顯存缴渊,以及中間運(yùn)算結(jié)果占用的顯存昔瞧。LMDeploy的KV Cache管理器可以通過設(shè)置--cache-max-entry-count參數(shù)凝化,控制KV緩存占用剩余顯存的最大比例。默認(rèn)的比例為0.8枪向。
運(yùn)行模型傍衡,查看顯存占用:
lmdeploy chat /root/internlm2-chat-1_8b
占用7816MB
改變參數(shù)
lmdeploy chat /root/internlm2-chat-1_8b --cache-max-entry-count 0.5
降低到了6600MB
2.3.3 使用W4A16量化
LMDeploy使用AWQ算法绣的,實(shí)現(xiàn)模型4bit權(quán)重量化燎悍。推理引擎TurboMind提供了非常高效的4bit推理cuda kernel,性能是FP16的2.4倍以上。
- 安裝依賴庫(kù)einops
- 執(zhí)行命令完成量化
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
再次使用0.5的--cache-max-entry-count,查看內(nèi)存占用
這次僅有5572MB玷或,低于之前的6600MB蔬胯。
2.4 LMDeploy 服務(wù)(serve)
我們將大模型封裝為API接口服務(wù)。
- 模型推理/服務(wù)。主要提供模型本身的推理,一般來(lái)說(shuō)可以和具體業(yè)務(wù)解耦重归,專注模型推理本身性能的優(yōu)化较鼓。可以以模塊、API等多種方式提供馍惹。
- API Server慎框。中間協(xié)議層薪丁,把后端推理/服務(wù)通過HTTP,gRPC或其他形式的接口,供前端調(diào)用称近。
- Client忆畅〖铱可以理解為前端,與用戶交互的地方掂之。通過通過網(wǎng)頁(yè)端/命令行去調(diào)用API接口槽卫,獲取模型推理/服務(wù)。
2.4.1 啟動(dòng) API 服務(wù)器
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
0.0.0.0的23333號(hào)端口喷好。
這一步由于Server在遠(yuǎn)程服務(wù)器上,所以本地需要做一下ssh轉(zhuǎn)發(fā)才能直接訪問。
ssh -CNg -L 23333:127.0.0.1:23333 root@ssh.intern-ai.org.cn -p 你的ssh端口號(hào)
在瀏覽器中打開本地的23333端口掘托。
2.4.2 命令行客戶端連接API服務(wù)器
運(yùn)行命令行客戶端
lmdeploy serve api_client http://localhost:23333
在命令行中即可與大模型交互。
此時(shí)的價(jià)格
2.4.3 網(wǎng)頁(yè)客戶端連接API服務(wù)器
使用Gradio作為前端,啟用網(wǎng)頁(yè)客戶端异赫,6006端口
lmdeploy serve gradio http://localhost:23333 \
--server-name 0.0.0.0 \
--server-port 6006
此時(shí)的架構(gòu):
2.5 Python 代碼集成
2.5.1 Python代碼集成運(yùn)行1.8B模型
編寫python腳本
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行澎胡,運(yùn)行pipeline,這里采用了批處理的方式稚伍,用一個(gè)列表包含兩個(gè)輸入个曙,lmdeploy同時(shí)推理兩個(gè)輸入,產(chǎn)生兩個(gè)輸出結(jié)果,結(jié)果返回給response
第5行对雪,輸出response
2.5.2 向TurboMind后端傳遞參數(shù)
在Python代碼中瑟捣,可以通過創(chuàng)建TurbomindEngineConfig栅干,向lmdeploy傳遞參數(shù)碱鳞。
from lmdeploy import pipeline, TurbomindEngineConfig
# 調(diào)低 k/v cache內(nèi)存占比調(diào)整為總顯存的 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)