| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat: svd_quant npu operator implementation Co-authored-by: alexeyvaryzgin<alexey.varyzgin@gmail.com> # message auto-generated for no-merge-commit merge: !159 merge alexeyvaryzgin/svd_quant into master feat: svd_quant npu operator implementation Created-by: alexeyvaryzgin Commit-by: alexeyvaryzgin Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> An SVDQuant operator implementation supported on Ascend David A5. ## 如何测试 <!--描述测试此改动的步骤和前提条件。--> 1. Compile all source code according README.md 2. Install custom operator to CANN according README.md 3. Install PyTorch operator according README.md 4. Execute the test script amct/tests/amct_ops/test_svd_quant.py ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> The README.md file has been updated. ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 代码重构 - [ ] 其他,请描述: See merge request: cann/amct!159 | 1 个月前 | |
新增HiF4-cast 直转工具 Co-authored-by: Zhang Jian<jianmusings@gmail.com> # message auto-generated for no-merge-commit merge: !201 merge jian/hifloat4-cast into master 新增HiF4-cast 直转工具 Created-by: zhangj1an Commit-by: Zhang Jian Merged-by: cann-robot Description: ## Latest Status [13 Aug 2026] Ready for review, CI已通过 --- ## Description <!--Describe your changes in detail, including the reasons for the changes and the methods adopted.--> 本PR希望把HiF4-cast工具集成到AMCT仓库中,需求编号为AR00002U9R。命令行调用、实现细节可以参见 https://gitcode.com/cann/amct/issues/163。 HiF4是一种4比特的层级缩放、块浮点格式。每64个元素为一个块,先用E6M2进行一级缩放,再以8个和4个数字为一组分别算出二、三级微指数,最后每个元素以S1P2表示(1个符号位+2个尾数位),可取{-1.75, -1.5, ... 0, ... 1.5, 1.75}共15个值。细节可参见HiF4技术报告 https://arxiv.org/abs/2602.11287。 ### 主要功能 | 输入 | 路径 | 命令 | 调用链 | 输出 | |---|---|---|---|---| | FP16/BF16 | 伪量化,仅注入HiF4误差,不输出新模型权重 | ptq --quant_dtype hifp --bit_config configs/hifloat4.yaml | fake_quant → hifloat4_fake_quant(NPU kernel / CPU fallback) | 注入HiF4误差,不产出文件 | | FP16/BF16 | 打包,输出HiF4打包字节 | deploy --quant_dtype hifp --granularity block | export_block_deploy → hif4_pack | HiF4 打包字节 | | HiF4 | 解码,输出FP32格式 | deploy --quant_dtype hifp --granularity tensor | convert_state_dict → hif4_unpack | FP32 | 其中,伪量化(BF16/FP16 → HiF4 → BF16/FP16)由NPU伪算子实现;打包和解码由PyTorch实现。打包格式为低位优先,元素0放在低4位,元素1放在高4位。当一个64元素块内出现NaN/+Inf/-Inf时,打包scale byte 0写入0xFF,解码时整块恢复为NaN。 ## Design (设计方案) ### 与开源HiF4仓库对比 本PR的HiF4-cast工具在 https://github.com/global-computing-consortium/HiFloat4 基础上,根据程禹最新的HiF4算子私仓内容,做了以下5点改进,已和程禹对齐。原本的github仓库中的伪量化(BF16/FP16 → HiF4 → BF16/FP16)是由NPU伪算子实现的。 1. 新增了打包函数,由PyTorch实现。存储格式为低位优先,元素 0 放在低 4 bit,元素 1 放在高 4 bit。 2. 在编解码函数中,在把元素除掉块scale,也做完二三级缩放后,在量化成S1P2之前,先做了一次round_to_bf16。 3. 在编解码函数中,当一个64元素块内出现NaN, +Inf, -Inf取值时,打包scale byte 0 写入0xFF, 解码时整块恢复为NaN。 4. 在编解码函数中,当对block max做规约时,从amax(dim=-1),改成了amax(dim=qdim, keepdim=True)。不再需要手动把qdim调整到-1维度。 5. 在伪量化算子中,在host 侧增加了一步处理:将 N 补零pad到 BATCH=512 的整数倍后再调用kernel,kernel不再需要处理当N不符合batch=512的整数的情况。 kernel 输出后裁剪回原长。 ### 适配AMCT仓库 为了将算法接入amct仓库,主要新增/修改以下模块: 1. 新增HiF4伪量化NPU算子文件夹:(amct_ops/hifloat4_cast/) ,做一次FP→HiF4→FP往返仿真。 2. 修改文件,新增HiF4 PyTorch实现的打包、解包、伪算子调度器(amct_pytorch/quantization/dtypes/hifp_impl.py) , 与HiF8并列存放。公开API: - hif4_pack(x) :打包算法, 浮点 → HiF4 uint8字节 - hif4_unpack(scale, value) :解包算法: HiF4 uint8字节 → FP32 - hifloat4_fake_quant(x, qdim=-1) : 伪算子调度器:NPU kernel优先,CPU fallback 内部共用一样的PyTorch算法, hif4_encode / hif4_decode(3级scale + S1P2 golden reference),保证PTQ和deploy路径数值一致。 3. 修改文件,在dtype和带有解码功能的deploy tensorwise函数中注册HiF4格式,(hifp.py、deploy_export.py)。 QuantDequantHifp 已支持 bits=4;convert_state_dict 新增HiF4检测与解码。 ## How to Test <!--Describe the steps and prerequisites for testing this change.--> ### 1. 单元测试 tests/amct_ops/test_hifloat4_cast.py, 里面包括了伪量化算子与golden参考的一致性和异常值处理的测试。 ### 2. CLI端到端的测试 bash # 伪量化:注入HiF4误差(ptq,不产出文件) python -m amct_pytorch.cli.llm.ptq \ --quant_dtype hifp --bit_config amct_pytorch/configs/w4a4.yaml \ --model <IN> --output_dir <OUT> # 打包:输出HiF4字节(deploy blockwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity block \ --model <IN> --output_dir <OUT> # 解码:输出FP32(deploy tensorwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity tensor \ --model <IN> --output_dir <OUT> 可以将模型权重打包又解码的产出和直接做伪量化的产出进行对比,如果达到逐比特一致说明算法正确。 ### 3. 看PPL是否符合预期 用amct仓库内的eval测试,比较BF16, MXFP4, HiF4在wikitext-2数据集上的PPL,看趋势是否符合预期。 <details> <summary> 调用命令</summary> # 1) BF16 baseline —— 不需要 quant_dtype / bit_config / quant_target python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode bf16 \ --seq_len 4096 --output_dir ./outputs # 2) MXFP4 W4A4 python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype mxfp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs # 3) HiF4 W4A4 —— 只改 quant_dtype python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype hifp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs 另外,当与github上的HiF4私仓github.com/ddddwee1/HiFloat-private (commit id: f511fdd)进行对比时,MXFP4的量化应调用hif4_gpu/quant_cy/base/cusrc/extended_quant_cuda.cu 里mx_shared_scale 函数的mxfp4_c725 分支,并且把round_to_decimal的阈值从1.8125改成1.75,就和amct仓库的实现是一致的。 </details> ## Test Result 在量化时,我们选择W4A4, 将模型的mlp和attn-linear部分进行量化,(其中也会量化linear attention)。 用Qwen3.5-9B和wikitext-2数据集,将HiF4在amct上进行了测试,结果与HiF4算子repo里的PPL趋势一致,HiF4的PPL比MXFP4会差0.5。 |量化选项|HiF4算子repo(程禹写的golden reference), 在A100上测试| amct, 该分支,在npu 910C上测试| |---|---|---| |BF16 baseline|8.202739840420143|8.176278114318848| |MXFP4 w4a4|9.664575071762391| 9.502161026000977| |HiF4 w4a4|10.020700353404631| 9.901074409484863| 由于该结果不太符合预期,HiF4并没有比MXFP4有优势,我们另外在下游数据集上进行了测试。结果显示在Qwen3.5-9B上,HiF4的精度比MXFP4好0.6. 作为对比,在Qwen3-8B上,HiF4的精度比MXFP4好1.7。这两个模型的主要差异在于千问3.5-9b的结构是(3层linear attention+1层full attention)x8,而千问3-8b的结构是36层full attention. ### Qwen3.5-9B上,HiF4的精度比MXFP4好0.6 | Dataset / Metric | FP16 | HiF4 (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 55.9 | 55.0 | 54.8 | +0.2 | | arc_easy (acc_norm) | 74.2 | 76.2 | 76.8 | -0.6 | | boolq (acc) | 89.1 | 86.8 | 85.0 | +1.8 | | copa (acc) | 89.0 | 89.0 | 89.0 | 0.0 | | piqa (acc_norm) | 80.1 | 78.8 | 78.2 | +0.6 | | sciq (acc_norm) | 96.0 | 96.2 | 95.3 | +0.9 | | hellaswag (acc_norm) | 78.1 | 76.3 | 74.8 | +1.5 | | **Average** | **80.3** | **79.8** | **79.1** | **+0.6** | 其中表格最后一行,未四舍五入之前的平均值应该是 HiF4 = 79.75,MXFP4 AMCT = 79.11,差值 = +0.64,表格里展示成一位小数就是 +0.6。 ### Qwen3-8B上,HiF4的精度比MXFP4好1.7 | Dataset / Metric | FP16 | (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 56.5 | 52.3 | 52.6 | -0.3 | | arc_easy (acc_norm) | 80.8 | 76.9 | 73.4 | +3.5 | | boolq (acc) | 86.6 | 85.9 | 84.5 | +1.4 | | copa (acc) | 85.0 | 84.0 | 82.0 | +2.0 | | piqa (acc_norm) | 77.7 | 76.3 | 75.2 | +1.0 | | sciq (acc_norm) | 95.6 | 95.8 | 94.3 | +1.5 | | hellaswag (acc_norm) | 75.0 | 73.9 | 71.3 | +2.6 | | **Average** | **79.6** | **77.9** | **76.2** | **+1.7** | 另外我们也将Qwen3.5-9b每一层W4A4量化后的SQNR进行了对比。HiF4在每一层的SQNR都比MXFP4高。 ### Qwen3.5-9B上,对权重作比较时,HiF4所有层的SQNR都优于MXFP4 | Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_a | 21.40 | 18.56 | +2.84 | | linear_attn/in_proj_b | 21.28 | 18.36 | +2.92 | | linear_attn/in_proj_qkv | 21.56 | 18.94 | +2.62 | | linear_attn/in_proj_z | 21.57 | 18.96 | +2.61 | | linear_attn/out_proj | 21.54 | 18.92 | +2.62 | | mlp/down_proj | 21.55 | 18.88 | +2.67 | | mlp/gate_proj | 21.56 | 18.91 | +2.65 | | mlp/up_proj | 21.56 | 18.91 | +2.65 | | self_attn/k_proj | 21.40 | 18.63 | +2.77 | | self_attn/o_proj | 21.51 | 18.88 | +2.63 | | self_attn/q_proj | 21.54 | 18.91 | +2.63 | | self_attn/v_proj | 21.43 | 18.71 | +2.72 | ### Qwen3.5-9B上,对激活作比较时,HiF4所有层的SQNR都优于MXFP4 | Activation / Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_{a,b,qkv,z} | 21.21 | 18.05 | +3.16 | | linear_attn/out_proj | 20.81 | 17.28 | +3.53 | | mlp/down_proj | 20.73 | 17.09 | +3.64 | | mlp/{gate,up}_proj | 20.72 | 17.79 | +2.93 | | self_attn/{q,k,v}_proj | 21.10 | 17.90 | +3.20 | | self_attn/o_proj | 20.72 | 17.21 | +3.51 | <details><summary> 单元测试9项通过 </summary> $ python -m pytest tests/amct_ops/test_hifloat4_cast.py -v tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_bf16 PASSED [ 11%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_fp16 PASSED [ 22%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_padded PASSED [ 33%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_zero_is_nan_free PASSED [ 44%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_2x128 PASSED [ 55%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_3x512 PASSED [ 66%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_1x64 PASSED [ 77%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_2x128 PASSED [ 88%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_3x512 PASSED [100%] ======================== 9 passed, 15 warnings in 1.98s ======================== </details> <details><summary> 以下两种方案达到了逐比特一致:1. NPU 伪算子(hifloat4_fake_quant) 和 2. PyTorch 打包再解包(hif4_pack + hif4_unpack)</summary> 以 Qwen3.5-9B MLP 权重形状(2560×10240, 10240×2560)的合成 BF16 张量在 NPU 上验证: python import torch from amct_pytorch.quantization.dtypes.hifp_impl import hifloat4_fake_quant, hif4_pack, hif4_unpack shapes = [(2560, 10240), (10240, 2560), (2560, 10240)] for M, N in shapes: x = torch.randn(M, N, dtype=torch.bfloat16).npu() npu_out = hifloat4_fake_quant(x).cpu() # NPU AscendC kernel scale, value = hif4_pack(x.cpu()) # CPU 打包 decoded = torch.from_numpy(hif4_unpack(scale, value)).to(torch.bfloat16) diff = (npu_out.to(torch.float32) - decoded.to(torch.float32)).abs().max().item() print(f' [{M}x{N}] diff={diff:.2e}', '✓' if diff < 1e-4 else '✗') 得到了以下输出内容: [2560x10240] diff=0.00e+00 ✓ [10240x2560] diff=0.00e+00 ✓ [2560x10240] diff=0.00e+00 ✓ All bit-identical ✓ </details> ## Documentation Updates <!--If this PR includes documentation updates, please indicate them here. For example: Updated the README.md file.--> 更新了HiF4伪算子的文档,amct_ops/hifloat4_cast/README.md 和 README_en.md。 ## Type Label <!-- [x] indicates selected --> - [ ] Bug fix - [x] New feature - [ ] Performance optimization - [ ] Documentation update - [x] Code refactoring - [ ] Other, please describe: See merge request: cann/amct!201 | 1 个月前 | |
新增HiF4-cast 直转工具 Co-authored-by: Zhang Jian<jianmusings@gmail.com> # message auto-generated for no-merge-commit merge: !201 merge jian/hifloat4-cast into master 新增HiF4-cast 直转工具 Created-by: zhangj1an Commit-by: Zhang Jian Merged-by: cann-robot Description: ## Latest Status [13 Aug 2026] Ready for review, CI已通过 --- ## Description <!--Describe your changes in detail, including the reasons for the changes and the methods adopted.--> 本PR希望把HiF4-cast工具集成到AMCT仓库中,需求编号为AR00002U9R。命令行调用、实现细节可以参见 https://gitcode.com/cann/amct/issues/163。 HiF4是一种4比特的层级缩放、块浮点格式。每64个元素为一个块,先用E6M2进行一级缩放,再以8个和4个数字为一组分别算出二、三级微指数,最后每个元素以S1P2表示(1个符号位+2个尾数位),可取{-1.75, -1.5, ... 0, ... 1.5, 1.75}共15个值。细节可参见HiF4技术报告 https://arxiv.org/abs/2602.11287。 ### 主要功能 | 输入 | 路径 | 命令 | 调用链 | 输出 | |---|---|---|---|---| | FP16/BF16 | 伪量化,仅注入HiF4误差,不输出新模型权重 | ptq --quant_dtype hifp --bit_config configs/hifloat4.yaml | fake_quant → hifloat4_fake_quant(NPU kernel / CPU fallback) | 注入HiF4误差,不产出文件 | | FP16/BF16 | 打包,输出HiF4打包字节 | deploy --quant_dtype hifp --granularity block | export_block_deploy → hif4_pack | HiF4 打包字节 | | HiF4 | 解码,输出FP32格式 | deploy --quant_dtype hifp --granularity tensor | convert_state_dict → hif4_unpack | FP32 | 其中,伪量化(BF16/FP16 → HiF4 → BF16/FP16)由NPU伪算子实现;打包和解码由PyTorch实现。打包格式为低位优先,元素0放在低4位,元素1放在高4位。当一个64元素块内出现NaN/+Inf/-Inf时,打包scale byte 0写入0xFF,解码时整块恢复为NaN。 ## Design (设计方案) ### 与开源HiF4仓库对比 本PR的HiF4-cast工具在 https://github.com/global-computing-consortium/HiFloat4 基础上,根据程禹最新的HiF4算子私仓内容,做了以下5点改进,已和程禹对齐。原本的github仓库中的伪量化(BF16/FP16 → HiF4 → BF16/FP16)是由NPU伪算子实现的。 1. 新增了打包函数,由PyTorch实现。存储格式为低位优先,元素 0 放在低 4 bit,元素 1 放在高 4 bit。 2. 在编解码函数中,在把元素除掉块scale,也做完二三级缩放后,在量化成S1P2之前,先做了一次round_to_bf16。 3. 在编解码函数中,当一个64元素块内出现NaN, +Inf, -Inf取值时,打包scale byte 0 写入0xFF, 解码时整块恢复为NaN。 4. 在编解码函数中,当对block max做规约时,从amax(dim=-1),改成了amax(dim=qdim, keepdim=True)。不再需要手动把qdim调整到-1维度。 5. 在伪量化算子中,在host 侧增加了一步处理:将 N 补零pad到 BATCH=512 的整数倍后再调用kernel,kernel不再需要处理当N不符合batch=512的整数的情况。 kernel 输出后裁剪回原长。 ### 适配AMCT仓库 为了将算法接入amct仓库,主要新增/修改以下模块: 1. 新增HiF4伪量化NPU算子文件夹:(amct_ops/hifloat4_cast/) ,做一次FP→HiF4→FP往返仿真。 2. 修改文件,新增HiF4 PyTorch实现的打包、解包、伪算子调度器(amct_pytorch/quantization/dtypes/hifp_impl.py) , 与HiF8并列存放。公开API: - hif4_pack(x) :打包算法, 浮点 → HiF4 uint8字节 - hif4_unpack(scale, value) :解包算法: HiF4 uint8字节 → FP32 - hifloat4_fake_quant(x, qdim=-1) : 伪算子调度器:NPU kernel优先,CPU fallback 内部共用一样的PyTorch算法, hif4_encode / hif4_decode(3级scale + S1P2 golden reference),保证PTQ和deploy路径数值一致。 3. 修改文件,在dtype和带有解码功能的deploy tensorwise函数中注册HiF4格式,(hifp.py、deploy_export.py)。 QuantDequantHifp 已支持 bits=4;convert_state_dict 新增HiF4检测与解码。 ## How to Test <!--Describe the steps and prerequisites for testing this change.--> ### 1. 单元测试 tests/amct_ops/test_hifloat4_cast.py, 里面包括了伪量化算子与golden参考的一致性和异常值处理的测试。 ### 2. CLI端到端的测试 bash # 伪量化:注入HiF4误差(ptq,不产出文件) python -m amct_pytorch.cli.llm.ptq \ --quant_dtype hifp --bit_config amct_pytorch/configs/w4a4.yaml \ --model <IN> --output_dir <OUT> # 打包:输出HiF4字节(deploy blockwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity block \ --model <IN> --output_dir <OUT> # 解码:输出FP32(deploy tensorwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity tensor \ --model <IN> --output_dir <OUT> 可以将模型权重打包又解码的产出和直接做伪量化的产出进行对比,如果达到逐比特一致说明算法正确。 ### 3. 看PPL是否符合预期 用amct仓库内的eval测试,比较BF16, MXFP4, HiF4在wikitext-2数据集上的PPL,看趋势是否符合预期。 <details> <summary> 调用命令</summary> # 1) BF16 baseline —— 不需要 quant_dtype / bit_config / quant_target python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode bf16 \ --seq_len 4096 --output_dir ./outputs # 2) MXFP4 W4A4 python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype mxfp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs # 3) HiF4 W4A4 —— 只改 quant_dtype python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype hifp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs 另外,当与github上的HiF4私仓github.com/ddddwee1/HiFloat-private (commit id: f511fdd)进行对比时,MXFP4的量化应调用hif4_gpu/quant_cy/base/cusrc/extended_quant_cuda.cu 里mx_shared_scale 函数的mxfp4_c725 分支,并且把round_to_decimal的阈值从1.8125改成1.75,就和amct仓库的实现是一致的。 </details> ## Test Result 在量化时,我们选择W4A4, 将模型的mlp和attn-linear部分进行量化,(其中也会量化linear attention)。 用Qwen3.5-9B和wikitext-2数据集,将HiF4在amct上进行了测试,结果与HiF4算子repo里的PPL趋势一致,HiF4的PPL比MXFP4会差0.5。 |量化选项|HiF4算子repo(程禹写的golden reference), 在A100上测试| amct, 该分支,在npu 910C上测试| |---|---|---| |BF16 baseline|8.202739840420143|8.176278114318848| |MXFP4 w4a4|9.664575071762391| 9.502161026000977| |HiF4 w4a4|10.020700353404631| 9.901074409484863| 由于该结果不太符合预期,HiF4并没有比MXFP4有优势,我们另外在下游数据集上进行了测试。结果显示在Qwen3.5-9B上,HiF4的精度比MXFP4好0.6. 作为对比,在Qwen3-8B上,HiF4的精度比MXFP4好1.7。这两个模型的主要差异在于千问3.5-9b的结构是(3层linear attention+1层full attention)x8,而千问3-8b的结构是36层full attention. ### Qwen3.5-9B上,HiF4的精度比MXFP4好0.6 | Dataset / Metric | FP16 | HiF4 (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 55.9 | 55.0 | 54.8 | +0.2 | | arc_easy (acc_norm) | 74.2 | 76.2 | 76.8 | -0.6 | | boolq (acc) | 89.1 | 86.8 | 85.0 | +1.8 | | copa (acc) | 89.0 | 89.0 | 89.0 | 0.0 | | piqa (acc_norm) | 80.1 | 78.8 | 78.2 | +0.6 | | sciq (acc_norm) | 96.0 | 96.2 | 95.3 | +0.9 | | hellaswag (acc_norm) | 78.1 | 76.3 | 74.8 | +1.5 | | **Average** | **80.3** | **79.8** | **79.1** | **+0.6** | 其中表格最后一行,未四舍五入之前的平均值应该是 HiF4 = 79.75,MXFP4 AMCT = 79.11,差值 = +0.64,表格里展示成一位小数就是 +0.6。 ### Qwen3-8B上,HiF4的精度比MXFP4好1.7 | Dataset / Metric | FP16 | (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 56.5 | 52.3 | 52.6 | -0.3 | | arc_easy (acc_norm) | 80.8 | 76.9 | 73.4 | +3.5 | | boolq (acc) | 86.6 | 85.9 | 84.5 | +1.4 | | copa (acc) | 85.0 | 84.0 | 82.0 | +2.0 | | piqa (acc_norm) | 77.7 | 76.3 | 75.2 | +1.0 | | sciq (acc_norm) | 95.6 | 95.8 | 94.3 | +1.5 | | hellaswag (acc_norm) | 75.0 | 73.9 | 71.3 | +2.6 | | **Average** | **79.6** | **77.9** | **76.2** | **+1.7** | 另外我们也将Qwen3.5-9b每一层W4A4量化后的SQNR进行了对比。HiF4在每一层的SQNR都比MXFP4高。 ### Qwen3.5-9B上,对权重作比较时,HiF4所有层的SQNR都优于MXFP4 | Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_a | 21.40 | 18.56 | +2.84 | | linear_attn/in_proj_b | 21.28 | 18.36 | +2.92 | | linear_attn/in_proj_qkv | 21.56 | 18.94 | +2.62 | | linear_attn/in_proj_z | 21.57 | 18.96 | +2.61 | | linear_attn/out_proj | 21.54 | 18.92 | +2.62 | | mlp/down_proj | 21.55 | 18.88 | +2.67 | | mlp/gate_proj | 21.56 | 18.91 | +2.65 | | mlp/up_proj | 21.56 | 18.91 | +2.65 | | self_attn/k_proj | 21.40 | 18.63 | +2.77 | | self_attn/o_proj | 21.51 | 18.88 | +2.63 | | self_attn/q_proj | 21.54 | 18.91 | +2.63 | | self_attn/v_proj | 21.43 | 18.71 | +2.72 | ### Qwen3.5-9B上,对激活作比较时,HiF4所有层的SQNR都优于MXFP4 | Activation / Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_{a,b,qkv,z} | 21.21 | 18.05 | +3.16 | | linear_attn/out_proj | 20.81 | 17.28 | +3.53 | | mlp/down_proj | 20.73 | 17.09 | +3.64 | | mlp/{gate,up}_proj | 20.72 | 17.79 | +2.93 | | self_attn/{q,k,v}_proj | 21.10 | 17.90 | +3.20 | | self_attn/o_proj | 20.72 | 17.21 | +3.51 | <details><summary> 单元测试9项通过 </summary> $ python -m pytest tests/amct_ops/test_hifloat4_cast.py -v tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_bf16 PASSED [ 11%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_fp16 PASSED [ 22%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_padded PASSED [ 33%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_zero_is_nan_free PASSED [ 44%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_2x128 PASSED [ 55%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_3x512 PASSED [ 66%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_1x64 PASSED [ 77%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_2x128 PASSED [ 88%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_3x512 PASSED [100%] ======================== 9 passed, 15 warnings in 1.98s ======================== </details> <details><summary> 以下两种方案达到了逐比特一致:1. NPU 伪算子(hifloat4_fake_quant) 和 2. PyTorch 打包再解包(hif4_pack + hif4_unpack)</summary> 以 Qwen3.5-9B MLP 权重形状(2560×10240, 10240×2560)的合成 BF16 张量在 NPU 上验证: python import torch from amct_pytorch.quantization.dtypes.hifp_impl import hifloat4_fake_quant, hif4_pack, hif4_unpack shapes = [(2560, 10240), (10240, 2560), (2560, 10240)] for M, N in shapes: x = torch.randn(M, N, dtype=torch.bfloat16).npu() npu_out = hifloat4_fake_quant(x).cpu() # NPU AscendC kernel scale, value = hif4_pack(x.cpu()) # CPU 打包 decoded = torch.from_numpy(hif4_unpack(scale, value)).to(torch.bfloat16) diff = (npu_out.to(torch.float32) - decoded.to(torch.float32)).abs().max().item() print(f' [{M}x{N}] diff={diff:.2e}', '✓' if diff < 1e-4 else '✗') 得到了以下输出内容: [2560x10240] diff=0.00e+00 ✓ [10240x2560] diff=0.00e+00 ✓ [2560x10240] diff=0.00e+00 ✓ All bit-identical ✓ </details> ## Documentation Updates <!--If this PR includes documentation updates, please indicate them here. For example: Updated the README.md file.--> 更新了HiF4伪算子的文档,amct_ops/hifloat4_cast/README.md 和 README_en.md。 ## Type Label <!-- [x] indicates selected --> - [ ] Bug fix - [x] New feature - [ ] Performance optimization - [ ] Documentation update - [x] Code refactoring - [ ] Other, please describe: See merge request: cann/amct!201 | 1 个月前 | |
feat: svd_quant npu operator implementation Co-authored-by: alexeyvaryzgin<alexey.varyzgin@gmail.com> # message auto-generated for no-merge-commit merge: !159 merge alexeyvaryzgin/svd_quant into master feat: svd_quant npu operator implementation Created-by: alexeyvaryzgin Commit-by: alexeyvaryzgin Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> An SVDQuant operator implementation supported on Ascend David A5. ## 如何测试 <!--描述测试此改动的步骤和前提条件。--> 1. Compile all source code according README.md 2. Install custom operator to CANN according README.md 3. Install PyTorch operator according README.md 4. Execute the test script amct/tests/amct_ops/test_svd_quant.py ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> The README.md file has been updated. ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 代码重构 - [ ] 其他,请描述: See merge request: cann/amct!159 | 1 个月前 | |
feat: svd_quant npu operator implementation Co-authored-by: alexeyvaryzgin<alexey.varyzgin@gmail.com> # message auto-generated for no-merge-commit merge: !159 merge alexeyvaryzgin/svd_quant into master feat: svd_quant npu operator implementation Created-by: alexeyvaryzgin Commit-by: alexeyvaryzgin Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> An SVDQuant operator implementation supported on Ascend David A5. ## 如何测试 <!--描述测试此改动的步骤和前提条件。--> 1. Compile all source code according README.md 2. Install custom operator to CANN according README.md 3. Install PyTorch operator according README.md 4. Execute the test script amct/tests/amct_ops/test_svd_quant.py ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> The README.md file has been updated. ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 代码重构 - [ ] 其他,请描述: See merge request: cann/amct!159 | 1 个月前 | |
新增HiF4-cast 直转工具 Co-authored-by: Zhang Jian<jianmusings@gmail.com> # message auto-generated for no-merge-commit merge: !201 merge jian/hifloat4-cast into master 新增HiF4-cast 直转工具 Created-by: zhangj1an Commit-by: Zhang Jian Merged-by: cann-robot Description: ## Latest Status [13 Aug 2026] Ready for review, CI已通过 --- ## Description <!--Describe your changes in detail, including the reasons for the changes and the methods adopted.--> 本PR希望把HiF4-cast工具集成到AMCT仓库中,需求编号为AR00002U9R。命令行调用、实现细节可以参见 https://gitcode.com/cann/amct/issues/163。 HiF4是一种4比特的层级缩放、块浮点格式。每64个元素为一个块,先用E6M2进行一级缩放,再以8个和4个数字为一组分别算出二、三级微指数,最后每个元素以S1P2表示(1个符号位+2个尾数位),可取{-1.75, -1.5, ... 0, ... 1.5, 1.75}共15个值。细节可参见HiF4技术报告 https://arxiv.org/abs/2602.11287。 ### 主要功能 | 输入 | 路径 | 命令 | 调用链 | 输出 | |---|---|---|---|---| | FP16/BF16 | 伪量化,仅注入HiF4误差,不输出新模型权重 | ptq --quant_dtype hifp --bit_config configs/hifloat4.yaml | fake_quant → hifloat4_fake_quant(NPU kernel / CPU fallback) | 注入HiF4误差,不产出文件 | | FP16/BF16 | 打包,输出HiF4打包字节 | deploy --quant_dtype hifp --granularity block | export_block_deploy → hif4_pack | HiF4 打包字节 | | HiF4 | 解码,输出FP32格式 | deploy --quant_dtype hifp --granularity tensor | convert_state_dict → hif4_unpack | FP32 | 其中,伪量化(BF16/FP16 → HiF4 → BF16/FP16)由NPU伪算子实现;打包和解码由PyTorch实现。打包格式为低位优先,元素0放在低4位,元素1放在高4位。当一个64元素块内出现NaN/+Inf/-Inf时,打包scale byte 0写入0xFF,解码时整块恢复为NaN。 ## Design (设计方案) ### 与开源HiF4仓库对比 本PR的HiF4-cast工具在 https://github.com/global-computing-consortium/HiFloat4 基础上,根据程禹最新的HiF4算子私仓内容,做了以下5点改进,已和程禹对齐。原本的github仓库中的伪量化(BF16/FP16 → HiF4 → BF16/FP16)是由NPU伪算子实现的。 1. 新增了打包函数,由PyTorch实现。存储格式为低位优先,元素 0 放在低 4 bit,元素 1 放在高 4 bit。 2. 在编解码函数中,在把元素除掉块scale,也做完二三级缩放后,在量化成S1P2之前,先做了一次round_to_bf16。 3. 在编解码函数中,当一个64元素块内出现NaN, +Inf, -Inf取值时,打包scale byte 0 写入0xFF, 解码时整块恢复为NaN。 4. 在编解码函数中,当对block max做规约时,从amax(dim=-1),改成了amax(dim=qdim, keepdim=True)。不再需要手动把qdim调整到-1维度。 5. 在伪量化算子中,在host 侧增加了一步处理:将 N 补零pad到 BATCH=512 的整数倍后再调用kernel,kernel不再需要处理当N不符合batch=512的整数的情况。 kernel 输出后裁剪回原长。 ### 适配AMCT仓库 为了将算法接入amct仓库,主要新增/修改以下模块: 1. 新增HiF4伪量化NPU算子文件夹:(amct_ops/hifloat4_cast/) ,做一次FP→HiF4→FP往返仿真。 2. 修改文件,新增HiF4 PyTorch实现的打包、解包、伪算子调度器(amct_pytorch/quantization/dtypes/hifp_impl.py) , 与HiF8并列存放。公开API: - hif4_pack(x) :打包算法, 浮点 → HiF4 uint8字节 - hif4_unpack(scale, value) :解包算法: HiF4 uint8字节 → FP32 - hifloat4_fake_quant(x, qdim=-1) : 伪算子调度器:NPU kernel优先,CPU fallback 内部共用一样的PyTorch算法, hif4_encode / hif4_decode(3级scale + S1P2 golden reference),保证PTQ和deploy路径数值一致。 3. 修改文件,在dtype和带有解码功能的deploy tensorwise函数中注册HiF4格式,(hifp.py、deploy_export.py)。 QuantDequantHifp 已支持 bits=4;convert_state_dict 新增HiF4检测与解码。 ## How to Test <!--Describe the steps and prerequisites for testing this change.--> ### 1. 单元测试 tests/amct_ops/test_hifloat4_cast.py, 里面包括了伪量化算子与golden参考的一致性和异常值处理的测试。 ### 2. CLI端到端的测试 bash # 伪量化:注入HiF4误差(ptq,不产出文件) python -m amct_pytorch.cli.llm.ptq \ --quant_dtype hifp --bit_config amct_pytorch/configs/w4a4.yaml \ --model <IN> --output_dir <OUT> # 打包:输出HiF4字节(deploy blockwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity block \ --model <IN> --output_dir <OUT> # 解码:输出FP32(deploy tensorwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity tensor \ --model <IN> --output_dir <OUT> 可以将模型权重打包又解码的产出和直接做伪量化的产出进行对比,如果达到逐比特一致说明算法正确。 ### 3. 看PPL是否符合预期 用amct仓库内的eval测试,比较BF16, MXFP4, HiF4在wikitext-2数据集上的PPL,看趋势是否符合预期。 <details> <summary> 调用命令</summary> # 1) BF16 baseline —— 不需要 quant_dtype / bit_config / quant_target python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode bf16 \ --seq_len 4096 --output_dir ./outputs # 2) MXFP4 W4A4 python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype mxfp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs # 3) HiF4 W4A4 —— 只改 quant_dtype python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype hifp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs 另外,当与github上的HiF4私仓github.com/ddddwee1/HiFloat-private (commit id: f511fdd)进行对比时,MXFP4的量化应调用hif4_gpu/quant_cy/base/cusrc/extended_quant_cuda.cu 里mx_shared_scale 函数的mxfp4_c725 分支,并且把round_to_decimal的阈值从1.8125改成1.75,就和amct仓库的实现是一致的。 </details> ## Test Result 在量化时,我们选择W4A4, 将模型的mlp和attn-linear部分进行量化,(其中也会量化linear attention)。 用Qwen3.5-9B和wikitext-2数据集,将HiF4在amct上进行了测试,结果与HiF4算子repo里的PPL趋势一致,HiF4的PPL比MXFP4会差0.5。 |量化选项|HiF4算子repo(程禹写的golden reference), 在A100上测试| amct, 该分支,在npu 910C上测试| |---|---|---| |BF16 baseline|8.202739840420143|8.176278114318848| |MXFP4 w4a4|9.664575071762391| 9.502161026000977| |HiF4 w4a4|10.020700353404631| 9.901074409484863| 由于该结果不太符合预期,HiF4并没有比MXFP4有优势,我们另外在下游数据集上进行了测试。结果显示在Qwen3.5-9B上,HiF4的精度比MXFP4好0.6. 作为对比,在Qwen3-8B上,HiF4的精度比MXFP4好1.7。这两个模型的主要差异在于千问3.5-9b的结构是(3层linear attention+1层full attention)x8,而千问3-8b的结构是36层full attention. ### Qwen3.5-9B上,HiF4的精度比MXFP4好0.6 | Dataset / Metric | FP16 | HiF4 (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 55.9 | 55.0 | 54.8 | +0.2 | | arc_easy (acc_norm) | 74.2 | 76.2 | 76.8 | -0.6 | | boolq (acc) | 89.1 | 86.8 | 85.0 | +1.8 | | copa (acc) | 89.0 | 89.0 | 89.0 | 0.0 | | piqa (acc_norm) | 80.1 | 78.8 | 78.2 | +0.6 | | sciq (acc_norm) | 96.0 | 96.2 | 95.3 | +0.9 | | hellaswag (acc_norm) | 78.1 | 76.3 | 74.8 | +1.5 | | **Average** | **80.3** | **79.8** | **79.1** | **+0.6** | 其中表格最后一行,未四舍五入之前的平均值应该是 HiF4 = 79.75,MXFP4 AMCT = 79.11,差值 = +0.64,表格里展示成一位小数就是 +0.6。 ### Qwen3-8B上,HiF4的精度比MXFP4好1.7 | Dataset / Metric | FP16 | (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 56.5 | 52.3 | 52.6 | -0.3 | | arc_easy (acc_norm) | 80.8 | 76.9 | 73.4 | +3.5 | | boolq (acc) | 86.6 | 85.9 | 84.5 | +1.4 | | copa (acc) | 85.0 | 84.0 | 82.0 | +2.0 | | piqa (acc_norm) | 77.7 | 76.3 | 75.2 | +1.0 | | sciq (acc_norm) | 95.6 | 95.8 | 94.3 | +1.5 | | hellaswag (acc_norm) | 75.0 | 73.9 | 71.3 | +2.6 | | **Average** | **79.6** | **77.9** | **76.2** | **+1.7** | 另外我们也将Qwen3.5-9b每一层W4A4量化后的SQNR进行了对比。HiF4在每一层的SQNR都比MXFP4高。 ### Qwen3.5-9B上,对权重作比较时,HiF4所有层的SQNR都优于MXFP4 | Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_a | 21.40 | 18.56 | +2.84 | | linear_attn/in_proj_b | 21.28 | 18.36 | +2.92 | | linear_attn/in_proj_qkv | 21.56 | 18.94 | +2.62 | | linear_attn/in_proj_z | 21.57 | 18.96 | +2.61 | | linear_attn/out_proj | 21.54 | 18.92 | +2.62 | | mlp/down_proj | 21.55 | 18.88 | +2.67 | | mlp/gate_proj | 21.56 | 18.91 | +2.65 | | mlp/up_proj | 21.56 | 18.91 | +2.65 | | self_attn/k_proj | 21.40 | 18.63 | +2.77 | | self_attn/o_proj | 21.51 | 18.88 | +2.63 | | self_attn/q_proj | 21.54 | 18.91 | +2.63 | | self_attn/v_proj | 21.43 | 18.71 | +2.72 | ### Qwen3.5-9B上,对激活作比较时,HiF4所有层的SQNR都优于MXFP4 | Activation / Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_{a,b,qkv,z} | 21.21 | 18.05 | +3.16 | | linear_attn/out_proj | 20.81 | 17.28 | +3.53 | | mlp/down_proj | 20.73 | 17.09 | +3.64 | | mlp/{gate,up}_proj | 20.72 | 17.79 | +2.93 | | self_attn/{q,k,v}_proj | 21.10 | 17.90 | +3.20 | | self_attn/o_proj | 20.72 | 17.21 | +3.51 | <details><summary> 单元测试9项通过 </summary> $ python -m pytest tests/amct_ops/test_hifloat4_cast.py -v tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_bf16 PASSED [ 11%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_fp16 PASSED [ 22%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_padded PASSED [ 33%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_zero_is_nan_free PASSED [ 44%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_2x128 PASSED [ 55%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_3x512 PASSED [ 66%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_1x64 PASSED [ 77%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_2x128 PASSED [ 88%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_3x512 PASSED [100%] ======================== 9 passed, 15 warnings in 1.98s ======================== </details> <details><summary> 以下两种方案达到了逐比特一致:1. NPU 伪算子(hifloat4_fake_quant) 和 2. PyTorch 打包再解包(hif4_pack + hif4_unpack)</summary> 以 Qwen3.5-9B MLP 权重形状(2560×10240, 10240×2560)的合成 BF16 张量在 NPU 上验证: python import torch from amct_pytorch.quantization.dtypes.hifp_impl import hifloat4_fake_quant, hif4_pack, hif4_unpack shapes = [(2560, 10240), (10240, 2560), (2560, 10240)] for M, N in shapes: x = torch.randn(M, N, dtype=torch.bfloat16).npu() npu_out = hifloat4_fake_quant(x).cpu() # NPU AscendC kernel scale, value = hif4_pack(x.cpu()) # CPU 打包 decoded = torch.from_numpy(hif4_unpack(scale, value)).to(torch.bfloat16) diff = (npu_out.to(torch.float32) - decoded.to(torch.float32)).abs().max().item() print(f' [{M}x{N}] diff={diff:.2e}', '✓' if diff < 1e-4 else '✗') 得到了以下输出内容: [2560x10240] diff=0.00e+00 ✓ [10240x2560] diff=0.00e+00 ✓ [2560x10240] diff=0.00e+00 ✓ All bit-identical ✓ </details> ## Documentation Updates <!--If this PR includes documentation updates, please indicate them here. For example: Updated the README.md file.--> 更新了HiF4伪算子的文档,amct_ops/hifloat4_cast/README.md 和 README_en.md。 ## Type Label <!-- [x] indicates selected --> - [ ] Bug fix - [x] New feature - [ ] Performance optimization - [ ] Documentation update - [x] Code refactoring - [ ] Other, please describe: See merge request: cann/amct!201 | 1 个月前 | |
新增HiF4-cast 直转工具 Co-authored-by: Zhang Jian<jianmusings@gmail.com> # message auto-generated for no-merge-commit merge: !201 merge jian/hifloat4-cast into master 新增HiF4-cast 直转工具 Created-by: zhangj1an Commit-by: Zhang Jian Merged-by: cann-robot Description: ## Latest Status [13 Aug 2026] Ready for review, CI已通过 --- ## Description <!--Describe your changes in detail, including the reasons for the changes and the methods adopted.--> 本PR希望把HiF4-cast工具集成到AMCT仓库中,需求编号为AR00002U9R。命令行调用、实现细节可以参见 https://gitcode.com/cann/amct/issues/163。 HiF4是一种4比特的层级缩放、块浮点格式。每64个元素为一个块,先用E6M2进行一级缩放,再以8个和4个数字为一组分别算出二、三级微指数,最后每个元素以S1P2表示(1个符号位+2个尾数位),可取{-1.75, -1.5, ... 0, ... 1.5, 1.75}共15个值。细节可参见HiF4技术报告 https://arxiv.org/abs/2602.11287。 ### 主要功能 | 输入 | 路径 | 命令 | 调用链 | 输出 | |---|---|---|---|---| | FP16/BF16 | 伪量化,仅注入HiF4误差,不输出新模型权重 | ptq --quant_dtype hifp --bit_config configs/hifloat4.yaml | fake_quant → hifloat4_fake_quant(NPU kernel / CPU fallback) | 注入HiF4误差,不产出文件 | | FP16/BF16 | 打包,输出HiF4打包字节 | deploy --quant_dtype hifp --granularity block | export_block_deploy → hif4_pack | HiF4 打包字节 | | HiF4 | 解码,输出FP32格式 | deploy --quant_dtype hifp --granularity tensor | convert_state_dict → hif4_unpack | FP32 | 其中,伪量化(BF16/FP16 → HiF4 → BF16/FP16)由NPU伪算子实现;打包和解码由PyTorch实现。打包格式为低位优先,元素0放在低4位,元素1放在高4位。当一个64元素块内出现NaN/+Inf/-Inf时,打包scale byte 0写入0xFF,解码时整块恢复为NaN。 ## Design (设计方案) ### 与开源HiF4仓库对比 本PR的HiF4-cast工具在 https://github.com/global-computing-consortium/HiFloat4 基础上,根据程禹最新的HiF4算子私仓内容,做了以下5点改进,已和程禹对齐。原本的github仓库中的伪量化(BF16/FP16 → HiF4 → BF16/FP16)是由NPU伪算子实现的。 1. 新增了打包函数,由PyTorch实现。存储格式为低位优先,元素 0 放在低 4 bit,元素 1 放在高 4 bit。 2. 在编解码函数中,在把元素除掉块scale,也做完二三级缩放后,在量化成S1P2之前,先做了一次round_to_bf16。 3. 在编解码函数中,当一个64元素块内出现NaN, +Inf, -Inf取值时,打包scale byte 0 写入0xFF, 解码时整块恢复为NaN。 4. 在编解码函数中,当对block max做规约时,从amax(dim=-1),改成了amax(dim=qdim, keepdim=True)。不再需要手动把qdim调整到-1维度。 5. 在伪量化算子中,在host 侧增加了一步处理:将 N 补零pad到 BATCH=512 的整数倍后再调用kernel,kernel不再需要处理当N不符合batch=512的整数的情况。 kernel 输出后裁剪回原长。 ### 适配AMCT仓库 为了将算法接入amct仓库,主要新增/修改以下模块: 1. 新增HiF4伪量化NPU算子文件夹:(amct_ops/hifloat4_cast/) ,做一次FP→HiF4→FP往返仿真。 2. 修改文件,新增HiF4 PyTorch实现的打包、解包、伪算子调度器(amct_pytorch/quantization/dtypes/hifp_impl.py) , 与HiF8并列存放。公开API: - hif4_pack(x) :打包算法, 浮点 → HiF4 uint8字节 - hif4_unpack(scale, value) :解包算法: HiF4 uint8字节 → FP32 - hifloat4_fake_quant(x, qdim=-1) : 伪算子调度器:NPU kernel优先,CPU fallback 内部共用一样的PyTorch算法, hif4_encode / hif4_decode(3级scale + S1P2 golden reference),保证PTQ和deploy路径数值一致。 3. 修改文件,在dtype和带有解码功能的deploy tensorwise函数中注册HiF4格式,(hifp.py、deploy_export.py)。 QuantDequantHifp 已支持 bits=4;convert_state_dict 新增HiF4检测与解码。 ## How to Test <!--Describe the steps and prerequisites for testing this change.--> ### 1. 单元测试 tests/amct_ops/test_hifloat4_cast.py, 里面包括了伪量化算子与golden参考的一致性和异常值处理的测试。 ### 2. CLI端到端的测试 bash # 伪量化:注入HiF4误差(ptq,不产出文件) python -m amct_pytorch.cli.llm.ptq \ --quant_dtype hifp --bit_config amct_pytorch/configs/w4a4.yaml \ --model <IN> --output_dir <OUT> # 打包:输出HiF4字节(deploy blockwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity block \ --model <IN> --output_dir <OUT> # 解码:输出FP32(deploy tensorwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity tensor \ --model <IN> --output_dir <OUT> 可以将模型权重打包又解码的产出和直接做伪量化的产出进行对比,如果达到逐比特一致说明算法正确。 ### 3. 看PPL是否符合预期 用amct仓库内的eval测试,比较BF16, MXFP4, HiF4在wikitext-2数据集上的PPL,看趋势是否符合预期。 <details> <summary> 调用命令</summary> # 1) BF16 baseline —— 不需要 quant_dtype / bit_config / quant_target python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode bf16 \ --seq_len 4096 --output_dir ./outputs # 2) MXFP4 W4A4 python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype mxfp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs # 3) HiF4 W4A4 —— 只改 quant_dtype python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype hifp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs 另外,当与github上的HiF4私仓github.com/ddddwee1/HiFloat-private (commit id: f511fdd)进行对比时,MXFP4的量化应调用hif4_gpu/quant_cy/base/cusrc/extended_quant_cuda.cu 里mx_shared_scale 函数的mxfp4_c725 分支,并且把round_to_decimal的阈值从1.8125改成1.75,就和amct仓库的实现是一致的。 </details> ## Test Result 在量化时,我们选择W4A4, 将模型的mlp和attn-linear部分进行量化,(其中也会量化linear attention)。 用Qwen3.5-9B和wikitext-2数据集,将HiF4在amct上进行了测试,结果与HiF4算子repo里的PPL趋势一致,HiF4的PPL比MXFP4会差0.5。 |量化选项|HiF4算子repo(程禹写的golden reference), 在A100上测试| amct, 该分支,在npu 910C上测试| |---|---|---| |BF16 baseline|8.202739840420143|8.176278114318848| |MXFP4 w4a4|9.664575071762391| 9.502161026000977| |HiF4 w4a4|10.020700353404631| 9.901074409484863| 由于该结果不太符合预期,HiF4并没有比MXFP4有优势,我们另外在下游数据集上进行了测试。结果显示在Qwen3.5-9B上,HiF4的精度比MXFP4好0.6. 作为对比,在Qwen3-8B上,HiF4的精度比MXFP4好1.7。这两个模型的主要差异在于千问3.5-9b的结构是(3层linear attention+1层full attention)x8,而千问3-8b的结构是36层full attention. ### Qwen3.5-9B上,HiF4的精度比MXFP4好0.6 | Dataset / Metric | FP16 | HiF4 (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 55.9 | 55.0 | 54.8 | +0.2 | | arc_easy (acc_norm) | 74.2 | 76.2 | 76.8 | -0.6 | | boolq (acc) | 89.1 | 86.8 | 85.0 | +1.8 | | copa (acc) | 89.0 | 89.0 | 89.0 | 0.0 | | piqa (acc_norm) | 80.1 | 78.8 | 78.2 | +0.6 | | sciq (acc_norm) | 96.0 | 96.2 | 95.3 | +0.9 | | hellaswag (acc_norm) | 78.1 | 76.3 | 74.8 | +1.5 | | **Average** | **80.3** | **79.8** | **79.1** | **+0.6** | 其中表格最后一行,未四舍五入之前的平均值应该是 HiF4 = 79.75,MXFP4 AMCT = 79.11,差值 = +0.64,表格里展示成一位小数就是 +0.6。 ### Qwen3-8B上,HiF4的精度比MXFP4好1.7 | Dataset / Metric | FP16 | (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 56.5 | 52.3 | 52.6 | -0.3 | | arc_easy (acc_norm) | 80.8 | 76.9 | 73.4 | +3.5 | | boolq (acc) | 86.6 | 85.9 | 84.5 | +1.4 | | copa (acc) | 85.0 | 84.0 | 82.0 | +2.0 | | piqa (acc_norm) | 77.7 | 76.3 | 75.2 | +1.0 | | sciq (acc_norm) | 95.6 | 95.8 | 94.3 | +1.5 | | hellaswag (acc_norm) | 75.0 | 73.9 | 71.3 | +2.6 | | **Average** | **79.6** | **77.9** | **76.2** | **+1.7** | 另外我们也将Qwen3.5-9b每一层W4A4量化后的SQNR进行了对比。HiF4在每一层的SQNR都比MXFP4高。 ### Qwen3.5-9B上,对权重作比较时,HiF4所有层的SQNR都优于MXFP4 | Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_a | 21.40 | 18.56 | +2.84 | | linear_attn/in_proj_b | 21.28 | 18.36 | +2.92 | | linear_attn/in_proj_qkv | 21.56 | 18.94 | +2.62 | | linear_attn/in_proj_z | 21.57 | 18.96 | +2.61 | | linear_attn/out_proj | 21.54 | 18.92 | +2.62 | | mlp/down_proj | 21.55 | 18.88 | +2.67 | | mlp/gate_proj | 21.56 | 18.91 | +2.65 | | mlp/up_proj | 21.56 | 18.91 | +2.65 | | self_attn/k_proj | 21.40 | 18.63 | +2.77 | | self_attn/o_proj | 21.51 | 18.88 | +2.63 | | self_attn/q_proj | 21.54 | 18.91 | +2.63 | | self_attn/v_proj | 21.43 | 18.71 | +2.72 | ### Qwen3.5-9B上,对激活作比较时,HiF4所有层的SQNR都优于MXFP4 | Activation / Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_{a,b,qkv,z} | 21.21 | 18.05 | +3.16 | | linear_attn/out_proj | 20.81 | 17.28 | +3.53 | | mlp/down_proj | 20.73 | 17.09 | +3.64 | | mlp/{gate,up}_proj | 20.72 | 17.79 | +2.93 | | self_attn/{q,k,v}_proj | 21.10 | 17.90 | +3.20 | | self_attn/o_proj | 20.72 | 17.21 | +3.51 | <details><summary> 单元测试9项通过 </summary> $ python -m pytest tests/amct_ops/test_hifloat4_cast.py -v tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_bf16 PASSED [ 11%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_fp16 PASSED [ 22%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_padded PASSED [ 33%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_zero_is_nan_free PASSED [ 44%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_2x128 PASSED [ 55%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_3x512 PASSED [ 66%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_1x64 PASSED [ 77%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_2x128 PASSED [ 88%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_3x512 PASSED [100%] ======================== 9 passed, 15 warnings in 1.98s ======================== </details> <details><summary> 以下两种方案达到了逐比特一致:1. NPU 伪算子(hifloat4_fake_quant) 和 2. PyTorch 打包再解包(hif4_pack + hif4_unpack)</summary> 以 Qwen3.5-9B MLP 权重形状(2560×10240, 10240×2560)的合成 BF16 张量在 NPU 上验证: python import torch from amct_pytorch.quantization.dtypes.hifp_impl import hifloat4_fake_quant, hif4_pack, hif4_unpack shapes = [(2560, 10240), (10240, 2560), (2560, 10240)] for M, N in shapes: x = torch.randn(M, N, dtype=torch.bfloat16).npu() npu_out = hifloat4_fake_quant(x).cpu() # NPU AscendC kernel scale, value = hif4_pack(x.cpu()) # CPU 打包 decoded = torch.from_numpy(hif4_unpack(scale, value)).to(torch.bfloat16) diff = (npu_out.to(torch.float32) - decoded.to(torch.float32)).abs().max().item() print(f' [{M}x{N}] diff={diff:.2e}', '✓' if diff < 1e-4 else '✗') 得到了以下输出内容: [2560x10240] diff=0.00e+00 ✓ [10240x2560] diff=0.00e+00 ✓ [2560x10240] diff=0.00e+00 ✓ All bit-identical ✓ </details> ## Documentation Updates <!--If this PR includes documentation updates, please indicate them here. For example: Updated the README.md file.--> 更新了HiF4伪算子的文档,amct_ops/hifloat4_cast/README.md 和 README_en.md。 ## Type Label <!-- [x] indicates selected --> - [ ] Bug fix - [x] New feature - [ ] Performance optimization - [ ] Documentation update - [x] Code refactoring - [ ] Other, please describe: See merge request: cann/amct!201 | 1 个月前 | |
feat: svd_quant npu operator implementation Co-authored-by: alexeyvaryzgin<alexey.varyzgin@gmail.com> # message auto-generated for no-merge-commit merge: !159 merge alexeyvaryzgin/svd_quant into master feat: svd_quant npu operator implementation Created-by: alexeyvaryzgin Commit-by: alexeyvaryzgin Merged-by: cann-robot Description: ## 描述 <!--在这里详细描述你的改动,包括改动的原因和所采取的方法。--> An SVDQuant operator implementation supported on Ascend David A5. ## 如何测试 <!--描述测试此改动的步骤和前提条件。--> 1. Compile all source code according README.md 2. Install custom operator to CANN according README.md 3. Install PyTorch operator according README.md 4. Execute the test script amct/tests/amct_ops/test_svd_quant.py ## 文档更新 <!--如果这个PR包含文档的更新,请在这里指出。例如:更新了README.md文件。--> The README.md file has been updated. ## 类型标签 <!-- [x] 表示选中 --> - [ ] Bug修复 - [x] 新特性 - [ ] 性能优化 - [ ] 文档更新 - [ ] 代码重构 - [ ] 其他,请描述: See merge request: cann/amct!159 | 1 个月前 | |
新增HiF4-cast 直转工具 Co-authored-by: Zhang Jian<jianmusings@gmail.com> # message auto-generated for no-merge-commit merge: !201 merge jian/hifloat4-cast into master 新增HiF4-cast 直转工具 Created-by: zhangj1an Commit-by: Zhang Jian Merged-by: cann-robot Description: ## Latest Status [13 Aug 2026] Ready for review, CI已通过 --- ## Description <!--Describe your changes in detail, including the reasons for the changes and the methods adopted.--> 本PR希望把HiF4-cast工具集成到AMCT仓库中,需求编号为AR00002U9R。命令行调用、实现细节可以参见 https://gitcode.com/cann/amct/issues/163。 HiF4是一种4比特的层级缩放、块浮点格式。每64个元素为一个块,先用E6M2进行一级缩放,再以8个和4个数字为一组分别算出二、三级微指数,最后每个元素以S1P2表示(1个符号位+2个尾数位),可取{-1.75, -1.5, ... 0, ... 1.5, 1.75}共15个值。细节可参见HiF4技术报告 https://arxiv.org/abs/2602.11287。 ### 主要功能 | 输入 | 路径 | 命令 | 调用链 | 输出 | |---|---|---|---|---| | FP16/BF16 | 伪量化,仅注入HiF4误差,不输出新模型权重 | ptq --quant_dtype hifp --bit_config configs/hifloat4.yaml | fake_quant → hifloat4_fake_quant(NPU kernel / CPU fallback) | 注入HiF4误差,不产出文件 | | FP16/BF16 | 打包,输出HiF4打包字节 | deploy --quant_dtype hifp --granularity block | export_block_deploy → hif4_pack | HiF4 打包字节 | | HiF4 | 解码,输出FP32格式 | deploy --quant_dtype hifp --granularity tensor | convert_state_dict → hif4_unpack | FP32 | 其中,伪量化(BF16/FP16 → HiF4 → BF16/FP16)由NPU伪算子实现;打包和解码由PyTorch实现。打包格式为低位优先,元素0放在低4位,元素1放在高4位。当一个64元素块内出现NaN/+Inf/-Inf时,打包scale byte 0写入0xFF,解码时整块恢复为NaN。 ## Design (设计方案) ### 与开源HiF4仓库对比 本PR的HiF4-cast工具在 https://github.com/global-computing-consortium/HiFloat4 基础上,根据程禹最新的HiF4算子私仓内容,做了以下5点改进,已和程禹对齐。原本的github仓库中的伪量化(BF16/FP16 → HiF4 → BF16/FP16)是由NPU伪算子实现的。 1. 新增了打包函数,由PyTorch实现。存储格式为低位优先,元素 0 放在低 4 bit,元素 1 放在高 4 bit。 2. 在编解码函数中,在把元素除掉块scale,也做完二三级缩放后,在量化成S1P2之前,先做了一次round_to_bf16。 3. 在编解码函数中,当一个64元素块内出现NaN, +Inf, -Inf取值时,打包scale byte 0 写入0xFF, 解码时整块恢复为NaN。 4. 在编解码函数中,当对block max做规约时,从amax(dim=-1),改成了amax(dim=qdim, keepdim=True)。不再需要手动把qdim调整到-1维度。 5. 在伪量化算子中,在host 侧增加了一步处理:将 N 补零pad到 BATCH=512 的整数倍后再调用kernel,kernel不再需要处理当N不符合batch=512的整数的情况。 kernel 输出后裁剪回原长。 ### 适配AMCT仓库 为了将算法接入amct仓库,主要新增/修改以下模块: 1. 新增HiF4伪量化NPU算子文件夹:(amct_ops/hifloat4_cast/) ,做一次FP→HiF4→FP往返仿真。 2. 修改文件,新增HiF4 PyTorch实现的打包、解包、伪算子调度器(amct_pytorch/quantization/dtypes/hifp_impl.py) , 与HiF8并列存放。公开API: - hif4_pack(x) :打包算法, 浮点 → HiF4 uint8字节 - hif4_unpack(scale, value) :解包算法: HiF4 uint8字节 → FP32 - hifloat4_fake_quant(x, qdim=-1) : 伪算子调度器:NPU kernel优先,CPU fallback 内部共用一样的PyTorch算法, hif4_encode / hif4_decode(3级scale + S1P2 golden reference),保证PTQ和deploy路径数值一致。 3. 修改文件,在dtype和带有解码功能的deploy tensorwise函数中注册HiF4格式,(hifp.py、deploy_export.py)。 QuantDequantHifp 已支持 bits=4;convert_state_dict 新增HiF4检测与解码。 ## How to Test <!--Describe the steps and prerequisites for testing this change.--> ### 1. 单元测试 tests/amct_ops/test_hifloat4_cast.py, 里面包括了伪量化算子与golden参考的一致性和异常值处理的测试。 ### 2. CLI端到端的测试 bash # 伪量化:注入HiF4误差(ptq,不产出文件) python -m amct_pytorch.cli.llm.ptq \ --quant_dtype hifp --bit_config amct_pytorch/configs/w4a4.yaml \ --model <IN> --output_dir <OUT> # 打包:输出HiF4字节(deploy blockwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity block \ --model <IN> --output_dir <OUT> # 解码:输出FP32(deploy tensorwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity tensor \ --model <IN> --output_dir <OUT> 可以将模型权重打包又解码的产出和直接做伪量化的产出进行对比,如果达到逐比特一致说明算法正确。 ### 3. 看PPL是否符合预期 用amct仓库内的eval测试,比较BF16, MXFP4, HiF4在wikitext-2数据集上的PPL,看趋势是否符合预期。 <details> <summary> 调用命令</summary> # 1) BF16 baseline —— 不需要 quant_dtype / bit_config / quant_target python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode bf16 \ --seq_len 4096 --output_dir ./outputs # 2) MXFP4 W4A4 python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype mxfp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs # 3) HiF4 W4A4 —— 只改 quant_dtype python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype hifp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs 另外,当与github上的HiF4私仓github.com/ddddwee1/HiFloat-private (commit id: f511fdd)进行对比时,MXFP4的量化应调用hif4_gpu/quant_cy/base/cusrc/extended_quant_cuda.cu 里mx_shared_scale 函数的mxfp4_c725 分支,并且把round_to_decimal的阈值从1.8125改成1.75,就和amct仓库的实现是一致的。 </details> ## Test Result 在量化时,我们选择W4A4, 将模型的mlp和attn-linear部分进行量化,(其中也会量化linear attention)。 用Qwen3.5-9B和wikitext-2数据集,将HiF4在amct上进行了测试,结果与HiF4算子repo里的PPL趋势一致,HiF4的PPL比MXFP4会差0.5。 |量化选项|HiF4算子repo(程禹写的golden reference), 在A100上测试| amct, 该分支,在npu 910C上测试| |---|---|---| |BF16 baseline|8.202739840420143|8.176278114318848| |MXFP4 w4a4|9.664575071762391| 9.502161026000977| |HiF4 w4a4|10.020700353404631| 9.901074409484863| 由于该结果不太符合预期,HiF4并没有比MXFP4有优势,我们另外在下游数据集上进行了测试。结果显示在Qwen3.5-9B上,HiF4的精度比MXFP4好0.6. 作为对比,在Qwen3-8B上,HiF4的精度比MXFP4好1.7。这两个模型的主要差异在于千问3.5-9b的结构是(3层linear attention+1层full attention)x8,而千问3-8b的结构是36层full attention. ### Qwen3.5-9B上,HiF4的精度比MXFP4好0.6 | Dataset / Metric | FP16 | HiF4 (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 55.9 | 55.0 | 54.8 | +0.2 | | arc_easy (acc_norm) | 74.2 | 76.2 | 76.8 | -0.6 | | boolq (acc) | 89.1 | 86.8 | 85.0 | +1.8 | | copa (acc) | 89.0 | 89.0 | 89.0 | 0.0 | | piqa (acc_norm) | 80.1 | 78.8 | 78.2 | +0.6 | | sciq (acc_norm) | 96.0 | 96.2 | 95.3 | +0.9 | | hellaswag (acc_norm) | 78.1 | 76.3 | 74.8 | +1.5 | | **Average** | **80.3** | **79.8** | **79.1** | **+0.6** | 其中表格最后一行,未四舍五入之前的平均值应该是 HiF4 = 79.75,MXFP4 AMCT = 79.11,差值 = +0.64,表格里展示成一位小数就是 +0.6。 ### Qwen3-8B上,HiF4的精度比MXFP4好1.7 | Dataset / Metric | FP16 | (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 56.5 | 52.3 | 52.6 | -0.3 | | arc_easy (acc_norm) | 80.8 | 76.9 | 73.4 | +3.5 | | boolq (acc) | 86.6 | 85.9 | 84.5 | +1.4 | | copa (acc) | 85.0 | 84.0 | 82.0 | +2.0 | | piqa (acc_norm) | 77.7 | 76.3 | 75.2 | +1.0 | | sciq (acc_norm) | 95.6 | 95.8 | 94.3 | +1.5 | | hellaswag (acc_norm) | 75.0 | 73.9 | 71.3 | +2.6 | | **Average** | **79.6** | **77.9** | **76.2** | **+1.7** | 另外我们也将Qwen3.5-9b每一层W4A4量化后的SQNR进行了对比。HiF4在每一层的SQNR都比MXFP4高。 ### Qwen3.5-9B上,对权重作比较时,HiF4所有层的SQNR都优于MXFP4 | Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_a | 21.40 | 18.56 | +2.84 | | linear_attn/in_proj_b | 21.28 | 18.36 | +2.92 | | linear_attn/in_proj_qkv | 21.56 | 18.94 | +2.62 | | linear_attn/in_proj_z | 21.57 | 18.96 | +2.61 | | linear_attn/out_proj | 21.54 | 18.92 | +2.62 | | mlp/down_proj | 21.55 | 18.88 | +2.67 | | mlp/gate_proj | 21.56 | 18.91 | +2.65 | | mlp/up_proj | 21.56 | 18.91 | +2.65 | | self_attn/k_proj | 21.40 | 18.63 | +2.77 | | self_attn/o_proj | 21.51 | 18.88 | +2.63 | | self_attn/q_proj | 21.54 | 18.91 | +2.63 | | self_attn/v_proj | 21.43 | 18.71 | +2.72 | ### Qwen3.5-9B上,对激活作比较时,HiF4所有层的SQNR都优于MXFP4 | Activation / Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_{a,b,qkv,z} | 21.21 | 18.05 | +3.16 | | linear_attn/out_proj | 20.81 | 17.28 | +3.53 | | mlp/down_proj | 20.73 | 17.09 | +3.64 | | mlp/{gate,up}_proj | 20.72 | 17.79 | +2.93 | | self_attn/{q,k,v}_proj | 21.10 | 17.90 | +3.20 | | self_attn/o_proj | 20.72 | 17.21 | +3.51 | <details><summary> 单元测试9项通过 </summary> $ python -m pytest tests/amct_ops/test_hifloat4_cast.py -v tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_bf16 PASSED [ 11%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_fp16 PASSED [ 22%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_padded PASSED [ 33%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_zero_is_nan_free PASSED [ 44%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_2x128 PASSED [ 55%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_3x512 PASSED [ 66%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_1x64 PASSED [ 77%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_2x128 PASSED [ 88%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_3x512 PASSED [100%] ======================== 9 passed, 15 warnings in 1.98s ======================== </details> <details><summary> 以下两种方案达到了逐比特一致:1. NPU 伪算子(hifloat4_fake_quant) 和 2. PyTorch 打包再解包(hif4_pack + hif4_unpack)</summary> 以 Qwen3.5-9B MLP 权重形状(2560×10240, 10240×2560)的合成 BF16 张量在 NPU 上验证: python import torch from amct_pytorch.quantization.dtypes.hifp_impl import hifloat4_fake_quant, hif4_pack, hif4_unpack shapes = [(2560, 10240), (10240, 2560), (2560, 10240)] for M, N in shapes: x = torch.randn(M, N, dtype=torch.bfloat16).npu() npu_out = hifloat4_fake_quant(x).cpu() # NPU AscendC kernel scale, value = hif4_pack(x.cpu()) # CPU 打包 decoded = torch.from_numpy(hif4_unpack(scale, value)).to(torch.bfloat16) diff = (npu_out.to(torch.float32) - decoded.to(torch.float32)).abs().max().item() print(f' [{M}x{N}] diff={diff:.2e}', '✓' if diff < 1e-4 else '✗') 得到了以下输出内容: [2560x10240] diff=0.00e+00 ✓ [10240x2560] diff=0.00e+00 ✓ [2560x10240] diff=0.00e+00 ✓ All bit-identical ✓ </details> ## Documentation Updates <!--If this PR includes documentation updates, please indicate them here. For example: Updated the README.md file.--> 更新了HiF4伪算子的文档,amct_ops/hifloat4_cast/README.md 和 README_en.md。 ## Type Label <!-- [x] indicates selected --> - [ ] Bug fix - [x] New feature - [ ] Performance optimization - [ ] Documentation update - [x] Code refactoring - [ ] Other, please describe: See merge request: cann/amct!201 | 1 个月前 | |
新增HiF4-cast 直转工具 Co-authored-by: Zhang Jian<jianmusings@gmail.com> # message auto-generated for no-merge-commit merge: !201 merge jian/hifloat4-cast into master 新增HiF4-cast 直转工具 Created-by: zhangj1an Commit-by: Zhang Jian Merged-by: cann-robot Description: ## Latest Status [13 Aug 2026] Ready for review, CI已通过 --- ## Description <!--Describe your changes in detail, including the reasons for the changes and the methods adopted.--> 本PR希望把HiF4-cast工具集成到AMCT仓库中,需求编号为AR00002U9R。命令行调用、实现细节可以参见 https://gitcode.com/cann/amct/issues/163。 HiF4是一种4比特的层级缩放、块浮点格式。每64个元素为一个块,先用E6M2进行一级缩放,再以8个和4个数字为一组分别算出二、三级微指数,最后每个元素以S1P2表示(1个符号位+2个尾数位),可取{-1.75, -1.5, ... 0, ... 1.5, 1.75}共15个值。细节可参见HiF4技术报告 https://arxiv.org/abs/2602.11287。 ### 主要功能 | 输入 | 路径 | 命令 | 调用链 | 输出 | |---|---|---|---|---| | FP16/BF16 | 伪量化,仅注入HiF4误差,不输出新模型权重 | ptq --quant_dtype hifp --bit_config configs/hifloat4.yaml | fake_quant → hifloat4_fake_quant(NPU kernel / CPU fallback) | 注入HiF4误差,不产出文件 | | FP16/BF16 | 打包,输出HiF4打包字节 | deploy --quant_dtype hifp --granularity block | export_block_deploy → hif4_pack | HiF4 打包字节 | | HiF4 | 解码,输出FP32格式 | deploy --quant_dtype hifp --granularity tensor | convert_state_dict → hif4_unpack | FP32 | 其中,伪量化(BF16/FP16 → HiF4 → BF16/FP16)由NPU伪算子实现;打包和解码由PyTorch实现。打包格式为低位优先,元素0放在低4位,元素1放在高4位。当一个64元素块内出现NaN/+Inf/-Inf时,打包scale byte 0写入0xFF,解码时整块恢复为NaN。 ## Design (设计方案) ### 与开源HiF4仓库对比 本PR的HiF4-cast工具在 https://github.com/global-computing-consortium/HiFloat4 基础上,根据程禹最新的HiF4算子私仓内容,做了以下5点改进,已和程禹对齐。原本的github仓库中的伪量化(BF16/FP16 → HiF4 → BF16/FP16)是由NPU伪算子实现的。 1. 新增了打包函数,由PyTorch实现。存储格式为低位优先,元素 0 放在低 4 bit,元素 1 放在高 4 bit。 2. 在编解码函数中,在把元素除掉块scale,也做完二三级缩放后,在量化成S1P2之前,先做了一次round_to_bf16。 3. 在编解码函数中,当一个64元素块内出现NaN, +Inf, -Inf取值时,打包scale byte 0 写入0xFF, 解码时整块恢复为NaN。 4. 在编解码函数中,当对block max做规约时,从amax(dim=-1),改成了amax(dim=qdim, keepdim=True)。不再需要手动把qdim调整到-1维度。 5. 在伪量化算子中,在host 侧增加了一步处理:将 N 补零pad到 BATCH=512 的整数倍后再调用kernel,kernel不再需要处理当N不符合batch=512的整数的情况。 kernel 输出后裁剪回原长。 ### 适配AMCT仓库 为了将算法接入amct仓库,主要新增/修改以下模块: 1. 新增HiF4伪量化NPU算子文件夹:(amct_ops/hifloat4_cast/) ,做一次FP→HiF4→FP往返仿真。 2. 修改文件,新增HiF4 PyTorch实现的打包、解包、伪算子调度器(amct_pytorch/quantization/dtypes/hifp_impl.py) , 与HiF8并列存放。公开API: - hif4_pack(x) :打包算法, 浮点 → HiF4 uint8字节 - hif4_unpack(scale, value) :解包算法: HiF4 uint8字节 → FP32 - hifloat4_fake_quant(x, qdim=-1) : 伪算子调度器:NPU kernel优先,CPU fallback 内部共用一样的PyTorch算法, hif4_encode / hif4_decode(3级scale + S1P2 golden reference),保证PTQ和deploy路径数值一致。 3. 修改文件,在dtype和带有解码功能的deploy tensorwise函数中注册HiF4格式,(hifp.py、deploy_export.py)。 QuantDequantHifp 已支持 bits=4;convert_state_dict 新增HiF4检测与解码。 ## How to Test <!--Describe the steps and prerequisites for testing this change.--> ### 1. 单元测试 tests/amct_ops/test_hifloat4_cast.py, 里面包括了伪量化算子与golden参考的一致性和异常值处理的测试。 ### 2. CLI端到端的测试 bash # 伪量化:注入HiF4误差(ptq,不产出文件) python -m amct_pytorch.cli.llm.ptq \ --quant_dtype hifp --bit_config amct_pytorch/configs/w4a4.yaml \ --model <IN> --output_dir <OUT> # 打包:输出HiF4字节(deploy blockwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity block \ --model <IN> --output_dir <OUT> # 解码:输出FP32(deploy tensorwise) python -m amct_pytorch.cli.llm.deploy \ --quant_dtype hifp --granularity tensor \ --model <IN> --output_dir <OUT> 可以将模型权重打包又解码的产出和直接做伪量化的产出进行对比,如果达到逐比特一致说明算法正确。 ### 3. 看PPL是否符合预期 用amct仓库内的eval测试,比较BF16, MXFP4, HiF4在wikitext-2数据集上的PPL,看趋势是否符合预期。 <details> <summary> 调用命令</summary> # 1) BF16 baseline —— 不需要 quant_dtype / bit_config / quant_target python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode bf16 \ --seq_len 4096 --output_dir ./outputs # 2) MXFP4 W4A4 python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype mxfp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs # 3) HiF4 W4A4 —— 只改 quant_dtype python -m amct_pytorch.eval \ --model $MODEL --model_name Qwen3.5-9B \ --device npu:0 --eval_mode quant \ --quant_dtype hifp \ --bit_config amct_pytorch/configs/w4a4.yaml \ --quant_target mlp attn-linear \ --seq_len 4096 --output_dir ./outputs 另外,当与github上的HiF4私仓github.com/ddddwee1/HiFloat-private (commit id: f511fdd)进行对比时,MXFP4的量化应调用hif4_gpu/quant_cy/base/cusrc/extended_quant_cuda.cu 里mx_shared_scale 函数的mxfp4_c725 分支,并且把round_to_decimal的阈值从1.8125改成1.75,就和amct仓库的实现是一致的。 </details> ## Test Result 在量化时,我们选择W4A4, 将模型的mlp和attn-linear部分进行量化,(其中也会量化linear attention)。 用Qwen3.5-9B和wikitext-2数据集,将HiF4在amct上进行了测试,结果与HiF4算子repo里的PPL趋势一致,HiF4的PPL比MXFP4会差0.5。 |量化选项|HiF4算子repo(程禹写的golden reference), 在A100上测试| amct, 该分支,在npu 910C上测试| |---|---|---| |BF16 baseline|8.202739840420143|8.176278114318848| |MXFP4 w4a4|9.664575071762391| 9.502161026000977| |HiF4 w4a4|10.020700353404631| 9.901074409484863| 由于该结果不太符合预期,HiF4并没有比MXFP4有优势,我们另外在下游数据集上进行了测试。结果显示在Qwen3.5-9B上,HiF4的精度比MXFP4好0.6. 作为对比,在Qwen3-8B上,HiF4的精度比MXFP4好1.7。这两个模型的主要差异在于千问3.5-9b的结构是(3层linear attention+1层full attention)x8,而千问3-8b的结构是36层full attention. ### Qwen3.5-9B上,HiF4的精度比MXFP4好0.6 | Dataset / Metric | FP16 | HiF4 (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 55.9 | 55.0 | 54.8 | +0.2 | | arc_easy (acc_norm) | 74.2 | 76.2 | 76.8 | -0.6 | | boolq (acc) | 89.1 | 86.8 | 85.0 | +1.8 | | copa (acc) | 89.0 | 89.0 | 89.0 | 0.0 | | piqa (acc_norm) | 80.1 | 78.8 | 78.2 | +0.6 | | sciq (acc_norm) | 96.0 | 96.2 | 95.3 | +0.9 | | hellaswag (acc_norm) | 78.1 | 76.3 | 74.8 | +1.5 | | **Average** | **80.3** | **79.8** | **79.1** | **+0.6** | 其中表格最后一行,未四舍五入之前的平均值应该是 HiF4 = 79.75,MXFP4 AMCT = 79.11,差值 = +0.64,表格里展示成一位小数就是 +0.6。 ### Qwen3-8B上,HiF4的精度比MXFP4好1.7 | Dataset / Metric | FP16 | (HiF4算子私仓的版本) | MXFP4 (AMCT实现的版本) | Δ HiF4 - MXFP4 | |---|---:|---:|---:|---:| | arc_challenge (acc_norm) | 56.5 | 52.3 | 52.6 | -0.3 | | arc_easy (acc_norm) | 80.8 | 76.9 | 73.4 | +3.5 | | boolq (acc) | 86.6 | 85.9 | 84.5 | +1.4 | | copa (acc) | 85.0 | 84.0 | 82.0 | +2.0 | | piqa (acc_norm) | 77.7 | 76.3 | 75.2 | +1.0 | | sciq (acc_norm) | 95.6 | 95.8 | 94.3 | +1.5 | | hellaswag (acc_norm) | 75.0 | 73.9 | 71.3 | +2.6 | | **Average** | **79.6** | **77.9** | **76.2** | **+1.7** | 另外我们也将Qwen3.5-9b每一层W4A4量化后的SQNR进行了对比。HiF4在每一层的SQNR都比MXFP4高。 ### Qwen3.5-9B上,对权重作比较时,HiF4所有层的SQNR都优于MXFP4 | Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_a | 21.40 | 18.56 | +2.84 | | linear_attn/in_proj_b | 21.28 | 18.36 | +2.92 | | linear_attn/in_proj_qkv | 21.56 | 18.94 | +2.62 | | linear_attn/in_proj_z | 21.57 | 18.96 | +2.61 | | linear_attn/out_proj | 21.54 | 18.92 | +2.62 | | mlp/down_proj | 21.55 | 18.88 | +2.67 | | mlp/gate_proj | 21.56 | 18.91 | +2.65 | | mlp/up_proj | 21.56 | 18.91 | +2.65 | | self_attn/k_proj | 21.40 | 18.63 | +2.77 | | self_attn/o_proj | 21.51 | 18.88 | +2.63 | | self_attn/q_proj | 21.54 | 18.91 | +2.63 | | self_attn/v_proj | 21.43 | 18.71 | +2.72 | ### Qwen3.5-9B上,对激活作比较时,HiF4所有层的SQNR都优于MXFP4 | Activation / Layer | HiF4 (dB) | MXFP4 (dB) | Δ HiF4 − MXFP4 | |---|---:|---:|---:| | linear_attn/in_proj_{a,b,qkv,z} | 21.21 | 18.05 | +3.16 | | linear_attn/out_proj | 20.81 | 17.28 | +3.53 | | mlp/down_proj | 20.73 | 17.09 | +3.64 | | mlp/{gate,up}_proj | 20.72 | 17.79 | +2.93 | | self_attn/{q,k,v}_proj | 21.10 | 17.90 | +3.20 | | self_attn/o_proj | 20.72 | 17.21 | +3.51 | <details><summary> 单元测试9项通过 </summary> $ python -m pytest tests/amct_ops/test_hifloat4_cast.py -v tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_bf16 PASSED [ 11%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_fp16 PASSED [ 22%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_padded PASSED [ 33%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4Kernel::test_kernel_zero_is_nan_free PASSED [ 44%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_2x128 PASSED [ 55%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_dequant_shape_3x512 PASSED [ 66%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_1x64 PASSED [ 77%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_2x128 PASSED [ 88%] tests/amct_ops/test_hifloat4_cast.py::TestHiFloat4CastShapes::test_packed_shape_3x512 PASSED [100%] ======================== 9 passed, 15 warnings in 1.98s ======================== </details> <details><summary> 以下两种方案达到了逐比特一致:1. NPU 伪算子(hifloat4_fake_quant) 和 2. PyTorch 打包再解包(hif4_pack + hif4_unpack)</summary> 以 Qwen3.5-9B MLP 权重形状(2560×10240, 10240×2560)的合成 BF16 张量在 NPU 上验证: python import torch from amct_pytorch.quantization.dtypes.hifp_impl import hifloat4_fake_quant, hif4_pack, hif4_unpack shapes = [(2560, 10240), (10240, 2560), (2560, 10240)] for M, N in shapes: x = torch.randn(M, N, dtype=torch.bfloat16).npu() npu_out = hifloat4_fake_quant(x).cpu() # NPU AscendC kernel scale, value = hif4_pack(x.cpu()) # CPU 打包 decoded = torch.from_numpy(hif4_unpack(scale, value)).to(torch.bfloat16) diff = (npu_out.to(torch.float32) - decoded.to(torch.float32)).abs().max().item() print(f' [{M}x{N}] diff={diff:.2e}', '✓' if diff < 1e-4 else '✗') 得到了以下输出内容: [2560x10240] diff=0.00e+00 ✓ [10240x2560] diff=0.00e+00 ✓ [2560x10240] diff=0.00e+00 ✓ All bit-identical ✓ </details> ## Documentation Updates <!--If this PR includes documentation updates, please indicate them here. For example: Updated the README.md file.--> 更新了HiF4伪算子的文档,amct_ops/hifloat4_cast/README.md 和 README_en.md。 ## Type Label <!-- [x] indicates selected --> - [ ] Bug fix - [x] New feature - [ ] Performance optimization - [ ] Documentation update - [x] Code refactoring - [ ] Other, please describe: See merge request: cann/amct!201 | 1 个月前 |
amct_ops — AMCT NPU 自定义算子
简介
定位:
amct_ops是 AMCT 的 NPU 自定义算子层,负责承载 PyTorch / torch_npu 尚未覆盖的低比特量化、数据类型转换等硬件级算子。- 与
amct_pytorch/聚焦的量化算法、压缩流程编排不同,amct_ops更贴近底层硬件实现。
独立优势:
- 职责清晰:
amct_pytorch通过 Python 接口或torch.ops.amct调用算子,无需关注 Ascend C kernel、C++ extension、CMake 编译等细节 - 独立开发:算子可按独立模块开发、构建和测试,避免主算法目录混杂 kernel 和构建逻辑
- 灵活扩展:新增低比特类型、量化辅助算子或调整 NPU 实现时,互不干扰
与 amct_pytorch/ 的分工:
| 维度 | amct_pytorch/ |
amct_ops/ |
|---|---|---|
| 关注点 | 压缩算法与流程编排 | 算子底层实现 |
| 语言 | Python | Ascend C kernel & C++ binding & Python 接口 |
| 产物 | .tar.gz 包(源码压缩包) | wheel 包(含 .so & Python 接口) |
| 复用性 | 绑定 AMCT 流程 | 独立的 PyTorch 扩展,不强依赖 AMCT 主流程 |
使用方式:
- 可独立安装的 PyTorch 扩展包(wheel 格式)
- 支持
amct_ops.<op>和torch.ops.amct.<op>两种接口
支持的算子
| 算子 | 说明 | Python 接口 |
|---|---|---|
hifloat8_cast |
FP16 / BF16 ↔ HiFloat8 双向转换 | encode_to_hifloat8(x)decode_from_hifloat8(x, dtype) |
hifloat4_cast |
FP16 / BF16 → HiFloat4 仿真(fake-quant,64 元素块缩放) | hifloat4_fake_quant(x, qdim=-1) |
目录结构
amct_ops/
├── hifloat8_cast/ # HiFloat8 转换算子源码(kernel + binding + Python 接口)
├── hifloat4_cast/ # HiFloat4 FP→HiF4→FP 仿真算子源码(kernel + binding + Python 接口)
├── svd_quant/ # 使用混合Mxfp4/Bf16算子的SVD量化方法
├── ops_build.sh # 统一构建入口
├── setup.py # wheel 打包配置
└── ops_init.py # 打包时复制为 __init__.py,提供包接口和文档
构建过程中会生成 build/、dist/、staging/、<op>/build/ 等目录,这些是本地构建产物,不需要提交。
构建与打包
所有算子通过amct_ops根目录的统一构建脚本一次性编译并打包为 wheel。
依赖要求
| 依赖 | 版本 |
|---|---|
| Python | >=3.9 |
| PyTorch | 2.7.1 或 2.1.0(需配套 torch_npu) |
| GCC / CMake | ≥ 7.3 / ≥ 3.16(推荐 3.20) |
| CANN(Toolkit & Ops) | ≥ 9.0.0(需提前安装 NPU 驱动 / 固件) |
完整环境部署请参见 快速安装
构建命令
cd amct_ops/
bash ops_build.sh [--soc <soc>] [<算子>]
# --soc 指定目标平台(默认 ascend910b):
# ascend910b A2(Ascend 910B1/B2/B3)
# ascend910_93 A3(Ascend 910_93)
# ascend950 A5(Ascend 950,需 CANN 编译器支持 dav-3510)
bash ops_build.sh # 全部算子,默认平台
bash ops_build.sh --soc ascend910_93 # 全部算子,指定平台
bash ops_build.sh hifloat8_cast # 指定算子,默认平台
bash ops_build.sh --soc ascend950 hifloat8_cast # 指定算子,指定平台
构建产物
构建产物位于 dist/amct_ops-1.0.0-cp*-cp*-linux_<arch>.whl,其中 <arch> 随构建主机自动生成为 x86_64 或 aarch64,包含所有算子的 Python 包及编译 .so。
wheel 文件名中的两个 cp* 分别表示 Python 实现/版本标签和 ABI 标签。例如,cp311-cp311 表示该 wheel 面向 CPython 3.11,并依赖 CPython 3.11 ABI;linux_<arch> 表示构建主机平台架构。
安装
pip install dist/amct_ops-*.whl
使用示例
安装后两种导入方式:
# 方式一:模块导入(有 IDE 补全和文档字符串)
from amct_ops.hifloat8_cast import encode_to_hifloat8, decode_from_hifloat8
y = encode_to_hifloat8(x) # FP16/BF16 → uint8
z = decode_from_hifloat8(y) # → bfloat16(默认)
z = decode_from_hifloat8(y, torch.float16) # → float16
# 方式二:torch.ops.amct(与其他 NPU 算子风格一致)
import amct_ops.hifloat8_cast # 触发 .so 加载
torch.ops.amct.encode_to_hifloat8(x)
torch.ops.amct.decode_from_hifloat8(y, torch.float16)
Python 内省
import amct_ops
help(amct_ops) # 查看所有子模块及接口列表
import amct_ops.hifloat8_cast
help(amct_ops.hifloat8_cast.encode_to_hifloat8) # 查看单个函数签名和文档
已知 CMake 告警
使用 pip 安装的 PyTorch 构建时,find_package(Torch) 可能输出如下告警:
static library kineto_LIBRARY-NOTFOUND not found.
该告警来自 PyTorch 自带的 TorchConfig.cmake,表示未找到 Kineto profiler 的静态库。当前 amct_ops 算子不依赖 PyTorch profiler / Kineto 能力;只要 CMake configure、编译和链接成功,该告警可以忽略。
新增算子
算子目录结构
每个算子独占一个子目录,结构参照 hifloat8_cast/:
<新算子>/
├── op_kernel/ # Ascend C kernel(.cpp + tiling.h)
├── op_extension/ # PyTorch C++ binding(host stub 调用 + TORCH_LIBRARY 注册)
├── python/<pkg>/ # Python 接口(__init__.py)
├── CMakeLists.txt # 独立编译入口
└── README.md # 算子说明文档
新增后无需修改 ops_build.sh 或 setup.py,构建脚本会自动发现 <op>/python/<pkg>/ 目录并打包。正式测试放在 tests/amct_ops/ 下,避免把构建产物、性能脚本或依赖额外参考实现的对比工具放入算子源码目录。
命名空间约束
所有算子必须注册到 amct 命名空间——与 amct_ops 包名一致,便于调用方区分 AMCT 自定义算子与 torch_npu 上游算子。
- C++ 侧:
TORCH_LIBRARY_FRAGMENT(amct, m)+TORCH_LIBRARY_IMPL(amct, PrivateUse1, m) - Python 侧:
torch.ops.amct.<算子名>或模块导入from amct_ops.xxx import ... - 算子名在
amct内须唯一,新增前先检索torch.ops.amct是否已存在同名算子。