尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
aclnnFlatQuantV2 算子拆解:两步矩阵乘 + 动态量化,CANN 上怎么写一次讲清
aclnnFlatQuantV2 算子拆解两步矩阵乘 动态量化CANN 上怎么写一次讲清【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-nnaclnnFlatQuantV2是 CANN 量化算子里的一个融合操作它把两次小矩阵乘 动态量化压进一次 kernel 完成省掉中间结果的读写。做 LLM 权重/激活低比特压缩的开发者在 Ascend 950PR/950DT 这类平台上替换掉矩阵乘 单独量化的算子链时会直接用到它。产品支持上目前没有覆盖 A2/A3 系列以 950 系列为主。V1 还是 V2三个场景直接判你要 pergroup 输出float4_e2m1FP4mxfp4 路线又想自定义目标类型的最大值比如取 8.0、10.0 而不是默认的 6.0——只有 V2 能传dstTypeMax选它。你走int4 / int32 的 pertoken路线每行一个 FP32 缩放因子两个版本行为一致V1 完全够用。拿不准就直接用 V2、把dstTypeMax设成0.0此时行为等价于 V1之后想调量化范围也只需改一个标量参数不必换接口。一句话新接入默认 V2dstTypeMax0.0是安全的保守姿势。拆开算两步矩阵乘再量化第 1 步右乘 kroneckerP2。这一步本质是沿特征维x 的尾轴 N做一次小矩阵变换。P2 是N×NN ≤ 256的小方阵代价可以忽略$$ x x \text{kroneckerP2} $$第 2 步左乘 kroneckerP1。P1 是M×MM ≤ 256的小方阵沿 x 的第 1 维做同样的事$$ x \text{kroneckerP1} x $$两步的目的是把旋转/重排这类低比特量化前的小变换直接融进主数据流全程不产生中间大张量。另外 pergroup 场景允许kroneckerP2传[0, 0]表示跳过右乘、只做左乘。第 3 步按模式量化——pertoken 或 pergroup。pertoken按行缩放沿 x 第 0 维逐行取最大绝对值除以 $(7 / \text{clipRatio})$ 得到每行的缩放因子再整行除过去$$ \text{quantScale}_k \max_i |x[k, i, :]| ; / ; (7 / \text{clipRatio}) $$$$ \text{out} x / \text{quantScale} $$pergroup按组缩放对应 float4_e2m1先把x从[K, M, N]reshape 成[K, M*N]再按 groupSize32 分组。组内缩放因子必须是 2 的整数次幂——这样才能塞进 ue8m0 这类只存指数位的格式ue8m0FP8 里只保留 8 位指数、没有尾数的特殊编码$$ \text{sharedExp} \log_2\big(\text{reduceMax}(x_2, \text{groupSize}32)\big) - \text{emax} $$$$ \text{quantScale} 2^{,\text{sharedExp}}, \qquad \text{out} x_2 / \text{quantScale} $$其中emax是组内元素绝对值的最大值。pergroup 场景的quantScale输出为[K, ceilDiv(M*N, 64), 2]、类型 FLOAT8_E8M0缩放信息就打包在里面。第 4 步dstTypeMax 非零时块缩放走上取整指数。这是 V2 的核心改动。目标类型的最大可表示值 $A_{\max}(DType)$ 不再固定取 6.0而是由你传入的dstTypeMax支持 6.0~12.0指定。每个块先求最大绝对值$$ S^b_{fp32} \frac{A_{\max}(D^b_{fp32})}{A_{\max}(DType)} $$然后把 $S^b_{fp32}$ 拆成无偏指数 $E^b_{int}$ 与尾数 $M^b_{fixp}$若它是正规数、$E^b_{int} 254$ 且尾数非零指数向上加 1 防溢出$$ E^b_{int} \leftarrow E^b_{int} 1 \quad (\text{仅上述条件成立时}) $$块缩放因子取 $S^b_{ue8m0} 2^{E^b_{int}}$换算因子 $R^b_{fp32} 1 / S^b_{ue8m0}$块内每个元素做 $d^i DType(d^i_{fp32} \cdot R^b_{fp32})$。最终输出是块缩放因子 块内量化数据的组合。两段式接口先问 workspace再执行第一段接口完成入参校验、算出所需 workspace并把整个计算流程打包成aclOpExecutor返回第二段接口拿这个执行器挂到 stream 上真正跑起来。这就是所有 aclnn 算子的 FlatQuantV2 调用流程原型如下aclnnStatus aclnnFlatQuantV2GetWorkspaceSize( const aclTensor *x, const aclTensor *kroneckerP1, const aclTensor *kroneckerP2, double clipRatio, double dstTypeMax, aclTensor *out, aclTensor *quantScale, uint64_t *workspaceSize, aclOpExecutor **executor); aclnnStatus aclnnFlatQuantV2( void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream);执行前记得workspaceSize 0才需要在 Device 侧aclrtMalloc执行器里已经带了全部参数第二段不需要再传任何张量。参数速查Tensor 入参 / 出参数据格式均为 ND全部支持非连续 Tensor输入侧数据类型仅 FLOAT16、BFLOAT16参数方向数据类型shape 与约束x输入FLOAT16、BFLOAT16[K, M, N]K ≤ 262144M、N ≤ 256N 的整除性取决于 out 类型见下表kroneckerP1输入与x一致[M, M]M 与 x 第 2 维一致kroneckerP2输入与x一致[N, N]N 与 x 第 3 维一致pergroup 场景允许[0, 0]跳过右乘out输出INT4、INT32、FLOAT4_E2M1INT32[K, M, N/8]x 的 N 须为 8 的倍数INT4与 x 相同N 须为偶数FLOAT4_E2M1[K, M*N]N 须为偶数quantScale输出FLOAT32、FLOAT8_E8M0INT4/INT32 路线[K]FLOAT4_E2M1 路线[K, ceilDiv(M*N, 64), 2]类型为 FLOAT8_E8M0标量参数参数取值含义clipRatio(0, 1]量化裁剪比例1 表示不裁剪dstTypeMax0.0 或 6.0~12.00.0 用目标精度默认最大值6.0~12.0 显式指定仅 FLOAT4_E2M1 生效一个能跑的完整示例下面只标注关键路径构造 Tensor → 两段调用 → 取回结果。完整可运行版含全部错误处理宏与资源初始化见仓库matmul/flat_quant/examples/test_aclnn_flat_quant_v2.cpp。#include acl/acl.h #include aclnnop/aclnn_flat_quant_v2.h int main() { // 固定写法device/stream 初始化 int32_t deviceId 0; aclrtStream stream; CHECK(aclInit(nullptr) ACL_SUCCESS); CHECK(aclrtSetDevice(deviceId) ACL_SUCCESS); CHECK(aclrtCreateStream(stream) ACL_SUCCESS); // 构造输入输出INT32 示例16x16x16 输入 - 16x16x2 输出 std::vectorint64_t xShape {16, 16, 16}; std::vectorint64_t p1Shape {16, 16}; std::vectorint64_t p2Shape {16, 16}; std::vectorint64_t outShape {16, 16, 2}; std::vectorint64_t scaleShape {16}; void *xDev nullptr, *p1Dev nullptr, *p2Dev nullptr; void *outDev nullptr, *scaleDev nullptr; aclTensor *x nullptr, *p1 nullptr, *p2 nullptr; aclTensor *out nullptr, *scale nullptr; double clipRatio 1.0; double dstTypeMax 0.0; // 默认值走目标精度默认最大值 // 填充数据、aclCreateTensor 创建各 Tensor此处略 CHECK(CreateAclTensor(xShape, xDev, aclDataType::ACL_FLOAT16, x) ACL_SUCCESS); CHECK(CreateAclTensor(p1Shape, p1Dev, aclDataType::ACL_FLOAT16, p1) ACL_SUCCESS); CHECK(CreateAclTensor(p2Shape, p2Dev, aclDataType::ACL_FLOAT16, p2) ACL_SUCCESS); CHECK(CreateAclTensor(outShape, outDev, aclDataType::ACL_INT32, out) ACL_SUCCESS); CHECK(CreateAclTensor(scaleShape, scaleDev, aclDataType::ACL_FLOAT, scale) ACL_SUCCESS); // 第一段校验 计算 workspace 拿执行器 uint64_t workspaceSize 0; aclOpExecutor *executor nullptr; CHECK(aclnnFlatQuantV2GetWorkspaceSize( x, p1, p2, clipRatio, dstTypeMax, out, scale, workspaceSize, executor) ACL_SUCCESS); void *workspaceAddr nullptr; if (workspaceSize 0) { CHECK(aclrtMalloc(workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST) ACL_SUCCESS); } // 第二段执行 CHECK(aclnnFlatQuantV2(workspaceAddr, workspaceSize, executor, stream) ACL_SUCCESS); CHECK(aclrtSynchronizeStream(stream) ACL_SUCCESS); // 把 out / quantScale 拷回 host 查看略 // 释放 Tensor、device 内存、workspace、stream复位 device略 return 0; }容易踩的坑集中说一遍三个输入x、kroneckerP1、kroneckerP2和两个输出out、quantScale一个都不能是空指针否则第一段直接返回 161001ACLNN_ERR_PARAM_NULLPTR。kroneckerP1/kroneckerP2的数据类型必须与x完全一致都只能是 FLOAT16 或 BFLOAT16不支持混用。out 的尾轴约束与类型绑定INT32 要求 x 的 N 是 out 尾轴的 8 倍INT4 要求 x 与 out 的 shape 完全一致FLOAT4_E2M1 的 out 是[K, M*N]的二维。pergroupfloat4_e2m1场景下quantScale的 shape 是三维的[K, ceilDiv(M*N, 64), 2]、类型 FLOAT8_E8M0别按[K]的 FP32 习惯去申请内存。dstTypeMax只在 FLOAT4_E2M1 输出下生效合法取值是 0.0 或 6.0~12.0其他值会被参数校验拒掉。[0, 0]的kroneckerP2跳过右乘仅限 pergroup 场景pertoken/int4/int32 场景下 P2 必须和 x 的尾轴等维。除空指针外的所有校验失败shape、dtype、clipRatio越界等统一返回 161002ACLNN_ERR_PARAM_INVALID先检查clipRatio ∈ (0, 1]、x 各维范围[1,262144]×[1,256]×[1,256]再逐条对上面几条。该算子默认确定性实现当前产品支持范围是 Ascend 950PR/950DTA2/A3 系列暂不支持。【免费下载链接】ops-nn本项目是CANN提供的神经网络类计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-nn创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

