Compile NEFF Executables from PyTorch Code
Motivation
When deploying models on AWS Inferentia or Trainium, torch_neuronx.trace compiles a PyTorch function into a NEFF (Neuron Executable File Format) binary. The API is straightforward in principle — you pass a callable and example inputs — but there are a few practical requirements that are easy to overlook:
- The traced callable must accept and return only tensors, or (possibly nested) lists, dicts, and tuples of tensors. Scalar arguments like
intorboolare not allowed directly. - Input shapes and dtypes must be fully concrete at trace time.
- The resulting NEFF is saved to a compiler working directory, not returned as an in-memory object.
This post walks through a concrete example: compiling a RoPE (Rotary Position Embedding) forward pass into a NEFF executable.
RoPE Implementation
The core implementation is adapted from ApplyRotaryEmb.forward_static in common vLLM kernels. It gathers cos/sin at the given positions, rotates the first rotary_dim dimensions of query (and key when present), and passes the tail through unchanged.
1 | |
Static Inputs
Every input must be a concrete tensor with fixed shapes and dtypes:
1 | |
Wrapping in a torch.nn.Module
torch_neuronx.trace requires the callable to accept only tensors and nested tensor containers. Scalars like head_size, rotary_dim, and is_neox_style cannot be passed directly. The idiomatic fix is to capture them in a torch.nn.Module:
1 | |
Scalars are baked in at construction time. At trace time, only tensor arguments flow through forward.
Tracing with torch_neuronx
With the wrapper and static inputs ready, tracing is a single call:
1 | |
- The second argument is a tuple of example inputs matching
forward‘s signature. --lnc=2targets two NeuronCores.- The NEFF file is written to
./compiler_workdir/. - The returned
tracedobject can also be used directly for inference within the same process.
Loading and Executing the Compiled NEFF
Once you have the NEFF binary, you can load and run it independently of the compilation toolchain using spike. This is useful when you want to ship a pre-compiled kernel without bundling the full Neuron compiler at deploy time.
I covered the full workflow — loading a NEFF, inspecting I/O metadata, creating SpikeTensor inputs, running inference, and reading results back — in the companion post: Compile NEFF Executables from NKI Kernels §4. The spike API is the same regardless of whether the NEFF originated from NKI or from torch_neuronx.trace.