sparse_flash_mla_grad
Applicable Products
Ascend 950PR/Ascend 950DT : Not supportedAtlas A3 training products/Atlas A3 inference products : SupportedAtlas A2 training products/Atlas A2 inference products : SupportedAtlas 200I/500 A2 inference products : Not supportedAtlas inference products : Not supportedAtlas training products : Not supported
Function
API Function:
sparse_flash_mla_grad: Computes the backward output of attention in theSparseFlashMlatraining use case. Supports Sliding Window Attention, Compressed Attention, and Sparse Compressed Attention.sparse_flash_mla_grad_metadata: Generates metadata before thesparse_flash_mla_gradmain operator. This API is reserved for future extension and currently has no actual effect. It outputs None.
Formula:
Phase 1: Select between the input ori_kv and cmp_kv based on different cmp_ratio use cases.
When cmp_ratio = 1 (SWA):
When cmp_ratio = 4 (SCFA):
else (CFA):
Phase 2: Calculate P, dP, and dS.
Phase 3: Calculate dQ, dKV, and dSinks.
Prototype
Before calling the sparse_flash_mla_grad API, call the sparse_flash_mla_grad_metadata API to complete load balancing calculation.
sparse_flash_mla_grad_metadata(num_heads_q, num_heads_kv, head_dim,
cu_seqlens_q=None, cu_seqlens_ori_kv=None, cu_seqlens_cmp_kv=None,
seqused_q=None, seqused_ori_kv=None, seqused_cmp_kv=None,
cmp_residual_kv=None, ori_topk_length=None, cmp_topk_length=None,
batch_size=None, max_seqlen_q=None, max_seqlen_ori_kv=None,
max_seqlen_cmp_kv=None, ori_topk=None, cmp_topk=None,
cmp_ratio=None, ori_mask_mode=0, cmp_mask_mode=0,
ori_win_left=-1, ori_win_right=-1,
layout_q="BSND", layout_kv="BSND", has_ori_kv=True, has_cmp_kv=True) -> Tensorsparse_flash_mla_grad(q, dout, attn_out, softmax_lse, ori_kv=None, cmp_kv=None,
ori_sparse_indices=None, cmp_sparse_indices=None, cu_seqlens_q=None,
cu_seqlens_ori_kv=None, cu_seqlens_cmp_kv=None, seqused_q=None,
seqused_ori_kv=None, seqused_cmp_kv=None, cmp_residual_kv=None,
ori_topk_length=None, cmp_topk_length=None,
sinks=None, metadata=None,
softmax_scale=None, cmp_ratio=None, ori_mask_mode=0, cmp_mask_mode=0,
ori_win_left=-1, ori_win_right=-1,
layout_q="BSND", layout_kv="BSND") -> (Tensor, Tensor, Tensor, Tensor, Tensor, Tensor)Parameters
sparse_flash_mla_grad_metadata
| Parameter | Parameter Type | Optional/Required | Description | Data Type | Dimension (Shape) |
|---|---|---|---|---|---|
| num_heads_q | int | Required | Indicates the number of heads of in the formula (that is, N1). | int | - |
| num_heads_kv | int | Required | Indicates the number of heads of or in the formula (that is, N2). | int | - |
| head_dim | int | Required | Indicates the head dimension (that is, D). | int | - |
| cu_seqlens_q | Tensor | Optional | Represents the accumulation of the effective token count of q in each batch. This parameter is mandatory when layout_q is TND. | int32 | 1 |
| cu_seqlens_ori_kv | Tensor | Optional | Represents the accumulation of the effective token count of ori_kv in each batch. This parameter is mandatory when layout_kv is TND. | int32 | 1 |
| cu_seqlens_cmp_kv | Tensor | Optional | Represents the accumulation of the effective token count of cmp_kv in each batch. This parameter is mandatory when layout_kv is TND. | int32 | 1 |
| seqused_q | Tensor | Optional | Indicates the number of tokens of query that actually participate in the operation in different batches. Currently only supports passing None. | int32 | 1 |
| seqused_ori_kv | Tensor | Optional | Indicates the number of tokens of ori_kv that actually participate in the operation in different batches. Currently only supports passing None. | int32 | 1 |
| seqused_cmp_kv | Tensor | Optional | Indicates the number of tokens of cmp_kv that actually participate in the operation in different batches. Currently only supports passing None. | int32 | 1 |
| cmp_residual_kv | Tensor | Optional | Indicates the remainder of the actual ori_s2 // cmpRatio for each batch. | int32 | 1 |
| ori_topk_length | Tensor | Optional | Indicates the actual optional topk length of ori_kv corresponding to each row of query. Currently only supports passing None. | int32 | 3/4 |
| cmp_topk_length | Tensor | Optional | Indicates the actual optional topk length of cmp_kv corresponding to each row of query. Currently only supports passing None. | int32 | 3/4 |
| batch_size | int | Optional | Indicates the input batch size (that is, B). | int | - |
| max_seqlen_q | int | Optional | Indicates the maximum sequence length of the input q in TND layout. | int | - |
| max_seqlen_ori_kv | int | Optional | Indicates the maximum sequence length of the input ori_kv in TND layout. | int | - |
| max_seqlen_cmp_kv | int | Optional | Indicates the maximum sequence length of the input cmp_kv in TND layout. | int | - |
| ori_topk | int | Optional | Indicates the topk length of ori_kv. | int | - |
| cmp_topk | int | Optional | Indicates the topk length of cmp_kv. | int | - |
| cmp_ratio | int | Optional | Represents the compression ratio. Value range: 1 to 128. | int | - |
| ori_mask_mode | int | Optional | Indicates the mask mode for the calculation of q and ori_kv. Currently only supports mode 4 (band mask, whose sliding window range is controlled by ori_win_left and ori_win_right, with the lower-right corner as the starting point). | int | - |
| cmp_mask_mode | int | Optional | Indicates the mask mode for the calculation of q and cmp_kv. Currently only supports mode 3 (rightDownCausal mask, corresponding to the lower-triangular scenario divided by the right vertex). | int | - |
| ori_win_left | int | Optional | Indicates the number of past tokens calculated for q in the calculation of q and ori_kv. Currently only supports the value 127. | int | - |
| ori_win_right | int | Optional | Indicates the number of future tokens calculated for q in the calculation of q and ori_kv. Currently only supports the value 0. | int | - |
| layout_q | str | Optional | Indicates the data arrangement format of q. Supports "BSND" and "TND". | str | - |
| layout_kv | str | Optional | Indicates the data arrangement format of ori_kv and cmp_kv. Supports "BSND" and "TND". Currently must be consistent with layout_q. | str | - |
| has_ori_kv | bool | Optional | Indicates whether ori_kv is passed in. | bool | - |
| has_cmp_kv | bool | Optional | Indicates whether cmp_kv is passed in. | bool | - |
sparse_flash_mla_grad
| Parameter | Parameter Type | Optional/Required | Description | Data Type | Dimension (Shape) |
|---|---|---|---|---|---|
| q | Tensor | Required | Corresponds to in the formula. | bfloat16, float16 | 3/4 |
| dout | Tensor | Required | Gradient of the attention forward output matrix, corresponding to in the formula. | bfloat16, float16 | 3/4 |
| attn_out | Tensor | Required | Attention forward output matrix, corresponding to in the formula. | bfloat16, float16 | 3/4 |
| softmax_lse | Tensor | Required | Output lse of the attention forward calculation. | float32 | 3/4 |
| ori_kv | Tensor | Optional | Corresponds to in the formula. Passing None is currently not supported. | bfloat16, float16 | 3/4 |
| cmp_kv | Tensor | Optional | Corresponds to in the formula. When None is passed, calculation follows the SWA scenario in the formula. | bfloat16, float16 | 3/4 |
| ori_sparse_indices | Tensor | Optional | Corresponds to the topk of the oriKv part (not supported yet). Currently only None is supported. | int32 | 3/4 |
| cmp_sparse_indices | Tensor | Optional | Corresponds to in the formula. | int32 | 3/4 |
| cu_seqlens_q | Tensor | Optional | Represents the cumulative sum of the effective token count of q in each batch. This parameter is mandatory when layout_q is TND. | int32 | 1 |
| cu_seqlens_ori_kv | Tensor | Optional | Represents the cumulative sum of the effective token count of ori_kv in each batch. This parameter is mandatory when layout_kv is TND. | int32 | 1 |
| cu_seqlens_cmp_kv | Tensor | Optional | Represents the cumulative sum of the effective token count of cmp_kv in each batch. This parameter is mandatory when layout_kv is TND. | int32 | 1 |
| seqused_q | Tensor | Optional | Indicates the number of tokens of query that actually participate in the operation in different batches. Currently only None is supported. | int32 | 1 |
| seqused_ori_kv | Tensor | Optional | Indicates the number of tokens of ori_kv that actually participate in the operation in different batches. Currently only None is supported. | int32 | 1 |
| seqused_cmp_kv | Tensor | Optional | Indicates the number of tokens of cmp_kv that actually participate in the operation in different batches. Currently only None is supported. | int32 | 1 |
| cmp_residual_kv | Tensor | Optional | Indicates the remainder of the actual ori_s2 // cmpRatio in each batch. Mandatory when cmp_kv is not empty and cmp_mask_mode is 3. | int32 | 1 |
| ori_topk_length | Tensor | Optional | Indicates the actual optional topk length of ori_kv corresponding to each query row. Currently only None is supported. | int32 | 3/4 |
| cmp_topk_length | Tensor | Optional | Indicates the actual optional topk length of cmp_kv corresponding to each query row. Currently only None is supported. | int32 | 3/4 |
| sinks | Tensor | Optional | Indicates the attention sink tensor. Passing None is currently not supported. | float32 | 1 |
| metadata | Tensor | Optional | Indicates the output of the metadata operator sunk by the preceding tiling. Currently only None is supported. | int32 | 1 |
| softmax_scale | double | Optional | Represents the scaling factor. The data type supports double. Default value: 1.0 / sqrt(D). | double | - |
| cmp_ratio | int | Optional | Represents the compression ratio. Value range: 1 to 128. | int | - |
| ori_mask_mode | int | Optional | Indicates the mask mode for the calculation of q and ori_kv. Currently only mode 4 is supported (band mask, with the sliding window range controlled by ori_win_left and ori_win_right, starting from the bottom-right corner). | int | - |
| cmp_mask_mode | int | Optional | Indicates the mask mode for the calculation of q and cmp_kv. Currently only mode 3 is supported (rightDownCausal mask, corresponding to the lower-triangular scenario divided by the right vertex). | int | - |
| ori_win_left | int | Optional | Indicates the number of past tokens that q calculates in the calculation of q and ori_kv. Currently only the value 127 is supported. | int | - |
| ori_win_right | int | Optional | Indicates the number of future tokens that q calculates in the calculation of q and ori_kv. Currently only the value 0 is supported. | int | - |
| layout_q | str | Optional | Indicates the data layout format of q. Supports "BSND" and "TND". | str | - |
| layout_kv | str | Optional | Indicates the data layout format of ori_kv and cmp_kv. Supports "BSND" and "TND". Currently must be consistent with layout_q. | str | - |
Return Value
sparse_flash_mla_grad_metadata
| Parameter | Parameter Type | Optional/Required | Description | Data Type | Dimension (Shape) |
|---|---|---|---|---|---|
| metadata | Tensor | Required | Indicates the core splitting result of the sparse_flash_mla_grad operator. | Not supported. The output is fixed to None. | - |
sparse_flash_mla_grad
| Parameter | Parameter Type | Optional/Required | Description | Data Type | Dimension (Shape) |
|---|---|---|---|---|---|
| dq | Tensor | Required | Corresponds to in the formula. | Same as q. | Same as q |
| dori_kv | Tensor | Optional | Indicates the gradient of the input ori_kv. | Same as ori_kv. | Same as ori_kv |
| dcmp_kv | Tensor | Optional | Indicates the gradient of the input cmp_kv. | Same as cmp_kv. | Same as cmp_kv |
| dsinks | Tensor | Optional | Indicates the gradient of the input sinks. | Same as sinks. | Same as sinks |
| ori_softmax_l1norm | Tensor | Optional | This parameter is not supported currently. The output is None. | float32 | Same as ori_sparse_indices |
| cmp_softmax_l1norm | Tensor | Optional | Indicates the L1Norm result of the softmax calculated from q and cmp_kv. The formula is reduceG(softmax)/G. In SCFA use cases, this output is not empty. In other use cases, the output is None. | float32 | Same as cmp_sparse_indices |
Constraints
- This API is supported only in training use cases.
- This API supports only single-operator mode calls.
- The data types of q, dout, attn_out, ori_kv, and cmp_kv must be consistent.
- The usage of cmp_kv and cmp_sparse_indices in each use case is as follows:
- SWA use case: cmp_kv == None && cmp_sparse_indices == None is required.
- SCFA use case: cmp_kv != None && cmp_sparse_indices != None is required.
- CFA use case: cmp_kv != None && cmp_sparse_indices == None is required.
Deterministic Computation
- Deterministic computation is not supported by default.
Example
Single-operator call
import math import random import numpy as np import torch import torch_npu import cann_ops_transformer S1 = 256 S2 = 1024 cmp_ratio = 4 actual_seq_q = [S1] actual_seq_ori_kv = [S2] actual_seq_cmp_kv = [S2 // cmp_ratio] cmp_residual = [i % cmp_ratio for i in actual_seq_ori_kv] T1 = sum(actual_seq_q) T2 = sum(actual_seq_ori_kv) T3 = sum(actual_seq_cmp_kv) B = 1 N1 = 64 N2 = 1 D = 512 K = 512 scaleValue = 1 / math.sqrt(D) dtype = torch.float16 input_layout = "TND" q_shape = tuple((T1, N1, D)) ori_kv_shape = tuple((T2, N2, D)) cmp_kv_shape = tuple((T3, N2, D)) out_shape = tuple((T1, N1, D)) lse_shape = tuple((N2, T1, N1 // N2)) cu_seq_qlen = [0] + [sum(actual_seq_q[:x+1]) for x in range(len(actual_seq_q))] cu_seq_ori_kvlen = [0] + [sum(actual_seq_ori_kv[:x+1]) for x in range(len(actual_seq_ori_kv))] cu_seq_cmp_kvlen = [0] + [sum(actual_seq_cmp_kv[:x+1]) for x in range(len(actual_seq_cmp_kv))] q = (torch.rand(q_shape).to(dtype)) * 2 ori_kv = (torch.rand(ori_kv_shape).to(dtype)) * 2 cmp_kv = (torch.rand(cmp_kv_shape).to(dtype)) * 2 if cmp_ratio != 1 else None dy = (torch.rand(out_shape).to(dtype)) * 2 out = (torch.rand(out_shape).to(dtype)) * 2 # Use the forward output attn_out in actual use cases. sinks = (torch.rand(N1).to(torch.float32)) * (128) lse = (torch.rand(lse_shape).to(torch.float32)) # Use the forward output lse in actual use cases. if cmp_ratio == 4: cmp_sparse_indices = torch.ones([T1, N2, K], dtype=torch.int32) * -1 accum_t = 0 for i in range(B): cur_s1 = actual_seq_q[i] cur_ori_s2 = actual_seq_cmp_kv[i] * cmp_ratio + cmp_residual[i] delta_s = cur_ori_s2 - cur_s1 for s1_idx in range(cur_s1): threshold = delta_s + s1_idx + 1 if delta_s + s1_idx + 1 >= 0 else 0 max_cmp_s2 = threshold // cmp_ratio cur_s2_idxs = np.arange(max_cmp_s2) if max_cmp_s2 < K: cmp_sparse_indices[accum_t, :, :max_cmp_s2] = torch.tensor(np.random.choice(cur_s2_idxs, size=max_cmp_s2, replace=False)) else: cmp_sparse_indices[accum_t, :, :] = torch.tensor(np.random.choice(cur_s2_idxs, size=K, replace=False)) accum_t += 1 else: cmp_sparse_indices = None cmp_kv_npu = cmp_kv.npu() if cmp_kv != None else None cmp_sparse_indices_npu = cmp_sparse_indices.npu() if cmp_sparse_indices != None else None cu_seq_qlen = None if input_layout != "TND" else torch.tensor(cu_seq_qlen).to(torch.int32).npu() cu_seq_ori_kvlen = None if input_layout != "TND" else torch.tensor(cu_seq_ori_kvlen).to(torch.int32).npu() cu_seq_cmp_kvlen = None if input_layout != "TND" else torch.tensor(cu_seq_cmp_kvlen).to(torch.int32).npu() cmp_residual_kv = torch.tensor(cmp_residual).to(torch.int32).npu() if cmp_residual != None else None metadata = cann_ops_transformer.ops.sparse_flash_mla_grad_metadata(N1, N2, D) npu_out = cann_ops_transformer.ops.sparse_flash_mla_grad( q.npu(), dy.npu(), out.npu(), lse.npu(), ori_kv=ori_kv.npu(), cmp_kv=cmp_kv_npu, cmp_sparse_indices=cmp_sparse_indices_npu, cu_seqlens_q=cu_seq_qlen, cu_seqlens_ori_kv=cu_seq_ori_kvlen, cu_seqlens_cmp_kv=cu_seq_cmp_kvlen, cmp_residual_kv=cmp_residual_kv, sinks=sinks.npu(), softmax_scale=scaleValue, cmp_ratio=cmp_ratio, layout_q=input_layout, layout_kv=input_layout, ori_win_left=127, ori_win_right=0, ori_mask_mode=4, cmp_mask_mode=3, metadata=metadata )