Fill in the memory delta when a 7B weight tensor moves from fp32 to bf16
fp32 uses 4 bytes per weight, bf16 uses 2, so a 7B tensor drops from 28 GB to 14 GB, freeing about 14 GB.
Imagine every weight is a card you have to store in a filing cabinet. In the wide format, each card needs a four-slot envelope. In the narrow format, each card only needs a two-slot envelope. The card itself does not change shape, only the packaging around it. If you have seven billion cards and you trade every wide envelope for a narrow one, you cut your storage shelves exactly in half. Same number of cards, half the cabinet space. That is the deal you get when you swap a model's weights from the wide format to the narrow one, and on a seven billion card collection the freed shelf space comes out to about fourteen gigabytes.
Detailed answer & concept explanation~6 min readEverything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example. Click to expand.
Everything you need to truly understand this topic: intuition, mechanics, step by step explanation, code, formulas, and worked example.
Everything important, quickly.
3 min: bytes per element for each format, scaling to a 7B tensor, the weight delta, why bf16 beats fp16, and how gradients and optimizer states sit on top of the weight footprint.
import torch
n_params = 7_000_000_000
bytes_per_fp32 = 4
bytes_per_bf16 = 2
fp32_gb = n_params * bytes_per_fp32 / 1024**3
bf16_gb = n_params * bytes_per_bf16 / 1024**3
saved_gb = fp32_gb - bf16_gb
print(f"fp32 weights: {fp32_gb:.1f} GB")
print(f"bf16 weights: {bf16_gb:.1f} GB")
print(f"freed by swap: {saved_gb:.1f} GB")
# Verify with a real tensor
weights_bf16 = torch.empty(n_params // 1_000_000, dtype=torch.bfloat16)
weights_fp32 = weights_bf16.to(torch.float32)
assert weights_fp32.element_size() == 2 * weights_bf16.element_size()| Format | Bits | Bytes per param | 7B tensor size |
|---|---|---|---|
| fp32 | 32 | 4 | ~28 GB |
| bf16 | 16 | 2 | ~14 GB |
| fp16 | 16 | 2 | ~14 GB |
| int8 | 8 | 1 | ~7 GB |
| nf4 | 4 | 0.5 | ~3.5 GB |
Real products, models, and research that use this idea.
- Llama 4 Maverick checkpoints ship as bf16 weights on Hugging Face, halving the disk and VRAM footprint relative to an fp32 release.
- DeepSeek V4 base weights are distributed in bf16 because every modern Hopper and Blackwell GPU executes bf16 matmul natively at full throughput.
- Qwen 3.5 fine-tuning guides assume bf16 weights plus fp32 master weights as the default mixed-precision recipe in 2026 training stacks.
- Hugging Face transformers loads bf16 checkpoints with torch_dtype=torch.bfloat16, the one-line incantation behind the 2x weight savings.
What an interviewer would ask next. Try answering before peeking at the approach.
QIf the model also needs gradients and Adam optimizer states, what is the full per-parameter memory in pure fp32 versus mixed-precision?
QWhy is bf16 preferred over fp16 in modern training even though both use 2 bytes?
Don't say thisRed flags and common mistakes that signal junior thinking. Click to expand.
Red flags and common mistakes that signal junior thinking. Click to expand.
Forgetting that the delta is the SAVINGS, not the new total. Reporting 28 GB or 16 GB instead of 14 GB usually means confusing the old size with the freed amount.
The night-before-the-interview bullets. Scan these on the way to the call.
Primary sources. Skim if you want the original framing.
Same topic, related formats. Practice these next.