FP8 W8A8

FP8 W8A8

vLLM은 Nvidia H100과 AMD MI300x 같은 GPU에서 하드웨어 가속을 사용한 FP8(8비트 부동 소수점) 가중치 및 활성화 양자화를 지원해요. W8A8은 Ada Lovelace, Hopper, Blackwell GPU에서 지원됩니다. Turing/Ampere GPU는 Marlin 커널을 활용한 W8A16(weight-only FP8)을 지원합니다. FP8로 모델을 양자화하면 모델 메모리 요구 사항을 2배 줄이고 정확도에 미치는 영향을 최소화하면서 처리량을 최대 1.6배까지 개선할 수 있습니다.

vLLM과 함께 사용할 준비가 된 인기 LLM의 양자화된 FP8 체크포인트 HF 컬렉션 을 방문하세요.

출처: 문서

본문

하드웨어에서 일반적으로 지원되는 FP8 타입은 두 가지 뚜렷한 표현이 있으며, 각각 다른 시나리오에서 유용합니다.

  • E4M3: 1개의 부호 비트, 4개의 지수 비트, 3개의 가수 비트로 구성됩니다. 최대 +/-448 및 nan 값을 저장할 수 있습니다.
  • E5M2: 1개의 부호 비트, 5개의 지수 비트, 2개의 가수 비트로 구성됩니다. 최대 +/-57344, +/-inf, nan 값을 저장할 수 있습니다. 증가된 동적 범위의 대가는 저장된 값의 정밀도가 낮아진다는 것입니다.

참고: FP8 연산은 compute capability >= 8.9(Ada Lovelace, Hopper, Blackwell)인 NVIDIA GPU에서 지원됩니다. FP8 모델은 compute capability >= 7.5(Turing)에서 FP8 Marlin을 활용한 weight-only W8A16으로 실행됩니다.

GEMM 커널 선택 (GEMM kernel selection)

vLLM은 로드 시점에 FP8 GEMM 커널을 자동으로 선택하고 시작 시 Selected <kernel> for <module> 줄을 로깅합니다. CUDA에서 block-quantized 체크포인트에 대해 순서대로 시도합니다: FlashInfer/DeepGEMM 하이브리드(Hopper 전용), DeepGEMM, CUTLASS, Marlin, Triton, Humming, 그다음 PyTorch 폴백. 네이티브 FP8 지원이 없는 GPU(예: Turing/Ampere)는 weight-only(W8A16) Marlin으로 갑니다.

오류 없이 추론이 멈춘다면 VLLM_USE_DEEP_GEMM=0 또는 --linear-backend cutlass 를 시도하세요.

--linear-backend 는 양자화된 선형 레이어에만 영향을 주며, MoE 전문가는 별도의 --moe-backend 를 사용합니다. 하드웨어에서 지원되지 않는 명시적 백엔드는 폴백하지 않고 오류를 발생시킵니다. 전체 목록은 CLI 참조의 KernelConfig 아래 문서화되어 있고 vllm serve --help=KernelConfig 로 확인할 수 있습니다.

설치 (Installation)

vLLM으로 고성능 FP8 양자화 모델을 만들려면 llm-compressor 라이브러리를 설치해야 합니다.

(venv-llm-compressor) pip install llmcompressor

또한 평가를 위해 vllmlm-evaluation-harness 를 설치합니다.

(venv-vllm) pip install vllm "lm-eval[api]>=0.4.12"

vLLM과 llm-compressor는 함께 동작하지 못할 수 있으므로 별도의 환경을 사용하세요.

양자화 과정 (Quantization Process)

양자화 과정은 세 가지 주요 단계로 구성됩니다.

  1. 모델 로드
  2. 양자화 적용
  3. vLLM에서 정확도 평가

1. 모델 로드 (Loading the Model)

표준 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",
    dtype="auto",
)
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)

2. 양자화 적용 (Applying Quantization)

FP8 양자화의 경우 간단한 RTN 양자화로 정확도를 회복할 수 있습니다. 다음을 사용하는 FP8_DYNAMIC 체계로 모든 Linear 레이어를 대상으로 하는 것을 권장합니다.

  • 가중치에 대한 정적, per-channel 양자화
  • 활성화에 대한 동적, per-token 양자화

간단한 RTN은 가중치 양자화에 데이터가 필요 없고 활성화는 동적으로 양자화되므로, 이 양자화 흐름에 보정 데이터가 필요 없습니다.

from llmcompressor 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. 정확도 평가 (Evaluating Accuracy)

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 로 정확도를 평가합니다(예: gsm8k 250개 샘플에서).

참고: 양자화된 모델은 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|

트러블슈팅 및 지원 (Troubleshooting and Support)

문제가 발생하거나 기능 요청이 있으면 vllm-project/llm-compressor GitHub 저장소에 이슈를 열어 주세요.

온라인 동적 양자화 (Online Dynamic Quantization)

원본 정밀도 BF16/FP16 모델의 FP8 동적 양자화는 보정 데이터 없이 vLLM으로 달성할 수 있습니다. 명령줄에서 --quantization="fp8" 를 지정하거나 LLM 생성자에서 quantization="fp8" 를 설정하면 이 기능을 활성화할 수 있어요.

이 모드에서는 모든 Linear 모듈(최종 lm_head 제외)의 가중치가 per-tensor 스케일로 FP8_E4M3 정밀도로 양자화됩니다. 활성화는 각 forward pass 중 최소/최대 값을 계산해 높은 정확도를 위한 동적 per-tensor 스케일을 제공합니다. 결과적으로 이 모드에서는 지연 시간 개선이 제한됩니다.

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)

더 알아보기 (Learn more)