LLM 大模型學習必知必會系列(十二):VLLM效能飛躍部署實踐:從推理加速到高效部署的全方位最佳化[更多內容:XInference/FastChat等框架]

汀、人工智能發表於2024-05-31

LLM 大模型學習必知必會系列(十二):VLLM效能飛躍部署實踐:從推理加速到高效部署的全方位最佳化[更多內容:XInference/FastChat等框架]

訓練後的模型會用於推理或者部署。推理即使用模型用輸入獲得輸出的過程,部署是將模型釋出到恆定執行的環境中推理的過程。一般來說,LLM的推理可以直接使用PyTorch程式碼、使用VLLM/XInference/FastChat等框架,也可以使用llama.cpp/chatglm.cpp/qwen.cpp等c++推理框架。

  • 常見推理方法
    • Greedy Search 貪婪搜尋方式。按照前面的講解,模型會按照詞表尺寸生成機率。貪婪方式會不斷選擇生成機率最大的token。該方法由於無腦選擇了最大機率,因此模型會傾向於生成重複的文字,一般實際應用中很少使用
    • Beam Search 和貪婪方式的區別在於,beam search會選擇機率最大的k個。在生成下一個token時,每個前序token都會生成k個,這樣整體序列就有k^2個,從這些序列中選擇組合機率最大的k個,並遞迴地執行下去。k在beam search演算法中被稱為beam_size
    • Sample 隨機取樣方式。按照詞表每個token的機率取樣一個token出來。這個方式多樣性更強,是目前主流的生成方式。

1. 前言

1.1 重要推理超引數

  • do_sample:布林型別。是否使用隨機取樣方式執行推理,如果設定為False,則使用beam_search方式

  • temperature:大於等於零的浮點數。公式為:

    $$
    q_i=\frac{\exp(z_i/T)}{\sum_{j}\exp(z_j/T)}\
    $$

    從公式可以看出,如果T取值為0,則效果類似argmax,此時推理幾乎沒有隨機性;取值為正無窮時接近於取平均。一般temperature取值介於[0, 1]之間。取值越高輸出效果越隨機。

    如果該問答只存在確定性答案,則T值設定為0。反之設定為大於0。

  • top_k:大於0的正整數。從k個機率最大的結果中進行取樣。k越大多樣性越強,越小確定性越強。一般設定為20~100之間。

    • 實際實驗中可以先從100開始嘗試,逐步降低top_k直到效果達到最佳。
  • top_p:大於0的浮點數。使所有被考慮的結果的機率和大於p值,p值越大多樣性越強,越小確定性越強。一般設定0.7~0.95之間。

    • 實際實驗中可以先從0.95開始降低,直到效果達到最佳。
    • top_p比top_k更有效,應優先調節這個引數。
  • repetition_penalty: 大於等於1.0的浮點數。如何懲罰重複token,預設1.0代表沒有懲罰。

1.2 KVCache

上面我們講過,自迴歸模型的推理是將新的token不斷填入序列生成下一個token的過程。那麼,前面token已經生成的中間計算結果是可以直接利用的。具體以Attention結構來說:

$$
\text { Attention }(Q, K, V)=\operatorname{softmax}\left(\frac{Q K^T}{\sqrt{d_k}}\right) V
$$

推理時的Q是單token tensor,但K和V都是包含了所有歷史token tensor的長序列,因此KV是可以使用前序計算的中間結果的,這部分的快取就是KVCache,其視訊記憶體佔用非常巨大。

2. VLLM框架

網址: https://github.com/vllm-project/vllm

vLLM是一個開源的大模型推理加速框架,透過PagedAttention高效地管理attention中快取的張量,實現了比HuggingFace Transformers高14-24倍的吞吐量。

PagedAttention 是 vLLM 的核心技術,它解決了LLM服務中記憶體的瓶頸問題。傳統的注意力演算法在自迴歸解碼過程中,需要將所有輸入Token的注意力鍵和值張量儲存在GPU記憶體中,以生成下一個Token。這些快取的鍵和值張量通常被稱為KV快取。

  • 主要特性
    • 透過PagedAttention對 KV Cache 的有效管理
    • 傳入請求的continus batching,而不是static batching
    • 支援張量並行推理
    • 支援流式輸出
    • 相容 OpenAI 的介面服務
    • 與 HuggingFace 模型無縫整合

