automatic mixed precision amp

**Automatic Mixed Precision (AMP)** is **the framework-integrated system that automatically converts operations to optimal precision (FP16/BF16 or FP32) based on operation type and numerical sensitivity — eliminating manual casting, providing dynamic loss scaling, and enabling mixed precision training with 3-5 lines of code, achieving 2-4× speedup and 50% memory reduction while maintaining model accuracy through intelligent operation-level precision selection and automatic gradient scaling**. **AMP Architecture:** - **Autocast Context**: with torch.cuda.amp.autocast(): automatically casts operations within context; matrix multiplies → FP16/BF16; reductions → FP32; softmax → FP32; no manual .half() or .float() calls required - **Operation Whitelist**: GEMM, convolution, attention use FP16/BF16 (Tensor Core operations); benefit from hardware acceleration; constitute 80-95% of training compute - **Operation Blacklist**: softmax, log_softmax, cross_entropy, layer_norm, batch_norm use FP32; numerically sensitive; require higher precision for stability - **Operation Graylist**: element-wise operations (add, multiply, ReLU) match input precision; if inputs are FP16, output is FP16; if mixed, promote to FP32; flexible precision based on context **PyTorch AMP Implementation:** - **Basic Pattern**: scaler = GradScaler(); with autocast(): output = model(input); loss = criterion(output, target); scaler.scale(loss).backward(); scaler.step(optimizer); scaler.update() - **GradScaler**: manages loss scaling automatically; scales loss before backward(); unscales gradients before optimizer step; skips step if overflow detected; adjusts scale dynamically - **Gradient Clipping**: scaler.unscale_(optimizer); torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm); scaler.step(optimizer); — unscale before clipping for correct norm calculation - **Multiple Optimizers**: separate GradScaler for each optimizer; or single scaler with multiple unscale/step calls; enables complex training loops (GANs, multi-task learning) **TensorFlow AMP Implementation:** - **Policy Setup**: policy = tf.keras.mixed_precision.Policy('mixed_float16'); tf.keras.mixed_precision.set_global_policy(policy); applies to all layers and operations - **Loss Scaling**: optimizer = tf.keras.optimizers.Adam(); optimizer = tf.keras.mixed_precision.LossScaleOptimizer(optimizer); wraps optimizer with automatic loss scaling - **Custom Training Loop**: with tf.GradientTape() as tape: predictions = model(inputs, training=True); loss = loss_fn(labels, predictions); scaled_loss = optimizer.get_scaled_loss(loss); scaled_gradients = tape.gradient(scaled_loss, model.trainable_variables); gradients = optimizer.get_unscaled_gradients(scaled_gradients); optimizer.apply_gradients(zip(gradients, model.trainable_variables)) - **Keras Integration**: model.compile(optimizer=optimizer, loss=loss, metrics=metrics); model.fit(dataset); — AMP automatic with LossScaleOptimizer; no changes to training loop **Dynamic Loss Scaling:** - **Initial Scale**: starts at 2¹⁶ = 65536 (PyTorch) or 32768 (TensorFlow); high enough to prevent most underflow; low enough to avoid immediate overflow - **Growth**: if no overflow for growth_interval steps (default 2000), scale *= growth_factor (default 2); gradually increases scale to maximize gradient precision - **Backoff**: if overflow detected (gradient contains Inf/NaN), scale /= backoff_factor (default 2); skip optimizer step; prevents NaN propagation; retries next iteration with lower scale - **Convergence**: scale converges to optimal value (typically 1024-8192); balances underflow prevention with overflow avoidance; adapts to model and training stage **Precision Selection Logic:** - **Compute-Intensive Ops**: operations with O(n³) or O(n²) complexity use FP16/BF16; matrix multiply, convolution, attention; maximize Tensor Core utilization - **Memory-Intensive Ops**: element-wise operations (O(n)) use input precision; add, multiply, ReLU; precision determined by inputs; minimal compute, precision less critical - **Numerically Sensitive Ops**: operations with exponentials, logarithms, divisions use FP32; softmax, layer_norm, loss functions; prevent overflow/underflow and maintain accuracy - **Custom Precision**: @torch.cuda.amp.custom_fwd and @torch.cuda.amp.custom_bwd decorators override default precision; enables fine-grained control for custom operations **Performance Optimization:** - **Tensor Core Utilization**: ensure matrix dimensions are multiples of 8 (FP16) or 16 (INT8); non-aligned dimensions reduce Tensor Core efficiency; pad if necessary - **Batch Size**: larger batches improve Tensor Core utilization; AMP memory savings enable 1.5-2× larger batches; larger batches → better GPU utilization → higher speedup - **Model Size**: AMP speedup increases with model size; small models (<10M parameters): 1.2-1.5× speedup; large models (>1B parameters): 2-4× speedup; overhead amortized over more compute - **Operation Fusion**: fused operations (fused_adam, fused_layer_norm) maintain FP16/BF16 throughout; avoid FP16→FP32→FP16 conversions; 10-20% additional speedup **BF16 vs FP16 in AMP:** - **BF16 Advantages**: no loss scaling needed; simpler code (no GradScaler); fewer failure modes; same performance as FP16 on Ampere+ - **BF16 Usage**: with torch.cuda.amp.autocast(dtype=torch.bfloat16): — uses BF16 instead of FP16; no other changes; recommended for Ampere/Hopper GPUs - **FP16 Usage**: default on Volta/Turing; requires GradScaler; more complex but necessary on older hardware - **Mixed BF16/FP16**: some operations use BF16, others FP16; framework selects based on hardware support; transparent to user **Debugging AMP Issues:** - **Overflow Detection**: scaler.get_scale() returns current scale; if scale decreases to <100, frequent overflow; reduce learning rate or use BF16 - **Underflow Detection**: if loss stops decreasing but gradients are non-zero, possible underflow; increase loss scale manually or use BF16 - **Accuracy Regression**: compare AMP vs FP32 accuracy; if AMP 80% for compute-bound kernels - **Memory Bandwidth**: AMP reduces memory traffic by 50%; measure achieved bandwidth; should be 1.5-2× higher than FP32 - **Speedup Measurement**: compare wall-clock time per epoch; AMP vs FP32; typical speedup 1.5-3× for large models; <1.5× indicates insufficient Tensor Core usage - **Memory Usage**: nvidia-smi shows memory consumption; AMP should reduce by 30-50%; enables larger batch sizes or models **Best Practices:** - **Always Use AMP**: on Volta+ GPUs, AMP provides free speedup; no accuracy loss for most models; 3-5 lines of code; no reason not to use - **Prefer BF16 on Ampere+**: simpler, more stable, same performance; FP16 only for Volta/Turing - **Combine with Other Optimizations**: AMP + gradient accumulation + checkpointing + FSDP enables training 100B+ models on 8×40GB GPUs - **Monitor Scale**: if scale <1000 or >100000, investigate; optimal scale typically 1024-8192; extreme values indicate numerical issues Automatic Mixed Precision is **the productivity breakthrough that makes mixed precision training accessible to all developers — by automating precision selection, loss scaling, and gradient management, AMP delivers 2-4× training speedup and 50% memory reduction with minimal code changes, making it the default training mode for modern deep learning and the foundation for training large-scale models efficiently**.

Go deeper with CFSGPT

Get AI-powered deep-dives, save terms, and run advanced simulations — free account.

Create Free Account