머신러닝 모델을 프로덕션에 배포할 때 가장 많이 고민하는 것 중 하나가 바로 수치 정밀도(Numerical Precision) 선택입니다. FP32로 학습한 모델을 FP16으로 서빙해도 될까? INT8 양자화는 언제 해야 할까? 이번 글에서는 정밀도 선택 전략을 정리했습니다.

TL;DR - 바쁜 분들을 위한 요약

"Train High, Infer Low" - 학습은 높은 정밀도로, 서빙은 낮은 정밀도로
상황 추천 조합 메모리 절감 안정성/품질 비고
LLM 학습/서빙 FP32+BF16 Mixed 학습 → BF16 추론 50% ⭐⭐⭐⭐⭐ 가장 일반적인 선택, 넓은 범위(±3.4×10³⁸), 수치 안정성 우수
고성능 서빙 FP32 학습 → BF16 추론 50% ⭐⭐⭐⭐⭐ A100, H100 등 최신 GPU 권장
컴퓨터 비전 추론 (제한적) FP32 학습 → FP16 추론 50% ⭐⭐⭐ ⚠️ 오버플로우 위험 (범위 ±65K)
모바일/엣지 디바이스 FP32 학습 → INT8 추론 (QAT) 75% ⭐⭐ 정확도 손실 1~5%, 정수 표현으로 제한적, 양자화 작업 필요

핵심: FP16은 정밀도는 높지만 표현 범위가 좁아서(최대값 65,504) 오버플로우 위험이 있습니다. INT8은 메모리 효율은 최고지만 정확도 손실이 가장 큽니다. 실무에서는 BF16이 가장 안정적이고 범용적입니다.

수치 정밀도, 왜 중요한가?

모델 서빙 시 정밀도 선택은 다음 세 가지에 직접적인 영향을 미칩니다:

  1. 추론 속도: FP16은 FP32 대비 최대 2배, INT8은 최대 4배 빠릅니다
  2. 메모리 사용량: 정밀도를 낮추면 모델 크기가 절반~1/4로 감소합니다
  3. 정확도: 정밀도를 낮추면 0.1%~5%의 정확도 손실이 발생할 수 있습니다

핵심 데이터 타입 4가지

FP32 (Float32) - 학습의 표준

구조: [1bit 부호][8bit 지수][23bit 가수] = 32bit
표현 범위: ±3.4 × 10³⁸
정밀도: 약 7~8자리

언제 사용?

  • 모델 학습 (Training)
  • 베이스라인 정확도 측정
  • 디버깅 및 검증

FP16 (Float16) - GPU 추론 가속

구조: [1bit 부호][5bit 지수][10bit 가수] = 16bit
표현 범위: ±65,504 ⚠️
정밀도: 약 3~4자리

장점: 메모리 50% 절감, 속도 2배 향상

단점: 좁은 표현 범위로 오버플로우 위험

언제 사용?

  • GPU에서 추론 가속
    • 컴퓨터 비전 모델 (이미지는 0~255로 정규화)
  • 하드웨어가 FP16에 최적화된 경우

BF16 (BFloat16) - 두마리 토끼 잡기

구조: [1bit 부호][8bit 지수][7bit 가수] = 16bit
표현 범위: ±3.4 × 10³⁸ (FP32와 동일\\!)
정밀도: 약 2~3자리

핵심 차이: FP16은 정밀도를, BF16은 표현 범위를 선택했습니다.

FP32:  [S][EEEEEEEE][MMMMMMMMMMMMMMMMMMMMMMM]
       1   8비트         23비트

FP16:  [S][EEEEE][MMMMMMMMMM]
       1   5비트   10비트  ← 지수 축소, 정밀도 우선

BF16:  [S][EEEEEEEE][MMMMMMM]
       1   8비트     7비트  ← 지수 유지, 범위 우선 (FP32 상위 16비트)

비유:

  • FP16 = 고성능 현미경 (세밀하지만 시야 좁음)
  • BF16 = 고성능 망원경 (시야 넓지만 세밀함 떨어짐)

언제 사용?

  • 대규모 언어 모델 (LLM) 학습 및 추론
  • TPU 또는 최신 GPU 사용 시
  • Gradient 안정성이 중요한 경우

INT8 - 엣지 디바이스의 필수

구조: 8bit 정수
표현 범위: -128 ~ 127 (또는 0 ~ 255)
메모리: FP32의 25%

장점: 매우 작은 메모리, 빠른 추론, 낮은 전력 소모

단점: 양자화 과정 필요, 1~5% 정확도 손실

언제 사용?

  • 모바일/엣지 디바이스 배포
  • 대규모 서빙 시스템 (비용 절감)
  • 실시간 처리가 필요한 경우

Mixed Precision Training (AMP)

최근 서빙에서는 Mixed Precision을 사용하는 것이 표준입니다.

Pure vs AMP

Pure BF16 (모든 연산을 BF16으로):

model = model.bfloat16()
output = model(input.bfloat16())

BF16 AMP (자동으로 섞어서 사용, 권장):

with torch.autocast(device_type='cuda', dtype=torch.bfloat16):
    output = model(input)

AMP는 어떻게 동작하나?

연산 종류 사용 정밀도 이유
Matmul, Conv BF16 계산 집약적, 속도 중요
ReLU, Pooling BF16 단순 연산
Softmax FP32 수치 안정성 중요 (exp 연산)
LayerNorm FP32 통계 계산, 정밀도 중요
Loss 계산 FP32 정확한 손실 값 필요

하드웨어 지원 체크하기

GPU

하드웨어 FP32 FP16 BF16 INT8
NVIDIA GPU (Ampere+)
NVIDIA GPU (Turing)
Google TPU
Apple Silicon

CPU

Intel CPU:

세대 모델 BF16 지원 가속 기술 성능
4세대 Xeon Sapphire Rapids (2023+) AMX 🚀 최고 (2~4배)
3세대 Xeon Ice Lake (2020+) AVX-512 BF16 ⚡ 우수 (1.5~2배)
Core 13/14세대 Raptor Lake (2022+) AVX-512 (일부) ⚡ 우수
구형 Cascade Lake 이전 X - -

AMD CPU:

세대 모델 BF16 지원
EPYC Genoa 4세대 (2022+)
Ryzen 7000 Zen 4 (2022+)
구형 Zen 3 이전 X

ARM CPU:

세대 모델 BF16 지원
AWS Graviton3 (2022+)
Apple M3/M4 (2023+)
구형 Zen 3 이전 X
import torch

# CPU BF16 지원 확인
if torch.cpu.amp.autocast_mode.is_autocast_available('cpu'):
    print("CPU BF16 지원됨\\!")

# CPU BF16 AMP 사용
with torch.cpu.amp.autocast():
    output = model(input)

결론

수치 정밀도 선택은 정확도, 성능, 비용의 트레이드오프입니다.

학습과 서빙의 정밀도를 반드시 맞출 필요는 없습니다. 오히려 다른 정밀도를 사용하는 것이 일반적입니다. FP32로 서빙한것과 BF16, FP16 으로 서빙했을때의 결과 품질이 어느정도의 차이를 보이는데 각 모델이나 서비스마다 직접 테스트 하면서 결정해야 합니다.

각 단계에서 정확도를 측정하고, 비즈니스 요구사항에 맞는 최적점을 찾는 것이 핵심입니다. "Train High, Infer Low" 전략으로 시작해서 점진적으로 최적화하세요.


참고 자료: