양자화 KV 캐시

양자화 KV 캐시 (Quantized KV Cache)

자기회귀 생성에서 LLM은 이전에 계산한 키-값(key-value) 쌍을 캐시해서 중복 계산을 피해요. 그런데 이 KV 캐시가 GPU 메모리의 상당 부분을 차지하고, 특히 긴 시퀀스일수록 더 커져요. 양자화 KV 캐시는 기본 모델 정밀도인 BF16 대신 FP8이나 FP4 같은 저정밀도 데이터 타입을 써서 KV 저장의 메모리 발자국을 줄이는 기법이에요.

출처: 공식문서

기본적으로 처리량(throughput) 최적화 기법이에요. 더 많은 토큰을 캐시할 수 있어서요. 다만 양자화 형식에 따라 아주 약간의 정확도 저하가 있을 수 있어요.

성능 경고: 양자화 KV 캐시를 attention 연산에서 쓰기 전에 역양자화(dequantize)해야 할 때, 역양자화가 attention 커널과 융합(fuse)되어 있지 않으면 성능이 극도로 느려질 수 있어요. 선택한 attention 백엔드가 양자화 KV 캐시를 지원하는지 반드시 확인하세요. 융합 미지원 백엔드는 상당한 처리량 저하로 메모리 이점을 상쇄할 수 있어요.

백엔드 지원: 모든 attention 백엔드가 양자화 KV 캐시를 지원하지는 않아요. 어떤 백엔드가 지원하는지는 Attention Backend를 참고하세요.

지원 형식

SGLang이 지원하는 양자화 KV 캐시 형식은 다음과 같아요.

FP8 형식

OCP (Open Compute Project)는 두 가지 흔한 8비트 부동소수점 형식을 규정해요.

  • E5M2 (지수 5비트, 가수 2비트): 더 넓은 동적 범위(±57344.0), 더 낮은 정밀도
  • E4M3 (지수 4비트, 가수 3비트): 더 높은 정밀도, 더 좁은 동적 범위(±240.0)

FP4 형식

FP4 양자화는 현재 실험적이에요.

OCPMXFP4 (Microscaling FP4), 즉 4비트 부동소수점 형식을 규정해요.

  • E2M1 (부호 1비트, 지수 2비트, 가수 1비트): 블록 기반 마이크로스케일링을 사용해 텐서를 연속 요소의 블록으로 나누고, 각 블록이 하나의 8비트 지수 스케일링 팩터를 공유해요. OCP는 32개 요소 블록을 규정하지만, SGLang의 현재 구현은 KV 캐시 양자화에 16개 요소 블록을 사용해요.

사용법

양자화 KV 캐시 켜기

서버를 띄울 때 --kv-cache-dtype 인자를 쓰면 켜져요.

# Enable FP8 E5M2 KV cache
python3 -m sglang.launch_server \
    --model-path deepseek-ai/DeepSeek-R1-0528 \
    --kv-cache-dtype fp8_e5m2 \

# Enable FP8 E4M3 KV cache
python3 -m sglang.launch_server \
    --model-path deepseek-ai/DeepSeek-R1-0528 \
    --kv-cache-dtype fp8_e4m3 \

# Enable NVFP4 FP4 E2M1 KV cache
python3 -m sglang.launch_server \
    --model-path nvidia/DeepSeek-R1-0528-NVFP4 \
    --kv-cache-dtype nvfp4 \

# Enable block-size-16 FP4 E2M1 KV cache
python3 -m sglang.launch_server \
    --model-path deepseek-ai/DeepSeek-R1-0528 \
    --kv-cache-dtype fp4_mx_block16 \

스케일링 팩터 (Scaling Factors)

FP8 양자화는 KV 캐시를 제대로 양자화·역양자화하려면 스케일링 팩터가 필요해요.

참고: 현재는 텐서당(스칼라) 스케일링 팩터만 지원돼요.

스케일링 팩터는 다음 두 가지로 제공할 수 있어요.

  • 체크포인트에서 로드: 사전 양자화 모델(예: ModelOpt)이 k_scale, v_scale 파라미터를 포함하면 자동으로 로드돼요.
  • JSON으로 제공: --quantization-param-path로 스케일링 팩터를 넘깁니다.

JSON 파일은 다음 형식을 따라야 해요.

{
  "kv_cache": {
    "dtype": "float8_e4m3fn",
    "scaling_factor": {
      "0": {
        "0": 1.0,
        "1": 1.0
      }
    }
  }
}

scaling_factor의 바깥 키는 텐서 병렬 랭크, 안쪽 키는 레이어 인덱스예요.

경고: 스케일링 팩터를 제공하지 않고 체크포인트에서도 찾지 못하면 기본값 1.0으로 갑니다. 이 경우 정확도 문제가 생길 수 있어요.

