跳到內容

FP8 W8A8

vLLM 支援使用 Nvidia H100 和 AMD MI300x 等 GPU 上的硬體加速進行 FP8(8 位浮點)權重和啟用量化。目前,W8A8 僅官方支援 Hopper 和 Ada Lovelace GPU。Ampere GPU 支援利用 Marlin 核的 W8A16(僅權重 FP8)。使用 FP8 量化模型可將模型記憶體需求減少 2 倍,並將吞吐量提高高達 1.6 倍,同時對精度影響極小。

請訪問 HF 集合,獲取可直接與 vLLM 一起使用的流行 LLM 的 FP8 量化檢查點

硬體中通常支援的 FP8 型別有兩種不同的表示形式,每種在不同場景下都很有用

  • E4M3:由 1 個符號位、4 個指數位和 3 個尾數位組成。它可以儲存高達 +/-448 的值和 nan
  • E5M2:由 1 個符號位、5 個指數位和 2 個尾數位組成。它可以儲存高達 +/-57344 的值、+/- infnan。增加動態範圍的代價是儲存值的精度降低。

注意

NVIDIA GPU 上支援計算能力 > 8.9 (Ada Lovelace, Hopper) 的 FP8 計算。FP8 模型將在計算能力 > 8.0 (Ampere) 的 GPU 上以僅權重 W8A16 模式執行,利用 FP8 Marlin。

安裝

為了使用 vLLM 生成高效能的 FP8 量化模型,您需要安裝 llm-compressor

pip install llmcompressor

量化過程

量化過程涉及三個主要步驟

  1. 載入模型
  2. 應用量化
  3. 在 vLLM 中評估精度

1. 載入模型

使用標準的 transformers AutoModel 類載入您的模型和分詞器

from transformers import AutoTokenizer, AutoModelForCausalLM

MODEL_ID = "meta-llama/Meta-Llama-3-8B-Instruct"
model = AutoModelForCausalLM.from_pretrained(
    MODEL_ID, device_map="auto", torch_dtype="auto",
)
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)

2. 應用量化

對於 FP8 量化,我們可以透過簡單的 RTN 量化來恢復精度。我們建議使用 FP8_DYNAMIC 方案針對所有 Linear 層,該方案使用

  • 權重的靜態、每通道量化
  • 啟用的動態、每令牌量化

由於簡單的 RTN 不需要資料進行權重S量化,並且啟用是動態量化的,因此此量化流程不需要任何校準資料。

程式碼
from llmcompressor.transformers import oneshot
from llmcompressor.modifiers.quantization import QuantizationModifier

# Configure the simple PTQ quantization
recipe = QuantizationModifier(
  targets="Linear", scheme="FP8_DYNAMIC", ignore=["lm_head"])

# Apply the quantization algorithm.
oneshot(model=model, recipe=recipe)

# Save the model: Meta-Llama-3-8B-Instruct-FP8-Dynamic
SAVE_DIR = MODEL_ID.split("/")[1] + "-FP8-Dynamic"
model.save_pretrained(SAVE_DIR)
tokenizer.save_pretrained(SAVE_DIR)

3. 評估精度

安裝 vllmlm-evaluation-harness 進行評估

pip install vllm lm-eval==0.4.4

vllm 中載入並執行模型

from vllm import LLM

llm = LLM("./Meta-Llama-3-8B-Instruct-FP8-Dynamic")
result = llm.generate("Hello my name is")
print(result[0].outputs[0].text)

使用 lm_eval 評估精度(例如,對 250 個 gsm8k 樣本)

注意

量化模型可能對 bos 令牌的存在敏感。 lm_eval 預設不新增 bos 令牌,因此請確保在執行評估時包含 add_bos_token=True 引數。

MODEL=$PWD/Meta-Llama-3-8B-Instruct-FP8-Dynamic
lm_eval \
  --model vllm \
  --model_args pretrained=$MODEL,add_bos_token=True \
  --tasks gsm8k  --num_fewshot 5 --batch_size auto --limit 250

以下是結果分數的示例

|Tasks|Version|     Filter     |n-shot|  Metric   |   |Value|   |Stderr|
|-----|------:|----------------|-----:|-----------|---|----:|---|-----:|
|gsm8k|      3|flexible-extract|     5|exact_match|↑  |0.768|±  |0.0268|
|     |       |strict-match    |     5|exact_match|↑  |0.768|±  |0.0268|

故障排除和支援

如果您遇到任何問題或有功能請求,請在 vllm-project/llm-compressor GitHub 倉庫上提出問題。

線上動態量化

使用 vLLM 可以實現將原始精度 BF16/FP16 模型動態量化為 FP8,而無需任何校準資料。您可以透過在命令列中指定 --quantization="fp8" 或在 LLM 建構函式中設定 quantization="fp8" 來啟用此功能。

在此模式下,所有 Linear 模組(除了最終的 lm_head)的權重都會以每張量(per-tensor)尺度量化到 FP8_E4M3 精度。啟用值在每次前向傳播期間計算其最小值和最大值,以提供動態的每張量尺度,從而實現高精度。因此,在此模式下,延遲改進是有限的。

from vllm import LLM

llm = LLM("facebook/opt-125m", quantization="fp8")
# INFO 06-10 17:55:42 model_runner.py:157] Loading model weights took 0.1550 GB
result = llm.generate("Hello, my name is")
print(result[0].outputs[0].text)

警告

目前,我們以原始精度載入模型,然後才量化為 8 位,因此您需要足夠的記憶體來載入整個模型。