TorchNeuron为PyTorch在AWS Trainium上提供了新的原生后端。Transformers、Diffusers和Kernels原生支持它,使在Trainium上运行模型并在HF Hub上分享它们比以往任何时候都更容易。

TorchNeuron

TorchNeuron是一个PyTorch插件,为Trainium带来了新后端,支持eager模式、torch.compile以及FSDP和TP等原生分布式API。 阅读Pytorch博客以了解有关TorchNeuron的更多信息。

自2026年10月20日起,TorchNeuron将作为公开测试版提供。研究人员和开发者可通过pip install torch-neuronx进行安装。

新后端,HF库中的原生接口

迄今为止,Hugging Face在AWS Trainium和Inferentia(分别专为大规模经济高效训练和推理而设计的AI芯片)上的体验是通过optimum-neuron提供的。该库依赖基于PyTorch XLA的torch-neuronx包。这在当时是自然的选择,但意味着需要像编译器一样思考:惰性张量而非eager执行、仅静态形状、每次图中断都需重新编译。Optimum Neuron的存在就是为了隐藏这些复杂性,并为此维护了自定义代码(建模类、训练器等)。

TorchNeuron改变了这一点。它直接集成到PyTorch中,并将neuron暴露为原生设备,支持eager执行、PyTorch自有的分布式原语(DTensor、FSDP2)以及torch.compile。

对于Hugging Face库而言,Trainium成为与其他设备无异的设备:Transformers、Diffusers、Accelerate、PEFT和TRL可直接在其上运行,使用与其他加速器相同的类和脚本。从现在起,我们建议Neuron用户直接使用这些库,而不是通过Optimum Neuron。

Transformers

推理

文本生成现已在Transformers中为广泛模型原生支持。借助TorchNeuron,排名前100的最常用文本生成模型架构中有89%可开箱即用,而Optimum Neuron v0.4.5仅为46%。您只需在代码中传入device_map=neuron参数,模型就会被移至Neuron设备。

以下是使用张量并行进行文本生成的示例,这将使您能够充分利用Neuron实例。请注意,它使用静态缓存进行生成,因为这在Neuron上强烈推荐,以避免频繁重新编译。

Python
import os

import torch
import torch.distributed as dist
import torch_neuronx # noqa: F401
from torch.distributed import DeviceMesh
from transformers import AutoModelForCausalLM, AutoTokenizer, GenerationConfig
from transformers.distributed import DistributedConfig
from transformers.generation.configuration_utils import CompileConfig

MODEL_ID = "Qwen/Qwen3.8-27B"
MAX_SEQ_LEN = 1024
PREFILL_CHUNK_SIZE = 512

dist.init_process_group(backend="neuron")
world_size = dist.get_world_size()

model = AutoModelForCausalLM.from_pretrained(
 MODEL_ID,
 dtype=torch.bfloat16,
 distributed_config=DistributedConfig(tp_size=world_size),
 device_mesh=DeviceMesh("neuron", list(range(world_size))),
).eval()

tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
if tokenizer.pad_token is None:
 tokenizer.pad_token = tokenizer.eos_token
tokenizer.padding_side = "left"

inputs = tokenizer.apply_chat_template(
 [{"role": "user", "content": "The future of AI is"}],
 add_generation_prompt=True,
 padding=True,
 tokenizer_kwargs={"pad_to_multiple_of": PREFILL_CHUNK_SIZE},
 return_tensors="pt",
)

generation_config = GenerationConfig(
 max_new_tokens=128,
 do_sample=False,
 use_cache=True,
 pad_token_id=tokenizer.pad_token_id,
 eos_token_id=tokenizer.eos_token_id,
 cache_implementation="static",
 max_cache_len=MAX_SEQ_LEN,
 prefill_chunk_size=PREFILL_CHUNK_SIZE,
 compile_config=CompileConfig(backend="neuron", fullgraph=False, dynamic=False),
)

with torch.no_grad():
 output_ids = model.generate(
 inputs["input_ids"],
 attention_mask=inputs["attention_mask"],
 generation_config=generation_config,
 )

