Nemotron
Training Nemotron-3-Nano-30B-A3B on H200
Ranked by tokens/s per GPU · 8,192-token SFT rows · global batch 128 · BF16
Notes for Nemotron-3-Nano-30B-A3B
- Weights: the BF16 checkpoint
nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-BF16(revision bf77c317), with no conversion: miles loads it through Megatron-Bridge (--megatron-to-hf-mode bridge), so--hf-checkpointand--ref-loadare both the checkpoint directory. MODEL_ARGScome from miles'scripts/models/nemotron-3-nano-30b-a3b.pyat commit 78527b91, printed bymiles/utils/external_utils/model_args_utils.py nemotron-3-nano-30b-a3b; run the command from a miles checkout at that commit.- It trains on its own rows, built with
--loss-mask-type qwen3_5(data/README.md).
The steps every recipe shares: Running a recipe.
Recipes
#1attune-tp1-pp2-ep47,814.0 tokens/s/GPUTP1 PP2 EP4 DP4max 8,192 tokens/GPU, no offload
- Starting point: miles' Nemotron-3-Nano launcher,
scripts/run_nemotron_3_nano.pyat miles 0.1.0 (model page https://miles.radixark.com/docs/models/nemotron/nemotron-3-nano-moe). miles publishes it as a GRPO smoke test with no tokens/s figure. Ported to this workload with its layout (TP 2 with sequence parallel, PP 2, EP 2, full recompute) and max 8,192 tokens/GPU on 8 H200, it measured 5,229.2 tokens/s/GPU; ATTUNE tuned it to 7,814.0 (+49%).
- Author
- ATTUNE (cite)
- GPUs
- 8 x H200 141 GB (AWS p5en.48xlarge, 8 per node)
- Layout
- TP 1, PP 2 (even split), CP 1, EP 4, ETP 1, DP 4; one 8,192-token row per microbatch (THD, max 8,192 tokens/GPU); full recompute (uniform, 1 layer); distributed optimizer; alltoall dispatcher; no offload
- Tokens/s per GPU
- 7,814.02
- $ / 1M tokens
- $0.28
- MFU
- 15.3% (N = 3,227,369,472 active parameters per token)
- Step-time CV
- 1.63%
- Convergence check
- correlation 0.9999997, final loss difference 4.3e-05, 0 pointwise failures over 20 steps
- Measured
- 2026-10-15
- GPU-hours
- 1.2
- Rows
nemotron3nano-tulu3-fixed8192-v1(rows_sha2568fc04d3ce32c2b2cf8b1255a84cd8627df647cb38b6cbbe69a8e6bbde0ce54c7)
Stack
- framework
- miles 0.1.0 (radixark/miles commit 78527b91, a slime fork), no local changes
- megatron lm
- radixark/Megatron-LM commit 37f91617 (megatron-core 0.16.0rc0), no local changes
- transformer engine
- 2.17.0
- pytorch
- 2.11.0 (CUDA 13.0 build)
- cuda
- 13.0
- nccl
- 2.28.9 (CUDA 13.0 build; printed by the measured run)
- deepep
- 1.2.1 (installed; the alltoall dispatcher does not use it)
- python
- 3.12.3
- network
- 8 GPUs per node, EFA (aws-ofi-nccl 1.20), 3.2 Tb/s RDMA per node
Environment
CUDA_DEVICE_MAX_CONNECTIONS=1PYTORCH_CUDA_ALLOC_CONF=expandable_segments:TrueTILELANG_CACHE_DIR=$KERNEL_CACHE/tilelangTRITON_CACHE_DIR=$KERNEL_CACHE/tritonTORCHINDUCTOR_CACHE_DIR=$KERNEL_CACHE/inductorFI_PROVIDER=efaFI_EFA_USE_DEVICE_RDMA=1
export CUDA_DEVICE_MAX_CONNECTIONS=1
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
export TILELANG_CACHE_DIR="$KERNEL_CACHE/tilelang"
export TRITON_CACHE_DIR="$KERNEL_CACHE/triton"
export TORCHINDUCTOR_CACHE_DIR="$KERNEL_CACHE/inductor"
export FI_PROVIDER=efa
export FI_EFA_USE_DEVICE_RDMA=1
MODEL_ARGS_LINE="$(python3 miles/utils/external_utils/model_args_utils.py nemotron-3-nano-30b-a3b)"
read -ra MODEL_ARGS <<< "$MODEL_ARGS_LINE"
python3 train.py \
--actor-num-nodes 1 \
--actor-num-gpus-per-node 8 \
--num-gpus-per-node 8 \
"${MODEL_ARGS[@]}" \
--hf-checkpoint "$HF_CKPT" \
--ref-load "$HF_CKPT" \
--megatron-to-hf-mode bridge \
--loss-type sft_loss \
--calculate-per-token-loss \
--disable-compute-advantages-and-returns \
--debug-train-only \
--rollout-function-path pretokenized_sft_rollout.generate_rollout \
--prompt-data "$SFT_DATA" \
--input-key messages \
--metadata-key metadata \
--num-rollout 20 \
--rollout-batch-size 128 \
--global-batch-size 128 \
--tensor-model-parallel-size 1 \
--pipeline-model-parallel-size 2 \
--context-parallel-size 1 \
--expert-model-parallel-size 4 \
--expert-tensor-parallel-size 1 \
--recompute-granularity full \
--recompute-method uniform \
--recompute-num-layers 1 \
--use-dynamic-batch-size \
--max-tokens-per-gpu 8192 \
--attention-backend auto \
--optimizer adam --lr 1e-5 --lr-decay-style cosine --min-lr 1e-6 \
--lr-warmup-fraction 0.1 --weight-decay 0.1 --adam-beta1 0.9 --adam-beta2 0.98 \
--attention-dropout 0.0 --hidden-dropout 0.0 \
--accumulate-allreduce-grads-in-fp32 --attention-softmax-in-fp32 \
--distributed-timeout-minutes 30
# recipes/nemotron-3-nano-30b-a3b/h200/attune-tp1-pp2-ep4.yaml
# An OpenRecipes recipe; the fields are documented in schema/recipe.schema.yaml.
schema_version: 1
model: Nemotron-3-Nano-30B-A3B
gpu:
type: H200
memory_gb: 141
count: 8
per_node: 8
instance: AWS p5en.48xlarge
author:
name: ATTUNE
url: https://arxiv.org/abs/2610.17528
status: verified
stack:
framework: miles 0.1.0 (radixark/miles commit 78527b91, a slime fork), no local changes
megatron_lm: radixark/Megatron-LM commit 37f91617 (megatron-core 0.16.0rc0), no local changes
transformer_engine: 2.17.0
pytorch: 2.11.0 (CUDA 13.0 build)
cuda: '13.0'
nccl: 2.28.9 (CUDA 13.0 build; printed by the measured run)
deepep: 1.2.1 (installed; the alltoall dispatcher does not use it)
python: 3.12.3
network: 8 GPUs per node, EFA (aws-ofi-nccl 1.20), 3.2 Tb/s RDMA per node
source: 'version dump of the measured run''s training image (same digest), 2026-10-13: installed TE, PyTorch, DeepEP,
megatron-core and miles, Megatron-LM and miles git commits (clean trees), Python; NCCL from the measured run''s log'
workload:
row_tokens: 8192
rows: SFT conversations
global_batch: 128
precision: bf16
dataset:
name: Tulu 3 SFT mixture
source: allenai/tulu-3-sft-mixture
revision: b14afda60f1bbebe55d5d2fa1e4df5042f97f8be
license: ODC-By 1.0
rows_sha256: 8fc04d3ce32c2b2cf8b1255a84cd8627df647cb38b6cbbe69a8e6bbde0ce54c7
build:
name: nemotron3nano-tulu3-fixed8192-v1
tokenizer: Nemotron-3-Nano-30B-A3B (revision bf77c3174f68ad409e1c2aa60daeb46e32d1c606; tokenizer.json sha256
c6021eb6847e682f89aa52d5eb6e8c7d902a23acfc8137e25211cf84828f1592; chat_template.jinja sha256
ab7813c3abdd9cb655905a410728b26c7884eca45ddfab8d9f931553485a7862)
loss_mask: qwen3_5
rows: 6400
row_tokens: 8192
padding_tokens: 0
seed: 42
packing: source conversations in a seeded global permutation, concatenated with an EOS token between them and cut
into consecutive 8,192-token rows; rows without supervised targets are skipped
supervised_token_ratio: 0.665
parquet_sha256: 7c0d4c1bd9f678b0815801a876cb8c460972424707d9f6d75883c336e1f70895
parquet_bytes: 85528499
builder: data/generate_fixed_sft.py with --loss-mask-type qwen3_5 (data/README.md)
layout:
label: TP1 PP2 EP4 DP4
summary: TP 1, PP 2 (even split), CP 1, EP 4, ETP 1, DP 4; one 8,192-token row per microbatch (THD, max 8,192
tokens/GPU); full recompute (uniform, 1 layer); distributed optimizer; alltoall dispatcher; no offload
highlights: max 8,192 tokens/GPU, no offload
tp: 1
pp: 2
vpp: 1
cp: 1
ep: 4
etp: 1
dp: 4
sequence_parallel: false
layer_split: null
max_tokens_per_gpu: 8192
rows_per_microbatch: 1
recompute:
granularity: full
method: uniform
num_layers: 1
offload: null
dispatcher: alltoall
result:
tokens_per_s_per_gpu: 7814.02
usd_per_million_tokens: 0.28
step_time_cv_percent: 1.63
mfu: 0.153
mfu_note: null
active_params:
count: 3227369472
source: https://huggingface.co/nvidia/NVIDIA-Nemotron-3-Nano-30B-A3B-BF16
revision: bf77c3174f68ad409e1c2aa60daeb46e32d1c606
measured: 2026-10-15
steps_per_run: 20
window:
- 5
- 19
window_tokens: 15728640
runs: 1
profiler: false
gpu_hours: 1.2
gpu_hours_note: GPUs x (scheduler admission to finish), including startup; the same run is the candidate arm of the
convergence check
correctness:
result: pass
summary: passed
reference: 'miles'' layout for Nemotron-3-Nano-30B-A3B (`scripts/run_nemotron_3_nano.py`): TP 2 with sequence parallel,
PP 2, EP 2, full recompute (uniform, 1 layer), Adam on the GPU, with max 8,192 tokens/GPU (one row) where the
launcher''s GRPO rollouts use 1,024. Model arguments, rows and schedule are the same in both recipes.'
configuration: pass
component_tests: []
convergence:
steps: 20
result: pass
correlation: 0.9999997
final_loss_difference: 4.3e-05
pointwise_failures: 0
note: 'candidate arm: the measured run; reference arm: a 20-step run of the reference recipe on the same image and
rows; the parity probe off in both'
rules: argument classes of ATTUNE's skill/scripts/correctness/rules/numerics_list.yaml (amazon-science/attune f2cb450);
20-step check by Megatron-Bridge validate_convergence with its pipeline thresholds
env:
CUDA_DEVICE_MAX_CONNECTIONS: '1'
PYTORCH_CUDA_ALLOC_CONF: expandable_segments:True
TILELANG_CACHE_DIR: $KERNEL_CACHE/tilelang
TRITON_CACHE_DIR: $KERNEL_CACHE/triton
TORCHINDUCTOR_CACHE_DIR: $KERNEL_CACHE/inductor
FI_PROVIDER: efa
FI_EFA_USE_DEVICE_RDMA: '1'
patches: []
run: |
export CUDA_DEVICE_MAX_CONNECTIONS=1
export PYTORCH_CUDA_ALLOC_CONF=expandable_segments:True
export TILELANG_CACHE_DIR="$KERNEL_CACHE/tilelang"
export TRITON_CACHE_DIR="$KERNEL_CACHE/triton"
export TORCHINDUCTOR_CACHE_DIR="$KERNEL_CACHE/inductor"
export FI_PROVIDER=efa
export FI_EFA_USE_DEVICE_RDMA=1
MODEL_ARGS_LINE="$(python3 miles/utils/external_utils/model_args_utils.py nemotron-3-nano-30b-a3b)"
read -ra MODEL_ARGS <<< "$MODEL_ARGS_LINE"
python3 train.py \
--actor-num-nodes 1 \
--actor-num-gpus-per-node 8 \
--num-gpus-per-node 8 \
"${MODEL_ARGS[@]}" \
--hf-checkpoint "$HF_CKPT" \
--ref-load "$HF_CKPT" \
--megatron-to-hf-mode bridge \
--loss-type sft_loss \
--calculate-per-token-loss \
--disable-compute-advantages-and-returns \
--debug-train-only \
--rollout-function-path pretokenized_sft_rollout.generate_rollout \
--prompt-data "$SFT_DATA" \
--input-key messages \
--metadata-key metadata \
--num-rollout 20 \
--rollout-batch-size 128 \
--global-batch-size 128 \
--tensor-model-parallel-size 1 \
--pipeline-model-parallel-size 2 \
--context-parallel-size 1 \
--expert-model-parallel-size 4 \
--expert-tensor-parallel-size 1 \
--recompute-granularity full \
--recompute-method uniform \
--recompute-num-layers 1 \
--use-dynamic-batch-size \
--max-tokens-per-gpu 8192 \
--attention-backend auto \
--optimizer adam --lr 1e-5 --lr-decay-style cosine --min-lr 1e-6 \
--lr-warmup-fraction 0.1 --weight-decay 0.1 --adam-beta1 0.9 --adam-beta2 0.98 \
--attention-dropout 0.0 --hidden-dropout 0.0 \
--accumulate-allreduce-grads-in-fp32 --attention-softmax-in-fp32 \
--distributed-timeout-minutes 30
notes: |
- Starting point: miles' Nemotron-3-Nano launcher, `scripts/run_nemotron_3_nano.py` at miles 0.1.0 (model page
https://miles.radixark.com/docs/models/nemotron/nemotron-3-nano-moe). miles publishes it as a GRPO smoke test with
no tokens/s figure. Ported to this workload with its layout (TP 2 with sequence parallel, PP 2, EP 2, full
recompute) and max 8,192 tokens/GPU on 8 H200, it measured 5,229.2 tokens/s/GPU; ATTUNE tuned it to 7,814.0 (+49%).
Citation
If you use a recipe by ATTUNE, please cite the paper.
@article{fan2026attune,
title = {{ATTUNE: Agentic Throughput Tuning for LLM Training}},
author = {Leo Fan and Hongyang Wang and Wenbo Chen and Jingguo Liu and Xian Li and Xuan Wang and
Ruochen Wen and Yiming Yan and Hao Wu and Zheshen Wang and Benoit Dumoulin},
journal = {arXiv preprint arXiv:2610.17528},
year = {2026},
url = {https://arxiv.org/abs/2610.17528}
}
Nemotron-3-Nano-30B-A3B on other GPUs
H100
–
No recipe yet
H200 · 8 GPUs · this page
7,814.0
tokens/s/GPU · $0.28 / 1M tokens
B200
–
No recipe yet