Swizzle Helper Functions
gemm_swizzle2d_Nz
Converts a GEMM iteration index to a 2D tile coordinate in the output matrix.
Tiles are grouped by columns, with adjacent groups traversing rows in reverse order, forming a serpentine scheduling pattern. The last group with fewer than swizzle_offset columns is handled automatically.
Signature
gemm_swizzle2d_Nz(
iter_id,
data_row_shape,
data_col_shape,
tile_row_shape,
tile_col_shape,
swizzle_offset=7,
)
Parameters
Parameter |
Description |
|---|---|
|
Current iteration index. Range: |
|
Number of rows in the output matrix, typically |
|
Number of columns in the output matrix, typically |
|
Number of rows per tile, typically |
|
Number of columns per tile, typically |
|
Number of column tiles per group, defaults to |
Return Value
Returns (data_row_idx, data_col_idx), the row and column indices of the tile.
Scheduling Order
For example, with a 3-row by 10-column tile grid and swizzle_offset=7: the first 7 columns traverse rows in the order 0 -> 1 -> 2, while the last 3 columns traverse in the order 2 -> 1 -> 0.
Use Cases
Used in the GEMM phase of distributed fused kernels.
Grouping tiles from adjacent columns helps improve cache locality for matrix data.
Serpentine traversal connects adjacent groups on the same row, reducing large jumps in tile coordinates.
The returned
(block_id_m, block_id_n)can be directly used to compute block addresses for A, B, and C.
Notes
The shape, tile, and
swizzle_offsetparameters must be greater than0.This function only adjusts the scheduling order and does not change the data layout.
Example
import triton
import triton.language as tl
from triton_dist.language.extra.ascend.algorithm import gemm_swizzle2d_Nz
@triton.jit
def gemm_tile_kernel(c_ptr, M, N, stride_cm, stride_cn,
BLOCK_M: tl.constexpr, BLOCK_N: tl.constexpr):
pid = tl.program_id(0)
ncore = tl.num_programs(0)
num_tiles = tl.cdiv(M, BLOCK_M) * tl.cdiv(N, BLOCK_N)
for iter_id in range(pid, num_tiles, ncore):
block_m, block_n = gemm_swizzle2d_Nz(
iter_id, M, N, BLOCK_M, BLOCK_N,
)
# Use offs_m and offs_n to compute block addresses for A, B, and C.
offs_m = block_m * BLOCK_M + tl.arange(0, BLOCK_M)
offs_n = block_n * BLOCK_N + tl.arange(0, BLOCK_N)
dist_swizzle2d_Nz
Converts a communication iteration index to a data tile, target rank, and tail block size.
Different tiles start communication from different ranks, avoiding multiple AI Cores concentrating access on the same rank.
Signature
dist_swizzle2d_Nz(
iter_id,
rank_size,
data_row_shape,
data_col_shape,
tile_row_shape,
tile_col_shape,
comm_npu_split=1,
)
Parameters
Parameter |
Description |
|---|---|
|
Current iteration index. Range: |
|
Number of ranks participating in communication. |
|
Number of data rows. |
|
Number of data columns. |
|
Maximum number of rows per tile. |
|
Maximum number of columns per tile. |
|
Number of ranks per interleaved scheduling group, defaults to |
Return Value
Returns (data_row_idx, data_col_idx, rank_idx, comm_row_size, comm_col_size):
data_row_idx,data_col_idx: Row and column indices of the tile.rank_idx: Target rank.comm_row_size,comm_col_size: Actual number of rows and columns in the current tile.
Use Cases
Used in fused kernels such as AllGather-GEMM, GEMM-ReduceScatter, and GEMM-AllReduce.
Rotating target ranks for different tiles helps reduce communication hotspots and access contention between ranks.
Notes
comm_npu_splitmust satisfyrank_size % comm_npu_split == 0.This function only adjusts the scheduling order and does not change the data layout.
Example
import triton
import triton.language as tl
from triton_dist.language.extra.ascend.algorithm import dist_swizzle2d_Nz
@triton.jit
def communication_kernel(rank_size, rows, cols,
TILE_M: tl.constexpr, TILE_N: tl.constexpr):
pid = tl.program_id(0)
ncore = tl.num_programs(0)
num_iters = rank_size * tl.cdiv(rows, TILE_M) * tl.cdiv(cols, TILE_N)
for iter_id in range(pid, num_iters, ncore):
# target_rank is used to select the remote rank; tile_rows and tile_cols are used to generate the tail block mask.
tile_m, tile_n, target_rank, tile_rows, tile_cols = dist_swizzle2d_Nz(
iter_id, rank_size, rows, cols, TILE_M, TILE_N,
)