TRL documentation

Training on AWS Trainium

You are viewing main version, which requires installation from source. If you'd like regular pip install, checkout the latest stable version (v1.16.0).
Hugging Face's logo
Join the Hugging Face community

and get access to the augmented documentation experience

to get started

Training on AWS Trainium

AWS Trainium runs PyTorch natively through the torch-neuronx package, which registers the neuron device. TRL trainers run on it without code changes. Neuron compiles a graph for each input shape it sees, and each compilation takes about a minute, so most of this page is about keeping shapes static. For installation and the Transformers side, see the Transformers AWS Trainium guide.

Installation

Install torch-neuronx by following the AWS Neuron setup guide, then install TRL in the same environment.

pip install trl

Supervised fine-tuning

The SFTTrainer quick start runs as is:

from datasets import load_dataset
from trl import SFTTrainer

trainer = SFTTrainer(
    model="Qwen/Qwen3-0.6B",
    train_dataset=load_dataset("trl-lib/Capybara", split="train"),
)
trainer.train()

On Neuron, pad_to_multiple_of defaults to 128 (its "auto" value), so the sequences are padded to a multiple of 128. This bounds the number of shapes, and so of compilations, to max_length / 128. Without it, every new sequence length triggers a compilation. On one NeuronCore, with per_device_train_batch_size=4, 20 steps of the example above take 130 s with the default and 260 s with pad_to_multiple_of=None.

The same applies to every trainer that has a pad_to_multiple_of option: DPO, KTO, Reward, GRPO, RLOO and Distillation.

Compiling the model

Set torch_compile=True to compile the model with the neuron backend. Dynamo’s automatic dynamic shapes produce graphs the Neuron backend can’t compile yet (#7660), so turn them off:

import torch
from datasets import load_dataset
from trl import SFTConfig, SFTTrainer

torch._dynamo.config.automatic_dynamic_shapes = False

trainer = SFTTrainer(
    model="Qwen/Qwen3-0.6B",
    args=SFTConfig(torch_compile=True),
    train_dataset=load_dataset("trl-lib/Capybara", split="train"),
)
trainer.train()

The first step compiles for about 2 minutes. After that, with per_device_train_batch_size=4, Qwen3-0.6B trains at 1.15 s/step on one NeuronCore, against 1.71 s/step without compilation.

Online methods

vLLM doesn’t run on Neuron, so GRPO and RLOO generate with Transformers. With the default dynamic cache, every generated token has a new shape, and a step takes several minutes. Use the static cache, which keeps the decoding shapes fixed:

from datasets import load_dataset
from trl import GRPOConfig, GRPOTrainer


# Reward completions close to 200 characters
def reward_len(completions, **kwargs):
    return [-abs(200 - len(completion)) / 100 for completion in completions]


trainer = GRPOTrainer(
    model="Qwen/Qwen3-0.6B",
    reward_funcs=reward_len,
    args=GRPOConfig(
        per_device_train_batch_size=4,
        num_generations=4,
        max_completion_length=128,
        cache_implementation="static",
        model_init_kwargs={"dtype": "bfloat16"},
    ),
    train_dataset=load_dataset("trl-lib/tldr", split="train"),
)
trainer.train()

The prompts are padded to pad_to_multiple_of before generation too, so the static cache only takes a few sizes. Each new size still compiles for about 12 minutes on one NeuronCore; once a size is compiled, a step of this example takes about 25 s.

The static cache needs a bf16 model for now: with the default fp32 model, the keys and values end up in different dtypes (#7664).

Data parallelism

On a trn2.3xlarge instance, which contains one Trainium2 chip, the default Logical NeuronCore configuration (LNC=2) pairs the chip’s 8 physical NeuronCores into 4 logical NeuronCores.

To train on all four, use Accelerate:

accelerate launch --num_processes 4 train.py

In this setup, SFT runs 3.6x faster on 4 NeuronCores than on 1.

To restrict a run to a subset of NeuronCores, set NEURON_RT_VISIBLE_CORES to 0,1, 2,3, or 0-3. Other combinations such as 1,2 are not supported: the Neuron runtime fails to set up collectives across them.

Update on GitHub