| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 29 天前 | ||
| 29 天前 | ||
| 29 天前 | ||
| 29 天前 |
QuantBatchMatmul MX
基于 CANNBot-DSL 实现的 MX 全量化矩阵乘算子,统一支持 MXFP8 和 MXFP4,
面向 Ascend NPU。MXFP8 输入支持 float8_e4m3fn、float8_e5m2,MXFP4
输入支持 float4_e2m1fn_x2;输出支持 float16、bfloat16 和 float32。
算子介绍
计算公式:
C[M,N]=Dequant(A)[M,K]@Dequant(B)[K,N]C[M,N] = Dequant(A)[M,K] @ Dequant(B)[K,N]
MXFP8 和 MXFP4 均沿 K 轴每 32 个数据使用一个 E8M0 Scale。公开 Scale
接口将相邻两个 Scale 组成一个 pair,因此 Scale 的分组轴长度为
ceil(K / 64),最后一维为 2。
| 特性与约束 | 说明 |
|---|---|
| 数据类型 | A/B 为 float8_e4m3fn、float8_e5m2 或 float4_e2m1fn_x2;输出为 float16、bfloat16 或 float32 |
| Scale | ScaleA/ScaleB 为 float8_e8m0fnu 三维 paired-scale Tensor |
| transpose | 通过 A/B 与 Scale 的 view shape 推导四种 transposeA/transposeB 组合 |
| 输入 | 二维 A/B 与三维 Scale Tensor |
| MXFP4 打包 | 物理连续内轴每个字节保存两个 FP4 元素;打包内轴必须为偶数,尾轮负载均衡只选择整字节边界的子块 |
| Bias | 可选一维 float32 Bias,长度为 N |
| 尾块 | 支持 M/N/K 非基本块整数倍;Host Tiling 对尾轮进行负载均衡并保留实际 M/N/K |
| 多核并行 | 自适应滑动窗口多核调度 |
| A 全载 | AL1_FULL_LOAD:A 与 ScaleA 常驻 L1,跨多个 N Tile 复用,B 与 ScaleB 沿 K 流式搬运 |
| Buffer | 按 L1 容量和 MTE2/Cube 模型选择数据 2/3/4 Buffer;L0A/L0B 使用双缓冲;L0C 容量足够时使用双缓冲 |
| UnitFlag | 中间 MMAD 使用 UnitFlag 2,最终 MMAD 与 FixPipe 使用 UnitFlag 3 |
| L2 cache | 按矩阵复用情况自适应开关 |
| 支持架构 | NPU ARCH 3510(Ascend 950PR / Ascend 950DT) |
算子由 Host 侧 tiling 推导 baseM/baseN/baseK、L1/L0 切分与 Buffer 参数,
Device Kernel 采用自适应滑动窗口多核调度、AL1 full-load 和 L1/L0 ping-pong
流水线,数据流为 GM -> L1(MTE2)-> L0A/L0B(MTE1)-> MMAD -> L0C -> GM
(FIXPIPE)。实现详见 quant_batch_matmul_mx.py。
快速开始
import torch
import torch_npu
from quant_batch_matmul_mx import npu_quant_matmul
M, K, N = 256, 256, 256
a = torch.randn(M, K).to(torch.float8_e4m3fn).npu() # (M, K)
b = torch.randn(N, K).to(torch.float8_e4m3fn).npu() # (N, K)
# [M, ceil(K / 64), 2] 为 ScaleAND,
# [N, ceil(K / 64), 2] 为 ScaleBDN。
scale_a = torch.full((M, (K + 63) // 64, 2), 127, dtype=torch.uint8).npu()
scale_b = torch.full((N, (K + 63) // 64, 2), 127, dtype=torch.uint8).npu()
scale_a = scale_a.view(torch.float8_e8m0fnu)
scale_b = scale_b.view(torch.float8_e8m0fnu)
c = npu_quant_matmul(
a,
b,
scale_a,
scale_b,
output_dtype=torch.float32,
)
npu_quant_matmul() 输入/输出说明:
| 参数 | shape | dtype | 说明 |
|---|---|---|---|
a |
MXFP8: (M,K)/(K,M);MXFP4: (M,K/2)/(K,M/2) | float8_e4m3fn / float8_e5m2 / float4_e2m1fn_x2 | A,左矩阵;MXFP4 shape 为物理打包 shape |
b |
MXFP8: (N,K)/(K,N);MXFP4: (N,K/2)/(K,N/2) | float8_e4m3fn / float8_e5m2 / float4_e2m1fn_x2 | B,右矩阵;MXFP4 shape 为物理打包 shape |
scale_a |
(M, ceil(K / 64), 2) 或 (ceil(K / 64), M, 2) | float8_e8m0fnu | A 的 ScaleA,分别对应 ScaleAND/ScaleADN |
scale_b |
(N, ceil(K / 64), 2) 或 (ceil(K / 64), N, 2) | float8_e8m0fnu | B 的 ScaleB,分别对应 ScaleBDN/ScaleBND |
bias |
(N,) | float32 | 可选 Bias |
output_dtype |
- | torch.dtype | 输出类型:float16、bfloat16 或 float32 |
返回值 c |
(M, N) | output_dtype | 矩阵乘结果 |
精度测试
测试代码位于 test/matmul/quant_matmul/test_quant_batch_matmul_mx.py,使用 pytest
驱动,运行命令如下:
pytest test/matmul/quant_matmul/test_quant_batch_matmul_mx.py -v
性能数据
本 Sample 与 built-in npu_quant_matmul(MX group 量化路径)在部分用例上的
性能对比结果如下。用例覆盖多种对齐与非对齐 Shape(7~43us),
MXFP8 E4M3 输入、FF/FT/TF/TT 布局及多种输出类型。
使用 msprof 采集 AI Core Kernel Task Duration,每个 Shape 预热 3 次后重复
15 次取中位数;图中不包含编译、Launch、同步和输入构造时间。

QuantBatchMatmul HiFloat8 TT
基于 CANNBot-DSL 实现的 TT(per-tensor)量化矩阵乘算子,重点展示 HiFloat8 数据在 Cube 上的矩阵乘计算,同时支持 INT8、FP8 E4M3FN 和 FP8 E5M2 输入,面向 Ascend NPU。
算子介绍
计算公式:
C[M,N]=(scaleA×scaleB)×(A[M,K]@B[K,N])C[M,N] = (scaleA \times scaleB) \times (A[M,K] @ B[K,N])
TT 量化对 A、B 各使用一个 FP32 标量 Scale:scale_a 为 ScaleA,
scale_b 为 ScaleB。ScaleA/ScaleB 作为 Kernel Runtime 参数从 GM 读取,设备侧
计算 deqScale = scaleA * scaleB,再通过 deq_scale 传给 FIXPIPE,L0C
累加结果写回 GM 时完成反量化。
HiFloat8 数据表示
HiFloat8 是 Ascend 支持的一种 8-bit 浮点数据格式,不等同于
torch.float8_e4m3fn 或 torch.float8_e5m2。Torch 当前没有对应的原生
torch.dtype,因此 A/B 使用 torch.int8 Tensor 保存 HiFloat8 编码,并设置
a_dtype=b_dtype=torch_npu.hifloat8。接口将存储字节原样传给 Kernel,
dtypes.hifloat8 告诉 Cube 按 HiFloat8 解释。a_dtype 和 b_dtype 必须
同时设置,且 A/B 存储类型必须都是 INT8。
| 特性与约束 | 说明 |
|---|---|
| 数据类型 | HiFloat8 使用 INT8 存储,并设置 a_dtype/b_dtype=torch_npu.hifloat8;也支持原生 INT8 或 E4M3FN/E5M2(两种 FP8 可混用) |
| 输出类型 | HiFloat8/FP8 输出 float16、bfloat16 或 float32;INT8 输出 float16 或 bfloat16 |
| 量化粒度 | TT:A、B 各一个 FP32 标量 Scale;设备侧计算 deqScale |
| transpose | A/B 的 view shape 固定为 (M,K)/(K,N),根据 stride 支持 FF/FT/TF/TT 四种存储布局 |
| 输入 | 二维 A/B 与标量 Scale Tensor |
| 多核并行 | 根据平台 AIC 数量进行自适应滑动窗口多核调度 |
| Buffer | 按 L1 容量选择数据 2/4 Buffer;L0A/L0B 使用双缓冲;L0C 容量足够时使用双缓冲 |
| L2 cache | 按矩阵复用情况自适应开关 |
| UnitFlag | 中间 MMAD 使用 UnitFlag 2,最终 MMAD 与 FixPipe 使用 UnitFlag 3 |
| 支持架构 | NPU ARCH 3510(Ascend 950PR / Ascend 950DT) |
输入路径
| 路径 | 输入 | L0C 累加 | 输出 |
|---|---|---|---|
| INT8 | int8 | int32 | float16 / bfloat16 |
| FP8 | float8_e4m3fn / float8_e5m2 | float32 | float16 / bfloat16 / float32 |
| HiFloat8 | int8 存储 Tensor,并设置 a_dtype/b_dtype=torch_npu.hifloat8 |
float32 | float16 / bfloat16 / float32 |
数据流:A/B GM → L1(MTE2,ping-pong)→ L0A/L0B(MTE1,ping-pong)
→ MMAD → L0C → FIXPIPE(使用设备侧计算的 deqScale)→ C GM。接口根据
Torch 输入 dtype 选择对应 DSL dtype、L0C 累加类型和合法输出类型。
快速开始
import torch
import torch_npu
from quant_batch_matmul_hif8_tt import npu_quant_matmul
M, K, N = 256, 256, 256
a = torch.randint(-5, 5, (M, K), dtype=torch.int8).npu()
b = torch.randint(-5, 5, (K, N), dtype=torch.int8).npu()
scale_a = torch.tensor([0.01], dtype=torch.float32).npu()
scale_b = torch.tensor([0.02], dtype=torch.float32).npu()
c = npu_quant_matmul(
a,
b,
scale_a,
scale_b,
a_dtype=torch_npu.hifloat8,
b_dtype=torch_npu.hifloat8,
output_dtype=torch.float32,
)
npu_quant_matmul() 输入/输出说明:
| 参数 | shape | dtype | 说明 |
|---|---|---|---|
a |
(M, K) | int8 / float8_e4m3fn / float8_e5m2 | 左矩阵;HiFloat8 使用 int8 存储;stride 决定 transposeA |
b |
(K, N) | int8 / float8_e4m3fn / float8_e5m2 | 右矩阵;HiFloat8 使用 int8 存储;stride 决定 transposeB |
scale_a |
(1,)、(1,1) 或标量 | float32 | ScaleA(A,per-tensor) |
scale_b |
(1,)、(1,1) 或标量 | float32 | ScaleB(B,per-tensor) |
a_dtype / b_dtype |
- | int | HiFloat8 输入时二者均传 torch_npu.hifloat8;其他输入不传 |
output_dtype |
- | torch.dtype | HiFloat8/FP8:float16/bfloat16/float32;INT8:float16/bfloat16 |
返回值 c |
(M, N) | output_dtype | 反量化后的矩阵乘结果 |
精度测试
测试代码位于 test/matmul/quant_matmul/test_quant_batch_matmul_hif8_tt.py,使用 pytest
驱动,运行命令如下:
pytest test/matmul/quant_matmul/test_quant_batch_matmul_hif8_tt.py -v
性能数据
本 Sample 与 built-in npu_quant_matmul 在部分用例上的性能对比结果如下。
用例采用较大的对齐与非对齐 Shape(13~77us),
覆盖 HiFloat8 / FP8 输入、FF/FT 布局及多种输出类型。
使用 msprof 采集 AI Core Kernel Task Duration,每个 Shape 预热 3 次后重复
15 次取中位数;图中不包含编译、Launch、同步和输入构造时间。

QuantBatchMatmul MXA8W4
基于 CANNBot-DSL 实现的混合精度量化矩阵乘算子(MXA8W4):激活为 MXFP8 (float8_e4m3fn + E8M0 Scale),权重为 MXFP4(float4_e2m1 + E8M0 Scale), 输出 float16,面向 Ascend NPU。
算子介绍
计算公式:
C[M,N]=(A[M,K]⋅sa)@(B[N,K]⋅sb)T+biasC[M,N] = (A[M,K] \cdot sa) @ (B[N,K] \cdot sb)^T + bias
其中 A/B 沿 K 轴每 32 个数据使用一个 E8M0 Scale(MX group size = 32)。
公开 Scale 接口将相邻两个 Scale 组成一个 pair,因此 Scale 的分组轴长度为
ceil(K / 64),最后一维为 2。B 的 fp4 数据以 uint8 打包(每字节 2 个
e2m1 元素,偶数 K 在低 nibble)。
| 特性与约束 | 说明 |
|---|---|
| 数据类型 | A 为 float8_e4m3fn,B 为打包 float4_e2m1(uint8 载体);输出 float16 |
| Scale | ScaleA/ScaleB 为 float8_e8m0fnu 三维 paired-scale Tensor |
| Shape | M/N 任意;K 为 32 的倍数且无上限(片上 K 状态全部窗化) |
| 尾块 | M/N/K 尾块由引擎在搬运途中补零;K 尾子块运行期缩窄(k_extent),读界不超过 align64(K) |
| 多核并行 | 平衡连续 tile 分配,自适应核数(grid 上限 32) |
| 架构 | 双核混合:AIV 权重转换 prologue + AIC MX matmul,CrossCore 通道交接 |
算子由 Host 侧 cost-model tiling 推导 baseM/baseN/baseK、L1 K 窗
(k_l1 = step_k × base_k,与 L0/mmad 块解耦)、环深与核数。device 侧
AIV 将 B 的 fp4 → fp8 做纯位置换转换([s e e m] → [s 0 0 e e m 0 0],
数值恒为 e2m1 的 2^-6,含次正规精确),经 UB 环形缓冲写入 CrossCore L1
通道;AIC 完成 A/B 的 MX 矩阵乘与 fixpipe 输出,转换的 2^-6 因子由
fixpipe deq_scale=64 与 host 侧 bias/64 补偿。数据流为
GM → L1(MTE2,nd2nz)→ L0A/L0B(MTE1,MX scale 联动加载)→ MMAD(MX)
→ L0C → GM(FIXPIPE)。实现详见 quant_batch_matmul_mxa8w4.py。
快速开始
import torch
import torch_npu
from quant_batch_matmul_mxa8w4 import matmul_mix_quant
M, K, N = 256, 352, 256
a = torch.randn(M, K).to(torch.float8_e4m3fn).npu() # (M, K)
codes = torch.randint(0, 16, (N, K), dtype=torch.uint8).npu()
b = (codes[:, 0::2] & 0xF) | ((codes[:, 1::2] & 0xF) << 4) # (N, K // 2)
# [M, ceil(K / 64), 2] 为 ScaleAND,[N, ceil(K / 64), 2] 为 ScaleBDN。
scale_a = torch.full((M, (K + 63) // 64, 2), 127, dtype=torch.uint8).npu()
scale_b = torch.full((N, (K + 63) // 64, 2), 127, dtype=torch.uint8).npu()
scale_a = scale_a.view(torch.float8_e8m0fnu)
scale_b = scale_b.view(torch.float8_e8m0fnu)
c = matmul_mix_quant(a, b, scale_a, scale_b) # (M, N) float16
matmul_mix_quant() 输入/输出说明:
| 参数 | shape | dtype | 说明 |
|---|---|---|---|
a |
(M, K) | float8_e4m3fn | A,左矩阵 |
b |
(N, K // 2) | uint8 | B,右矩阵(fp4 e2m1 打包,偶数 K 低 nibble) |
scale_a |
(M, ceil(K / 64), 2) | float8_e8m0fnu | ScaleA(ScaleAND) |
scale_b |
(N, ceil(K / 64), 2) | float8_e8m0fnu | ScaleB(ScaleBDN) |
bias |
(N,) | torch.float32 | 可选,bias(内部按 2^-6 补偿) |
返回值 c |
(M, N) | float16 | 矩阵乘结果 |
精度测试
测试代码位于 test/matmul/quant_matmul/test_quant_batch_matmul_mxa8w4.py,
11 个用例(5 组代表性形状 × 含 bias + 输入校验,覆盖尾块/部分尾窗/深环/退化形状),pytest 驱动:
pytest test/matmul/quant_matmul/test_quant_batch_matmul_mxa8w4.py -v
性能数据
与 CANN 内置 aclnnQuantMatmulV5(QuantBatchMatmulV4 官方 kernel +
SWAT tiling solver)在 100 形状(方形/常规/瘦长/尾块 × M 扫描/宽 N/
奇 M,N/K 尾残差/大 K ≤ 16384/种子随机)上的 msprof task duration
对比(比值 = aclnn / 本实现,大于 1 表示本实现更快):几何平均
1.170,76/100 形状领先,无落后超过 9% 的形状;小形状(K ≤ 1024)
最高 2.28x,尾块形状(K 非 256 倍数)1.07-1.38x。