팁: FP4 (MXFP4) 는 FP8과 달리 양자화·역양자화 중 스케일링 팩터를 그때그때 자동으로 처리해요. 사전 양자화 모델이나 외부 스케일링 팩터 파일이 필요 없고, 블록 기반 스케일링 팩터를 필요할 때 동적으로 계산해요.

성능 고려사항

메모리 절감

양자화 KV 캐시는 확실한 메모리 절감을 제공해요.

  • BF16 → FP4: BF16보다 약 3.56배 많은 토큰을 수용해요 (스케일링 팩터 오버헤드 포함).

참고: FP4와 FP8 양자화는 블록 기반 스케일링 팩터에 추가 메모리가 필요해서, 순수 비트 폭 감소에 비해 실질 메모리 절감은 줄어들어요. FP4(블록 크기 16)는 FP8보다 약 1.78배, BF16보다 약 3.56배 많은 토큰을 지원해요. FP8과 BF16 사이의 상대 토큰 용량은 이 비율에서 유도할 수 있어요.

이 덕분에 같은 메모리 예산 안에서 더 긴 컨텍스트를 다루거나 더 많은 동시 요청을 처리할 수 있어요.

정확도 영향

FP8 정확도

FP8 E4M3 양자화는 대개 아주 약간의 정확도 저하만 일으켜요. 영향은 모델 구조, 시퀀스 길이, 양자화 형식에 따라 다르고 (일반적으로 E4M3가 E5M2보다 정확도가 좋아요).

FP4 정확도

FP4 (MXFP4) 양자화는 상당한 메모리 절감을 주는데, 정확도 영향은 모델 크기와 데이터셋 복잡도에 따라 달라져요. PR #10078 (MLA)와 PR #12612 (MHA)의 예비 정확도 테스트 결과는 다음과 같아요.

대형 모델 (예: Qwen3-235B-A22B, DeepSeek-R1-0528)

대규모 모델에서는 FP4가 FP8/BF16에 가까운 정확도를 유지해요. 특히 단순한 데이터셋에서요.

Model Dataset KV16 KV8 (FP8 E4M3) KV4 (FP4 E2M1)
Qwen3-235B-A22B gsm8k 0.9168 0.9181 0.9186
Qwen3-235B-A22B aime25 0.7733 0.7333 0.6000
Qwen3-235B-A22B gpqa_diamond 0.7010 0.6899 0.6778
DeepSeek-R1-0528 gsm8k 0.9157 0.9154 0.9124
DeepSeek-R1-0528 aime25 0.5067 0.4934 0.4000
DeepSeek-R1-0528 gpqa_diamond 0.7707 0.7697 0.7273

소형 모델 (예: GPT-OSS-120B)

소형 모델에서는 FP4가 더 뚜렷한 정확도 저하를 보여요. 특히 어려운 데이터셋에서요.

Model Dataset KV16 KV8 (FP8 E4M3) KV4 (FP4 E2M1)
GPT-OSS-120B gsm8k 0.9161 0.9163 0.9152
GPT-OSS-120B aime25 0.7533 0.7667 0.3533
GPT-OSS-120B gpqa_diamond 0.5081 0.5434 0.3202

주요 관찰:

  • 단순한 데이터셋 (예: gsm8k): FP4가 모델 크기와 무관하게 FP8/BF16에 가까운 정확도를 유지해요.
  • 모델 크기가 중요해요: 대형 모델(200B+ 파라미터)은 일반적으로 소형 모델보다 FP4 양자화를 더 잘 견뎌요.
  • 컨텍스트 길이: 긴 컨텍스트 시나리오에서는 양자화 오차의 누적이 커질 수 있어서 정확도 저하가 더 두드러질 수 있어요.

팁: FP4 정확도를 자신의 모델과 워크로드에서 평가해 보세요. 단순한 작업의 대형 모델은 보통 최소한의 저하만 보이지만, 소형 모델이나 복잡한 추론 작업은 허용 가능한 정확도를 위해 FP8이나 BF16이 필요할 수 있어요.

모범 사례 (Best Practices)

  • 사전 양자화 모델을 쓰세요: 체크포인트에 스케일링 팩터가 포함되도록 오프라인에서 양자화된 모델을 선호해요.
  • 올바른 형식을 고르세요: 더 나은 정확도를 위해 fp8_e4m3(권장)을, 더 넓은 동적 범위를 위해 fp8_e5m2를, 최대 메모리 절감(실험적)을 위해 nvfp4/fp4_mx_block16을 쓰세요.
  • 백엔드 호환성을 확인하세요: 선택한 attention 백엔드가 양자화 KV 캐시를 지원하는지 확인해요.

참고: 함께 보면 좋은 자료로 Quantization, Attention Backend, Server Arguments가 있어요.

더 알아보기 (Learn more)