if dist.get_rank() == 0:
 prompt_len = inputs["input_ids"].shape[1]
 print(tokenizer.decode(output_ids[0, prompt_len:], skip_special_tokens=True))

训练

既然Neuron是原生PyTorch设备,在Trainium上的训练就使用与其他加速器相同的Hugging Face库:Transformers、Accelerate、PEFT和TRL。您不再需要专用训练器或模型代码的Neuron特定分支。标准的TRL微调脚本只需少量Neuron特定设置即可在Trainium实例上运行。

以下是基于TRL的SFTTrainer构建的监督微调脚本。如果您以前在GPU上使用TRL微调过模型,它应该看起来很熟悉。

Python
import os

import torch
from datasets import load_dataset
from transformers.distributed import DistributedConfig

from trl import ModelConfig, ScriptArguments, SFTConfig, SFTTrainer, TrlParser

def main(script_args, training_args, model_args):
 # The Neuron backend can't compile Dynamo's automatic dynamic shapes yet (https://github.com/huggingface/trl/issues/7660)
 torch._dynamo.config.automatic_dynamic_shapes = False

training_args.model_init_kwargs = {
 "revision": model_args.model_revision,
 "trust_remote_code": training_args.trust_remote_code,
 "attn_implementation": model_args.attn_implementation,
 "dtype": model_args.dtype,
 "device_map": None,
 }
 if int(os.environ.get("WORLD_SIZE", "1")) > 1:
 # The model is sharded on the TP x FSDP grid as its weights are loaded
 training_args.model_init_kwargs["distributed_config"] = DistributedConfig(
 tp_size=int(os.environ.get("TP_SIZE", "1")),
 fsdp_size=int(os.environ.get("FSDP_SIZE", "1")),
 )

# Prepare dataset
 train_dataset = load_dataset(
 script_args.dataset_name,
 name=script_args.dataset_config,
 split=script_args.dataset_train_split,
 )
 # UltraChat also has a string `prompt` column, which makes TRL treat it as a prompt-completion dataset.
 train_dataset = train_dataset.select_columns(["messages"])

# Training
 trainer = SFTTrainer(
 model=model_args.model_name_or_path,
 args=training_args,
 train_dataset=train_dataset,
 )

trainer.train()
 trainer.save_model(training_args.output_dir)
 trainer.end()

if __name__ == "__main__":
 parser = TrlParser((ScriptArguments, SFTConfig, ModelConfig))
 script_args, training_args, model_args = parser.parse_args_and_config()
 main(script_args, training_args, model_args)

并行性由Transformers原生处理。您在model_init_kwargs中放入包含张量并行(TP)和FSDP大小的DistributedConfig,SFTTrainer将其传递给from_pretrained,模型在加载权重时被分片。Trainer看到模型已经分布式,不会再次包装它。您不需要--fsdp标志或Accelerate FSDP配置。

脚本中没有任何内容与Trainium绑定:相同的代码可在任何硬件上运行。在Trainium上运行时,有几点值得了解:

静态形状。该脚本禁用torch.compile中的自动动态形状,并使用包装打包以生成最多2048个token的序列。在TRL ≥ 1.16中,Neuron上的批次会填充到128个token的倍数,从而限制输入形状的数量。相同形状的后续步骤会重用已编译的图。

启用torch.compile。只需传入--torch_compile true即可:在Trainium实例上,torch.compile会检测设备并自动选择Neuron后端,无需其他配置。

异步权重加载关闭。Transformers 内置的异步权重加载在 Neuron 上不受支持,因此目前我们使用 HF_DEACTIVATE_ASYNC_LOAD=1 将其禁用。

下面的命令使用 torchrun 启动训练,它为每个 NeuronCore 启动一个进程。TP_SIZE 和 FSDP_SIZE 设置并行布局,它们的乘积是进程数:这里是 4 x 8 = 32,与 --nproc_per_node 匹配。这 32 个进程形成一个 4 x 8 的网格。张量并行将每一层拆分到 TP 组的 4 个核心上,而 FSDP 则将参数、梯度和优化器状态在 8 个 TP 组之间分片。

