nki(matrix_transpose): NKI (Trainium) implementation - #291
bowencui123 wants to merge 5 commits into
Conversation
Split out of the consolidated NKI branch cecilia/feature/nki-vector-add (nki-all-operators, PR #259) so each operator can be reviewed on its own. Supersedes PR #183 (older per-operator branch). - includes `NkiAutotuner` wiring (search space over the kernel's tile/loop parameter; defaults unchanged) Co-Authored-By: Cecilia123li <68335867+Cecilia123li@users.noreply.github.com> Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012Q38kGmXvyoeM1qtCbheSL
Merges NKI backend timing into results/csv/matrix_transpose_default.csv, run against this branch's impl_nki.py on trn2.3xlarge with the LNC2 execution contract (NEURON_LOGICAL_NC_CONFIG=2, NEURON_RT_NUM_CORES=1, NEURON_CC_FLAGS="--target trn2 --lnc 2"). All cases pass correctness verification. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AQseF7nyesBh8KZAp8g7Cm
| @@ -0,0 +1,101 @@ | |||
| from types import SimpleNamespace | |||
There was a problem hiding this comment.
I think the current NKI implementation is algorithmically correct, but the copy path may be unnecessarily expensive compared with both the Torch/Neuron baseline and the Triton/cuTile implementations.
Triton and cuTile both effectively perform a direct contiguous load/store copy:
input -> output
The current NKI implementation instead explicitly stages every tile through SBUF:
HBM -> SBUF -> HBM
via:
a_tile = nl.ndarray((p_sz, f_sz), dtype=a_input.dtype, buffer=nl.sbuf)
nisa.dma_copy(
dst=a_tile,
src=a_input[p_start:p_end, f_start:f_end],
)
nisa.dma_copy(
dst=hbm_result_tile[p_start:p_end, f_start:f_end],
src=a_tile,
)For a pure matrix copy, this extra SBUF staging does not appear necessary. nisa.dma_copy supports HBM-to-HBM copies, so it may be worth testing a direct path such as:
nisa.dma_copy(
dst=hbm_result_tile[p_start:p_end, f_start:f_end],
src=a_input[p_start:p_end, f_start:f_end],
)The performance pattern also suggests this is a bandwidth/path-efficiency issue rather than an algorithmic-complexity issue. For example, at N=4096:
- fp16:
torch_nki = 0.1143 ms,NKI = 0.1738 ms - bf16:
torch_nki = 0.1144 ms,NKI = 0.1739 ms - fp32:
torch_nki = 0.2168 ms,NKI = 0.3294 ms
So NKI is consistently around 1.5x slower, with a very similar ratio across dtypes.
There is also one baseline issue worth checking. The Torch implementation is:
B = A + 0On Torch/XLA, A + 0 may be algebraically simplified by the compiler, potentially turning the Torch baseline into an optimized copy/output-materialization path rather than an actual elementwise-add kernel.
Could we please:
- Inspect the generated Torch HLO to confirm whether
A + 0is eliminated. - Benchmark a direct HBM-to-HBM NKI
dma_copy. - Compare that result against the current
HBM -> SBUF -> HBMimplementation.
I think this would clarify whether the current gap is mainly caused by unnecessary SBUF staging. From the TileBench symmetry perspective, the current implementation is algorithmically equivalent to Triton/cuTile, but the memory-movement strategy is not yet as closely aligned.
…spose # Conflicts: # results/csv/matrix_transpose_default.csv
…anspose blocks), no host pad; exact int8 XLA torch baseline (int16 transpose + clamp); rerun default+autotune benchmarks Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01ScXYNjrrKGgDUVNHxv7HJt
NKI (AWS Trainium) implementation of matrix_transpose, split out of the consolidated NKI branch
cecilia/feature/nki-vector-add(nki-all-operators, #259) so each operator can be reviewed independently. Supersedes #183 (older per-operator branch: legacyneuronxcc.nkiimports; this is the migratedimport nkiversion).Files: A benchmarks/operators/matrix_transpose/impl_nki.py
Status: verified on trn2 (default + autotune; NKI 0.350 ms @ 4096x1024 fp16)
NkiAutotunerwiring (search space over the kernel's tile/loop parameter; defaults unchanged)Implementation by @Cecilia123li. Timing/identity infrastructure: #261; Trainium peak/roofline infra: #262.
🤖 Generated with Claude Code
https://claude.ai/code/session_012Q38kGmXvyoeM1qtCbheSL
Autotune (already on this branch)
tile(square nc_transpose tile <=128)BLOCK_TILEautotune=Falsekeeps the previous constants. Validation on trn2, case 0: