
人工智能深度学习算子库CANNAscend【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址https://gitcode.com/cann/asc-devkit点击查看免费下载导读本文以昇腾算子编程语言Ascend C开发套件仓库中的 Normalization 高阶 API 样例集为主线系统讲解 DeepNorm、LayerNorm、LayerNormGrad、LayerNormGradBeta、Normalize、RmsNorm、WelfordUpdate、WelfordFinalize 等归一化高阶 API 在真实 Kernel 工程中的端到端用法。读者将掌握归一化样例工程的目录组织、Kernel 直调工程的编译运行流程、各高阶 API 的输入输出规格与 Tiling 数据准备方法并能直接对照仓库源码deepnorm.asc、layernorm.asc等复现训练/推理场景下的归一化计算。归一化高阶 API 样例集总览examples/01_simd_cpp_api/04_advanced_api/02_normalization目录下的样例集覆盖了归一化操作不同特性的典型用法每个样例均基于 Kernel 直调样例工程给出端到端实现包含数据生成脚本、CMake 编译工程、数据读写工具与.asc核函数实现。目录名称功能描述支持的产品deepnorm基于 Kernel 直调样例工程调用 DeepNorm 高阶 API 实现 deepnorm 单样例。在深层神经网络训练过程中执行层 LayerNorm 归一化时可用 DeepNorm 替代通过扩大残差连接α 系数来提高 Transformer 的稳定性Ascend 950PR/Ascend 950DTAtlas A3 训练系列产品/Atlas A3 推理系列产品Atlas A2 训练系列产品/Atlas A2 推理系列产品layernorm在一个核函数中连续调用 LayerNorm、LayerNormGrad、LayerNormGradBeta 三个高阶 API实现 LayerNorm 的完整前向和反向传播同上layernorm_v2在一个核函数中连续调用 LayerNorm 和 Normalize 高阶 API两者配合实现完整的归一化计算同上rmsnorm调用 RmsNorm 高阶 API 实现 rmsnorm 单样例对 shape 为 [BSH] 的输入数据做 RmsNorm 归一化同上welford在一个核函数中连续调用 WelfordUpdate 和 WelfordFinalize 高阶 API实现完整的 Welford 在线算法用于在线计算均值和方差同上各子样例对 CANN 软件版本的要求为Ascend 950PR/Ascend 950DT 需 CANN 9.1.0Atlas A3、Atlas A2 训练/推理系列产品需 CANN 9.0.0。公共工程结构与编译运行流程样例目录结构五个样例的目录结构完全一致以 deepnorm 为例见 deepnorm/README.md├── deepnorm │ ├── scripts │ │ ├── gen_data.py // 输入数据和真值数据生成脚本 │ ├── CMakeLists.txt // 编译工程文件 │ ├── data_utils.h // 数据读入写出函数 │ ├── deepnorm.asc // Ascend C 样例实现 调用样例 │ └── README.md // 样例说明文档gen_data.py负责生成二进制输入数据与 golden 真值data_utils.h提供ReadFile/WriteFile等主机侧读写工具*.asc同时包含 Host 侧 Tiling 生成、设备侧 Kernel 类实现与主机侧启动验证代码。环境变量配置根据当前环境上 CANN 开发套件包的安装方式配置环境变量source ${install_path}/cann/set_env.sh说明${install_path}为 CANN 包安装目录未指定安装目录时默认安装至/usr/local/Ascend下。编译与执行在样例根目录下依次执行mkdir -p build cd build; # 创建并进入build目录 cmake ..;make -j; # 编译工程默认npu模式 python3 ../scripts/gen_data.py # 生成测试输入数据 ./demo # 执行编译生成的可执行程序执行样例使用 CPU 调试或 NPU 仿真模式时添加-DCMAKE_ASC_RUN_MODEcpu或-DCMAKE_ASC_RUN_MODEsim参数即可cmake -DCMAKE_ASC_RUN_MODEcpu -DCMAKE_ASC_ARCHITECTURESdav-2201 ..;make -j; # cpu调试模式 cmake -DCMAKE_ASC_RUN_MODEsim -DCMAKE_ASC_ARCHITECTURESdav-2201 ..;make -j; # NPU仿真模式注意切换编译模式前需清理 cmake 缓存可在 build 目录下执行rm CMakeCache.txt后重新 cmake。编译选项说明选项可选值说明CMAKE_ASC_RUN_MODEnpu默认、cpu、sim运行模式NPU 运行、CPU 调试、NPU 仿真CMAKE_ASC_ARCHITECTURESdav-2201默认、dav-3510NPU 架构dav-2201 对应 Atlas A2 训练系列产品/Atlas A2 推理系列产品和 Atlas A3 训练系列产品/Atlas A3 推理系列产品dav-3510 对应 Ascend 950PR/Ascend 950DT执行成功时终端输出test pass!说明计算结果与 golden 真值完成精度对比并通过。CMake 工程组织以 deepnorm/CMakeLists.txt 为例工程通过find_package(ASC REQUIRED)引入 Ascend C 编译框架以ASC作为编译语言将.asc源码编译为可执行程序并链接tiling_api、register、platform、unified_dlog、graph_base等宿主侧运行库--npu-arch编译选项由CMAKE_ASC_ARCHITECTURES注入。DeepNorm 样例α 缩放残差提升深层 Transformer 稳定性功能与公式DeepNorm 在深层神经网络训练场景下用扩大残差连接α 系数的方式提升 Transformer 深层网络的训练稳定性计算公式为$$ DeepNorm(x) LayerNorm(α * X SubLayer(X)) $$其中 α 为残差缩放系数SubLayer(X)为子层输出样例中由第二个输入张量直接提供。输入输出规格项nameshapedata typeformat样例输入inputX[4, 16, 64]floatND样例输入inputGx[4, 16, 64]floatND样例输入beta[1, 64]floatND样例输入gamma[1, 64]floatND样例输出output[4, 16, 64]floatND样例输出outputMean[4, 16]floatND样例输出outputVariance[4, 16]floatND核函数名为deepnorm_custom。shape 语义为 B4、S16、H64均值与方差按 [B, S] 维度输出。实现要点对照源码见 deepnorm.ascHost 侧 TilingL32-L64构造TensorShape({4,16,64})后调用AscendC::GetDeepNormMaxMinTmpSize(srcShape, sizeof(float), isReuseSource, isBasicBlock, maxValue, minValue)获取接口计算所需的最大/最小临时空间样例取minValue作为工作空间大小以保证功能正确再调用AscendC::GetDeepNormTilingInfo根据输入 shape 与工作空间大小获取 kernel 侧 Tiling 参数封装进自定义DeepNormTilingData结构体。Kernel 侧数据流遵循CopyIn → Compute → CopyOut三段式。CopyIn用AscendC::DataCopy将 inputX、inputGx、gamma、beta 从 GM 搬入 UB 队列Compute中调用模板化高阶 APIAscendC::DeepNormT, isReuseSrc, isBasicBlock(outputLocal, meanLocal, varianceLocal, inputXLocal, inputGxLocal, betaLocal, gammaLocal, (T)alpha, (T)epsilon, tilingData.deepnormTiling)L155-L157CopyOut将结果搬回 GM。参数取值核函数入口处定义alpha -5.5、epsilon 65504L226-L227是样例为验证功能固定的取值isReuseSource false、isBasicBlock true。精度对比Host 侧对 output、mean、variance 三份结果分别与golden_output_*.bin对比绝对误差与相对误差均小于EPS 1e-5时判定通过L247-L268。LayerNorm 样例一个核函数内完成前向与反向传播功能与价值本样例在一个核函数中连续调用 LayerNorm、LayerNormGrad、LayerNormGradBeta 三个高阶 API完成 LayerNorm 的完整前向和反向传播计算。在训练场景中可以一次性得到前向输出、输入梯度与参数梯度减少中间结果在 GM/UB 之间的往返搬运提高计算效率。相似接口提示Ascend C 还提供BatchNorm、GroupNorm调用方式与LayerNorm一致见 impl/adv_api/detail/normalization 下同名目录的接口实现。输入输出规格项nameshapedata typeformat样例输入inputXGm[2, 32, 16]floatND样例输入gammaGm[1, 16]floatND样例输入betaGm[1, 16]floatND样例输入dyGm[2, 32, 16]floatND样例输出outputYGm[2, 32, 16]floatND样例输出outputMeanGm[2, 32]floatND样例输出outputVarGm[2, 32]floatND样例输出outputPdXGm[2, 32, 16]floatND样例输出outputPdGammaGm[1, 16]floatND样例输出outputPdBetaGm[1, 16]floatND核函数名为layernorm_custom实现固定 shapeinputX[2, 32, 16]、gamma[1, 16]、beta[1, 16]、dy[2, 32, 16]的融合 LayerNorm 样例。三步链式计算对照源码见 layernorm.asc 的Compute()L175-L227LayerNorm 前向输入 inputX、gamma、beta调用AscendC::LayerNormfloat, false(yLocal, meanLocal, varLocal, xLocal, gammaLocal, betaLocal, epsilon, layernormTiling_)得到输出 y、均值 mean、方差 var。LayerNormGrad 反向输入 dy、inputX、var、mean、gamma调用AscendC::LayerNormGradfloat, false(pdXLocal, resForGammaLocal, dyLocal, xLocal, varLocal, meanLocal, gammaLocal, epsilon, layernormGradTiling_)得到输入梯度 pd_x 与中间结果 resForGamma。LayerNormGradBeta 参数梯度输入 dy、resForGamma调用AscendC::LayerNormGradBetafloat, false(pdGammaLocal, pdBetaLocal, resForGammaLocal, dyLocal, layernormGradBetaTiling_)得到 gamma 与 beta 的梯度 pd_gamma、pd_beta。Tiling 实现融合 Tiling 的关键在于为三个 API 分别准备独立 Tiling分别调用GetLayerNormMaxMinTmpSize、GetLayerNormGradMaxMinTmpSize、GetLayerNormGradBetaMaxMinTmpSize获取三个接口的最大/最小临时空间取三者最小值的最大值作为统一工作空间minRequired max(minTmpSize1, minTmpSize2, minTmpSize3)。根据输入 shape、工作空间大小分别调用GetLayerNormNDTilingInfo、GetLayerNormGradNDTilingInfo、GetLayerNormGradBetaNDTilingInfo生成三个 kernel 侧 Tiling并设置epsilon 0.0001f防止方差为 0 时出现除零错误layernorm.asc L34-L68。融合 Tiling 数据使用BEGIN_TILING_DATA_DEF/TILING_DATA_FIELD_DEF_STRUCT/REGISTER_TILING_DATA_CLASS宏定义与注册Host 侧SaveToBuffer序列化后传入 kernelL23-L30、L70-L75。LayerNormV2 样例LayerNorm 与 Normalize 融合对比功能与公式本样例基于 Kernel 直调样例工程在一个核函数中依次调用 LayerNorm 和 Normalize 高阶 API两者配合完成完整归一化计算并对比两种 API 的输出结果验证数学等价性。样例使用AR 格式shape 为 [A, R]A 为批处理轴R 为归一化轴A32、R32$$ y_i \gamma_i \cdot \frac{x_i - \mu}{\sqrt{var \epsilon}} \beta_i $$其中 LayerNorm 计算均值 mean 与标准差倒数 rstd随后由 rstd 反推方差$$ var 1/(rstd*rstd) - \epsilon $$Normalize 以 LayerNorm 的原始输入 inputX、均值 mean 和推算出的 var 作为输入完成归一化。输入输出规格项nameshapedata typeformat样例输入inputXGm[32, 32]floatND样例输入gammaGm[32]floatND样例输入betaGm[32]floatND样例输出outputGm[32, 32]floatND样例输出outputMeanGm[32]floatND样例输出outputRstdGm[32]floatND样例输出normalizeOutputGm[32, 32]floatND样例输出normalizeRstdGm[32]floatND核函数名为layernormv2_custom。实现要点对照源码见 layernorm_v2.ascTiling 准备先以isComputeRstd true、isOnlyOutput false调用GetLayerNormMaxMinTmpSize与GetLayerNormNDTilingInfo生成 LayerNorm Tiling再调用GetNormalizeMaxMinTmpSize获取 Normalize 临时空间。源码对 3510 架构做了兜底处理normalizeTmpSize normalizeMinValue 0 ? 32 : normalizeMinValueL80-L81避免初始化为 0。LayerNorm 计算使用配置AscendC::LayerNormConfig{false, false, false, true}isOutputRstdtrueA2/A3 系列输出 rstd配合LayerNormPara{aLength, rLength, rLengthWithPad}调用AscendC::LayerNormfloat, float, false, layernormConfigL182-L188。rstd → var 推导用向量指令链完成Mul计算 rstd²、Reciprocal求倒数、Adds减去 epsilonL191-L194。Normalize 计算使用NormalizeConfig{ReducePattern::AR, -1, false, false, false}调用 Normalize输入复用 LayerNorm 的原始输入与统计量L196-L200。计算前后通过AscendC::AscendCUtils::SetOverflow(1)/SetOverflow(0)包裹便于定位溢出L141-L145。RmsNorm 样例RMS 归一化功能与公式RmsNorm 对 shape 为 [BSH] 的输入数据做 RMS 归一化无需计算均值仅使用均方根对输入做缩放$$ y_i \frac{x_i}{\sqrt{\frac{1}{N}\sum_{i 1}^{N}x_i^2\varepsilon}}\times\gamma $$输入输出规格项nameshapedata typeformat样例输入src[4, 8, 64]floatND样例输入gamma[64]floatND样例输出dst[4, 8, 64]floatND核函数名为rmsnorm_custom未使用基本块模式isBasicBlock false。实现要点对照源码见 rmsnorm.ascTiling 流程AscendC::GetRmsNormMaxMinTmpSize获取接口计算所需的最大和最小临时空间后根据 mode 计算出使用大小 stackSize再调用AscendC::GetRmsNormTilingInfo根据输入 shape 和工作空间大小获取 kernel 侧 Tiling 参数封装到RmsNormTilingData结构体传入 kernel。Tiling 计算逻辑L70-L125临时空间大小与 block 对齐ONE_BLK_SIZE挂钩half 类型按 2 倍系数折算Tiling 输出mainBshLength主循环单次处理的元素数、mainBsLength、loopRound主循环轮数、tailBshLength尾块元素数与inputTailPos尾块起始位置等字段供 kernel 侧做分段循环reciprocalOfHLength 1.0f / originalHLength直接以倒数形式参与计算避免除法开销。Kernel 数据流输入数据先搬运进片上存储UB调用 RmsNorm 高阶 API 完成计算再将结果搬出到外部存储。Welford 样例在线计算均值和方差算法原理Welford 是一种在线计算均值和方差的方法可以在单次数据遍历中逐步计算均值和方差优势在于无需存储所有样本即可逐步计算全部样本的均值和方差只需对数据遍历一次减少访存次数提高计算性能。两个核心 API 的数学定义WelfordUpdate在线更新$M_t M_{t-1} (x_t - M_{t-1}) / n$$S_t S_{t-1} (x_t - M_{t-1}) \times (x_t - M_t)$WelfordFinalize汇总多块结果$Mean \frac{\sum(M_i \cdot n_i)}{\sum n_i}$$Var \frac{\sum(S_i (Mean_i - Mean)^2 \cdot n_i)}{\sum n_i}$输入输出规格项nameshapedata typeformat样例输入srcGm[1, 64]floatND样例输入inMeanGm[1, 64]floatND样例输入inVarGm[1, 64]floatND样例输出outMeanGm[1, 64]floatND样例输出outVarGm[1, 64]floatND样例输出finalMeanGm[8]floatND样例输出finalVarGm[8]floatND核函数名为welford_coop_custom实现固定 shapeRN1AB64的融合 Welford 样例。实现要点对照源码见 welford.ascTiling 流程调用AscendC::GetWelfordUpdateMaxMinTmpSize(srcShape, dtypesizeT, dtypesizeU, false, inplace, maxsize, minsize)获取 WelfordUpdate 计算所需的最大/最小临时空间使用最小值作为工作空间确保功能正确随后通过CopyTilingData将 GM 中的 Tiling 数据拷贝到 kernel 侧L53-L79、L82-L91。WelfordUpdate 调用通过WelfordUpdateConfig{true/false}控制是否 inplace原地更新并传入WelfordUpdateParam{nLength, rLength, abComputeLength, nRec}有临时空间时额外传入tmpLocalTensorL179-L203。WelfordFinalize 调用先以Duplicate初始化 finalize 输入构造 countsint32 计数SetValue(0, 1)与 mean/var 输入缓冲再调用AscendC::WelfordFinalizefalse汇总。注意WelfordFinalizePara存在架构差异dav-2201 下tailCount0时tailCountLength必须为 0而 3510 需要传入WelfordFinalizeConfig代码用__NPU_ARCH__ 3510宏做分支处理L225-L247且abLength8满足 32 字节对齐要求。最终输出两组结果每个数据块的局部均值/方差outMean/outVar以及汇总后的全局均值/方差finalMean/finalVar。源码级支撑Host 侧 Tiling 与 Kernel 侧实现归一化高阶 API 的实现布局仓库中归一化高阶 API 的声明位于 include/adv_api/normalizationHost 侧 Tiling 生成实现位于 impl/adv_api/tiling/normalization设备侧 Kernel 实现位于 impl/adv_api/detail/normalization。从目录布局看detail/normalization下按算子名分别组织batchnorm、deepnorm、groupnorm、layernorm、layernormgrad、normalize、rmsnorm、welfordfinalize 等且 deepnorm 按架构拆分出deepnorm_3510_impl.h、deepnorm_v200_impl.h、deepnorm_v220_impl.h等变体可以推断不同 SoC 系列对应不同的指令实现路径。Tiling 函数族的使用规律所有样例共用同一套 Host 侧 Tiling 函数族命名规律为GetXxxMaxMinTmpSizeGetXxxNDTilingInfo/GetXxxTilingInfo。例如 deepnorm_tiling_impl.cpp 中GetDeepNormMaxMinTmpSize先做 Host 公共参数检查CheckDeepNormHostCommon内部再计算 max/min 临时空间GetDeepNormTilingInfo则基于输入 shape、工作空间大小与isBasicBlock标志生成 kernel 侧 Tiling。而 layernorm_tiling_impl.cpp 中GetLayerNormNDTilingInfoImpl承担核心计算并提供带isComputeRstd参数的重载供 LayerNormV2 场景使用。各样例实现模式小结样例使用的核心高阶 APITiling 关键函数Kernel 侧关键调用deepnormDeepNormGetDeepNormMaxMinTmpSize、GetDeepNormTilingInfoDeepNormT,false,true(...)layernormLayerNorm、LayerNormGrad、LayerNormGradBeta三组 GetXxxMaxMinTmpSize GetXxxNDTilingInfoLayerNormfloat,false、LayerNormGradfloat,false、LayerNormGradBetafloat,falselayernorm_v2LayerNorm、NormalizeGetLayerNormMaxMinTmpSize、GetNormalizeMaxMinTmpSizeLayerNormfloat,float,false,LayerNormConfig、Normalize...rmsnormRmsNormGetRmsNormMaxMinTmpSize、GetRmsNormTilingInfoRmsNormT,falsewelfordWelfordUpdate、WelfordFinalizeGetWelfordUpdateMaxMinTmpSizeWelfordUpdatefloat,float,false,cfg、WelfordFinalizefalse总结与实战建议归一化高阶 API 将均值/方差统计、归一化、梯度回传等高频计算封装为单次 API 调用开发者只需按GetXxxMaxMinTmpSize → GetXxxNDTilingInfo → 高阶 API 调用三步走即可完成端到端实现五个样例提供了可直接复制的模板。训练场景融合诉求前向 反向一次完成可参考 layernorm 样例的多 API 链式调用与统一工作空间规划数值稳定性诉求可参考 layernorm_v2 的epsilon处理与 welford 的在线算法。多架构适配时需关注isBasicBlock、inplace 配置与WelfordFinalizePara等架构差异参数切换产品系列前务必清理 cmake 缓存并正确设置CMAKE_ASC_ARCHITECTURES。赞分享人工智能深度学习算子库CANNAscend【免费下载链接】asc-devkit本项目是CANN 推出的昇腾AI处理器专用的算子程序开发语言原生支持C和C标准规范主要由类库和语言扩展层构成提供多层级API满足多维场景算子开发诉求。项目地址https://gitcode.com/cann/asc-devkit点击查看免费下载相关推荐基于CANN的鸿蒙端侧RMSNorm自定义算子开发实战Ascend C高阶API实现与麒麟芯片部署基于CANN的鸿蒙端侧RMSNorm自定义算子开发实战Ascend C高阶API实现与麒麟芯片部署 本文以 cann recipes harmony infe示例工程Ascend快速上手 btop把 CPU、内存、GPU 和进程装进一个终端快速上手 btop把 CPU、内存、GPU 和进程装进一个终端 btop 是运行在终端里的实时资源监控工具打开它你能同时看到 CPU、内存、磁盘、网CLI指标监控运维CANN Ascend C Matmul 与 LeakyRelu 融合算子实战高阶 API 与基础 API 双路线解析CANN Ascend C Matmul 与 LeakyRelu 融合算子实战高阶 API 与基础 API 双路线解析 导读 本文基于 CANN 开源仓库 c示例工程CANN上一篇Eventyay 支持文档项目教程下一篇POT开源项目使用教程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考