RecOps Running Case Documentation
Introduction
What Is RecOps
RecOps is a set of custom operators for recommendation scenarios built on Ascend C. It provides basic operator capabilities for framework components (tf_rec_v1, tf_rec_v2, torch_rec_v1, torch_rec_v2) and supports Atlas A2/A3/A5 devices.
Core positioning:
- A custom operator set for recommendation scenarios built on Ascend C.
- Focused on fusing and accelerating key compute paths such as
Embedding,Attention, andOptimizer. - Supports mainstream recommendation frameworks such as
tf_recandtorch_rec.
Repository: RecSDK repository on GitCode
Running Case
This case briefly introduces the HSTU_V1 forward operator hstu_dense_forward and how to compile and run it in an NPU environment.
Introduction to the HSTU_V1 Forward Operator
Hierarchical Sparse Transformer Unit (HSTU) is a sparse attention fusion operator for recommendation scenarios. It fuses QK matrix multiplication, SiLU activation, scaling, mask application, and matrix multiplication with V into a single fused operator. This greatly reduces memory access overhead and kernel scheduling overhead, which enables high-performance training of recommendation models on Ascend NPUs.
In the HSTU_V1 version, we implement the hstu_dense_forward forward operator as the concrete Ascend NPU implementation of the HSTU fused operator. The following table compares its features with NV HSTU_V3.
| Feature | Functionality | ASCEND HSTU_V1 (Atlas A2/A3 Ascend950PR/DT) | NV HSTU_V3 (hopper, Ada, Ampere) Releases/v25.11/7492d4b |
Description | |
|---|---|---|---|---|---|
| HSTU forward features | Basic attention functions | Attention mechanism | Supported | Supported | Implements the core part of HSTU attention. S = Q * KT P = silu(S) O = P * V |
| Multi-head attention (MHA) | Supported | Supported | The number of query heads corresponds one to one with the number of key heads. | ||
| Grouped-query attention (GQA) | Supported | Supported | The number of query heads corresponds to the number of key heads in a many-to-one relationship. | ||
| Variable-length sequence format | Supported | Supported | Implements HSTU attention support for variable-length sequences. | ||
| Floating-point calculation types | Supports FP32, FP16, BF16 | Supports FP16, BF16 | The reference NV HSTU_V3 supports only FP16 and BF16 floating-point types. | ||
| FP8 quantization types | Supports cast |
Supports cast,per-block,per-head,per-batch,per-tensor |
Performs FP8 quantization at the element, block, head, batch, and tensor levels. | ||
| Relative attention bias | Whether rab is passed in |
Supports passing rab,or omitting rab. |
Supports passing rab in [b, n, s, s] format,or omitting rab. |
Implements the relative bias part of HSTU attention. | |
Support for rab broadcasting |
Not supported | Supports passing rab in [b, 1, s, s] format. |
Implements the rab broadcast function. |
||
| Mask | Support no mask | Supported | Supported | Bidirectional mask. | |
| Support causal mask | Supported (context + history + target) | Supported (context + history + target) | The causal mask is built from num_context, num_targets, and target_group_size. Any one of them can be None. For the specific parameter combinations, see the feature analysis. |
||
| Support local mask | Not supported | Supported | Local mask. | ||
| Support arbitrary mask | Not supported | Supported | User-defined mask parameters. | ||
| Page | Support Page feature | Supported | Supported | Used to implement the page HSTU feature of the KV cache. |
Computing Principles