VLLM支援絕大多數LLM模型的推理加速。它使用如下的方案大幅提升推理速度:

  1. Continuous batching

    • 在實際推理過程中,一個批次多個句子的輸入的token長度可能相差很大,最後生成的模型輸出token長度相差也很大。在python樸素推理中,最短的序列會等待最長序列生成完成後一併返回,這意味著本來可以處理更多token的GPU算力在對齊過程中產生了浪費。continous batching的方式就是在每個句子序列輸出結束後馬上填充下一個句子的token,做到高效利用算力。

  2. PagedAttention

    • 推理時的視訊記憶體佔用中,KVCache的碎片化和重複記錄浪費了50%以上的視訊記憶體。VLLM將現有輸入token進行物理分塊,使每塊視訊記憶體內部包含了固定長度的tokens。在進行Attention操作時,VLLM會從物理塊中取出KVCache並計算。因此模型看到的邏輯塊是連續的,但是物理塊的地址可能並不連續。這和虛擬記憶體的思想非常相似。另外對於同一個句子生成多個回答的情況,VLLM會將不同的邏輯塊對映為一個物理塊,起到節省視訊記憶體提高吞吐的作用。

值得注意的是,VLLM會預設將顯示卡的全部視訊記憶體預先申請以提高快取大小和推理速度,使用者可以透過引數gpu_memory_utilization控制快取大小。

首先安裝VLLM:

pip install vllm
import os
os.environ['VLLM_USE_MODELSCOPE'] = 'True'
from vllm import LLM, SamplingParams
prompts = [
    "Hello, my name is",
    "The president of the United States is",
    "The capital of France is",
    "The future of AI is",
]
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)
llm = LLM(model="qwen/Qwen-1_8B", trust_remote_code=True)
outputs = llm.generate(prompts, sampling_params)

#Print the outputs.
for output in outputs:
    prompt = output.prompt
    generated_text = output.outputs[0].text
    print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")

注意,截止到本文件編寫完成,VLLM對Chat模型的推理支援(模板和結束符)存在問題,在實際進行部署時請考慮使用SWIFT或者FastChat。

LLM的generate方法支援直接輸入拼接好的tokens(prompt_token_ids引數,此時不要傳入prompts引數),所以外部可以按照自己的模板進行拼接後傳入VLLM,SWIFT就是使用了這種方法

在量化章節中我們講解了AWQ量化,VLLM直接支援傳入量化後的模型進行推理:

from vllm import LLM, SamplingParams
import os
import torch
os.environ['VLLM_USE_MODELSCOPE'] = 'True'

#Sample prompts.
prompts = [
    "Hello, my name is",
    "The president of the United States is",
    "The capital of France is",
    "The future of AI is",
]
#Create a sampling params object.
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)

#Create an LLM.
llm = LLM(model="ticoAg/Qwen-1_8B-Chat-Int4-awq", quantization="AWQ", dtype=torch.float16, trust_remote_code=True)
#Generate texts from the prompts. The output is a list of RequestOutput objects
#that contain the prompt, generated text, and other information.
outputs = llm.generate(prompts, sampling_params)
#Print the outputs.
for output in outputs:
    prompt = output.prompt
    generated_text = output.outputs[0].text
    print(f"Prompt: {prompt!r}, Generated text: {generated_text!r}")

VLLM官方文件可以檢視這裡

3.SWIFT

網址:https://github.com/modelscope/swift/tree/main

SWIFT(Scalable lightWeight Infrastructure for Fine-Tuning)是基於PyTorch的輕量級、開箱即用的模型微調、推理框架。它不僅整合了各類開源tuners,如LoRA、QLoRA、Adapter等,並且融合了ModelScope獨立自研的特有tuner ResTuning,得益於此,各個模態的開發者均可以找到適合自己模型的開發方式。

SWIFT的tuners不僅適配於所有Transformer結構的模型,也適配於其他結構的深度學習模型,做到一行程式碼建立可微調模型,實現引數高效、記憶體高效和時間高效的訓練流程。

SWIFT可以無縫整合到ModelScope生態系統中,打通資料集讀取、模型下載、模型訓練、模型推理、模型上傳等流程。此外,SWIFT與PEFT完全相容, 熟悉PEFT的使用者可以使用SWIFT能力結合ModelScope的模型進行便捷地訓練推理。