Docker容器名冲突排查指南:从报错原理到彻底解决

Docker容器名冲突排查指南:从报错原理到彻底解决

第一次在终端里看到docker: Error response from daemon: Conflict. The container name "/mysql" is already in use by container时,很多人的第一反应是“我是不是配置写错了?” 其实这个报错和 MySQL 无关,和配置也无关&#xf…

📅 2026/10/21 2:15:41
五步把 Windows 11 瘦身:tiny11builder 完整实战指南与避坑清单

五步把 Windows 11 瘦身:tiny11builder 完整实战指南与避坑清单

五步把 Windows 11 瘦身:tiny11builder 完整实战指南与避坑清单 【免费下载链接】tiny11builder WinUI app for building smaller, customized Windows 11 images. 项目地址: https://gitcode.com/GitHub_Trending/ti/tiny11builder Tiny11Builder 是一套开源 PowerShel…

📅 2026/10/21 2:15:41
pit_xs_224.in1k图像Embedding提取教程:num_classes=0与forward_features两种写法全解

pit_xs_224.in1k图像Embedding提取教程:num_classes=0与forward_features两种写法全解

【免费下载链接】pit_xs_224.in1k 项目地址: https://ai.gitcode.com/hf_mirrors/timm/pit_xs_224.in1k 点击查看 免费下载 本教程详解 pit_xs_224.in1k 图像模型的 Embedding 提取方法,对比 num_classes0 参数与 forward_features 函数两种写法&#x…