hstu_dense_forward Operator File Structure
-- hstu_dense_forward
|-- c310
|-- op_kernel # Kernel-side implementation of the hstu_dense_forward operator for A5.
|-- run.sh # Installation script for the hstu_dense_forward operator for A5.
|-- onnx_plugin # Supports ONNX model conversion for hstu_dense_forward.
|-- v220
|-- op_host # Host-side implementation of the hstu_dense_forward operator.
|-- op_kernel # Kernel-side implementation of the hstu_dense_forward operator.
|-- pic # Operator implementation diagram.
|-- hstu_dense_forward.json # Operator prototype configuration.
|-- run.sh # Installation script for the hstu_dense_forward operator for A2/A3.
|-- README.md # Operator documentation for hstu_dense_forward.
hstu_dense_forward Forward Inference Inputs and Outputs
| Name | Input/Output | Data Type | Data Format | Range | Description |
|---|---|---|---|---|---|
| q | Input | Tensor[float32/float16/bfloat16] | [B, S, N_q, D]/ [s_b, N, D] |
B∈[1, 2048] S∈[1, 20480] N_q∈[1, 16] D∈[1, 512] |
B: batch_size, indicates the batch size. S: seq_len, indicates the sequence length. N: head_num, indicates the number of heads. D: head_dim, indicates the dimension. s_b is the sum of the actual sequence lengths of each batch in jagged format. |
| k | Input | Tensor[float32/float16/bfloat16] | [B, S, N_k, D]/ [s_b, N, D] |
Same as q | GQA support: The number of K heads can be smaller than the number of Q heads, but N_q must be divisible by N_k. |
| v | Input | Tensor[float32/float16/bfloat16] | [B, S, N_k, D]/ [s_b, N, D] |
B∈[1, 2048] S∈[1, 20480] N_q∈[1, 16] D∈[16, 512] and is a multiple of 16 |
Same as k. |
| mask | Input | Tensor[float32/float16/bfloat16] | [B, N, S, S] | NA | S is the maximum sequence length of the model, max_seq_len.Pass None when you do not use a mask. The type must match q.N must stay consistent with q. |
| attn_bias | Input | Tensor[float32/float16/bfloat16] | [B, N, S, S] | NA | S is the maximum sequence length of the model, max_seq_len.Pass None when you do not use attn_bias. The type must match q.N must stay consistent with q. |
| seq_offsets_q | Input | Tensor[int32_t/int64_t] | [B + 1] | NA | Indicates the actual Q sequence-length offset of each batch, increasing from 0. The user must ensure validity. This takes effect only in jagged format. |
| seq_offsets_k | Input | Tensor[int32_t/int64_t] | [B + 1] | NA | Indicates the actual K sequence-length offset of each batch, increasing from 0. The user must ensure validity. This takes effect only in jagged format. |
| seq_offsets_t | Input | Tensor[int32_t/int64_t] | [B + 1] | NA | Target sequence offset tensor. |
| kv_cache | Input | Tensor[float32/float16/bfloat16] | [num_pages, 2, page_size, N, D] | page_size∈{32, 128, 256} | KV cache tensor used to store historical Key-Value pairs. |
| page_offsets | Input | Tensor[int32_t/int64_t] | [B + 1] | NA | Page offset tensor. |
| page_ids | Input | Tensor[int32_t/int64_t] | [page_offsets[-1]] | NA | Page ID tensor. |
| last_page_len | Input | Tensor[int32_t/int64_t] | [B] | NA | Last page length tensor. |
| num_context | Input | Tensor[int32_t/int64_t] | [B] | The value range is [0, 256]. Other values are not restricted or monitored. | Context count tensor. |
| num_target | Input | Tensor[int32_t/int64_t] | [B] | The value range is [0, 512]. Other values are not restricted or monitored. | Target count tensor. |
| mask_type | Input | int | NA | 0: Use the built-in lower triangular mask. No mask needs to be passed in. 1: Use the built-in upper triangular mask. No mask needs to be passed in. Currently not supported. 2: Do not use a mask. 3: Use a custom mask. In this case, the user must define and pass in the mask. |
NA |
| max_seq_len_q | Input | int | NA | [1, 20480] | Indicates the maximum Q sequence length of the model. |
| max_seq_len_k | Input | int | NA | [1, 20480] | Indicates the maximum K sequence length of the model. |
| silu_scale | Input | float | NA | NA | Supports a user-defined value. If no value is passed in, the default value is 1/max_seq_len. |
| layout | Input | string | NA | "normal": indicates that the data format of q, k, and v is [B, S, N, D]."jagged": indicates that the data format of q, k, and v is [s_b, N, D]. |
NA |
| target_group_size | Input | int | NA | Currently, only {0, 1, 3} is monitored. Other values are not restricted or monitored. |
Used when the built-in target mask is created. When target_group_size is 0, no target mask is created. |
| is_delta_qk | Input | int | NA | NA | Whether the QK sequences have the same length: 0 = same length, 1 = different lengths. |
| alpha | Input | float | NA | NA | Alpha scaling parameter. |
| attn_output | Output | Tensor[float32/float16/bfloat16] | [B, S, N, D]/ [s_b, N, D] |
Same as q | Same as q. |
Note:
- The data in the B, S, N, and D dimensions cannot be 0. If any of them is 0, the operator input is empty and the operator does not run.
- The B, S, and N parameters affect the device memory occupied by bias and mask. Set the parameter values based on actual memory usage.
Operating Environment Dependencies
Hardware Environment
| Hardware Model | Supported |
|---|---|
| Atlas A2 training series products | Yes |
| Atlas A3 training series products | Yes |
| Atlas A5 training series products | Yes |
| Atlas inference series products | Yes |
Software Dependencies
CANN: Ascend CANN toolkit. Ensure that the environment variables are set correctly.
source /usr/local/Ascend/ascend-toolkit/set_env.sh
Currently, two software version pairings are supported: PyTorch 2.6.0 and PyTorch 2.7.1. Before calling the operator, you must install the matching software stack and the required operators. The detailed mappings are as follows:
| Compatible Version | PyTorch | torch-npu | torchrec | fbgemm_gpu | hybrid_torchrec |
|---|---|---|---|---|---|
| 1 | 2.6.0 | 2.6.0 | 1.1.0+npu | 1.1.0 | 1.1.0 |
| 2 | 2.7.1 | 2.7.1 | 1.2.0+npu | 1.2.0 | 1.2.0 |
Single-Operator Usage Instructions
Operator Compilation
Enter the implementation directory of the HSTU_V1 forward operator (cust_op/ascendc_op/ai_core_op/hstu_dense_forward, A5 under c310, A2/A3 under v220) and run the compilation and deployment command. By default, this compiles and installs the AI Core type for Atlas A2 training series products.
If you specify the AI Core type for compilation:
bash run.sh --ai-core ai_core-(soc_version)
Obtain
soc_versionfor the AI processor model as follows:
- Run the
npu-smi infocommand on the server where the Ascend AI processor is installed to query theChip Namefield. The actual configuration value isAscendplus the chip name. For example, ifChip Nameisxxxyy, the actual configuration value isAscendxxxyy.Operator projects created for AI processor models in the same series share the same basic functions for operator development, compilation, and deployment.
Operator Adaptation Layer Compilation
Enter the adaptation layer directory of the HSTU_V1 forward operator (cust_op/framework/torch_plugin/torch_library/hstu) and compile the operator adaptation layer.
bash build_ops.sh
After the command finishes, the xxx.so file is generated in the current build directory. When you call the operator, run the following command to load it.
import torch
torch.ops.load_library("path/to/build/xxx.so") # Replace this with the absolute path of the .so file.
Single-Operator Running Case
import torch
import torch_npu
torch.ops.load_library("path/to/build/xxx.so") # Replace this with the absolute path of the previously generated .so file.
# GQA configuration: 8 Q heads and 2 K/V heads.
batch_size = 2
seq_len = 256
num_heads_q = 8 # Number of Q heads.
num_heads_k = 2 # Number of K/V heads in GQA mode.
head_dim = 64
# Generate data.
q = torch.randn(batch_size * seq_len, num_heads_q, head_dim, dtype=torch.float16).npu()
k = torch.randn(batch_size * seq_len, num_heads_k, head_dim, dtype=torch.float16).npu() # The number of K heads is smaller than the number of Q heads.
v = torch.randn(batch_size * seq_len, num_heads_k, head_dim, dtype=torch.float16).npu() # The number of V heads is equal to the number of K heads.
# Call the operator in jagged format.
seq_offsets_q = torch.tensor([0, 128, 256], dtype=torch.int64).npu()
seq_offsets_k = torch.tensor([0, 128, 256], dtype=torch.int64).npu()
output = torch.ops.mxrec.hstu_jagged(
q=q,
k=k,
v=v,
mask=None,
attn_bias=None,
mask_type=0, # Lower triangular mask.
max_seq_len=256,
max_seq_len_k=256,
silu_scale=1.0/256,
seq_offset=seq_offsets_q,
seq_offset_k=seq_offsets_k
)
# Output shape: [batch_size * seq_len, num_heads_q, head_dim]
print(output.shape) # torch.Size([512, 8, 64])
Note:
- For details about the
hstu_dense_forwardoperator, seecust_op/ascendc_op/ai_core_op/hstu_dense_forward/README.md. - For test cases of the
hstu_dense_forwardoperator, see thecust_op/test/hstu_dense/torchdirectory.