作為ModelScope獨立自研的開源輕量級tuner ResTuning,該技術在cv、多模態等領域均經過了系列驗證,在訓練效果和其他微調方法相當的情況下,可以做到視訊記憶體節省30%~60%,為cv、多模態模型的訓練提供了新的正規化,在未來會應用在越來越多的場景上。

  • SWIFT 框架主要特徵特性:
    • 具備SOTA特性的Efficient Tuners:用於結合大模型實現輕量級(在商業級顯示卡上,如RTX3080、RTX3090、RTX4090等)訓練和推理,並取得較好效果
    • 使用ModelScope Hub的Trainer:基於transformers trainer提供,支援LLM模型的訓練,並支援將訓練後的模型上傳到ModelScope Hub中
    • 可執行的模型Examples:針對熱門大模型提供的訓練指令碼和推理指令碼,並針對熱門開源資料集提供了預處理邏輯,可直接執行使用
    • 支援介面化訓練和推理

在SWIFT中,我們支援了VLLM的推理加速手段。

pip install ms-swift[llm] openai

只需要執行下面的命令就可以使用VLLM加速推理:

swift infer --model_id_or_path qwen/Qwen-1_8B-Chat --max_new_tokens 128 --temperature 0.3 --top_p 0.7 --repetition_penalty 1.05 --do_sample true

也支援在部署中使用VLLM:

swift deploy --model_id_or_path qwen/Qwen-1_8B-Chat --max_new_tokens 128 --temperature 0.3 --top_p 0.7 --repetition_penalty 1.05 --do_sample true

呼叫:

from openai import OpenAI
client = OpenAI(
    api_key='EMPTY',
    base_url='http://localhost:8000/v1',
)
model_type = client.models.list().data[0].id
print(f'model_type: {model_type}')

query = '浙江的省會在哪裡?'
messages = [{
    'role': 'user',
    'content': query
}]
resp = client.chat.completions.create(
    model=model_type,
    messages=messages,
    seed=42)
response = resp.choices[0].message.content
print(f'query: {query}')
print(f'response: {response}')

#流式
messages.append({'role': 'assistant', 'content': response})
query = '這有什麼好吃的?'
messages.append({'role': 'user', 'content': query})
stream_resp = client.chat.completions.create(
    model=model_type,
    messages=messages,
    stream=True,
    seed=42)

print(f'query: {query}')
print('response: ', end='')
for chunk in stream_resp:
    print(chunk.choices[0].delta.content, end='', flush=True)
print()

"""Out[0]
model_type: qwen-7b-chat
query: 浙江的省會在哪裡?
response: 浙江省的省會是杭州市。
query: 這有什麼好吃的?
response: 杭州有許多美食,例如西湖醋魚、東坡肉、龍井蝦仁、叫化童子雞等。此外,杭州還有許多特色小吃,如西湖藕粉、杭州小籠包、杭州油條等。
"""

4.llama.cpp

llama.cpp是使用c++語言編寫的對llama系列模型進行高效推理或量化推理的開源庫。該庫使用了ggml底層計算庫進行推理。在使用之前需要額外將python的weights轉為ggml格式或gguf格式方可使用。和llama.cpp類似,還有相容ChatGLM模型的chatglm.cpp和相容qwen模型的qwen.cpp和mistral的mistral.cpp。

安裝依賴:

pip install modelscope
git clone --recursive https://github.com/QwenLM/qwen.cpp && cd qwen.cpp
cmake -B build
cmake --build build -j --config Release

下載模型:

from modelscope import snapshot_download
print(snapshot_download('qwen/Qwen-1_8B-Chat'))
#/mnt/workspace/.cache/modelscope/qwen/Qwen-1_8B-Chat

將原始模型轉換為ggml支援的格式:

python3 qwen_cpp/convert.py -i /mnt/workspace/.cache/modelscope/qwen/Qwen-1_8B-Chat -t q4_0 -o qwen1_8b-ggml.bin
./build/bin/main -m qwen1_8b-ggml.bin --tiktoken /mnt/workspace/.cache/modelscope/qwen/Qwen-1_8B-Chat/qwen.tiktoken -p 你好
#你好!有什麼我可以幫助你的嗎?

量化章節中我們介紹,GGML庫適合於CPU執行,因此推薦使用者在CPU環境中或邊緣計算中考慮cpp庫進行推理。

5.FastChat

FastChat Github地址: https://github.com/lm-sys/FastChat
FastChat架構:https://github.com/lm-sys/FastChat/blob/main/docs/server_arch.md

FastChat是一個開源推理庫,側重於模型的分散式部署實現,並提供了OpenAI樣式的RESTFul API。是一個開放平臺,用於訓練、服務和評估基於大型語言模型的聊天機器人。

  • FastChat 的核心功能包括:
    • 最先進模型的訓練和評估程式碼(例如,Vicuna、MT-Bench)。
    • 具有 Web UI 和 OpenAI 相容 RESTful API 的分散式多模型服務系統

