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
또한 평가를 위해 vllm 과 lm-evaluation-harness 를 설치합니다.
(venv-vllm) pip install vllm "lm-eval[api]>=0.4.12"
vLLM과 llm-compressor는 함께 동작하지 못할 수 있으므로 별도의 환경을 사용하세요.
양자화 과정 (Quantization Process)
양자화 과정은 세 가지 주요 단계로 구성됩니다.
- 모델 로드
- 양자화 적용
- 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)