This document is relevant for: Trn2, Trn3
GPSIMD Top-K Kernel API Reference#
Top-k over the last dimension using the GpSIMD nisa.topk instruction.
Background#
The gpsimd_topk kernel computes top-k over the last dimension using the GpSIMD nisa.topk instruction. The companion create_gpsimd_topk_config builds a GpsimdTopkConfig from an input shape (2D or 3D) and parameters.
API Reference#
Source code for this kernel API can be found at: gpsimd_topk.py
create_gpsimd_topk_config#
gpsimd_topk#
- nkilib.experimental.topk.gpsimd_topk(inp: nl.NkiTensor, config: GpsimdTopkConfig) Tuple[nl.NkiTensor, nl.NkiTensor]#
Top-k over the last dimension using the GpSIMD nisa.topk instruction.
- Parameters:
inp (
nl.NkiTensor) – [BxS, V] bfloat16 input tensor in HBM.config (
GpsimdTopkConfig) – GpsimdTopkConfig describing the problem and sharding.
Notes:
Each vocab row is loaded into its 16-partition nisa.topk snake with a BLOCKED / contiguous DMA: partition p reads the contiguous HBM run inp[row, p*n_cols:(p+1)*n_cols] (free-stride 1), so snake position s = p + 16*c holds vocab index p*n_cols + c. The 16-partition snake LAYOUT is mandated by nisa.topk, but the ORDER of the placement is a free bijection (any order yields the same top-k value set). The blocked order is chosen so the load is contiguous; the alternative “snake position i == vocab index i” fill gives an identity remap but forces a transpose-on-load (.ap [[1,16],[16,n]], free-stride 16 -> non-contiguous per partition), which is avoided here. The returned snake-position indices are remapped back to vocab space on-chip before the index store.
8 rows (groups of 16 partitions) are processed per nisa.topk call.
The hardware nisa.topk output order is not relied upon: the K values + paired snake-position indices are de-snaked and then sorted descending on-chip; the snake->vocab index remap is applied to the final k indices.
Two-phase structure: phase 1 runs nisa.topk per 8-row tile and de-snakes the K (value, index) pairs into per-row HBM buffers; phase 2 runs the descending sort ONCE over up to 128 rows (one row per partition) instead of once per 8-row tile. max8 / nc_match_replace8 / nc_n_gather are per-partition free-dim ops, so widening the sort from 8 to up to 128 partitions is free Vector-engine parallelism and removes the redundant per-tile sort passes (the measured HW bottleneck).
config.sorted gates only the phase-2 descending sort. When False the sort is skipped and the K results are compacted to [0, k) in arbitrary order; the value set and value<->index pairing are unchanged.
Dimensions:
BxS: number of rows (flattened batch*sequence)
V: vocab size (reduction dimension), 8 <= V < 65536
This document is relevant for: Trn2, Trn3