代码
TP_SIZE=4 FSDP_SIZE=8 HF_DEACTIVATE_ASYNC_LOAD=1 uv run torchrun --nproc_per_node=32 sft_neuron_example.py \
 --model_name_or_path Qwen/Qwen3-8B \
 --dataset_name HuggingFaceH4/ultrachat_200k \
 --dataset_train_split train_sft \
 --output_dir Qwen3-8B-sft-tp4-fsdp8 \
 --dtype bfloat16 \
 --max_length 2048 \
 --packing true \
 --packing_strategy wrapped \
 --learning_rate 2e-5 \
 --warmup_steps 0.03 \
 --num_train_epochs 1 \
 --logging_steps 2 \
 --per_device_train_batch_size 4 \
 --gradient_accumulation_steps 4 \
 --save_only_model true \
 --torch_compile true

我们在 8 个 Trainium2 芯片(32 个 NeuronCores)上运行它,这是一个 trn2.48xlarge 实例的一半。

训练运行至完成,trainer.save_model 会写入标准的 Transformers 检查点。其中没有任何内容与 Neuron 绑定:您可以直接将其推送到 Hugging Face Hub,并在任何其他硬件上加载它。

Diffusers

推理

Diffusers 库中的许多管道与 TorchNeuron 在 eager 模式和编译模式下兼容。FLUX.1-dev、FLUX.2、Qwen-Image、Qwen-Image-2.1 和 H3 还兼容张量并行,以充分利用您的 Neuron 设备。以下是一个展示如何使用 TP 的示例:

Python
import torch, torch.distributed as dist, torch_neuronx # TP
from torch.distributed.device_mesh import DeviceMesh # TP
from diffusers import QwenImage21Pipeline, QwenImage21Transformer2DModel, TensorParallelConfig

# Distributed devices initialization
dist.init_process_group(backend="neuron") # TP
dev = torch.neuron.current_device()
mesh = DeviceMesh("neuron", list(range(8))) # TP=8

# Pipeline initialization
model = "Qwen/Qwen-Image-2.1"
transformer = QwenImage21Transformer2DModel.from_pretrained(
 model,
 subfolder="transformer",
 torch_dtype=torch.bfloat16,
 parallel_config=TensorParallelConfig(mesh=mesh), # TP
)
pipe = QwenImage21Pipeline.from_pretrained(
 model,
 transformer=transformer,
 torch_dtype=torch.bfloat16,
)
pipe.vae.to(dev)
pipe.transformer.compile_repeated_blocks(backend="neuron", fullgraph=True, dynamic=False)

# Image generation
emb, mask, _ = pipe.encode_prompt(prompt="A capybara wearing a wizard hat, oil painting", device="cpu") # text encoder stays on CPU
image = pipe(
 prompt_embeds=emb.to(dev),
 prompt_embeds_mask=mask.to(dev) if mask is not None else None,
 height=1024,
 width=1024,
 num_inference_steps=40,
 generator=torch.Generator("cpu").manual_seed(0), # same noise on every rank
).images[0]
if dist.get_rank() == 0:
 image.save("out.png")

您可以使用以下命令运行这段代码:NEURON_LOGICAL_NC_CONFIG=2 torchrun --nproc_per_node=8 run.py。

越来越多的管道将与 TP 兼容。如果您喜欢的管道不兼容,您也可以按照本指南为其添加支持。

内核

请务必查看 Neuron 团队的内核,因为越来越多的 Neuron 内核将在 Hub 上提供,以加速您的模型。 Neuron 内核可以使用 Neuron Kernel Interface (NKI) 编写,它提供更底层的控制来优化操作。这样,用户可以运行自己的自定义操作并在 hub 上分享它们。

例如,您可以使用此内核来加速您的视觉 Transformer,在 Trainium 上最高可实现 2.4 倍加速!

致谢

特别感谢 AWS 团队在 TorchNeuron 上的工作,以及他们对我们反馈的快速响应,使 HF 集成尽可能完善。