Skip to content

[FEAT] Interpret NKI ISA instructions and more nl operations in the NKI interpreter - #540

Open
mark14wu wants to merge 1 commit into
fix/nki-official-kernelsfrom
fix/nki-isa-ops
Open

mark14wu wants to merge 1 commit into
fix/nki-official-kernelsfrom
fix/nki-isa-ops

Conversation

@mark14wu

@mark14wu mark14wu commented Nov 8, 2026

Copy link
Copy Markdown
Collaborator

Stacked on #539 (base branch fix/nki-official-kernels); retarget to main after #539 merges.

Summary

#539 lets the legacy NKI interpreter (frontend="nki") run kernels written in the style of AWS's NKI samples, but the samples' larger kernels use NKI ISA instructions (nisa.*) that the interpreter does not implement. Without them, the kernel calls NKI's real implementation and fails with RuntimeError: calling NKI API outside of NKI kernels is not supported. This PR implements them, plus the nl operations those kernels use, with NKI's semantics:

  • nisa: nc_matmul (stationary.T @ moving, fp32), nc_transpose, activation / activation_reduce (op(data * scale + bias), optional reduction into reduce_res), tensor_tensor, tensor_scalar / tensor_scalar_reduce, scalar_tensor_tensor, tensor_reduce, tensor_tensor_scan, tensor_copy, memset, affine_select, reciprocal, iota, dma_copy, dma_transpose, get_nc_version (gen2, a Trn1 NeuronCore).
  • nl: ds, num_programs, program_ndim, full, ones, shared_constant, shared_identity_matrix, transpose, floor, mod.
  • Operators given as numpy ufuncs or as nl functions (nl.add, nl.max, nl.sum, ...) map to numpy ufuncs by name.
  • nisa.dma_copy and nisa.dma_transpose read and write through load / store, so analysis clients see their HBM accesses as loads and stores. NKITransformer rewrites nisa.dma_copy(dst=o[...], src=x[...]) and nisa.dma_transpose(x[...]) to pass the subscripts as dst_keys / src_keys.

The samples' kernels also needed these fixes:

  • 1-D tiles. A 1-D tile has only the partition dimension; NKI broadcasts it along the free axes. numpy aligned it with the last axis, so nisa.activation(op=nl.exp, data=t, scale=A[c0:c1, j]) failed with operands could not be broadcast together with shapes (128,512) (128,). Binary operations, scale / bias, and scalar operands now align a 1-D tile with axis 0.
  • par_dim. Kernels import it directly (from neuronxcc.nki.language import par_dim), so nl.ndarray((par_dim(128), n), ...) received NKI's ParDim objects; shapes now take their value.
  • nl.mgrid. Its result has .p and .x (and .y, .z) for its axes, as in NKI.
  • Assignment. Assigning a [P, 1] result to a [P] slot reshapes it, as store already does.
  • Slices past the tensor. NKI keeps the tile's size, but numpy truncated the slice and changed the tile's shape. A key of ints and slices with an out-of-range slice is now indexed with arrays, so the tile keeps its shape and the out-of-bounds lanes reach masked_load. An unmasked out-of-bounds load now raises IndexError there, as NKI's simulator does, instead of failing on mask.shape.
  • Shared HBM aliasing. Builder.ndarray named a shared-HBM tensor after its caller's frame so that every program of the grid gets the same array. That caller was the op-patching wrapper, so every shared-HBM tensor of a kernel shared one name, and one array. It now uses the kernel's allocation site.
  • Tracer. It accepts a boolean mask (a condition on Python ints) and slices whose bounds are computed (nl.ds(start, size)).

Tests

Not modeled: kernels that allocate SBUF by address (ncc.sbuf.mod_alloc) and rely on two tiles sharing the same memory. Such tiles are separate arrays here.

🤖 Generated with Claude Code

https://claude.ai/code/session_0169QRxKtsivkLDCS5f7rrsm

…KI interpreter

Implements, with NKI's semantics, the nisa instructions that AWS's NKI
samples use: nc_matmul, nc_transpose, activation, activation_reduce,
tensor_tensor, tensor_scalar, tensor_scalar_reduce, scalar_tensor_tensor,
tensor_reduce, tensor_tensor_scan, tensor_copy, memset, affine_select,
reciprocal, iota, dma_copy, dma_transpose, get_nc_version; and nl.ds,
num_programs, program_ndim, full, ones, shared_constant,
shared_identity_matrix, transpose, floor, mod. nisa.dma_copy and
nisa.dma_transpose read and write through load/store, so clients see their
HBM accesses; NKITransformer passes their subscripted operands as keys.

Also: a 1-D tile (partition only) broadcasts along the free axes; shapes
accept par_dim objects imported from NKI; nl.mgrid results have .p/.x;
assigning a [P, 1] result to a [P] slot reshapes it; a slice past the
tensor keeps the tile's size instead of being truncated by numpy, and an
unmasked out-of-bounds load raises IndexError as in NKI; shared-HBM
tensors were all named after the op-patching wrapper's frame and so
aliased one array; the tracer accepts boolean masks and slices with
computed bounds.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0169QRxKtsivkLDCS5f7rrsm

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant