尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

CANN ops-math Floor 算子完全指南:数学语义、aclnn 两段式接口与 AscendC 内核实现

CANN ops-math Floor 算子完全指南:数学语义、aclnn 两段式接口与 AscendC 内核实现 CANN ops-math Floor 算子完全指南数学语义、aclnn 两段式接口与 AscendC 内核实现【免费下载链接】ops-math本项目是CANN提供的数学类基础计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-mathFloor向下取整是神经网络与科学计算中广泛使用的基础数学算子在 CANN ops-math 算子库中以experimental/math/floor目录形式独立维护。本文以该算子的 README 为骨架结合 aclnnFloor 接口文档、调用样例 及 op_api / op_host / op_kernel 各层源码完整讲解 Floor 算子的功能定义、参数约束、两段式 aclnn 调用流程、底层计算图与内核实现原理帮助读者在 Atlas A2 系列产品上快速完成算子调用与结果验证。算子概述与产品支持情况功能定义Floor 算子对输入张量self的每一个元素执行向下取整操作对于任意实数input_i返回不大于它的最大整数out_i。注意它不同于截断取整向零取整对于负数而言结果更小。其计算公式为$$out_i \lfloor input_i \rfloor$$以算子仓库中的 调用样例 为例输入张量{1.3, 2.5, 6.7, -4, -1.4, -1.6, -8, -16.9}经过 Floor 计算后输出为{1, 2, 6, -4, -2, -2, -8, -17}——其中-1.4向下取整为-2、-16.9向下取整为-17充分体现了向下而非截断的语义。产品支持情况根据 README 的说明Floor 算子当前支持的产品如下产品是否支持Atlas A2 训练系列产品 / Atlas 800I A2 推理产品 / A200I A2 Box 异构组件√仓库目录结构Floor 算子在仓库中的源码组织遵循 CANN 算子标准分层结构experimental/math/floor/ ├── CMakeLists.txt # 模块构建配置 ├── README.md # 算子功能与调用说明本文主体 ├── docs/aclnnFlooraclnnInplaceFloor.md # aclnn 接口详细说明 ├── examples/test_aclnn_floor.cpp # 可直接运行的调用样例 ├── op_api/ # 对外 API 层aclnnFloor / l0op::Floor ├── op_host/ # Host 侧算子定义与 Tiling 计算 ├── op_kernel/ # Device 侧AscendC 内核实现 └── tests/ut/ # op_api 与 op_host 单元测试参数说明与数据约束算子入参出参根据 README 的参数说明表Floor 算子只有一组输入输出参数名输入/输出/属性描述数据类型数据格式self输入待进行 floor 计算的入参公式中的input_iFLOAT、FLOAT16、BFLOAT16NDout输出待进行 floor 计算的出参公式中的out_iFLOAT、FLOAT16、BFLOAT16ND约束说明README 中明确指出 Floor 算子的约束说明为无即对 shape、维度上限等没有额外限制在 aclnn 接口层面对维度的要求是 0-8 维且out的 shape 需与self保持一致。源码层的定义印证从算子注册定义 op_host/floor_def.cpp 可以看到Floor 算子在算子信息库中注册为输入xREQUIRED支持ge::DT_FLOAT16、ge::DT_FLOAT、ge::DT_BF16三种数据类型格式为ge::FORMAT_ND输出yREQUIRED数据类型与格式同输入AICore 配置this-AICore().AddConfig(ascend910b)即针对 910B 系列A2架构的内核配置。这与 README 中FLOAT、FLOAT16、BFLOAT16 ND 格式的说明完全一致。值得一提的是在 aclnn_floor.cpp 的CheckDtypeValid中接口层按 NPU 架构区分了两套数据类型支持列表DTYPE_SUPPORT_LIST_910INT64/INT32/INT16/INT8、UINT64/UINT32/UINT16/UINT8、DOUBLE/FLOAT/FLOAT16与DTYPE_SUPPORT_LIST_910B在 910 基础上追加 BF16对整型输入内核实际不参与计算结果直接等价于输入本身见下文计算图分析因此浮点类型的语义才是 Floor 的核心。aclnnFloor 两段式接口详解Floor 算子对外提供aclnnAscendCL Neural Network方式调用采用 CANN 标准的两段式接口设计必须先调用aclnnFloorGetWorkspaceSize获取计算所需 workspace 大小并创建执行器再调用aclnnFloor真正执行计算。函数原型aclnnStatus aclnnFloorGetWorkspaceSize( const aclTensor *self, aclTensor *out, uint64_t *workspaceSize, aclOpExecutor **executor)aclnnStatus aclnnFloor( void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, const aclrtStream stream)完整的参数与返回值说明见 aclnnFlooraclnnInplaceFloor.md。第一段接口 aclnnFloorGetWorkspaceSize参数名输入/输出描述使用说明数据类型数据格式维度(shape)非连续 Tensorself输入待进行floor计算的输入张量无BFLOAT16、FLOAT16、FLOAT32ND0-8√out输出floor计算的输出张量shape 与self相同BFLOAT16、FLOAT16、FLOAT32ND0-8√workspaceSize输出返回 device 侧执行该算子时所需的 workspace 大小-----executor输出返回 op 执行器包含算子计算流程-----第一段接口会完成入参检查在以下场景返回错误返回码错误码描述ACLNN_ERR_PARAM_NULLPTR161001传入的 tensor 是空指针。ACLNN_ERR_PARAM_INVALID161002self 数据类型或格式不在支持范围内self 数据维度超过 8 维self 与 out 的数据形状不一致。这些检查在源码中的实现位于 aclnn_floor.cpp 的CheckParamsFloor函数依次执行空指针检查CheckNotNull2Tensor、数据类型匹配与支持范围检查CheckDtypeValid要求self与out类型一致、shape 一致性检查CheckSameShape1In1Out以及格式检查CheckFormat拒绝私有存储格式。第二段接口 aclnnFloor参数名输入/输出描述workspace输入在 Device 侧申请的 workspace 内存地址。workspaceSize输入workspace 的大小由第一段接口aclnnFloorGetWorkspaceSize获取。executor输入op 执行器包含算子计算流程。stream输入指定执行任务的 Stream。第二段接口通过框架能力CommonOpExecutorRun在指定 stream 上异步执行计算返回值同样为aclnnStatus状态码。Inplace 变体 aclnnInplaceFloor除标准接口外仓库还提供了原地计算变体aclnnInplaceFloor声明见 aclnn_floor.h它只有一个输入输出合一的参数selfRef计算完成后结果直接写回原张量适用于无需保留原始输入的场景可节省一份输出内存。其实现即GetWorkspaceSizeCommon(selfRef, selfRef, ...)复用与aclnnFloor完全相同的内部流程。端到端调用示例仓库在 examples/test_aclnn_floor.cpp 提供了完整的可运行样例覆盖了从环境初始化到资源释放的完整调用链路。整体流程分为七个步骤初始化 device 与 stream固定写法aclInit(nullptr)→aclrtSetDevice(deviceId)→aclrtCreateStream(stream)构造输入输出 aclTensor通过aclrtMalloc申请 device 内存aclrtMemcpy完成 Host→Device 数据拷贝按连续 tensor 规则计算 strides 后调用aclCreateTensor创建aclTensor两段式调用算子调用aclnnFloorGetWorkspaceSize(self, out, workspaceSize, executor)获取 workspace 大小与执行器若workspaceSize 0用aclrtMalloc申请 workspace 内存调用aclnnFloor(workspaceAddr, workspaceSize, executor, stream)执行计算同步等待aclrtSynchronizeStream(stream)确保异步任务完成取回结果aclrtMemcpy将 Device 侧结果拷贝回 Host逐元素打印释放 aclTensoraclDestroyTensor(self/out)释放资源aclrtFree释放 device 内存与 workspace、aclrtDestroyStream、aclrtResetDevice、aclFinalize。其中CreateAclTensor模板函数可复用于任意数据类型样例中以ACL_FLOAT为例。样例的输出打印结果为result[0] is: 1.000000 result[1] is: 2.000000 result[2] is: 6.000000 result[3] is: -4.000000 result[4] is: -2.000000 result[5] is: -2.000000 result[6] is: -8.000000 result[7] is: -17.000000该样例的具体编译与执行步骤可参考 docs/aclnnFlooraclnnInplaceFloor.md 中指向的通用编译运行说明两段式接口使用规范见仓库docs/zh/context下的上下文文档在配置好 CANN 工具链后按普通 C 程序编译链接 aclnn 库即可运行。底层实现原理Floor 算子的完整执行路径横跨 op_api、op_host、op_kernel 三层下面结合源码逐一拆解。计算图与 L0 算子分派op_api 层aclnn_floor.cpp 的GetWorkspaceSizeCommon展示了接口层的计算图构建逻辑若self为空 tensor直接返回workspaceSize 0若self非连续先调用l0op::Contiguous转为连续张量整型输入短路IsIntegralType(self-GetDataType())为真时结果直接复用连续化后的输入整型取整结果等于自身不再下发内核浮点输入调用l0op::Floor执行真正计算若out为非连续 tensor通过l0op::ViewCopy将计算结果写回目标视图。整体计算图可表示为Self → Contiguous → l0op::Floor → ViewCopy → outl0op::Floor的实现见 op_api/floor.cpp它先依据输入数据类型自动分配输出张量然后按类型分派——支持列表AICORE_DTYPE_SUPPORT_LISTFLOAT、FLOAT16、BF16内的输入走FloorAiCoreADD_TO_LAUNCHER_LIST_AICORE其他类型回退到FloorAiCpuADD_TO_LAUNCHER_LIST_AICPU形成 AiCore/AiCPU 双路径兜底。Tiling 计算op_host 层op_host/floor_tiling.cpp 实现了算子切分策略关键参数包括BLOCK_SIZE 512U数据对齐的基本块大小UB_DATA_NUM_FLOAT 4U、UB_DATA_NUM_OTHER 6UFLOAT 与其他类型在 UB 中的缓冲占比FLOAT 直接调用硬件 Floor 指令占用的中间缓冲更少MIN_ELEM_PER_CORE 512U每个核处理的最小元素数下限。Tiling 流程为从平台信息获取 UB 大小与核数GetPlatformInfo→ 根据输入 shape 与数据类型字节长计算总数据量与单 tile 可承载元素数GetShapeAttrsInfo→ 依据MIN_ELEM_PER_CORE与实际可用的 block 数裁剪核数 → 计算大核/小核各自的数据量与 tile 数CalculateCoreBlockNums→ 通过platform_ascendc::PlatformAscendC::GetLibApiWorkSpaceSize()申请系统 workspaceGetWorkspaceSize→ 写入 tiling data 并设置blockDim。tiling 数据的载体定义在 op_kernel/floor_tiling_data.h包含smallCoreDataNum、bigCoreDataNum、finalBigTileNum、finalSmallTileNum、tileDataNum、smallTailDataNum、bigTailDataNum、tailBlockNum等字段用于在 Device 侧还原每个核的数据切分信息。AscendC 内核op_kernel 层内核主体为 op_kernel/floor.h 中的MyFloor::KernelFloor采用典型的 AscendC 流水线设计双缓冲BUFFER_NUM 2输入队列inQueueX与输出队列outQueueY各开 2 块缓冲Process()中CopyIn → Compute → CopyOut三段式循环实现搬运与计算的重叠核间负载均衡Init中根据tailBlockNum区分大核多分一个 block与小核通过bigCoreDataNum - smallCoreDataNum修正小核的全局缓冲偏移类型差异化计算Compute对float直接调用向量指令AscendC::Floor(yLocal, xLocal, n)一次完成对 FLOAT16/BF16先AscendC::Cast到 float 临时缓冲执行Floor后再以RoundMode::CAST_FLOOR舍入模式Cast回原类型从而规避半精度指令不支持直接 floor 的问题尾部数据搬运最后一个 tile 使用DataCopyExtParamsDataCopyPad处理非对齐的尾块数据。内核入口 op_kernel/floor.cpp 通过REGISTER_TILING_DEFAULT/GET_TILING_DATA_WITH_STRUCT接收 tiling 数据并按 tiling key见 floor_tiling_key.h实例化模板schMode对应 FLOAT 与其他类型的调度分支。单元测试与构建算子的正确性由 tests/ut 下的测试保障op_api/test_aclnn_floor.cpp验证两段式接口的调用与计算结果op_host/test_floor_tiling.cpp验证 tiling 数据计算的正确性含大核/小核、尾块等边界场景。构建方面CMakeLists.txt 通过统一的add_all_modules_sources(OPTYPE floor ACLNNTYPE aclnn_exclude)宏将 op_api、op_host、op_kernel 各层源码纳入 ops-math 工程编译。贡献说明根据 README 的贡献记录Floor 算子由个人开发者 xchencehn 于 2026/2/13 贡献至开源仓贡献内容为Floor 算子适配开源仓即完成了算子从闭源形态到 CANN ops-math 开源仓库的适配、文档编写与测试配套。小结本文从算子语义、产品支持、参数约束、两段式 aclnn 接口、端到端样例到三层源码实现完整剖析了 CANN ops-math 中 Floor 算子的全貌。核心要点可归纳为Floor 对每个元素向下取整负数的结果小于等于截断取整输入输出均为 ND 格式的 FLOAT/FLOAT16/BFLOAT16shape 一致、支持非连续张量调用时必须遵守GetWorkspaceSize 获取执行器与 workspace → 申请 workspace → 执行的两段式规范内核侧对 FLOAT 直接使用硬件 Floor 指令对半精度类型通过 float 中转 CAST_FLOOR舍入完成计算。读者可基于 调用样例 快速在自己的 Atlas A2 环境上复现并参照 接口文档 与各层源码继续深入。【免费下载链接】ops-math本项目是CANN提供的数学类基础计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-math创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表