AMCT amct_ops 自定义算子测试实战:从 ops_build.sh 构建到 HiFloat8/HiFloat4 cast 的 NPU 硬件验证
【免费下载链接】amctAMCT是CANN提供的昇腾AI处理器亲和的模型压缩工具仓。项目地址: https://gitcode.com/cann/amct
本文讲解 AMCT 仓库中tests/amct_ops测试套件的完整运行方法:如何用 ops_build.sh 编译 HiFloat4/HiFloat8 cast 与 SVDQuant 等 NPU 算子、以 staging 目录或 wheel 两种方式运行对应 unittest,以及使用 HiFloat8 dtype 冒烟脚本对原生 cast 与amct_opsfallback 路径做确定性硬件验证。读完后你可以独立在昇腾 NPU 机器上完成「构建算子 → 跑测试 → 判定硬件路径是否真正可用」的完整闭环,并理解每个测试背后的验证契约(round-trip 精度、shape/dtype/device 不变量、退出码语义)。
一、前置条件:先构建 amct_ops 算子包
tests/amct_ops中的所有测试都依赖已编译的amct_opsPython 包和算子.so文件,执行测试前必须先构建amct_ops。构建统一由 ops_build.sh 完成:
bash amct_ops/ops_build.sh [<op_name>] # 构建全部算子(默认 ascend910b / A2) bash amct_ops/ops_build.sh hifloat8_cast # 仅构建 hifloat8_cast bash amct_ops/ops_build.sh --soc ascend950 svd_quant # 指定 SOC + 指定算子从脚本实现看,构建流程分为四步:加载 CANN 环境(要求ASCEND_HOME_PATH已设置)、按 SOC 编译各算子、把各算子的 Python 包与.so汇集到amct_ops/staging/目录、最后用pip wheel打包出dist/amct_ops-*.whl。其中两个关键细节直接影响测试环境:
SOC 到 NPU 架构的映射:脚本支持三种 SOC,默认值为
ascend910b(见 ops_build.sh#L61):--soc取值硬件 NPU_ARCH 说明 ascend910b(默认)Ascend A2(910B1/B2/B3) dav-2201对应 x86 下的 A2 机型 ascend910_93Ascend A3(910B4) dav-2201与 A2 共用 ISA,UB 大小由运行时平台 API 区分 ascend950Ascend A5 dav-3510dav-3510 指令集 同时脚本按主机 CPU 架构选择 CANN 包目录:
x86_64/amd64映射到x86_64-linux,aarch64/arm64映射到aarch64-linux,其他架构直接报错退出。SVDQuant 的平台约束:
svd_quant算子只在ascend950上构建——脚本中若目标 SOC 不是ascend950,会打印'svd_quant' operator builds for ascend950 socket only并将其加入跳过列表(见 ops_build.sh#L123-L128)。这意味着在 A2 机器上构建全量算子时,staging 中不会出现svd_quant子包,对应的test_svd_quant也就无法运行。
staging 目录的结构是「一个算子一个子包」:脚本把<op>/python/<pkg>/下的*.py与<op>/build/下编译出的*.so一起拷贝到staging/amct_ops/<pkg>/,并以 ops_init.py 作为包入口__init__.py。按 ops_init.py 的文档,包内可用的子模块包括:
amct_ops.hifloat8_cast:encode_to_hifloat8(x)(FP16/BF16 → uint8)与decode_from_hifloat8(x, dtype=bfloat16)(uint8 → FP16/BF16),也可通过torch.ops.amct.encode_to_hifloat8/torch.ops.amct.decode_from_hifloat8访问;amct_ops.hifloat4_cast:hifloat4_fake_quant(x, qdim=-1),在 NPU 上做 FP16/BF16 → HiFloat4 → FP16/BF16 的 fake-quant 往返,其中 HiFloat4 是 4-bit 块标度浮点,每 64 个元素共享一组 3 级 scale,qdim指定的维度长度必须是 64 的倍数,否则算子抛RuntimeError(见 hifloat4_cast/ops.py)。
二、方式一:使用 staging 运行(推荐开发使用)
开发调试阶段推荐直接指向 staging 目录运行,避免反复安装 wheel。在仓库根目录下执行:
bash amct_ops/ops_build.sh <op_name> PYTHONPATH=amct_ops/staging python3 -m unittest <test_module>其中<op_name>是amct_ops下的算子目录名(如hifloat8_cast、hifloat4_cast、svd_quant),<test_module>是tests.amct_ops下的 unittest 模块名,例如tests.amct_ops.test_hifloat8_cast。
如果算子需要特定 SOC 或其他构建参数,按算子 README 或ops_build.sh --help补充对应参数。SVDQuant 由于仅支持ascend950,运行方式为:
bash amct_ops/ops_build.sh --soc ascend950 svd_quant PYTHONPATH=amct_ops/staging python3 -m unittest tests.amct_ops.test_svd_quant注意 staging 模式下PYTHONPATH=amct_ops/staging这一行环境变量不能省略——unittest 中from amct_ops.hifloat8_cast import ...的导入正是通过这个路径命中的;而tests.amct_ops.test_*的模块名则要求从仓库根目录启动python3 -m unittest,使tests包可被导入(test_svd_quant.py内部通过from .quantize_ref import ...做相对导入,test_svd_quant.py#L16-L17)。
三、方式二:安装 wheel 后运行
需要长期验证或跨目录使用时,可将构建产物安装为正式 wheel:
bash amct_ops/ops_build.sh <op_name> pip install amct_ops/dist/amct_ops-*.whl python3 -m unittest <test_module>SVDQuant 的 wheel 安装示例:
bash amct_ops/ops_build.sh --soc ascend950 svd_quant pip install amct_ops/dist/amct_ops-*.whl python3 -m unittest tests.amct_ops.test_svd_quant安装 wheel 后无需再设置PYTHONPATH,amct_ops作为已安装包直接可导入。两种方式在验证对象上没有差别,差别仅在于算子代码的加载位置(staging 源码目录 vs site-packages)。
四、测试环境要求与典型测试内容
运行测试前需满足以下环境要求:
- 已 source CANN 环境变量,例如
$ASCEND_HOME_PATH/set_env.sh(构建脚本本身也依赖该变量,未设置会直接报错退出,见 ops_build.sh#L104-L113); - 当前环境可用
torch、torch_npu; - 当前机器可访问 NPU,测试会调用
torch.npu.set_device(0)绑定 0 号设备; - 特定算子可能有额外依赖或平台约束,例如
test_svd_quant依赖已构建或已安装的 SVDQuant 自定义算子,且当前构建脚本仅在ascend950SOC 上构建该算子。
从测试代码看,各 unittest 模块验证的重点各有不同:
- test_hifloat8_cast.py:验证
encode_to_hifloat8/decode_from_hifloat8的 dtype 契约(输入仅接受 FP16/BF16,编码输出为 uint8,解码默认回到 bfloat16 且可指定 float16)、基础与随机的 round-trip 相等性、边界值(0.001、0.01、±1、±100 等十余个定点)的误差,以及特殊值编码表(+Inf→0x6F、-Inf→0xEF、NaN→0x80 等,见 test_hifloat8_cast.py#L24-L30)。 - test_hifloat4_cast.py:将 NPU 上的
hifloat4_fake_quant内核与纯 torch 的 CPU 参考实现hifloat4_fake_quant(来自 amct_pytorch/quantization/dtypes/hifp_impl.py)做逐元素对比,容差 1e-6;另含零输入块、非对齐维度抛错、以及 NaN/Inf 块「整块污染为 NaN 且后续 kernel 发射仍正常」的设备健康度回归测试。无 NPU 时该类整体跳过(@unittest.skipUnless(_npu_available(), ...))。 - test_svd_quant.py:使用纯 PyTorch 的 MX4 量化参考 quantize_ref.py(实现 E2M1 组共享指数量化与反量化,含
py_quantize_mx4/py_dequantize_mx4两个 oracle 函数),针对 Prefill/Decode、Rank 32/64/128 组合的大批量矩阵形状用例,验证 SVDQuant 自定义算子的量化结果与参考实现一致。
五、HiFloat8 dtype 冒烟验证
除 unittest 外,run_hifloat8_dtype_smoke.py 提供了一条针对 dtype 层的冒烟验证路径:用固定种子的 FP16/BF16 输入(覆盖零值、正负值、幂次值、边界值如 ±32768 与torch.finfo(dtype).tiny,外加 16 个 seed=2026 的随机数),对以下三条路径做 round-trip 验证:
- torch_npu 的原生 HiFloat8 cast;
amct_ops的hifloat8_castfallback;- 「原生优先、原生失败自动切换 amct_ops」的自动路由(对应 run_hifloat8_dtype_smoke.py#L103-L120 中
_run_backend的 auto 分支)。
三种后端的运行命令:
# 仅验证 torch_npu 原生 HiFloat8 cast python3 tests/amct_ops/run_hifloat8_dtype_smoke.py --backend native # 仅验证 amct_ops hifloat8_cast PYTHONPATH=amct_ops/staging \ python3 tests/amct_ops/run_hifloat8_dtype_smoke.py --backend amct_ops # 原生优先,失败时自动尝试 amct_ops PYTHONPATH=amct_ops/staging \ python3 tests/amct_ops/run_hifloat8_dtype_smoke.py --backend auto可通过--device npu:1指定其他设备(默认npu:0)。脚本对 FP16 与 BF16 各构造一份输入,检查输出 shape 未变、dtype 未变、device 未变、误差有限,输出包含以下契约与指标的 JSON:hardware_path_verified、environment(CANN 路径、设备名、torch/torch_npu/amct_ops 版本)、每条结果的max_abs_error/mean_abs_error等(见 run_hifloat8_dtype_smoke.py#L123-L142)。
退出码语义(与 run_hifloat8_dtype_smoke.py#L192-L221 的实现一致):
- 成功(所有契约通过):退出码
0,JSON 中hardware_path_verified: true; - shape、dtype 或 device 契约失败:退出码
1,hardware_path_verified: false; - 缺少 NPU、
torch_npu、amct_ops或后端执行失败:向 stderr 输出错误 JSON 对象(requested_backend/hardware_path_verified: false/error),以非零状态退出(导入或运行时错误路径返回2)。
最后需要特别强调一条验证边界:仅通过py_compile、--help或 CPU 单元测试不能证明硬件路径可用。在未于真实 NPU 环境执行上述命令之前,原生路径与amct_ops路径都应记录为「硬件路径未验证」(hardware path not validated)——这是该冒烟脚本被设计为「硬件验证判据」而非普通单测的原因。
六、快速核对清单
在实际排障时,可以按以下顺序快速定位问题:
bash amct_ops/ops_build.sh --help或直接查看 ops_build.sh 头部注释,确认 SOC 与主机架构是否在支持范围内;- 检查
amct_ops/staging/amct_ops/下是否同时存在目标子包的*.py和*.so(构建日志第 3 步会打印每个算子收集到的.so数量); - 确认已
source $ASCEND_HOME_PATH/set_env.sh,且torch.npu.is_available()为 True; - 若只跑 HiFloat8 冒烟,优先用
--backend auto观察 JSON 中实际命中的backend字段,再分别用native/amct_ops复现,以区分是原生 cast 还是 fallback 算子的问题; - 中文/英文说明互为对照:中文版见 tests/amct_ops/README.md,本文对应的英文版为 tests/amct_ops/README_en.md。
【免费下载链接】amctAMCT是CANN提供的昇腾AI处理器亲和的模型压缩工具仓。项目地址: https://gitcode.com/cann/amct
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考