- 算子库
- 人工智能
- 深度学习
- Ascend
【免费下载链接】ops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
导读
本指南围绕 CANN ops-transformer 仓库中attention/recurrent_gated_delta_rule算子的 pytest 测试框架展开,它覆盖了该算子在 NPU 上功能验证的完整链路:CPU 侧复现算子逻辑生成 golden 数据、NPU 侧通过 TorchNPU 直调算子、以及两者之间的精度对比。读完本文,你将掌握 single / rdv / random / random_npu / mss 五种测试模式的用法、随机用例生成规则、双层种子复现机制,以及 mssanitizer 设备侧内存检测的接入方式,可直接用于该算子的日常调测与回归验证。
一、框架定位与整体架构
1.1 要解决什么问题
RecurrentGatedDeltaRule(循环门控 Delta 规则,RGDR)是一种应用于线性注意力机制与循环神经网络的算子,在每个时间步根据输入q_t、k_t、v_t与上一隐藏状态S_{t-1}计算输出o_t与新状态S_t(算法公式见 算子 README)。由于计算过程带循环依赖,NPU kernel 的正确性验证不能只靠"跑通",必须逐元素与可靠参照实现比对。该测试框架正是为此设计:
- CPU 侧:复现算子功能用以生成 golden 数据;
- NPU 侧:通过 TorchNPU 进行算子直调获取实际数据;
- 精度对比:进行 CPU 与 NPU 结果的精度对比验证算子功能。
1.2 与算子工程的关系
该测试框架位于算子的tests/pytest/目录,与算子源码同仓管理:
- 算子接口声明:recurrent_gated_delta_rule.h 定义了
l0op::RecurrentGatedDeltaRule的入参顺序(query、key、value、beta、stateRef、actualSeqLengths、ssmStateIndices、g、gk、numAcceptedTokens、scaleValue); - 测试中通过
torch_npu.npu_recurrent_gated_delta_rule(...)以 eager 方式直调该接口(见下文 golden 脚本); - 算子功能、参数表与产品支持情况见 算子 README 及 aclnnRecurrentGatedDeltaRule 文档。
二、当前实现范围:参数约束速查
测试框架当前支持的参数范围如下,这也是所有用例(含随机用例)生成时必须遵守的边界:
| 参数 | 约束 |
|---|---|
| batch_size | 大于 0 |
| mtp | 1 ~ 8 |
| Nk、Nv | ≤ 256,且 Nv ≥ Nk、Nv 需整除 Nk |
| Dk、Dv | ≤ 512 |
| actual_seq_lengths | 长度为 batch_size;数值 ≥ 0 且 ≤ mtp;不指定时默认长度为 batch_size、数值为 mtp 的数组;T = sum(actual_seq_lengths) |
| ssm_state_indices | 长度为 T;数值需小于 block_num;不指定时默认[0,1,...,T-1] |
| block_num | 手动传入,需 ≥ T |
| data_type | BF16 |
| query / key_datarange | 左区间最小 -1,右区间最大 1 |
| gamma / gamma_k_datarange | 右区间最大 0 |
| beta_datarange | 左区间最小 0,右区间最大 1 |
三、环境配置与前置条件
3.1 前置要求
- 安装 TorchNPU 安装包(需及时更换为最新版本),官方安装教程见 Ascend/pytorch;
- 完成环境安装和环境变量配置,具体操作参考仓库根目录的 README。
3.2 custom 包调用
框架支持 custom 包调用方式,即在编译安装好的 CANN 环境上以 custom 算子包形式加载本算子后运行测试。
四、pytest 文件结构与职责
tests/pytest/ ├── test_run.sh # 执行脚本(五种模式入口) ├── conftest.py # pytest 钩子:逐用例记录参数/结果/精度/种子,会话结束落 CSV ├── recurrent_gated_delta_rule_golden.py # CPU 侧 golden 实现 + CPU/NPU 精度对比 ├── pytest.ini # pytest 基础配置 ├── test_recurrent_gated_delta_rule_single.py # 单用例运行主程序(参数化入口) ├── recurrent_gated_delta_rule_operator_single.py# CPU 侧算子逻辑 + NPU 算子直调封装 ├── test_recurrent_gated_delta_rule_paramset.py # 单用例入参配置 └── test_recurrent_gated_delta_rule_paramset_rdv.py # RDV 测试入参配置各文件职责如下:
- test_run.sh:shell 执行入口,根据第一个参数分发到 single / rdv / random / random_npu / mss 分支,自动创建
output/目录、生成时间戳日志与 CSV 路径,并通过tee保存屏显; - conftest.py:两条核心钩子。
_set_tensor_seed夹具在每条用例前固定torch与torch.npu的随机种子(TORCH_SEED指定则用指定值,否则自动生成并回写);pytest_runtest_makereport逐用例采集结果、入参、精度 PctRlt、错误信息,pytest_sessionfinish在会话结束写入 CSV; - recurrent_gated_delta_rule_golden.py:包含 CPU golden 实现
cpu_recurrent_gated_delta_rule、数据生成器rand_range、精度对比函数check_result以及 eager 直调封装run_recurrent_gated_delta_rule_eager; - test_recurrent_gated_delta_rule_single.py:定义
param_names与随机参数生成器_generate_random_param_dict,用@pytest.mark.ci+@pytest.mark.parametrize将用例参数化执行; - pytest.ini:基础 pytest 配置(
log_format = %(message)s),标记ci由主程序文件中的@pytest.mark.ci使用。
4.1 主流程代码骨架
执行链路为:test_run.sh设置TEST_MODE与CSV_FILE→test_recurrent_gated_delta_rule_single.py根据模式构建参数组合 →recurrent_gated_delta_rule_operator_single.output_operator解包参数 →run_recurrent_gated_delta_rule_eager依次完成参数校验、数据生成、CPU golden、NPU 直调与精度断言。核心直调代码如下:
npu_out = torch_npu.npu_recurrent_gated_delta_rule( query, key, value, init_state, beta=beta, scale=scale_value, actual_seq_lengths=act_seq_len, ssm_state_indices=ssm_state_indices, num_accepted_tokens=num_accepted_tokens, g=g, gk=gk, )五、五种测试模式与使用方法
在tests/pytest/目录下执行test_run.sh,不同参数对应不同模式。
5.1 单用例调测(single)
- 手动配置 test_recurrent_gated_delta_rule_paramset.py 中的参数(文件内置
Testcase0、Testcase1两组,通过ENABLED_PARAMS启用); - 执行:
bash test_run.sh single5.2 RDV 测试(rdv)
RDV 模式使用 test_recurrent_gated_delta_rule_paramset_rdv.py 中预定义的参数池ENABLED_PARAMS_RDV,覆盖 batch_size × mtp × dk × dv 组合、nk/nv 比例矩阵、大 shape(如 dk=dv=512)以及 state 为 fp32 / 非连续(non-contiguous)的变体,适用于批量回归:
bash test_run.sh rdv从源码看,rdv 参数池由GROUP_1~GROUP_6与L0_L1_CASES拼接而成,并通过_gen_fp32_state_cases、_gen_non_contiguous_state_cases派生 state 数据类型与内存布局的交叉组合,最终用例规模为_ALL_BF16_CASES × 4。
5.3 随机用例测试(random)
随机生成 N 条用例并执行(含 CPU golden 精度对比),可用RANDOM_SEED环境变量固定随机种子复现(不指定则自动生成并记录到 CSV):
bash test_run.sh random 1005.4 随机用例测试(仅 NPU,random_npu)
随机生成 N 条用例,设置SKIP_GOLDEN=1跳过 CPU golden 计算与精度对比,仅执行 NPU 算子。由于输入张量直接在 NPU 上生成,host 内存占用低,执行速度更快:
bash test_run.sh random_npu 1005.5 mssanitizer 检测(mss)
随机生成 N 条用例,仅 NPU 执行(不跑 golden),并在 mssanitizer 下运行,检测设备侧内存越界、非法地址访问等问题。屏显含====== ERROR即判定 FAIL(脚本退出码为 1)。默认只检测本算子 kernel(--kernel-name=RecurrentGatedDeltaRule),跳过 ZerosLike/ViewCopy/TensorMove/rand 等旁路 kernel 的检测开销:
bash test_run.sh mss 10mssanitizer 安装(前置条件):
- 官方快速入门文档:mssanitizer 快速入门;
- CANN 工具包已自带时无需额外安装(如
/home/developer/Ascend/cann-9.2.0/bin/mssanitizer,确保其所在目录在 PATH 中); - 未自带时源码编译安装:
git clone https://gitcode.com/Ascend/mssanitizer.git cd mssanitizer python3 build.py # 编译完成后安装 run 包 artifacts/mindstudio-sanitizer_26.0.0_x86_64.run --run --install-path=/home/developer/Ascend/mss 模式环境变量定制:
MSS_TOOL=racecheck bash test_run.sh mss 10 # 换检测工具(memcheck/racecheck/initcheck/synccheck) MSS_KERNEL='' bash test_run.sh mss 10 # 关闭kernel过滤,检测全部kernel MSS_EXTRA_OPTS='--leak-check=yes --full-backtrace=yes' bash test_run.sh mss 10 # 追加mssanitizer参数 MSSANITIZER_BIN=/path/to/mssanitizer bash test_run.sh mss 10 # 指定mssanitizer路径从 test_run.sh 源码看,mss 模式还有两个值得关注的实现细节:_mss_preflight前置校验会先跑 1 条用例确认 mssanitizer 真正拦截到 kernel(日志中出现[mssanitizer] Start...sanitizer on kernel),否则直接中止,避免"检测无效但显示通过"的假象;MSS_BATCH分批模式下每批使用seed+i独立种子重启 mssanitizer,避免 host 内存累积,CSV/log 追加写入单一文件。
六、随机用例生成规则
random / random_npu / mss 三种模式共用同一套随机参数生成器_generate_random_param_dict(见 test_recurrent_gated_delta_rule_single.py),在算子约束内从 0 随机生成,不依赖 single/rdv 参数池。每条用例的入参生成规则如下(按算子接口入参顺序):
| 接口入参 | 随机规则 | 约束/说明 |
|---|---|---|
| query (T, Nk, Dk) | T=B×mtp, Nk=randint(1,256), Dk=randint(1,min(512,budget)) | dtype 固定 bf16 |
| key (T, Nk, Dk) | 复用 Nk/Dk | datarange 固定 [-1,1] |
| value (T, Nv, Dv) | Nv=Nk×randint(1,256//Nk), Dv=randint(1,min(512,budget//Dk)) | datarange 随机 choice([-10,10], [-1,1]) |
| state (BlockNum, Nv, Dv, Dk) | BlockNum=B×mtp, 复用 Nv/Dv/Dk | dtype 随机 choice(bf16,fp32), datarange [-10,10] |
| beta (T, Nv) | 复用 T/Nv | datarange 固定 [0,1] |
| scale | 1/sqrt(Dk) | 自动计算 |
| actual_seq_lengths (B,) | 默认全 mtp | 不指定时自动生成 |
| ssm_state_indices (T,) | 默认 [0,1,...,T-1] | 不指定时自动生成 |
| num_accepted_tokens (B,) | has_num_accepted_tokens=True 时 randint(1, mtp) | 50%概率启用 |
| g (T, Nv) | has_gamma=True 时生成, datarange choice(4种负值区间) | 50%概率启用, dtype fp32 |
| gk (T, Nv, Dk) | has_gamma_k=True 时生成, datarange choice(4种负值区间) | 50%概率启用, dtype fp32 |
| state_non_contiguous | choice([False, True]) | 50%概率非连续 |
其他固定项:data_type 固定 bfloat16;query/key_datarange 固定 [-1,1];beta_datarange 固定 [0,1];state_datarange 固定 [-10,10]。
shape 约束:0<Nk≤256、0<Nv≤256 且 Nv≥Nk 且 Nv%Nk==0、0<Dk≤512、0<Dv≤512、mtp≤8、BlockNum≥T。
内存约束:Dk×Dv 受 state 元素数上限_STATE_ELEM_CAP=2.0B约束(budget = STATE_ELEM_CAP // (BlockNum × Nv)),防止单进程 host OOM。源码注释给出了估算依据:单 case host 峰值 ≈ baseline(1.6GB) + 10×state 元素字节数(bf16 state 最坏情形下原张量 2E +.to(fp32)4E +.clone()4E = 10E),取 2.0B 时 host 峰值约 21.6GB,不超出 24GB 上限;NPU HBM 远不构成瓶颈。
随机种子机制:
RANDOM_SEED控制 shape/参数序列(一个 seed 对应一组确定的 N 条用例参数);TORCH_SEED控制张量数值(每条用例独立,conftest 自动生成并记 CSV);- 不设
RANDOM_SEED时自动生成并回写os.environ,conftest 落 CSV; - 复现:
RANDOM_SEED=<seed> bash test_run.sh random N(整批复现)或TORCH_SEED=<tensor_seed>配合 CSV 入参(单条数值级复现)。
重复概率:参数空间约 5×10¹⁰(500 亿),10000 条撞车概率 <0.1%,实际不会重复。
七、结果输出与复现
所有模式执行后均输出到output/目录(已 gitignore):
run_<时间戳>.log/mss_<时间戳>.log:完整执行日志(tee 屏显);result_<时间戳>.csv:逐用例结果表,每行一条用例,列含义如下:
| 列 | 说明 |
|---|---|
| random_seed | 随机 shape 序列种子(random 系模式;single/rdv 为固定参数集无此值) |
| tensor_seed | 本条用例张量数值种子(每条独立记录) |
| test_mode | single/rdv/random |
| check_type | precision=带 golden 精度对比 / execution_only=仅 NPU 执行 / execution_only+mss_<tool>=mssanitizer 检测 |
| result | pytest 执行结果(PASSED/FAILED/SKIPPED) |
| mss_check | mssanitizer 检测结论(PASS/FAIL(errors=N)/CRASH),仅 mss 模式由脚本解析日志回填 |
| out_pct_rlt / state_pct_rlt | 输出与 state 的精度达标率 PctRlt 真实值(如 99.999982%),仅 precision 模式记录 |
| batch_size...state_non_contiguous(24 列) | 本条用例全部入参 |
| errmsg | 失败详情(截断 2000 字符) |
关于mss_check回填的实现:由于 mssanitizer 报错时 pytest 仍可能 PASSED,test_run.sh 中的_backfill_mss_check函数会解析日志中====== ERROR块的个数并回填到 CSV 对应列;分批模式下_merge_batch_csvs负责将各批次 CSV 按顺序合并为单一文件。
失败用例复现(两层种子配合 CSV 入参):
# 整批复现(同 shape 序列):CSV 取 random_seed RANDOM_SEED=<random_seed> bash test_run.sh random N # 单条数值级复现(同 shape + 同张量数值):CSV 取入参与 tensor_seed TORCH_SEED=<tensor_seed> bash test_run.sh random 1八、环境变量汇总
| 变量 | 作用 | 适用模式 |
|---|---|---|
| RANDOM_SEED | 固定随机 shape 序列种子(不设则自动生成并记 CSV) | random/random_npu/mss |
| TORCH_SEED | 固定张量数值种子(不设则每条自动生成并记 CSV) | 全部 |
| RANDOM_CASE_COUNT | 随机用例条数(test_run.sh 已透传) | random 系 |
| SKIP_GOLDEN | =1 跳过 CPU golden 与精度对比,仅 NPU 执行 | random_npu/mss |
| CSV_FILE | 指定 CSV 输出路径(test_run.sh 已自动设置) | 全部 |
| CSV_APPEND | =1 时 CSV 追加写入(分批模式自动设置,手动使用需自行管理 header) | 全部 |
| MSS_BATCH | mss 分批大小,每批重启 mssanitizer 避免 host 内存累积(0=不分批) | mss |
| MSS_TOOL | mssanitizer 检测工具(memcheck/racecheck/initcheck/synccheck) | mss |
| MSS_KERNEL | kernel 过滤名(默认 RecurrentGatedDeltaRule,置空检全部) | mss |
| MSS_EXTRA_OPTS | 追加 mssanitizer 参数(如 --leak-check=yes) | mss |
| MSSANITIZER_BIN | mssanitizer 可执行文件路径 | mss |
九、日志与 CSV 自动保存
所有模式均通过tee自动保存屏显到output/目录(已 gitignore):
| 模式 | 日志文件 | CSV 文件 |
|---|---|---|
| single/rdv/random/random_npu | output/run_<timestamp>.log | output/result_<timestamp>.csv |
| mss(单进程) | output/mss_<timestamp>.log | output/result_<timestamp>.csv |
| mss(分批 MSS_BATCH>0) | output/mss_<timestamp>.log(追加) | output/result_<timestamp>.csv(追加) |
十、精度对比实现要点
golden 侧精度对比的核心是 recurrent_gated_delta_rule_golden.py 中的check_result函数,其判定策略可归纳为三层:
- 达标率门槛:使用
np.isclose(rtol, atol, equal_nan=True)逐元素比对,统计PctRlt = 通过元素数 / 总数 × 100%,默认pct_thd=0.005(即允许 0.5% 比例不达标); - 误差上限保护:即使达标率满足,若归一化相对误差
max_error >= max_diff_hd(10.0)仍判失败,防止个别元素严重溢出; - 溢出监控:golden 侧出现 inf/nan 时单独上报并计数。
对 bf16 使用rtol=0.0078125, atol=0.0001,其他类型使用rtol=0.005, atol=0.000025;大张量按1<<22分块比对以控制 host 峰值内存。run_recurrent_gated_delta_rule_eager在最后对输出与 state 两个结果分别断言Pass,任一失败即用例失败。
十一、与算子实现的衔接:从测试回看算子语义
测试框架中 golden 的计算流程与 算子 README 中的公式严格对应:每个时间步先对状态施加门控衰减S = S * alpha * alphak,再按 delta 规则更新S = S + (v - S·k) * beta * k^T,最后o = S·q / sqrt(Dk)(cpu_recurrent_gated_delta_rule中q = q * scale_value即对应1/sqrt(d_k)缩放)。state 在测试中以stateRef语义原地更新(npu_state_out = init_state),ssm_state_indices将每个时间步映射到对应状态块,num_accepted_tokens用于从 batch 中已接受 token 位置初始化状态——这些行为均可从测试入参与 golden 实现直接观察到。若需进一步阅读算子侧实现,可参考 op_host 目录 下的 def/infershape/tiling 源文件与 op_kernel 目录 的 kernel 实现。
十二、快速上手指南
- 在仓库根目录完成 README 所述的环境安装与配置,并安装 TorchNPU;
- 首次验证推荐先跑单用例:配置 test_recurrent_gated_delta_rule_paramset.py 后执行
bash test_run.sh single; - 需要批量回归时执行
bash test_run.sh rdv; - 泛化验证用
RANDOM_SEED=<seed> bash test_run.sh random 100,需要快速执行(不做精度对比)用bash test_run.sh random_npu 100; - 内存安全检测在安装 mssanitizer 后执行
bash test_run.sh mss 10,并可用MSS_TOOL/MSS_BATCH等环境变量定制; - 所有结果均自动落盘
output/result_<timestamp>.csv,失败用例按 CSV 中的random_seed与tensor_seed两层种子即可精确复现。
- 算子库
- 人工智能
- 深度学习
- Ascend
【免费下载链接】ops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
相关推荐
CANN SHMEM 算子泛化性测试框架实战指南:基于 pytest 的随机化精度验证方案
CANN SHMEM 算子泛化性测试框架实战指南:基于 pytest 的随机化精度验证方案 本指南完整解析 tests/examples/README.md h
通信高性能计算人工智能CANNAscendCANN ops-transformer FIA 算子 A2/A3 pytest 精度泛化测试框架实战
CANN ops transformer FIA 算子 A2/A3 pytest 精度泛化测试框架实战 本文围绕 ops transformer 仓库中 exp
算子库人工智能深度学习Ascendlightning_indexer 算子 pytest 测试框架实战:CPU Golden 生成、NPU 直调与精度对比全流程解析
lightning_indexer 算子 pytest 测试框架实战:CPU Golden 生成、NPU 直调与精度对比全流程解析 导读 本文以 CANN op
算子库人工智能深度学习Ascend
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考