Mixed Precision
Beim Training mit gemischter Präzision werden neuronale Netzwerke mit 16-Bit-Berechnungen und FP32-Mastergewichten trainiert. Das senkt Speicherbedarf und Trainingszeit. Behandelt werden Loss Scaling, BF16 und AMP.
Gemischte Präzision ist ein Trainingsverfahren, bei dem die meisten Berechnungen eines neuronalen Netzes in einem 16-Bit-Gleitkommaformat ausgeführt werden, entweder FP16 (halbe Genauigkeit) oder BF16. Dabei bleibt eine 32-Bit-Kopie (FP32) der Modellgewichte erhalten, und numerisch empfindliche Operationen werden in FP32 ausgeführt. 16-Bit-Werte benötigen halb so viel Speicher und Bandbreite wie FP32-Werte. Die Tensor Cores moderner GPUs multiplizieren sie zudem deutlich schneller. Gemischte Präzision verkürzt daher das Training und ermöglicht größere Batchgrößen im Speicher, ohne die FP32-Genauigkeit zu beeinträchtigen. Das von Micikevicius et al. 2018 beschriebene Verfahren mit FP32-Mastergewichten, FP16-Arithmetik und Loss Scaling wird heute von Frameworks für Deep Learning als automatische gemischte Präzision (AMP) umgesetzt.
So funktioniert gemischte Genauigkeit#
Drei Bestandteile sorgen dafür, dass Backpropagation und Gewichtsaktualisierungen beim 16-Bit-Training dieselbe Genauigkeit wie beim FP32-Training erreichen:
- FP32-Mastergewichte: Der Optimierer wendet jedes Update auf eine FP32-Kopie der Gewichte an. Ein winziges Update, das direkt zu einem FP16-Gewicht addiert wird, würde häufig weggerundet, weil FP16 nur etwa drei signifikante Dezimalstellen beibehält.
- Präzision pro Operation: Ein Autocast-Kontext führt Matrixmultiplikationen und Faltungen mit 16 Bit aus, wo Tensor Cores den größten Geschwindigkeitszuwachs bieten, und hält Reduktionen, Softmax und Verlustfunktion in FP32.
- Loss Scaling: FP16 kann keine Beträge unter etwa 6 × 10⁻⁸ darstellen. Viele kleine Gradienten würden daher zu null unterlaufen. Wird der Verlust vor der Backpropagation mit einem Skalierungsfaktor multipliziert, verschiebt das jeden Gradienten in den darstellbaren FP16-Bereich. Vor der Gewichtsaktualisierung werden die Gradienten durch denselben Faktor geteilt.
In PyTorch AMP übernimmt torch.autocast die Umwandlung der Datentypen pro Operation und GradScaler das Loss Scaling:
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}")Auf der CPU gibt das Beispiel für die Schichtausgabe torch.bfloat16 und für die Gewichte sowie deren Gradienten jeweils torch.float32 aus. Auf einer NVIDIA-GPU lautet die Ausgabe torch.float16. Die 16-Bit-Berechnungen und die FP32-Mastergewichte kommen in einem Trainingsschritt gemeinsam zum Einsatz.
GradScaler von PyTorch passt den Skalierungsfaktor dynamisch an. Der Startwert beträgt 65,536. Sobald die skalierten Gradienten Werte inf oder NaN enthalten, halbiert das Verfahren den Faktor und überspringt den Schritt. Nach 2,000 aufeinanderfolgenden Schritten ohne Überlauf wird der Faktor verdoppelt. So pendelt sich der Faktor knapp unter dem Wert ein, bei dem die Gradienten überlaufen.
FP16, BF16 und Formate mit geringerer Präzision#
FP16 verwendet 5 Bit für den Exponenten und 10 für die Mantisse. Es ist daher präzise, läuft aber bei Werten über 65,504 über. BF16 behält die 8 Exponentenbits von FP32 bei und deckt damit denselben Wertebereich bis etwa 3.4 × 10³⁸ ab. Mit nur 7 Mantissenbits braucht es kein Loss Scaling, rundet dafür aber gröber. BF16 läuft auf NVIDIA-GPUs ab der Ampere-Generation, auf Google-TPUs und auf vielen neueren CPUs. Es ist das übliche Trainingsformat für große Sprachmodelle. Dasselbe Prinzip setzt sich mit FP8 auf Hopper- und Blackwell-GPUs über NVIDIA-Transformer Engine sowie mit FP4-Formaten wie NVFP4 auf Blackwell fort.
Gemischte Präzision in der Praxis#
Das größte praktische Risiko bei AMP besteht darin, dass ein Modell oder eine GPU NaN-Verluste mit 16 Bit erzeugt. Das Training mit Ultralytics YOLO26 aktiviert AMP standardmäßig mit amp=True. Zunächst werden die FP32- und AMP-Vorhersagen eines YOLO26n-Modells auf CUDA-GPUs verglichen. Bei Abweichungen oder bei einer GPU aus einer Serie, die dafür bekannt ist, unter AMP NaN-Verluste zu erzeugen, etwa der GTX-16-Serie, wird auf FP32 zurückgegriffen. Mit amp="bf16" wird BF16-Autocast aktiviert und Loss Scaling ausgeschaltet.
Gemischte Präzision wird überall dort eingesetzt, wo das Training durch Speicher oder Zeit begrenzt ist. Teams, die autonome Fahrzeuge entwickeln, trainieren Modelle zur Objekterkennung mit Millionen hochauflösender Einzelbilder. Durch den halbierten Speicherbedarf der Aktivierungen sind größere Bilder und Batches möglich. Bei der medizinischen Bildanalyse überschreiten 3D-CT- und MRT-Volumina häufig den GPU-Speicher in FP32. 16-Bit-Aktivierungen ermöglichen das Training von Segmentierungs modellen mit vollständigen Volumina.
Gemischte Präzision im Vergleich zu verwandten Konzepten#
- Modellquantisierung: Bei der Quantisierung wird ein trainiertes Modell für eine schnellere Inferenz in Ganzzahlen mit geringerer Präzision wie INT8 umgewandelt. Gemischte Präzision beschleunigt dagegen das Training und behält Gleitkomma-Gewichte bei.
- Quantisierungsbewusstes Training: QAT simuliert beim Training die Rundung auf Ganzzahlen, damit das Modell nach der Bereitstellung mit INT8 seine Genauigkeit beibehält.
- Halbe Genauigkeit: Halbe Genauigkeit bezeichnet das FP16-Zahlenformat selbst. Gemischte Präzision ist das Trainingsverfahren, das FP16 mit FP32 kombiniert. Reines FP16-Training ohne FP32-Mastergewichte oder Loss Scaling verliert kleine Updates durch Rundung und kleine Gradienten durch Unterlauf und konvergiert oft nicht.










