ttnn.transformer.sparse_sdpa
- ttnn.transformer.sparse_sdpa(q: ttnn.Tensor, kv: ttnn.Tensor, indices: ttnn.Tensor, v_dim: int, *, kv_format: SparseKVFormat, attention_sink: ttnn.Tensor | None, scale: float | None, k_chunk_size: int, cache_batch_idx: int | None, block_cyclic_sp_axis: int | None, block_cyclic_chunk_local: int | None, block_cyclic_cache_tp_sharded: bool) ttnn.Tensor
-
Sparse MLA prefill (DeepSeek DSA), Blackhole single-chip. softmax(Q@Kᵀ·scale masked)@V over the top-k selected latents per query token; V = kv[…, :v_dim]. Masking is baked into indices (0xFFFFFFFF = masked; sentinels are a contiguous tail). Inputs are ROW-MAJOR DRAM-interleaved. K_DIM (the q/kv head dim) is taken from the tensors.
- Parameters:
-
q (ttnn.Tensor)[1, H, S, K_DIM] bf16 or fp8_e4m3 (H a multiple of 32)
kv (ttnn.Tensor)[1, 1, T, K_DIM] bf16/raw fp8, or one packed scaled-FP8 row per token; interpretation is selected only by kv_format, never inferred from width. The packed DSA row is [512 FP8 | 4 FP32 scales | 64 BF16 RoPE] = 656 bytes. When cache_batch_idx is set, B may exceed 1 and kv may be ND-sharded.
indices (ttnn.Tensor)[1, 1, S, TOPK] uint32
v_dim (int)width of V (leading v_dim cols of the K_DIM-wide cache); the output width.
- Keyword Arguments:
-
kv_format (SparseKVFormat)explicit physical/logical format of kv.
attention_sink (ttnn.Tensor, optional)[1, 1, 1, H] unpadded interleaved ROW_MAJOR BF16 tensor in DRAM. One scalar per head, shared across tokens. As in classic SDPA, the sink is multiplied by scale and contributes only to the softmax denominator. DeepSeek-V4 sinks are already scaled logits: pass (model_sink / scale).reshape(1, 1, 1, H) (scale != 0) to contribute exp(model_sink). Defaults to None.
scale (float, optional)defaults to K_DIM**-0.5.
k_chunk_size (int)defaults to 128 (must divide TOPK, multiple of 32).
compute_kernel_config (ttnn.DeviceComputeKernelConfig, optional) –
cache_batch_idx (int, optional)select the batch slot of a shared [B, 1, T, K_DIM] kv cache. It is a dynamic runtime arg, so changing the slot does not recompile. Changing T also reuses the program for a plain interleaved cache, but recompiles for sharded or block-cyclic caches.
block_cyclic_sp_axis (int, optional)when set (with block_cyclic_chunk_local), indices are NATURAL token positions and kv is stored block-cyclic across an SP-sharded cache; the kernel remaps each index natural->physical page on the fly (no host reorder needed). This is the MESH axis the cache was striped over: sp is read from the mesh shape on that axis (the op derives it, so it cannot disagree with the device). T % sp == 0 required. Both must be set together.
block_cyclic_chunk_local (int, optional)the per-shard chunk length (chunk_size_global / sp). Required iff block_cyclic_sp_axis is set. Cross-checked against q’s per-chip seq length: must be q_isl or tp*q_isl (tp = mesh_size/sp) — the only two values it can legally take.
block_cyclic_cache_tp_sharded (bool)True = the cache is striped across ALL sp*tp devices (linear chip = sp_coord*tp + tp_coord), so stripes = sp*tp and per-stripe chunk = block_cyclic_chunk_local/tp.
- Returns:
-
ttnn.Tensor[1, H, S, v_dim] ROW-MAJOR, DRAM interleaved; dtype matches q (bf16->bf16, fp8->fp8).