FP8 ViT 인코더 어텐션
FP8 ViT 인코더 어텐션 (FP8 ViT Encoder Attention)
큰 이미지(예: QHD, 4K)와 상대적으로 짧은 텍스트 프롬프트/생성을 다루는 시각 이해 워크로드에서는, 텍스트 모델이 양자화되어 있을 때(예: NVFP4) ViT 인코더 어텐션이 상당한 병목이 될 수 있어요. vLLM은 NVIDIA GPU의 FlashInfer cuDNN과 AMD GPU의 AITER를 통해 ViT 인코더 어텐션에 선택적 FP8 양자화를 지원합니다. Q/K/V는 어텐션 호출 직전에 즉시 FP8로 양자화됩니다.
참고:
- 현재 Qwen3-VL 계열 모델(
qwen3_vl,qwen3_vl_moe,qwen3_5,qwen3_5_moe, 그리고 Qwen3 ViT를 사용하는 다른 모델)만 지원합니다.- 동적 스케일링은 ViT 전체 CUDA 그래프와 호환되지 않습니다.
- 성능 이점은 대부분 QHD/4K 해상도나 멀티이미지 요청에서 드러납니다. 작은 이미지는 양자화 오버헤드(양자화 커널 3회 실행 + 언패딩) 때문에 속도 향상이 없을 수 있습니다.
- FP8 텐서코어 속도 향상은 GB200보다 GB300에서 더 두드러집니다.
- ROCm에서는 packed 가변 길이 이미지 및 비디오 배치가 AITER의 네이티브 varlen FP8 어텐션으로 지원됩니다.
출처: 문서
본문
요구 사항 (Requirements)
- NVIDIA: cuDNN >= 9.17.1인 FlashInfer cuDNN 백엔드.
- AMD: gfx942(MI300 시리즈) 또는 gfx950(MI350 시리즈)에서
flash_attn_varlen_fp8_pertensor_func지원이 있는 AITER.
사용법 (Usage)
--mm-encoder-attn-dtype fp8 를 전달하고 현재 플랫폼의 백엔드를 선택해 FP8 ViT 어텐션을 활성화합니다.
vllm serve $MODEL \
--mm-encoder-attn-backend FLASHINFER \
--mm-encoder-attn-dtype fp8
# AMD ROCm
vllm serve $MODEL \
--mm-encoder-attn-backend ROCM_AITER_FA \
--mm-encoder-attn-dtype fp8
기본적으로(스케일 파일 없음) 동적 스케일링 이 사용됩니다. 관찰된 Q/K/V amax 값의 16-항목 순환 버퍼가 per-forward 스케일 업데이트를 주도합니다. 이는 보정 없이 BF16 정확도를 맞추지만 약간의 per-forward 오버헤드를 추가합니다.
캘리브레이션-원회, 재사용 워크플로우 (권장, Calibrate-Once, Reuse Workflow)
프로덕션에서는 대표 데이터셋에서 정적 스케일을 한 번 캘리브레이션하고 재사용해 동적 오버헤드를 피하세요.
# Step 1: calibrate and save scales (runs dynamic scaling for 16 passes,
# then dumps the learned scales to JSON).
vllm bench mm-processor \
--model $MODEL --mm-encoder-attn-backend $MM_ATTN_BACKEND \
--mm-encoder-attn-dtype fp8 \
--mm-encoder-fp8-scale-save-path /path/to/scales.json \
--dataset-name hf --dataset-path lmarena-ai/VisionArena-Chat \
--num-prompts 100
# Step 2: serve with static scales (no dynamic overhead).
vllm serve $MODEL \
--mm-encoder-attn-backend $MM_ATTN_BACKEND \
--mm-encoder-attn-dtype fp8 \
--mm-encoder-fp8-scale-path /path/to/scales.json
저장된 스케일은 --mm-encoder-fp8-scale-save-margin(기본 1.5)만큼 곱해져 보정 세트에 없는 활성화 이상치에 대한 여유를 남깁니다. 이 기본값은 데이터셋 전반에 일반화되는 것으로 검증되었습니다(예: VisionArena-Chat 캘리브레이션이 ChartQA에서 BF16 정확도를 유지).
스케일 파일 형식 (Scale File Format)
{
"visual.blocks.0.attn.attn": {"q": 224.0, "k": 198.0, "v": 210.0},
"visual.blocks.1.attn.attn": {"q": 218.0, "k": 195.0, "v": 207.0}
}
q_scale / k_scale / v_scale 키도 별칭으로 허용됩니다.
성능 (Performance)
코어 cuDNN 어텐션 커널(PyTorch profiler, cudnn_generated_fort_native_sdpa_sm100_flash_fprop, head_dim=128, seq_len=8192):
| 하드웨어 | BF16 | FP8 | Speedup |
|---|---|---|---|
| GB200 | 350 us | 312 us | 1.12x |
| GB300 | 300 us | 211 us | 1.42x |
종단 간 인코더 순방향 시간(GB200의 Qwen3-VL-30B-A3B-Instruct, 요청당 3개 이미지):
| 해상도 | BF16 중앙값 | FP8 중앙값 | Speedup |
|---|---|---|---|
| HD (720x1280) | 31.77 ms | 36.39 ms | 0.87x |
| FullHD (1080x1920) | 57.99 ms | 58.73 ms | ~same |
| QHD (1440x2560) | 131.83 ms | 122.30 ms | 1.08x |
| 4K (2160x3840) | 543.44 ms | 460.31 ms | 1.18x |
크로스오버는 요청당 3개 이미지의 FullHD 부근입니다. QHD 이상에서는 FP8이 이깁니다.
MI300X의 완전한 AITER 어텐션 호출(BF16 입력, 16 헤드, head_dim=72; FP8은 Q/K/V 양자화 포함):
| 시퀀스 길이 | AITER BF16 | AITER FP8 | Speedup |
|---|---|---|---|
| 2304 | 0.467 ms | 0.337 ms | 1.38x |
| 4096 | 0.812 ms | 0.764 ms | 1.06x |
| 8192 | 2.555 ms | 2.364 ms | 1.08x |
| 16384 | 9.769 ms | 8.655 ms | 1.13x |
정확도 (Accuracy)
ChartQA, Qwen3-VL-8B-Instruct, 500 샘플. FP8 static은 VisionArena-Chat에서 캘리브레이션된 스케일(기본 1.5x 마진)을 사용합니다.
| 메트릭 | BF16 | FP8 dynamic | FP8 static |
|---|---|---|---|
| relaxed_accuracy | 0.780 | 0.776 | 0.780 |
| anywhere_accuracy | 0.806 | 0.816 | 0.814 |
| exact_match | 0.584 | 0.582 | 0.578 |
세 구성 모두 통계적 노이즈 범위 내에서 일치하며, 한 데이터셋에서 캘리브레이션한 정적 스케일이 다른 데이터셋에도 일반화된다는 것을 확인해 줍니다.