BFloat16 (BF16)
BFloat16 (BF16) ist ein 16-Bit-Gleitkommaformat mit dem 8-Bit-Exponent und einem 7-Bit-Bruchteil von FP32. Es bietet den Wertebereich von FP32 bei halbem Speicherbedarf. So unterscheidet es sich von FP16.
BFloat16 (Gleitkommaformat nach dem Vorbild des Gehirns, BF16) ist ein 16-Bit-Gleitkommaformat mit 1 Vorzeichenbit, 8 Exponentenbits und 7 Mantissenbits. Es behält dieselbe Exponentenbreite wie das standardmäßige 32-Bit-Gleitkommaformat (FP32) bei und deckt daher denselben Wertebereich von etwa 1,2 × 10⁻³⁸ bis 3,4 × 10³⁸ ab, während jede Zahl nur halb so viel Speicher benötigt. Der Nachteil ist die Genauigkeit: 7 Mantissenbits reichen nur für zwei bis drei signifikante Dezimalstellen. Deep Learning verträgt diese Rundung gut. Das Format wurde bei Google Brain für Googles TPUs entwickelt und ist zum standardmäßigen 16-Bit-Format für das Training großer Modelle auf modernen GPUs und Beschleunigern geworden.
Wie BF16 Zahlen darstellt#
Ein BF16-Wert ist genau die obere Hälfte eines FP32-Werts: Vorzeichen und Exponent sind gleich, während die Mantisse von 23 auf 7 Bits gekürzt wird. Bei der Umwandlung von FP32 in BF16 werden daher nur die unteren 16 Bits weggerundet. Bei der Rückumwandlung werden Nullen angefügt, wodurch sich das Format kostengünstig in Hardware implementieren lässt. Das andere verbreitete 16-Bit-Format, IEEE FP16 oder halbe Genauigkeit, teilt die Bits anders auf: 5 Exponentenbits und 10 Mantissenbits bieten eine höhere Genauigkeit auf Kosten des Wertebereichs. Ein Vergleich der drei Formate anhand derselben Werte zeigt den Kompromiss:
import torch
# Largest value, smallest normal value, and spacing just above 1.0 for each format
for dtype in [torch.float32, torch.float16, torch.bfloat16]:
info = torch.finfo(dtype)
print(f"{dtype!s:15} max={info.max:.3g} tiny={info.tiny:.3g} eps={info.eps:.3g}")
# A large activation, a tiny gradient, and a value that needs fine precision
x = torch.tensor([70000.0, 1e-8, 1.001953125])
print("FP16:", x.half().tolist())
print("BF16:", x.bfloat16().tolist())BF16 erreicht einen Höchstwert von 3.39e38 gegenüber 65,504 bei FP16. Sein kleinster normalisierter Wert von 1.18e-38 entspricht dem von FP32. FP16 wandelt 70,000 in unendlich und 1e-8 in null um, während BF16 beide Werte als 70,144 beziehungsweise etwa 1.0e-8 beibehält. Die feinere Abstufung von FP16 (eps 0.000977 gegenüber 0.00781 bei BF16) stellt 1.001953125 exakt dar; BF16 rundet den Wert auf 1.0.
BF16 und FP16 im Training#
Beim Training ist der Wertebereich wichtiger als die Genauigkeit. Gradienten fallen oft unter die kleinsten FP16-Werte und verschwinden dann. Beim FP16-Training mit gemischter Genauigkeit wird daher der Verlust vor der Rückpropagation mit einem Skalierungsfaktor multipliziert. Dieser Faktor wird verringert, sobald Gradienten überlaufen – ein Verfahren, das als Verlustskalierung bezeichnet wird. BF16 benötigt keine Verlustskalierung, da sein Wertebereich dem von FP32 entspricht. Das BF16-Training erzielt bei Bildverarbeitungs-, Sprach-, Sprachverstehens- und Empfehlungsmodellen mit derselben Anzahl von Iterationen Ergebnisse, die FP32 entsprechen, ohne die Hyperparameter zu ändern. Beim Training mit gemischter Genauigkeit wird eine Masterkopie der Gewichte in FP32 behalten. Matrixmultiplikationen laufen in BF16 mit FP32-Akkumulation, da beim Summieren vieler Produkte mit 7 Mantissenbits in BF16 zu viel Genauigkeit verloren ginge. Die Wahl zwischen den beiden 16-Bit-Formaten hängt hauptsächlich von der Hardware ab:
PyTorch verwendet BF16 über automatische gemischte Genauigkeit mit torch.autocast(device_type="cuda", dtype=torch.bfloat16). Ultralytics YOLO bietet dieselbe Option für das Training mit amp="bf16". Damit wird der Vorwärtsdurchlauf unter BF16-Autocast ausgeführt und der Gradienten-Skalierer deaktiviert, den der standardmäßige FP16-Modus verwendet – auf CUDA-GPUs mit nativer BF16-Unterstützung.
Hardwareunterstützung#
Googles Cloud-TPUs der zweiten und dritten Generation führen Multiplikationen in ihren Matrixeinheiten mit BF16 aus und akkumulieren die Ergebnisse in FP32. Auch spätere TPU-Generationen behielten das Format bei. NVIDIA-GPUs verarbeiten BF16 ab der Ampere-Generation auf Tensor Cores, darunter die GPUs A100, H100 und Blackwell. Intel-Xeon-Prozessoren beschleunigen BF16 mit Advanced Matrix Extensions (AMX) auf der CPU. Auf einer NVIDIA A100 erreichen BF16- und FP16-Berechnungen auf Tensor Cores beide eine Spitzenleistung von 312 teraFLOPS – das 16-Fache der 19,5 teraFLOPS der GPU bei standardmäßigen FP32-Berechnungen.
BF16 und verwandte Formate#
- Halbe Genauigkeit (FP16): Das IEEE-16-Bit-Format mit höherer Genauigkeit und deutlich kleinerem Wertebereich. Es ist für Inferenz weiterhin verbreitet, da die Aktivierungen innerhalb seines Wertebereichs bleiben und die höhere Genauigkeit hilfreich ist.
- TF32: Ein NVIDIA-Tensor-Core-Rechenmodus mit dem 8-Bit-Exponenten von BF16 und der 10-Bit-Mantisse von FP16. Bibliotheken können ihn für FP32-Matrixmultiplikationen auf Ampere- und neueren GPUs verwenden, während die Tensoren im 32-Bit-Format gespeichert bleiben.
- FP8: 8-Bit-Gleitkommaformate wie E4M3 und E5M2, die von Hopper- und Blackwell-GPUs unterstützt werden und den Speicherbedarf für das Training und die Inferenz der größten Modelle nochmals halbieren.
- Modellquantisierung: Wandelt trainierte Gewichte für den Einsatz in ganzzahlige Formate wie INT8 oder INT4 um.
BF16 in großen Sprachmodellen#
Die meisten Modelle mit offenen Gewichten für große Sprachmodelle (LLMs) werden mit gemischter BF16-Genauigkeit trainiert und mit BF16-Gewichten veröffentlicht. Diese dienen als Referenz für quantisierte FP8- und INT4-Versionen. Bei 2 Byte pro Parameter benötigen die Gewichte eines Modells mit 70 Milliarden Parametern in BF16 140 GB – mehr als die 80 GB einer einzelnen NVIDIA H100. Um ein solches Modell bereitzustellen, muss es daher in BF16 auf mindestens zwei GPUs verteilt werden.










