Low-Precision Training Guide#
This guide explains how to train with sub-BF16 precisions (FP8 and FP4) in Megatron Core, summarizes the trade-offs between the available recipes, and provides ready-to-use configurations for the most common scenarios.
Low-precision support in Megatron Core is built on
Transformer Engine (TE). Megatron
exposes TE recipes through TransformerConfig fields (and matching CLI flags)
so you can switch recipes without touching model code.
When to Use Low Precision#
Compared to a BF16 baseline, low precision delivers:
Higher training throughput — TE FP8/FP4 GEMMs on Hopper, Ada, and Blackwell hit substantially higher TFLOPS than BF16.
Lower activation and parameter memory — Activations and (optionally) parameters are stored in 8 or 4 bits.
Less DP communication bandwidth — With
--fp8-param-gather/--fp4-param-gather, the parameter all-gather is performed in the quantized dtype.
The trade-off is numerics: not every model converges identically to BF16 under every recipe. The recipe and configuration choices below let you balance throughput, memory, and stability.
Hardware and Recipe Compatibility#
Recipe ( |
Format flag |
Required architecture |
Transformer Engine |
Typical use |
|---|---|---|---|---|
|
|
Hopper, Ada, Blackwell |
Broadly available; see TE release notes |
Stable baseline FP8, supports CPU offload |
|
|
Hopper, Ada, Blackwell |
See TE release notes |
Current-scaling FP8, no amax history |
|
|
Blackwell |
See TE release notes |
Block-scaled E4M3, optimized for B200/GB200 |
|
|
Hopper, Blackwell |
See TE release notes |
1×128 / 128×128 block scaling (DeepSeek-style) |
|
|
Blackwell |
≥ |
NVFP4 block-scaling for additional memory / bandwidth savings |
|
|
depends on quantizer |
depends on quantizer |
User-supplied quantizer via |
Only the NVFP4 minimum (Transformer Engine >= 2.7.0.dev0) is enforced by
Megatron at startup (see arguments.py).
For the other recipes, refer to the
Transformer Engine release notes
for the exact version that introduced each recipe on your target hardware.
--fp8-format and --fp4-format are mutually exclusive; you can only enable
one of FP8 or FP4 per run.
Recipe Reference#
Each recipe is selected by passing both the format flag (which turns the recipe on) and the recipe name (which picks the scaling strategy).
delayed — Delayed scaling FP8#
The historical default. The scaling factor is computed from a rolling amax history.
Minimum config:
--fp8-format hybrid \
--fp8-recipe delayed \
--fp8-amax-history-len 1024 \
--fp8-amax-compute-algo max
Optional knobs: --fp8-margin (default 0), --fp8-param-gather,
--fp8-wgrad (set to False to keep wgrad in higher precision).
When to use:
You need the broadest hardware support (Hopper and newer).
You require FP8 + optimizer CPU offload (see optimizer_cpu_offload.md) — only
delayedis supported in that mode.You want the most validated recipe across community-trained models.
tensorwise — Per-tensor current scaling FP8#
Computes the scale from the current tensor, removing the amax history buffer
and the warmup-window dependency of delayed.
Minimum config:
--fp8-format hybrid \
--fp8-recipe tensorwise \
--fp8-param-gather
When to use:
You want a simpler, history-free FP8 recipe on Hopper/Ada/Blackwell.
You see instability during the first hundred steps with
delayed(typical amax-warmup behavior).Production RL / SFT workloads. See examples/rl/model_configs/nemotron5_56b.sh for a complete recipe.
mxfp8 — Block-scaled E4M3 (Blackwell)#
Microscaled FP8: a power-of-two scale per 1×32 block. Native to Blackwell Tensor Cores.
Minimum config:
--fp8-format e4m3 \
--fp8-recipe mxfp8 \
--fp8-param-gather \
--reuse-grad-buf-for-mxfp8-param-ag
--reuse-grad-buf-for-mxfp8-param-ag reuses the gradient buffer for the
parameter all-gather and is strongly recommended whenever you combine mxfp8
with --fp8-param-gather — Megatron will warn otherwise (see
OptimizerConfig).
Optional: --keep-fp8-transpose-cache keeps the row-wise / column-wise FP8
data on the device to avoid recomputation under fine-grained activation
offloading.
When to use:
Blackwell hardware (B200, GB200).
You want strong throughput on Blackwell for both dense and MoE models.
See examples/gptoss/02_train.sh for a worked end-to-end example.
blockwise — DeepSeek-style block scaling#
1×128 activation blocks paired with 128×128 weight blocks. Originally popularized by the DeepSeek-V3 recipe.
Minimum config:
--fp8-format e4m3 \
--fp8-recipe blockwise \
--fp8-param-gather
When to use:
You are reproducing or fine-tuning a model trained with the DeepSeek FP8 recipe.
You need better numerical headroom for outlier channels than
tensorwise/mxfp8while staying in FP8.
nvfp4 — NVFP4 block scaling (Blackwell)#
FP4 with NVFP4 block scaling. Provides additional memory and bandwidth savings on top of FP8.
Minimum config:
--fp4-format e2m1 \
--fp4-param-gather
Requires Transformer Engine ≥ 2.7.0.dev0.
When to use:
Blackwell hardware where FP4 GEMM kernels are available.
You have validated your model under FP4 QAT or are willing to apply
--first-last-layers-bf16and additional stability mitigations (see below).
NVFP4 is an actively evolving recipe in Megatron Core. Track the 2026 Q2 roadmap for the latest fixes (e.g. NVFP4 param gather, MXFP8 / NVFP4 mixed-precision work).
custom — User-supplied quantizer#
Set --fp8-recipe custom (or --fp4-recipe custom) and provide a Python
import path to a quantizer factory via --fp8-quantizer-factory or
--fp4-quantizer-factory. Use this when you need per-module overrides — also
see --te-precision-config-file for declarative per-module precision control.
Numerical Stability Knobs#
Beyond picking a recipe, the following options are the main levers when a run diverges or shows higher loss than the BF16 baseline.
Flag |
Effect |
When to enable |
|---|---|---|
|
Keep the first / last |
First defense against early-training instability under any FP8/FP4 recipe. |
|
Controls how many layers |
Increase to 2–4 for FP4 or very deep models. |
|
Adds |
Loss spikes despite recipe / first-last mitigation. |
|
Controls |
Tune when |
|
Keeps |
Final fallback when MoE / long-context runs show gradient noise. |
|
Restricts amax all-reduce to the TP/CP domain. |
Large DP scales where global amax reduction is expensive. |
Memory Knobs#
Once a recipe is stable, the following options reduce memory further:
--fp8-param-gather/--fp4-param-gather— Keep parameters quantized and all-gather them in the quantized dtype. Requires the distributed optimizer, Torch FSDP2, Megatron-FSDP, or inference mode.--reuse-grad-buf-for-mxfp8-param-ag— Required companion formxfp8 + --fp8-param-gather(see above).--keep-fp8-transpose-cache— Trades memory for compute by avoiding recomputation of the FP8 transpose under fine-grained activation offloading. See fine_grained_activation_offloading.md.Precision-aware optimizer —
--use-precision-aware-optimizerenables the TEFusedAdampath and lets you store optimizer state in lower precision:--main-grads-dtype {fp32, bf16}--exp-avg-dtype {fp32, fp16, bf16, fp8}--exp-avg-sq-dtype {fp32, fp16, bf16, fp8}
Configuration Cookbook#
The following minimal recipes are starting points. All assume a BF16 model init plus the distributed optimizer.
Hopper / H100 — fastest stable FP8#
--bf16 \
--fp8-format hybrid \
--fp8-recipe tensorwise \
--fp8-param-gather \
--use-distributed-optimizer
Use delayed instead of tensorwise if you also need optimizer CPU offload.
Blackwell / B200 — fastest FP8#
--bf16 \
--fp8-format e4m3 \
--fp8-recipe mxfp8 \
--fp8-param-gather \
--reuse-grad-buf-for-mxfp8-param-ag \
--use-distributed-optimizer
Blackwell / B200 — maximum memory / bandwidth savings (FP4)#
--bf16 \
--fp4-format e2m1 \
--fp4-param-gather \
--first-last-layers-bf16 \
--num-layers-at-start-in-bf16 2 \
--num-layers-at-end-in-bf16 2 \
--use-distributed-optimizer
FP8 with optimizer CPU offload#
--bf16 \
--fp8-format hybrid \
--fp8-recipe delayed \
--fp8-param-gather \
--use-distributed-optimizer \
--optimizer-cpu-offload
Only delayed is supported with CPU offload — Megatron enforces this in
arguments.py.
FP8 with Megatron-FSDP#
Use the FP8 recipe of your choice and the FSDP precision policy described in
megatron_fsdp.md. The relevant FSDP-side
flags are --megatron-fsdp-main-params-dtype,
--megatron-fsdp-main-grads-dtype, and --megatron-fsdp-grad-comm-dtype.
See examples/megatron_fsdp/train_llama3_8b_fsdp_h100_fp8.sh.
Minimum-memory optimizer#
Layer on top of any recipe above:
--use-precision-aware-optimizer \
--main-grads-dtype bf16 \
--exp-avg-dtype fp8 \
--exp-avg-sq-dtype fp8
Feature Compatibility Matrix#
Recipe |
Distributed optimizer |
Megatron-FSDP |
Pipeline parallel |
CUDA Graph |
Optimizer CPU offload |
Inference |
|---|---|---|---|---|---|---|
|
✓ |
✓ |
✓ |
✓ |
✓ (required) |
✓ |
|
✓ |
✓ |
✓ |
✓ |
✗ |
✓ |
|
✓ (recommended) |
✓ |
✓ |
✓ ( |
✗ |
✓ |
|
✓ |
✓ |
✓ |
✓ |
✗ |
✓ |
|
✓ |
✓ |
✓ |
partial — see roadmap |
✗ |
partial |
--fp8-param-gather / --fp4-param-gather additionally require the
distributed optimizer, Torch FSDP2, Megatron-FSDP, or inference mode.
End-to-End Examples#
Example |
Recipe |
Notes |
|---|---|---|
|
Reference H100 single-node FP8 run. |
|
|
FP8 + Megatron-FSDP. |
|
hybrid + |
GPT-OSS Megatron Bridge example. |
|
|
RL workload, large MoE. |
|
|
DeepSeek-style blockwise FP8. |
Troubleshooting#
Loss spikes early in training — Enable
--first-last-layers-bf16, bump--num-layers-at-{start,end}-in-bf16, and/or raise--fp8-margin. Switching fromtensorwise/mxfp8todelayedprovides a more conservative baseline.Slow convergence vs. BF16 — Verify your recipe matches the hardware table above; mismatched recipes silently fall back to slower paths.
OOM at the optimizer step — Enable
--use-precision-aware-optimizerand lower--exp-avg-dtype/--exp-avg-sq-dtype. If still tight, enable optimizer CPU offload (requires--fp8-recipe delayed).--fp8-param-gatherrejected at startup — Add--use-distributed-optimizer(or run with Torch FSDP2 / Megatron-FSDP).MXFP8 + param-gather warning — Add
--reuse-grad-buf-for-mxfp8-param-ag; this is the supported MXFP8 param-gather path.--fp4-format requires Transformer Engine >= 2.7.0.dev0— Upgrade TE or fall back to an FP8 recipe.MXFP8 + inference CUDA Graph errors —
--inference-cuda-graph-scope=blockis only supported with--fp8-recipe mxfp8; for other recipes use a different graph scope.
See Also#
Megatron-FSDP — Mixed-precision policy, quantized parameter handling.
Distributed Optimizer — Required for
--fp8-param-gather/--fp4-param-gather.Optimizer CPU Offload — Constraints on FP8 recipe choice.
Fine-Grained Activation Offloading — Interaction with
--keep-fp8-transpose-cache.Transformer Engine documentation — Authoritative reference for the underlying recipes.