This document is relevant for: Trn2, Trn3
nki.language.tiles#
- nki.language.tiles(source: nki.language.NkiTensor | nki.language.NkiTileGrid | nki.language.NkiBlockGrid, *, tile_shape: Optional[tuple[int, ...]] = None) NkiTileGrid[source]#
Decompose a tensor into a logical grid of fixed-size tiles.
The returned grid is a view over
source, indexed by tile coordinate rather than by manually calculated element offsets and strides. A kernel can selectsrc_tiles[i, j]to address one tile,src_tiles[i, :]to address a row of tiles, orsrc_tiles[:, j]to address a column.For example,
tile_shape=(128, 256)over a(512, 1024)tensor produces a4 x 4grid:F (free dimension) 256 256 256 256 +---------+---------+---------+---------+ P 128 | (0,0) | (0,1) | (0,2) | (0,3) | (partition) +---------+---------+---------+---------+ 128 | (1,0) | (1,1) | (1,2) | (1,3) | +---------+---------+---------+---------+ 128 | (2,0) | (2,1) | (2,2) | (2,3) | +---------+---------+---------+---------+ 128 | (3,0) | (3,1) | (3,2) | (3,3) | +---------+---------+---------+---------+Note
Grid indexing preserves the grid abstraction.
src_tiles[i, j]returns a one-tileNkiTileGrid, not anNkiTensor. Usesrc_tiles[i, j].datawhen an NKI instruction requires the underlying tensor operand. Accessingdatais also a view operation.- Parameters:
source – The tensor region to tile. It may be a direct
NkiTensor, an existingNkiTileGrid, or anNkiBlockGrid. The returned grid shares its storage, dtype, buffer, offsets, and physical strides.tile_shape – The nominal shape of one tile in source-element units, with at least two dimensions. Every entry must be a positive, exact Python integer. It is required when
sourceis anNkiTensorand optional whensourceis already a grid. For an HBM tensor, fewer dimensions thansourceleaves the leading dimensions as batch coordinates. A tile extent may be larger than its source extent, producing one partial tile.
- Returns:
An
NkiTileGridoversource. Itsshapecounts addressable tiles, itstile_shaperecords the nominaltile_shape, and itselement_shaperecords the number of selected elements in each source dimension. Partial boundary tiles expose only valid elements, although independently allocated on-chip storage may reserve nominal tile capacity behind them.- Raises:
TypeError – if
sourceis unsupported,tile_shapeis omitted for anNkiTensor, a shape is not a tuple of exact Python integers, or the source buffer is not an NKIMemoryRegion.ValueError – if
tile_shapehas fewer than two dimensions, contains a nonpositive extent, has a rank incompatible with the source, the source is an indirectNkiTensor, the source buffer is unsupported, or an existing grid cannot be retiled while preserving its selected addresses.
Examples:
import nki import nki.isa as nisa import nki.language as nl @nki.jit def scale_by_tile(src): dst = nl.ndarray( src.shape, dtype=src.dtype, buffer=nl.shared_hbm ) src_tiles = nl.tiles(src, tile_shape=(128, 256)) dst_tiles = nl.tiles(dst, tile_shape=(128, 256)) for i in range(src_tiles.shape[0]): for j in range(src_tiles.shape[1]): src_tile = src_tiles[i, j] dst_tile = dst_tiles[i, j] tile = nl.ndarray( src_tile.element_shape, dtype=src.dtype, buffer=nl.sbuf, ) nisa.dma_copy(dst=tile.data, src=src_tile.data) nisa.tensor_scalar( dst=tile.data, data=tile.data, op0=nl.multiply, operand0=2.0 ) nisa.dma_copy(dst=dst_tile.data, src=tile.data) return dst
Source kinds.
The source can be
NkiTensororNkiTileGridorNkiBlockGrid.source tile_shape result ------------------ ----------------- ------------------------------ HBM NkiTensor required tile grid over HBM SBUF NkiTensor required tile grid over SBUF PSUM NkiTensor required tile grid over PSUM NkiTileGrid omitted same tile-grid view NkiTileGrid supplied address-preserving retile NkiBlockGrid omitted remove block grouping NkiBlockGrid supplied remove blocks, then retile
Both
NkiBlockGridforms remove the block-coordinate level. Omittingtile_shapepreserves the existing tile structure. Supplying it rebuilds the tile grid at the requested compute grain. See Retiling section below.Remainder tiles.
Grid dimensions use ceiling division. When a source extent is not an exact multiple of its tile extent, the final tile is clamped to the remaining elements. For
source.shape == (300, 600)andtile_shape == (128, 256):column 0 column 1 column 2 256 elements 256 elements 88 elements +--------------+--------------+-----------+ row 0: 128 elements | 128 x 256 | 128 x 256 | 128 x 88 | +--------------+--------------+-----------+ row 1: 128 elements | 128 x 256 | 128 x 256 | 128 x 88 | +--------------+--------------+-----------+ row 2: 44 elements | 44 x 256 | 44 x 256 | 44 x 88 | +--------------+--------------+-----------+The nominal
tile_shaperemains(128, 256), whilesrc_tiles[-1, -1].data.shapeis(44, 88). The selected boundary tile reportsis_remainder == True. Its logical extent anddataoperand contain no padding.# check if last row/col tiles are partials src_tiles[-1].is_remainder src_tiles[:, -1].is_remainder src_tiles[-1, -1].is_remainder
See also
nki.language.blocks(): Group tiles into blocks.NkiTileGrid: Tile-grid metadata and indexing.NkiGrid.data: Access a selected region as an NKI tensor.
This document is relevant for: Trn2, Trn3