Mixed Precision
혼합 정밀도는 16비트 연산과 FP32 마스터 가중치를 사용해 신경망을 학습시키며, 메모리 사용량과 학습 시간을 줄입니다. 손실 스케일링, BF16, AMP를 다룹니다.
혼합 정밀도는 신경망의 연산 대부분을 FP16(반정밀도) 또는 BF16과 같은 16비트 부동소수점 형식으로 실행하면서, 32비트(FP32) 마스터 사본의 모델 가중치를 유지하고 수치적으로 민감한 연산은 FP32로 실행하는 학습 기법입니다. 16비트 값은 FP32의 절반에 해당하는 메모리와 대역폭을 사용하며, 최신 GPU의 Tensor Core는 16비트 값을 훨씬 빠르게 곱합니다. 따라서 혼합 정밀도는 학습 시간을 단축하고 더 큰 배치 크기를 메모리에 담으면서 FP32와 같은 수준의 정확도를 유지합니다. Micikevicius 등이 2018년에 설명한 기법은 FP32 마스터 가중치, FP16 연산, 손실 스케일링을 사용하며, 현재 딥러닝 프레임워크는 이를 자동 혼합 정밀도(AMP)로 자동화합니다.
혼합 정밀도의 작동 방식#
16비트 학습에서 역전파와 가중치 업데이트가 FP32 학습의 정확도를 유지하도록 하는 요소는 세 가지입니다.
- FP32 마스터 가중치: 옵티마이저는 가중치의 FP32 사본에 각 업데이트를 적용합니다. FP16은 유효 십진 숫자를 약 세 자리만 유지하므로 FP16 가중치에 작은 업데이트를 직접 더하면 반올림으로 사라지는 경우가 많습니다.
- 연산별 정밀도: autocast 컨텍스트는 Tensor Core가 가장 큰 속도 향상을 제공하는 행렬 곱셈과 컨볼루션을 16비트로 실행하고, 리덕션, 소프트맥스, 손실은 FP32로 유지합니다.
- 손실 스케일링: FP16은 약 6 × 10⁻⁸보다 작은 크기를 표현할 수 없으므로 작은 그래디언트가 다수 0으로 언더플로할 수 있습니다. 역전파 전에 손실에 스케일 계수를 곱하면 모든 그래디언트가 FP16의 표현 범위로 이동하며, 가중치를 업데이트하기 전에 같은 계수로 그래디언트를 다시 나눕니다.
PyTorch AMP에서는 torch.autocast이 연산별 형 변환을 처리하고 GradScaler가 손실 스케일링을 처리합니다.
import torch
from torch import nn
# Use FP16 on an NVIDIA GPU and BF16 on CPU
device = "cuda" if torch.cuda.is_available() else "cpu"
dtype = torch.float16 if device == "cuda" else torch.bfloat16
model = nn.Linear(512, 10).to(device) # master weights stay in FP32
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
scaler = torch.amp.GradScaler(device, enabled=dtype == torch.float16) # loss scaling for FP16 only
x = torch.randn(64, 512, device=device)
with torch.autocast(device_type=device, dtype=dtype):
out = model(x) # the matrix multiply runs in 16-bit
loss = out.float().pow(2).mean()
scaler.scale(loss).backward()
scaler.step(optimizer)
scaler.update()
print(f"Output: {out.dtype}, weights: {model.weight.dtype}, gradients: {model.weight.grad.dtype}")CPU에서 이 코드는 레이어 출력에 torch.bfloat16을 출력하고 가중치와 그래디언트 모두에 torch.float32을 출력합니다. NVIDIA GPU에서는 출력이 torch.float16입니다. 16비트 연산과 FP32 마스터 가중치는 하나의 학습 단계에서 함께 사용됩니다.
PyTorch의 GradScaler은 스케일을 동적으로 조정합니다. 65,536에서 시작해 스케일된 그래디언트에 inf 또는 NaN 값이 포함되면 스케일을 절반으로 줄이고 해당 단계를 건너뜁니다. 오버플로 없이 2,000단계를 연속으로 수행하면 스케일을 두 배로 늘리므로, 그래디언트가 오버플로하기 직전보다 약간 낮은 지점에 계수가 자리 잡습니다.
FP16, BF16 및 저정밀도 형식#
FP16은 지수부에 5비트, 가수부에 10비트를 사용하므로 정밀하지만 65,504를 초과하면 오버플로합니다. BF16은 FP32와 같은 8개의 지수 비트를 유지해 약 3.4 × 10³⁸까지 같은 범위를 표현하지만 가수부는 7비트뿐입니다. 따라서 손실 스케일링이 필요하지 않은 대신 반올림 정밀도가 낮습니다. BF16은 Ampere 세대 이후의 NVIDIA GPU, Google TPU, 최신 CPU 다수에서 실행되며, 대규모 언어 모델 학습에 일반적으로 사용되는 형식입니다. 같은 개념은 NVIDIA의 Transformer Engine을 통한 Hopper 및 Blackwell GPU의 FP8, 그리고 Blackwell의 NVFP4와 같은 FP4 형식으로도 이어집니다.
실무에서의 혼합 정밀도#
AMP에서 주의할 주요 위험은 16비트로 NaN 손실을 생성하는 모델 또는 GPU입니다. Ultralytics YOLO26 학습은 기본적으로 AMP를 활성화하고 amp=True를 사용합니다. 먼저 CUDA GPU에서 YOLO26n 모델의 FP32 예측과 AMP 예측을 비교하고, 결과가 다르거나 GTX 16 시리즈처럼 AMP에서 NaN 손실을 생성하는 것으로 알려진 시리즈에 GPU가 속하면 FP32로 전환합니다. amp="bf16"를 설정하면 손실 스케일링을 끈 BF16 autocast로 전환됩니다.
혼합 정밀도는 학습이 메모리 또는 시간에 제약받는 상황에서 널리 사용됩니다. 자율주행 차량을 개발하는 팀은 고해상도 프레임 수백만 장으로 객체 탐지 모델을 학습합니다. 이때 활성화 메모리를 절반으로 줄이면 더 큰 이미지와 배치 크기를 사용할 수 있습니다. 의료 이미지 분석에서는 3D CT 및 MRI 볼륨이 FP32로 GPU 메모리를 초과하는 경우가 많으며, 16비트 활성화를 사용하면 전체 볼륨을 대상으로 세그멘테이션 모델을 학습할 수 있습니다.
혼합 정밀도와 관련 개념 비교#
- 모델 양자화: 양자화는 학습된 모델을 INT8과 같은 저정밀도 정수로 변환해 추론 속도를 높이는 반면, 혼합 정밀도는 부동소수점 가중치를 유지하면서 학습 속도를 높입니다.
- 양자화 인식 학습: QAT는 학습 중 정수 반올림을 시뮬레이션하여 INT8 배포 후에도 모델의 정확도를 유지합니다.
- 반정밀도: 반정밀도는 FP16 숫자 형식 자체를 가리키며, 혼합 정밀도는 FP16과 FP32를 결합하는 학습 기법입니다. FP32 마스터 가중치나 손실 스케일링 없이 FP16만으로 학습하면 작은 업데이트는 반올림으로 사라지고 작은 그래디언트는 언더플로하며, 수렴에 실패하는 경우가 많습니다.