pip3 install "fschat[model_worker,webui]"
python3 -m fastchat.serve.controller

在新的terminal中啟動:

FASTCHAT_USE_MODELSCOPE=true python3 -m fastchat.serve.model_worker --model-path qwen/Qwen-1_8B-Chat --revision v1.0.0

之後在新的terminal中可以執行介面進行推理:

python3 -m fastchat.serve.gradio_web_server

6.DeepSpeed

網址:https://github.com/microsoft/DeepSpeed

網址:https://www.deepspeed.ai/training/

Deepspeed並行框架介紹https://github.com/wzzzd/LLM_Learning_Note/blob/main/Parallel/deepspeed.md

Deepspeed是微軟推出的一個開源分散式工具,其集合了分散式訓練、推斷、壓縮等高效模組。 該工具旨在提高大規模模型訓練的效率和可擴充套件性。它透過多種技術手段來加速訓練,包括模型並行化、梯度累積、動態精度縮放、本地模式混合精度等。DeepSpeed還提供了一些輔助工具,如分散式訓練管理、記憶體最佳化和模型壓縮等,以幫助開發者更好地管理和最佳化大規模深度學習訓練任務。此外,deepspeed基於pytorch構建,只需要簡單修改即可遷移。 DeepSpeed已經在許多大規模深度學習專案中得到了應用,包括語言模型、影像分類、目標檢測等。

  • DeepSpeed是由Microsoft提供的分散式訓練工具,旨在支援更大規模的模型和提供更多的最佳化策略和工具。與其他框架相比,DeepSpeed支援更大規模的模型和提供更多的最佳化策略和工具。其中,主要優勢在於支援更大規模的模型、提供了更多的最佳化策略和工具(例如 ZeRO 和 Offload 等)

    • 用 3D 並行化實現萬億引數模型訓練: DeepSpeed 實現了三種並行方法的靈活組合:ZeRO 支援的資料並行,流水線並行和張量切片模型並行。3D 並行性適應了不同工作負載的需求,以支援具有萬億引數的超大型模型,同時實現了近乎完美的視訊記憶體擴充套件性和吞吐量擴充套件效率。此外,其提高的通訊效率使使用者可以在網路頻寬有限的常規群集上以 2-7 倍的速度訓練有數十億引數的模型。
    • ZeRO-Offload 使 GPU 單卡能夠訓練 10 倍大的模型: 為了同時利用 CPU 和 GPU 記憶體來訓練大型模型,我們擴充套件了 ZeRO-2。我們的使用者在使用帶有單張英偉達 V100 GPU 的機器時,可以在不耗盡視訊記憶體的情況下執行多達 130 億個引數的模型,模型規模擴充套件至現有方法的10倍,並保持有競爭力的吞吐量。此功能使數十億引數的模型訓練更加大眾化,,併為許多深度學習從業人員開啟了一扇探索更大更好的模型的窗戶。
    • 透過 DeepSpeed Sparse Attention 用6倍速度執行10倍長的序列: DeepSpeed提供了稀疏 attention kernel ——一種工具性技術,可支援長序列的模型輸入,包括文字輸入,影像輸入和語音輸入。與經典的稠密 Transformer 相比,它支援的輸入序列長一個數量級,並在保持相當的精度下獲得最高 6 倍的執行速度提升。它還比最新的稀疏實現快 1.5–3 倍。此外,我們的稀疏 kernel 靈活支援稀疏格式,使使用者能夠透過自定義稀疏結構進行創新。
    • 1 位元 Adam 減少 5 倍通訊量: Adam 是一個在大規模深度學習模型訓練場景下的有效的(也許是最廣為應用的)最佳化器。然而,它與通訊效率最佳化演算法往往不相容。因此,在跨裝置進行分散式擴充套件時,通訊開銷可能成為瓶頸。我們推出了一種 1 位元 Adam 新演算法,以及其高效實現。該演算法最多可減少 5 倍通訊量,同時實現了與Adam相似的收斂率。在通訊受限的場景下,我們觀察到分散式訓練速度提升了 3.5 倍,這使得該演算法可以擴充套件到不同型別的 GPU 群集和網路環境。
  • 推理框架小結

    • 如果CPU推理,llama.cpp 結合模型int4量化,最佳的選擇
    • GPU推理,微軟的 DeepSpeed-FastGen 是一個好的選擇
    • 手機終端推理,MLC LLM可以作為候選

更多優質內容請關注公號:汀丶人工智慧;會提供一些相關的資源和優質文章,免費獲取閱讀。

相關文章