ATTUNE: Agentic Throughput Tuning for LLM Training
Organizations: Amazon
Abstract
The throughput of an LLM training job depends on its recipe: how the model is split across GPUs, how memory is traded for compute, and which kernels and communication overlaps it uses. The best recipe changes with every model, accelerator and framework version. Automated tuners search a fixed space of knobs and check only that a job runs, so they miss levers outside that space and can ship a configuration that silently changes training. ATTUNE is a coding agent that tunes any working recipe unattended within a GPU-hour budget. Guided by a skill of search rules, scripts and lessons from past tuning campaigns, it diagnoses each run and changes one lever at a time. A correctness gate outside the agent refuses any argument known to change the training objective. ATTUNE tunes Amazon's production post-training recipes on H100, H200 and B200 clusters, raising throughput by 1.7x on average. It beats the published throughput of four of NVIDIA's own benchmark recipes on NVIDIA's AutoModel framework by 6-17%. On models held out from its development, it improves the strongest public recipes most where they were written for another setting, by up to 2.6x on MiniMax-M2, and least where the vendor tuned them for the same hardware. Given the same GPU-hour budget, it outperforms existing automated tuners, including Bayesian optimization, random search and OptiCo, a recent LLM-agent tuner. Its gain on GLM-4.5 is more than four times the best alternative's. The same coding agent without ATTUNE's skill gains less and fails half its launches. We release ATTUNE at https://github.com/amazon-science/attune and OpenRecipes, a leaderboard of tuned and verified training recipes, at https://openrecipes.ai.
Figures & tables
| Throughput (tok/s/GPU) | Gain over | ||||||
|---|---|---|---|---|---|---|---|
| Model | GPUs | Baseline | ATTUNE | Baseline | Published | MFU (%) | GPU-h (budget) |
| Reproduced on NeMo AutoModel | |||||||
| Qwen3-30B-A3B | 8 H100 | 11,963.1 | 13,151.1 | +9.9% | +9.2% | 27.9 30.7 | 37.2 (70) |
| GPT-OSS-20B | 8 H100 | 12,970.3 | 15,222.5 | +17.4% | +16.6% | 30.1 35.3 | 18.1 (65) |
| Nemotron-3-Nano | 8 H100 | 16,538.1 | 17,726.7 | +7.2% | +5.6% | 33.4 35.8 | 23.5 (65) |
| Llama-3.1-70B | 64 H100 | 801.2 | 1,012.5 | +26.4% | +16.8% | 36.4 46.0 | 133.4 (500) |
| Model | Tuner | Gain | GPU-h used | Launches | Failed launches (GPU-h) | Wall-clock |
|---|---|---|---|---|---|---|
| GLM-4.5 | ATTUNE | +33.9% | 669 | 8.3 | 24% (60) | 6.4 h |
| OptiCo | 0.0% | 1,407 | 22.7 | 19% (78) | 15.7 h | |
| BO (TPE) | +1.8% | 1,675 | 19.7 | 39% (186) | 9.6 h | |
| BO + pre-filter | +3.9% | 1,695 | 13.7 | 5% (58) | 9.5 h | |
| Random search | +7.8% | 1,688 | 22.7 | 51% (278) | 10.2 h | |
| MiniMax-M2 | ATTUNE | +164.2% | 203 | 13.3 | 23% (25) | 3.1 h |
| Arm | GLM-4.7-Flash gain, % | p | Failed | GPU-h to +20% | Nemotron-3-Nano gain, % | p | Failed | GPU-h to +20% |
|---|---|---|---|---|---|---|---|---|
| Full ATTUNE | +88.0 (81.7–96.6) | – | 17% | 3.9 (5/5) | +49.4 (47.1–51.4) | – | 32% | 5.2 (5/5) |
| Bare agent | +66.9 (54.7–94.5) | 0.016 | 50% | 9.0 (5/5) | +42.9 (35.9–48.8) | 0.008 | 50% | 7.2 (5/5) |
| Fixed knobs | +18.1 (15.6–21.4) | 0.004 | 13% | 19.8 (2/5) | +48.6 (41.3–51.3) | 0.42 | 33% | 3.1 (5/5) |
| No diagnosis | +73.4 (21.3–96.5) | 0.24 | 19% | 4.9 (5/5) | +47.5 (41.9–50.2) | 0.14 | 41% | 3.1 (5/5) |
| Runs with a known answer | Gate passes | Gate rejects |
|---|---|---|
| Legitimate: 132 runs on six models | 132 | 0 |
| Legitimate: 328 ablation runs on two models (Section 3.4) | 328 | 0 |
| Faulty: 24 runs of 14 faults | 9 runs of four faults that move the first step’s loss by 2% or less: one gradient bucket’s reduction skipped (five models), load-balancing loss zeroed, loss mask shifted by one token, QK-norm gradients summed over tensor-parallel ranks | 15 : 6 objective-changing arguments and 4 configuration defects, refused before launch; 5 code faults that change the forward pass (labels offset by one token, attention sinks ignored), caught at step 0 |
| Faulty: 19 ablation runs with an uneven pipeline split on Nemotron-3-Nano-30B-A3B | 0 | 19 , refused as a known stack defect; step-0 loss 215–768% above the baseline’s |
| Model | H100 | H200 | B200 |
|---|---|---|---|
| Qwen3.5-122B | 2.49 | 1.32 | 1.26 |
| Qwen3.5-397B | 1.25 | 1.06 | 3.91 |
| GLM-5.2 | 1.07 | 2.54 | 2.21 |
Appendix figures & tables14 assets
Supplementary material from the paper’s appendix.
Appendix
| Model | Source | Rows tokens |
|---|---|---|
| Llama-3.1-405B | Project Gutenberg, PG-19 book list (mirror texts); Llama-3.1 tokenizer | 6,400 8,192 |
| Mixtral-8x22B | Project Gutenberg, PG-19 book list (mirror texts); Mixtral tokenizer | 64,000 4,096 |
| GLM-4.5 | HuggingFaceFW/fineweb-edu , sample/10BT shards 000–002; GLM-4.5 tokenizer | 225,280 4,096 |
| MiniMax-M2 | HuggingFaceFW/fineweb-edu , sample/10BT shards 000–002; MiniMax-M2 tokenizer | 28,160 8,192 |
| Model | Changes from the public recipe |
|---|---|
| Llama-3.1-405B, 128 B200 | Per-token loss; vocabulary unpadded to match the converted checkpoint; data-parallel and tensor-parallel communication overlap kept on as published, through stack fixes and a gloo bootstrap; learning rate scaled by 1/30 for the released weights |
| Mixtral-8x22B, 128 H100 | RoPE base 10 6 as in the released model, which the recipe omits; selective recomputation of the expert activation to fit in memory (the recipe recomputes nothing); userbuffers bootstrap over gloo |
| GLM-4.5, 128 B200 | Multi-token-prediction layer removed; B200 instead of the recipe’s H100, with the published layout unchanged; data-parallel overlap kept on as published, through a stack fix |
| MiniMax-M2, 64 B200 | Supervised training on fixed 8,192-token rows of FineWeb-Edu instead of the recipe’s reinforcement-learning loop; 64 GPUs instead of 128, with tensor, pipeline, expert-tensor and context parallelism kept; released FP8 weights dequantized to BF16; expert parallelism 4 8 to fit in memory; QK-norm weight gradients averaged rather than summed over tensor-parallel ranks |
| Model | Type | GPUs | Public recipe and workload | Published | Our stack |
|---|---|---|---|---|---|
| Reproduced on NeMo AutoModel | |||||
| Qwen3-30B-A3B | MoE (30B, 3B active) | 8 H100 | AutoModel benchmark; mock tokens, balanced routing, random init; seq 4K, GBS 512, BF16 | 12,040 (MFU 28%) | 11,963.1 |
| GPT-OSS-20B | MoE (21B, 3.6B active) | 8 H100 | AutoModel benchmark; mock tokens, balanced routing, random init; seq 4K, GBS 256, BF16 | 13,058 (MFU 30%) | 12,970.3 |
| Nemotron-3-Nano-30B-A3B | hybrid Mamba MoE (30B, 3.5B active) | 8 H100 | AutoModel benchmark; mock tokens, balanced routing, random init; seq 4K, GBS 512, BF16 | 16,789 (MFU 34%) | 16,538.1 |
| Llama-3.1-70B | dense (70B) | 64 H100 | AutoModel pretrain benchmark; mock tokens, released weights; seq 8K, GBS 128, BF16 | 866.8 (MFU 39%) | 801.2 |
| Ported to slime and Megatron-LM | |||||
| Known stack defect | How it shows | Refused on |
|---|---|---|
| Fused routing (a same-math swap) | breaks exact BF16 ties differently and routes some tokens to other experts; fails its component test | Mixtral-8x22B, GLM-4.5, MiniMax-M2, GLM-4.7-Flash |
| Gradient-accumulation fusion off (a same-math swap) | adds a BF16 rounding where main gradients are FP32; fails its component test | Mixtral-8x22B, GLM-4.5, MiniMax-M2 |
| Expert parallelism 1 with expert-tensor parallelism of 4 or more | silently changes training: step 0 matches the baseline, and the loss departs from it after the first update | Mixtral-8x22B, GLM-4.5, MiniMax-M2 |
| Context parallelism 8 with virtual stages | hangs at step 0 | Mixtral-8x22B |
| Context parallelism above 4 | a step takes about 1,800 s | GLM-4.5 |
| Tensor parallelism 16 | cannot run | MiniMax-M2 |
| Run | Models | Configuration check | Step-0 loss shift | Gate |
|---|---|---|---|---|
| Fault-free: replicates, single placement or packing changes, runs of the public recipe and legitimate recipes whose step-0 numerics differ from the baseline | GLM-4.5 (27), MiniMax-M2 (31), Mixtral-8x22B (28), Llama-3.1-405B (4); development: GPT-OSS-20B (32), GPT-OSS-120B (10) | admitted | at most 1.98% | 132 of 132 pass |
| EP 1 with ETP of 4 or more (a real stack defect that silently changes training) | GLM-4.5, Mixtral-8x22B, MiniMax-M2 | refused | at most 0.02% | rejected |
| PP 32, which halves the load-balancing loss while the language-model loss stays identical (a real stack defect) | GLM-4.5 | refused | 0.00% | rejected |
| Argument faults: capacity factor 1, learning rate 10, global batch changed | development: Qwen3.5-122B-A10B | refused | +7.6%, 0.02%, +0.2% | rejected |
| Argument faults: BF16 gradient reduction, per-token loss off, auxiliary-loss coefficient changed | development: Qwen3.5-122B-A10B | refused | 0.04%, +0.5%, 0.01% | rejected |
| Labels offset by one token | GLM-4.5, MiniMax-M2, Llama-3.1-405B; development: GPT-OSS-120B | passes | +190% to +872% | rejected |
| Component | Version |
|---|---|
| OS | Ubuntu 24.04 |
| Python | 3.12.3 (training image) |
| PyTorch | 2.11.0 (CUDA 12.9 build) |
| CUDA | 12.9 |
| NCCL / libfabric NCCL plugin | 2.28.9 / 1.20.0 |
| Megatron-LM | commit 1dcf0da |
| Model | Calibration mean (tokens/s/GPU) | Band | Unprofiled launch (GPU-h) | Budget per campaign (GPU-h) | |
|---|---|---|---|---|---|
| Llama-3.1-405B / 128 B200 | 399.36 | 1.29% | 3.88% | 61.38 | 1,850 |
| Mixtral-8x22B / 128 H100 | 1,091.69 | 0.95% | 3.00% | 24.57 | 740 |
| GLM-4.5 / 128 B200 | 728.19 | 0.49% | 3.00% | 62.58 | 1,880 |
| MiniMax-M2 / 64 B200 | 893.18 | 0.95% | 3.00% | 17.58 | 530 |
| Arm | # | Shipped | Gain | GPU-h used | Stop | Shipped changes |
|---|---|---|---|---|---|---|
| ATTUNE | 1 | 885.7 | +22.4% | 753.6 | agent | PP 8 16; EP 16 8; first/last-stage layers 10/10 4/4; DeepEP dispatcher; shared-expert overlap off |
| ATTUNE | 2 | 1,119.3 | +54.7% | 626.3 | agent | TP 2 1; PP 8 16; EP 16 8; VP off 2; first/last-stage layers 10/10 4/4; full recompute |
| ATTUNE | 3 | 902.1 | +24.7% | 627.3 | agent | EP 16 8; DeepEP dispatcher; shared-expert overlap off; data-parallel overlaps off |
| OptiCo | 1 | 723.6 | 0.0% | 1,274.4 | no launch | none (public recipe) |
| OptiCo | 2 | 723.6 | 0.0% | 1,543.8 | budget | none (public recipe) |
| OptiCo | 3 | 723.6 | 0.0% | 1,402.2 | no launch | none (public recipe) |
| Arm | # | Shipped | Gain | GPU-h used | Stop | Shipped changes |
| MiniMax-M2 / 64 B200 | ||||||
| ATTUNE | 1 | 2,423.1 | +170.7% | 200.2 | agent | TP 2 1; PP 2 4; first/last-stage layers even 15/15; 2 rows per microbatch; data-parallel overlaps on; optimizer offload off |
| ATTUNE | 2 | 2,235.8 | +149.8% | 197.3 | agent | PP 2 8; first/last-stage layers even 7/7; 4 rows per microbatch; optimizer offload off |
| ATTUNE | 3 | 2,436.3 | +172.2% | 213.0 | agent | TP 2 1; PP 2 8; VP off 2; first/last-stage layers even 8/6; recompute uniform block, 2 layers; optimizer offload off |
| OptiCo | 1 | 1,101.3 | +23.0% | 301.4 | no launch | TP 2 1; data-parallel overlaps on; cross-entropy fusion on |
| OptiCo | 2 | 1,109.9 | +24.0% | 384.5 | no launch | TP 2 1; data-parallel overlaps on; cross-entropy fusion on |
| Arm | Gain | GPU-h used | Launches | Failed launches (GPU-h) | Wall-clock |
|---|---|---|---|---|---|
| Full ATTUNE | +33.9% (+22.4, +54.7, +24.7%) | 669 | 8.3 | 24% (60) | 6.4 h |
| Multi-agent committee | +28.3% (+5.5, +55.7, +23.8%) | 604 | 6.0 | 17% ( 30 ) | 5.1 h |
| Public-guide catalog | +29.1% (+28.7, +29.6, +29.0%) | 870 | 9.3 | 11% (54) | 7.0 h |
| Minimal skill (no lever catalog) | +30.3% (+32.5, +29.6, +28.7%) | 773 | 10.0 | 13% (41) | 6.2 h |
| Recipe | Replaced recipe | Gain | $ per 1M tokens |
|---|---|---|---|
| Qwen3.5-122B, 48 H100 | Megatron-Bridge | 2.49 | 4.86 1.95 |
| Qwen3.5-122B, 32 H200 | in-house | 1.32 | 1.24 0.94 |
| Qwen3.5-122B, 16 B200 | in-house | 1.26 | 1.94 1.54 |
| Qwen3.5-397B, 128 H100 | verl | 1.25 | 7.80 6.23 |
| Qwen3.5-397B, 48 H200 | verl † | 1.06 | 7.68 7.22 |
| Qwen3.5-397B, 64 B200 | verl ‡ | 3.91 | 12.00 3.07 |
| Knob | GLM-4.5 (128 GPUs) | MiniMax-M2 (64 GPUs) |
|---|---|---|
| Tensor parallelism | 1, 2, 4, 8 | 1, 2, 4, 8 |
| Pipeline parallelism | 1, 2, 4, 8, 16 | 1, 2, 4, 8, 16 |
| Expert parallelism | 1, 2, 4, 8, 16, 32 (1 only with expert-tensor parallelism 2) | 1, 2, 4, 8, 16, 32, 64 (1 only with expert-tensor parallelism 2) |
| Expert-tensor parallelism | 1, 2, 4, 8 | 1, 2, 4, 8 |
| Virtual stages per rank | off, 2, 4, 23 | off, 2, 31 |
| Pipeline split | balanced, light first, light last, light both | balanced, light first, light last, light both |
| Run | Change result (tokens/s/GPU) | The agent’s reasoning, quoted |
|---|---|---|
| pp16ep8 | PP 8 16, EP 16 8, first/last-stage layers 10/10 4/4, expert all-to-all inside a node 707.6, tie | “clearly comm/overhead-bound”; “EP placement is throughput-neutral here” |
| tp1pp8 | TP 2 1 out of memory | “TP1 (no SP, unsharded activations) doesn’t fit at PP8; it needs more PP.” |
| tp1pp16 | TP 2 1 at PP 16, EP 8 out of memory | “memory-infeasible at both PP8 and PP16 with selective recompute” |
| tp1pp16fr | + full recomputation 1,072.7, win (+47.3%) | “our step has many tiny 1-row microbatches lots of launch idle … full recompute may be ~free here AND it enables the TP1 fit” |
| tp1pp8fr | back to PP 8, EP 16 stopped early, 668 | “the cross-node EP a2a (and DP16 comm) is now exposed” |
| tp1pp16s53 | first/last-stage layers 4/4 5/3 stopped early, 1,083 | “the pipeline is not stage-imbalance-bound; it’s uniformly comm/launch-bound” |
| Check | Covers | Result |
|---|---|---|
| Lessons checked against the campaigns’ own records | 155 lessons of the catalog distilled from development campaigns | 71 correct and general; 34 rewritten to their general form; 31 wrong; 11 unsupported; 8 resting on one model or campaign |
| Current model asked, without the skill, about each entry (Claude Opus 5.5, three answers per question) | 106 entries of the curated catalog | 19 answered fully; 59 partly; 27 contradicted; 1 not known |
Efficient Language Model Training
Efficient language model training studies how to reduce the data, compute, memory, time, energy, and cost needed to build capable language models.
See all 159 papers