Half the memory, twice the speed (often)
Mixed-precision training runs most operations in float16 or bfloat16 while keeping a small set of numerically sensitive ops (softmax, normalization, loss reduction) in float32. On Ampere+ GPUs and Apple Silicon this typically gives a 1.5–2x speedup AND roughly halves memory usage for activations.
The modern PyTorch API is torch.amp (not the older torch.cuda.amp, which is deprecated). Two ingredients:
autocast(device_type='cuda', dtype=...)— context manager that picks the right precision per op.GradScaler(device_type)— only needed for fp16. Scales the loss up before backward to prevent gradient underflow in the narrow fp16 range, then unscales before the optimizer step.
fp16 vs bf16
- bfloat16 — same exponent range as float32, less precision in the mantissa. Available on Ampere+ NVIDIA GPUs (A100, RTX 30/40 series, H100) and Apple Silicon. No GradScaler needed. The recommended modern default.
- float16 — narrower exponent range. Needs GradScaler. Still relevant for older GPUs (V100, T4, RTX 20-series).
What you actually wrap
Wrap the forward pass and loss computation. Backward stays outside the autocast block. Optimizer step stays outside too.