lite_boost.ops.chunk_gated_delta_rule
- lite_boost.ops.chunk_gated_delta_rule(query, key, value, beta, initial_state, actual_seq_lengths, g=None, scale_value=1.0)[source]
Chunked (prefill) Gated Delta Rule operator on NPU (ascend_a2 op).
Wraps
torch.ops.lite_boost.chunk_gated_delta_rule, which maps to the CANN AscendC operatoraclnnChunkGatedDeltaRuleon A2. The user-facing BNSD layout is converted to the TND layout expected by the CANN op;query/key/value/beta/initial_stateare cast to the low dtype (bfloat16 or float16, following the input dtype; fp32/other inputs default to bfloat16) while the optional gategstays float32, andactual_seq_lengthsis passed through directly (T = sum(actual_seq_lengths)).At each time step \(t\) the Gated Delta Rule computes the new recurrent state and the attention output as
\[S_t = \alpha_t S_{t-1} + \beta_t (v_t - \alpha_t S_{t-1} k_t) k_t^{\top}\]\[o_t = S_t q_t \cdot scale\]where \(\alpha_t = \exp(g_t)\) is the decay factor (with
gomitted the decay is disabled, i.e. \(\alpha_t = 1\)), and \(\beta_t\) is the delta update step size. This operator is the chunked (blocked-parallel) implementation of the recurrence above, which is more efficient than the token-by-token form on long sequences and thus suited for the prefill phase; it produces the output at every step as well as the final state.Supported only on A2; 300I Duo is not supported.
- Parameters:
query (Tensor) – Query tensor with shape \((B, N_k, S, D_k)\). Cast to the low dtype before computation.
key (Tensor) – Key tensor with shape \((B, N_k, S, D_k)\). Cast to the low dtype before computation.
value (Tensor) – Value tensor with shape \((B, N_v, S, D_v)\).
N_vmust be an integer multiple ofN_k(GQA: each key head maps toN_v / N_kvalue heads). Cast to the low dtype before computation.beta (Tensor) – Delta update step size with shape \((B, N_v, S)\), in the range [0, 1]. Cast to the low dtype before computation.
initial_state (Tensor) – Incoming recurrent state with shape \((B, N_v, D_k, D_v)\) (transposed to the op's value-first
[B, N_v, D_v, D_k]layout).actual_seq_lengths (Tensor) – Per-batch token counts with shape \((B)\), dtype int32. Each element must be within
[0, S]— the BNSDSdim is the padded per-batch length and only the firstactual_seq_lengths[b]tokens of each batch are valid. Non-uniform lengths are supported: the binding packs the valid tokens into TND tensors withT = sum(actual_seq_lengths), and output positions beyond each batch's length are zero-filled.g (Tensor, optional) – Global decay gate with shape \((B, N_v, S)\), dtype float32, must be negative. This range is not validated: validating it would introduce extra reduction ops (min/max over the tensor) and add noticeable overhead in the inference path. Out-of-range values do not raise but yield meaningless results.
Nonedisables the decay gate (hasGamma=0 path). Default:None.scale_value (float, optional) – Attention scale applied to query. Default:
1.0.
- Returns:
tuple[Tensor, Tensor]
out (Tensor) — Attention output with shape \((B, N_v, S, D_v)\), same dtype as the low-dtype cast of the inputs (bfloat16 by default). Valid for the first
actual_seq_lengths[b]positions of each batch; padded positions are zero-filled.final_state (Tensor) — Updated recurrent state with shape \((B, N_v, D_k, D_v)\), same dtype as out.
- Raises:
RuntimeError – If the input tensor shapes, dtypes or devices are invalid, or if the CANN operator execution fails.
Note
This operator is supported on A2 only; 300I Duo is not supported (there the registered vendor exposes a different aclnn signature, the
ascend_300iduoop).All input tensors must reside on the same NPU device.
N_v(number of value heads) must be an integer multiple ofN_k(number of key/query heads); each key head servesN_v / N_kvalue heads.The BNSD
Sdim is the padded per-batch sequence length; only the firstactual_seq_lengths[b]tokens of each batch are valid. Non-uniformactual_seq_lengthsare packed/unpacked automatically, and padded output positions are zero-filled.The CANN op accepts both bfloat16 and float16 for q/k/v/beta/state via DataTypeList; the input dtype is followed and fp32/other inputs default to bfloat16. The optional gate
gis always float32.
- Supported Platforms:
Ascend
Examples
>>> import torch >>> import lite_boost.ops as lite_ops >>> device = torch.device("npu:0") >>> B, N, S, Dk, Dv = 1, 8, 16, 32, 64 >>> query = torch.randn(B, N, S, Dk, device=device, dtype=torch.bfloat16) >>> key = torch.randn(B, N, S, Dk, device=device, dtype=torch.bfloat16) >>> value = torch.randn(B, N, S, Dv, device=device, dtype=torch.bfloat16) >>> beta = torch.rand(B, N, S, device=device, dtype=torch.bfloat16) * 0.9 + 0.05 >>> initial_state = torch.zeros(B, N, Dk, Dv, device=device, dtype=torch.bfloat16) >>> actual_seq_lengths = torch.tensor([S], dtype=torch.int32, device=device) >>> out, final_state = lite_ops.chunk_gated_delta_rule( ... query, key, value, beta, initial_state, actual_seq_lengths) >>> print(out.shape) torch.Size([1, 8, 16, 64]) >>> print(final_state.shape) torch.Size([1, 8, 32, 64]) >>> print(out.dtype) torch.bfloat16