CANN opbase op_common math 模块详解:CeilDiv、FloorDiv 与对齐工具函数实战指南

发布时间:2026/9/18 15:10:24
CANN opbase op_common math 模块详解:CeilDiv、FloorDiv 与对齐工具函数实战指南 CANN opbase op_common math 模块详解CeilDiv、FloorDiv 与对齐工具函数实战指南【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase本文围绕 op_common math 接口文档 展开系统讲解Ops::Base命名空间下FloorDiv、CeilDiv、FloorAlign、CeilAlign、IsFloatEqual五个数学工具函数的功能、约束与边界行为并结合 主机侧实现头文件、算子内核侧实现头文件 与 单元测试 剖析其底层细节。读完本文你可以在算子的 Tiling/Infershape 代码中正确选用这些工具函数处理除法取整、内存对齐和浮点相等判断并理解零值防护与溢出防护等边界设计。模块概览与源码位置math 模块是 op_common 提供给算子开发者的一组小型头文件级数学工具集其接口索引见 math.md涵盖以下五个函数FloorDiv向下取整的除法FloorAlign以 align 为单元向下对齐CeilDiv向上取整的除法CeilAlign以 align 为单元向上对齐IsFloatEqual判断两个 float/double 数值是否相等这组函数的主机侧Host实现集中在 math_util.h全部以 C 模板形式内联定义在Ops::Base命名空间中通过std::enable_if做类型约束因此算子开发者只需包含头文件即可在 Tiling 与 Infershape 代码中直接使用无需链接额外的库。FloorDiv向下取整的除法接口定义功能说明向下取整的除法。函数原型摘自 FloorDiv 文档template typename T auto FloorDiv(T x, T y) - typename std::enable_ifstd::is_integralT::value, T::type参数名输入/输出说明x输入被除数y输入除数返回值T返回向下取整的除法结果当除数为 0 时返回被除数零除数防护。约束说明除数和被除数请使用相同类型整型不包括 bool 类型。源码实现math_util.h 中的实现非常精炼template typename T auto FloorDiv(T x, T y) - typename std::enable_ifstd::is_integralT::value, T::type { return y 0 ? x : x / y; }要点有二零除数防护y 0时直接返回x避免触发除零异常/未定义行为。这在 Tiling 代码中处理动态 shapeshape 维度可能临时为 0 或非法值时非常重要让调用方无需每次都手动判空除数。整型语义底层直接复用 C 整型除法。从源码结构看对于负数操作数其实际行为是 C 标准的向零截断而非严格的数学向下取整在常见的 shape/大小计算场景中操作数均为非负值二者一致。调用示例关键代码示例如下仅供参考不支持直接拷贝运行FloorDivint32_t(10, 3) // 返回 3单元测试 test_util.cpp 中的验证覆盖了常规值与极大值边界EXPECT_EQ(FloorDivint32_t(10, 3), 3); EXPECT_EQ(FloorDivint32_t(87, 20), 4); EXPECT_EQ(FloorDivint64_t(999, 100), 9); EXPECT_EQ(FloorDivint32_t(std::numeric_limitsint32_t::max(), 8), 268435455);CeilDiv向上取整的除法接口定义功能说明向上取整的除法。由于符号类型存在不同处理需求文档见 CeilDiv给出了两个重载原型template typename T auto CeilDiv(T x, T y) - typename std::enable_ifstd::is_signedT::value, T::type template typename T auto CeilDiv(T x, T y) - typename std::enable_ifstd::is_unsignedT::value, T::type参数名输入/输出说明x输入被除数y输入除数返回值T返回向上取整的除法结果当除数为 0 时返回被除数。约束说明除数和被除数是相同类型整型不包括 bool 类型。调用示例CeilDivint32_t(5000, 4096) // 返回 2源码实现符号位异或技巧math_util.h 的两个重载实现如下// 有符号版本 template typename T auto CeilDiv(T x, T y) - typename std::enable_ifstd::is_signedT::value, T::type { if (y ! 0 x ! 0) { const T quotient x / y; return (x % y ! 0 ((x ^ y) 0)) ? (quotient 1) : quotient; } return x; } // 无符号版本 template typename T auto CeilDiv(T x, T y) - typename std::enable_ifstd::is_unsignedT::value, T::type { if (y ! 0 x ! 0) { const T quotient x / y; return (x % y ! 0) ? (quotient 1) : quotient; } return x; }这段实现值得细读它正确处理了 C 整型除法向零截断与向上取整之间的语义差无符号版本被除数、除数非负C 商就是向下取整值只要余数非零商加 1 即为向上取整结果。有符号版本(x ^ y) 0是一个符号位判断技巧——x与y同号同号时异或符号位为 0结果非负才需要加 1。当x、y异号时C 的向零截断商本身恰好等于数学意义下的向上取整值例如CeilDiv(10, -3)中 C 商为 -3而真正的 ceil(-10/3) -3因此不加 1 反而是正确的。单元测试 test_util.cpp 验证了典型取整行为EXPECT_EQ(CeilDivint32_t(5000, 4096), 2); EXPECT_EQ(CeilDivint32_t(130, 32), 5); EXPECT_EQ(CeilDivint32_t(999, 100), 10);FloorAlign 与 CeilAlign以 align 为单元的对齐FloorAlign向下对齐功能说明以align为单元向下对齐。原型摘自 FloorAlign 文档template typename T auto FloorAlign(T x, T align) - typename std::enable_ifstd::is_integralT::value, T::type参数名输入/输出说明x输入待向下对齐的数值align输入对齐的单元返回值T返回以align为单元向下对齐的结果当 align 为 0 时返回 0。约束说明待向下对齐的数值和对齐的单元是相同类型整型不包括 bool 类型。调用示例FloorAlignint32_t(12345, 4096) // 返回 12288源码实现 即align 0 ? 0 : x / align * align先整除得到对齐单元个数再乘回对齐单元天然保证结果落在align的整数倍上且不超过x。CeilAlign向上对齐功能说明以align为单元向上对齐。原型摘自 CeilAlign 文档template typename T auto CeilAlign(T x, T align) - typename std::enable_ifstd::is_integralT::value, T::type参数名输入/输出说明x输入待向上对齐的数值align输入对齐的单元返回值T返回以align为单元向上对齐的结果当 align 为 0 时返回 0。约束说明待向上对齐的数值和对齐的单元是相同类型整型不包括 bool 类型。调用示例CeilAlignint32_t(1000, 64) // 返回 1024源码实现 是五个函数中防御最充分的一个template typename T auto CeilAlign(T x, T align) - typename std::enable_ifstd::is_integralT::value, T::type { if (align 0) { return 0; } T div CeilDiv(x, align); if (div std::numeric_limitsT::max() / align) { return std::numeric_limitsT::max(); } return div * align; }这里有两层保护值得注意复用 CeilDiv向上对齐 向上取整的商 × 对齐单元逻辑上零除数防护也随之继承。乘法溢出防护在div * align之前先检查div max / align一旦乘积会溢出则钳制返回std::numeric_limitsT::max()而不是产生回绕后的错误值。单元测试 test_util.cpp 专门验证了这一钳制行为EXPECT_EQ(CeilAlignint32_t(1000, 64), 1024); EXPECT_EQ(CeilAlignint32_t(12345, 4096), 16384); EXPECT_EQ(CeilAlignint32_t(std::numeric_limitsint32_t::max(), 8), std::numeric_limitsint32_t::max());IsFloatEqual浮点相等判断接口定义功能说明判断两个 float 类型或 double 类型的数值是否相等。原型摘自 IsFloatEqual 文档template typename T auto IsFloatEqual(T a, T b) - typename std::enable_ifstd::is_floating_pointT::value, bool::type参数名输入/输出说明a输入待比较参数数据类型支持 float、doubleb输入待比较参数数据类型支持 float、double返回值bool类型。true表示两个 float 或 double 类型数值相等false表示不相等。约束说明文档标注为无但原型通过std::is_floating_pointT限定了只支持浮点类型。源码实现NaN、Inf 与 epsilon 三层判断直接写a b对浮点数并不可靠源码实现 分三层处理template typename T auto IsFloatEqual(T a, T b) - typename std::enable_ifstd::is_floating_pointT::value, bool::type { if (std::isnan(a) || std::isnan(b)) { return false; // NaN 与任何值包括自身都不相等 } if (std::isinf(a) || std::isinf(b)) { return std::signbit(a) std::signbit(b); // 同号无穷大视为相等 } return fabs(a - b) std::numeric_limitsT::epsilon(); // 正常值按类型 epsilon 容差比较 }NaN 优先IEEE 754 规定 NaN 不等于任何值任何含 NaN 的比较直接返回false无穷大按符号比较inf与inf相等、-inf与inf不等有限值按epsilon容差以类型自身的最小精度单位std::numeric_limitsT::epsilon()作为差值上界避免浮点表示误差导致本应相等的值被判为不等。调用示例Infershape 场景文档给出的示例展示了该函数在算子 Infershape 代码中的典型用法——读取delta属性并拒绝取值为 0 的配置摘自 IsFloatEqual 文档float delta; if (op.GetAttr(delta, delta) ge::GRAPH_FAILED) { std::string err_msg GetInputInvalidErrMsg(delta); VECTOR_INFER_SHAPE_INNER_ERR_REPORT(TbeGetName(op), err_msg); return GRAPH_FAILED; } if (IsFloatEqual(delta, 0.0f)) { string excepted_value ConcatString(not equal to 0); std::string err_msg GetAttrValueErrMsg(delta, ConcatString(delta), excepted_value); VECTOR_INFER_SHAPE_INNER_ERR_REPORT(TbeGetName(op), err_msg); return GRAPH_FAILED; }这段代码体现了属性值等于某个字面量的校验模式由于delta从属性解析而来直接用delta 0.0f比较存在浮点误差风险IsFloatEqual(delta, 0.0f)是更稳妥的写法。主机侧与算子内核侧实现对比值得注意的是opbase 为同一组工具函数提供了两份实现主机侧 op_host/util/math_util.h 与算子内核侧 op_kernel/math_util.h。内核侧版本通过__aicore__ inline修饰供 AI Core 上的 Tiling/Kernel 代码使用并针对小位宽类型做了位宽扩展防溢出处理摘自 op_kernel/math_util.htemplate typename T __aicore__ inline T CeilDiv(T a, T b) { using type typename std::conditionalsizeof(T) sizeof(uint8_t) || sizeof(T) sizeof(uint16_t), uint32_t, uint64_t::type; type res (static_casttype(a) static_casttype(b) - 1) / static_casttype(b); return static_castT(res); } template typename T __aicore__ inline T CeilAlign(T a, T b) { using type typename std::conditionalsizeof(T) sizeof(uint8_t) || sizeof(T) sizeof(uint16_t), uint32_t, uint64_t::type; type res (static_casttype(a) static_casttype(b) - 1) / static_casttype(b) * static_casttype(b); return static_castT(res); }从源码结构看内核侧CeilDiv/CeilAlign采用经典的(a b - 1) / b公式并先扩展到uint32_t/uint64_t再运算当T为uint8_t/uint16_t时a b - 1的中间结果可能超出原类型表示范围扩展位宽正是为了防止小类型下的中间溢出。开发者在两侧代码中调用时应留意内核侧实现针对非负整型场景设计负数语义与主机侧有符号版本不完全等同选型时请按目标运行环境包含对应头文件。单元测试与仓库内的实际应用单元测试覆盖单元测试 tests/op_common/ut/test_util.cpp 对四个整型函数逐一构造了断言覆盖三类典型输入常规值如CeilDivint32_t(5000, 4096) 2、FloorAlignint32_t(12345, 4096) 12288非整除边界如FloorAlignint32_t(1023, 64) 960、CeilAlignint32_t(257, 32) 288类型极限值如CeilDivint64_t(std::numeric_limitsint64_t::max(), 8)、CeilAlignuint64_t(std::numeric_limitsuint64_t::max(), 8)验证大值路径与溢出钳制逻辑。实际应用Reduce Tiling 调度在仓库的公共 Tiling 实现中这些函数是 shape/内存规模换算的高频工具。以 reduce_tiling.cpp 为例// 计算输入张量按元素大小折算的单元数 return CeilDiv(opDag_.maxInputBytes, static_castuint64_t(ge::GetSizeByDataType(opInput_.inputDtype))); ... // CacheLine 调度中的对齐换算 cacheLineStep CeilDiv(cacheSize, cacheLineShape); cacheLineStep cacheLineStep sliceShape_[i] ? FloorAlign(cacheLineStep, sliceShape_[i]) : cacheLineStep;以及 UBUniform Block空间计算中的CeilAlign(shape[i], ubBlockSize)reduce_tiling.cpp 第 582、667-688 行。可见CeilDivFloorAlign/CeilAlign的组合正是按块切分、块间对齐这一 Tiling 核心模式的数学基础先向上取整保证覆盖全部数据再向下对齐使块边界落在合法单元上。小结选型建议与边界速查结合本文对文档与源码的梳理给算子开发者一份速查表函数用途零值/边界行为关键防护FloorDiv向下取整除法y 为 0 时返回 x零除数防护CeilDiv向上取整除法y 或 x 为 0 时返回 x符号异或保证混合符号取整正确FloorAlign向下对齐align 为 0 时返回 0零对齐防护CeilAlign向上对齐align 为 0 时返回 0零对齐防护 乘法溢出钳制到类型最大值IsFloatEqual浮点相等判断NaN 恒不等Inf 按符号epsilon 容差比较这些函数都以模板内联形式提供、无额外依赖配合 math 接口索引文档 与各子页面查阅细节即可覆盖算子开发中绝大多数整型取整、对齐与浮点比较需求。【免费下载链接】opbase本项目是CANN算子库的基础框架库为算子提供公共依赖文件和基础调度能力。项目地址: https://gitcode.com/cann/opbase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询