📅 2026/10/21 2:15:41
MORE NEWS

更多资讯

📰

NVFP4:让大模型从零预训练跑在4位浮点上

训练大模型最怕的从来不是模型推不动,而是显存和带宽在物理上先投降。我最近读了一篇硬核的预训练论文,标题是“Pretraining Large Language Models with NVFP4”,核心就一句话:让大语言模型从零预训练阶段,前向、反向…

📰

MX Linux 25.1双Init并存:SysVinit与systemd自由切换

一提到“你的发行版到底该用哪套init”,Linux社区的讨论经常就变成立场之争。systemd派觉得日志、依赖、资源控制统统内置才是现代系统该有的样子;传统派则认为一个脚本一个脚本顺序执行、每步都可预期的SysVinit才叫优雅。大多数发行版早就不纠结这个问…

📰

SheerID-Verification-Tool部署指南:从本地到生产环境的无缝迁移

SheerID-Verification-Tool部署指南:从本地到生产环境的无缝迁移 SheerID-Verification-Tool是一款轻量级工具,专为集成和测试SheerID验证工作流设计,能简化API请求、处理响应并支持学生等项目的资格检查。本指南将帮助你实现从本地开发到生…

📰

NVFP4预训练大模型:从量化训练到部署的全面解析

最近把这篇《Pretraining Large Language Models with NVFP4》翻来覆去读了几遍,越读越觉得它不只是“又一篇4位精度论文”,更像是给整个量化生态指了一个新方向。过去大家默认FP4只能做推理阶段的压缩,谁在预训练里碰4位精度,谁就…

📰

统一API架构下GPT-5.2与DeepSeek-V3.2模型选型与路由降级实战

最近在做模型网关项目时,我需要在同一个系统里同时接入GPT-5.2和DeepSeek-V3.2。如果你也正在搞Agent应用、企业内部知识库或者面向C端的智能助手,大概率会和我遇到同一类麻烦:模型各有各的强项,但应用层总不能为每一个模型单独写…

📰

AI驱动流程自动化实战:架构师视角的拆解与落地要点

这两年我听到最多的一个词就是“AI驱动流程自动化”,不少做架构的朋友都在琢磨怎么靠它往上走一档。作为AI应用架构师,很多人觉得我们干的就是接几个大模型接口、写点提示词,但真正深入做过端到端自动化的人才会明白,这套东西的难…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