
CANN ops-math FresnelSin 算子深度解析从数学定义到 NPU 图模式调用【免费下载链接】ops-math本项目是CANN提供的数学类基础计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-mathFresnelSin 是 CANN ops-math 数学算子库中用于计算 Fresnel 正弦积分S(x)的逐元素数学算子。本文以 math/fresnel_sin/README.md 为骨架结合算子定义、Shape/DataType 推导、Tiling 与 Kernel 源码系统讲解该算子的数学原理、支持的产品与数据类型、参数约束、图模式调用方式以及基于 Cephes 多项式逼近的 NPU 实现细节帮助读者在 Ascend NPU 上正确使用并深入理解该算子。产品支持情况FresnelSin 算子对当前主流 Ascend 硬件平台的支持情况如下来源math/fresnel_sin/README.md产品是否支持Ascend 950PR/Ascend 950DT√Atlas A3 训练系列产品/Atlas A3 推理系列产品√Atlas A2 训练系列产品/Atlas A2 推理系列产品√Atlas 200I/500 A2 推理产品×Atlas 推理系列产品√Atlas 训练系列产品√需要特别注意的是Atlas 200I/500 A2 推理产品不支持该算子。从源码层面看算子 CMake 配置math/fresnel_sin/CMakeLists.txt中set(SUPPORT_COMPUTE_UNIT ascend950)Tiling 目录为arch35即该算子的 Kernel 与 Tiling 实现主要面向 Arch35 架构Ascend 950 系列这与产品支持表中 Ascend 950 系列、Atlas A2/A3 系列等新平台支持、老一代 A2 推理小卡不支持的情况吻合。功能说明与数学定义FresnelSin 算子计算Fresnel 正弦积分Fresnel Sine Integral其数学定义为$$S(x) \int_{0}^{x} \sin\left(\frac{\pi}{2} t^{2}\right) \mathrm{d}t$$该函数是物理光学菲涅尔衍射、波动光学标量衍射理论、通信与信号处理中常用的特殊函数与 Fresnel 余弦积分 C(x) 成对出现。在 CANN ops-math 中该算子在 NPU 上对输入张量中的每个元素逐元素计算 S(x)是典型的 Elementwise逐元素数学算子。结合 math/fresnel_sin/op_kernel/arch35/fresnel_sin.h 的实现可以归纳出该函数在代码层面利用的几个关键数学性质奇函数性质S(−x) −S(x)核函数中通过计算 |x| 后恢复符号来利用该性质HandleSpecialValues中的Abs 符号恢复逻辑极限性质S(∞) 1/2S(−∞) −1/2核函数对 ±Inf 输入直接输出 ±0.5小参数多项式逼近当 |x| 较小时x² 2.5625采用有理多项式Cephes 系数逼近大参数渐近展开当 |x| 较大时采用渐近级数展开涉及 1/(π·x²) 的幂次。参数说明FresnelSin 算子共两个参数均为 ND 布局来源math/fresnel_sin/README.md 参数表参数名输入/输出/属性描述数据类型数据格式x输入待进行 Fresnel 正弦积分计算的入参公式中的 xBFLOAT16、FLOAT16、FLOATNDy输出Fresnel 正弦积分计算的出参公式中的 S(x)BFLOAT16、FLOAT16、FLOATND上述参数与数据类型在算子注册源码中得到完全印证。math/fresnel_sin/op_host/fresnel_sin_def.cpp 中通过OpDef注册了输入x与输出y输入xParamType(REQUIRED)支持{ge::DT_FLOAT, ge::DT_FLOAT16, ge::DT_BF16}三种数据类型格式为FORMAT_ND并开启AutoContiguous()输出y与输入相同的数据类型集合与 ND 格式该算子配置了DynamicRankSupportFlag(true)与DynamicShapeSupportFlag(true)即支持动态 Shape 与动态 Rank1D8DPrecisionReduceFlag(true)表示允许精度降级配置。此外算子原型 math/fresnel_sin/op_graph/fresnel_sin_proto.h 中的注册信息与 TensorFlow 的FresnelSin算子保持兼容REG_OP(FresnelSin).INPUT(x, ...).OUTPUT(y, ...)而 math/fresnel_sin/framework/fresnel_sin_tf_plugin.cpp 中FrameworkType(TENSORFLOW)、OriginOpType(FresnelSin)则明确了该算子在框架侧对接 TensorFlow 算子FresnelSin。约束说明不支持 DOUBLEFP64数据类型。该约束在多个源码层次均有体现算子定义层 math/fresnel_sin/op_host/fresnel_sin_def.cpp 中DataType仅声明DT_FLOAT/DT_FLOAT16/DT_BF16Tiling 层 math/fresnel_sin/op_host/arch35/fresnel_sin_tiling_arch35.cpp 中GetShapeAttrsInfo会检查输入数据类型supportedDtype集合仅包含DT_FLOAT, DT_FLOAT16, DT_BF16一旦输入为 DOUBLE 会返回GRAPH_FAILED并记录unsupported日志虽然算子原型fresnel_sin_proto.h的注释中提及 double但实际注册与 Tiling 校验均不接受 FP64。调用说明调用方式调用样例说明图模式调用math/fresnel_sin/examples/test_geir_fresnel_sin.cpp通过图模式调用 FresnelSin 算子图模式调用流程解析math/fresnel_sin/examples/test_geir_fresnel_sin.cpp 展示了完整的图模式调用流程主要包括以下步骤初始化 GE 全局环境ge::GEInitialize并设置全局选项例如{ge.exec.deviceId, 0}, {ge.graphRunMode, 1}构建计算图创建ge::Graph通过op::FresnelSin(fresnel_sin1)创建算子节点使用宏ADD_INPUT构造输入占位符op::Data并生成输入数据、ADD_OUTPUT声明输出 TensorDesc示例中的输入 Shape 为{2, 4}配置图输入输出graph.SetInputs(inputs).SetOutputs(outputs)创建 Session 并构图ge::Session创建后调用session-AddGraph(graph_id, graph, graph_options)执行图session-RunGraph(graph_id, input, output)触发编译与执行结果落盘与资源释放将输入/输出 Tensor 分别导出为tc_ge_irrun_test_0008_npu_input_{i}.bin与tc_ge_irrun_test_0008_npu_output_{i}.bin文件最后delete session并调用ge::GEFinalize()。值得注意的是示例还调用了aclgrphDumpGraph(graph, ./dump, ...)将图结构 dump 到本地便于调试。GenOnesData支持从本地test_input.bin读取真实输入数据若文件不存在则回退为全零数据并打印 WARN 提示。算子实现原理Cephes 多项式逼近FresnelSin 的 NPU Kernel 实现在 math/fresnel_sin/op_kernel/arch35/fresnel_sin.h命名空间NsFresnelSin其注释明确标注系数来源为Cephesfresnl.c/ TensorFlowspecial_math_op_misc_impl.h即与业界通用数值算法库保持一致。整体计算分为三条路径1. 小参数分支多项式逼近当 x² 2.5625 时采用有理分式逼近$$S(|x|) \approx |x|^{3} \cdot \frac{P_{SN}(x^{4})}{Q_{SD}(x^{4})}$$其中SN为 5 次多项式6 个系数、SD为首项为 1 的 6 次多项式7 个系数。核函数中通过Mul/Adds循环以Horner霍纳法求值P_SN与Q_SD再相除并乘以 |x|³Mul(b5, b6, b1)最终用CompareScalarSelect按掩码把该分支结果写入结果缓冲区b3见ComputePolynomialBranch。2. 大参数分支渐近展开当 x² ≥ 2.5625 时使用渐近级数展开。定义辅助量 t 1/(π·x²)、u t²将 S(x) 表示为 f 与 g 两项$$f 1 - u \cdot \frac{P_{FN}(u)}{Q_{FD}(u)},\qquad g t \cdot \frac{P_{GN}(u)}{Q_{GD}(u)}$$其中FN9 次10 系数、FD10 次11 系数、GN10 次11 系数、GD11 次12 系数四组系数在源码中均有完整定义。该分支还需要计算约化相位角(π/2)·(x² mod 4)随后通过Sin/Cos组合出振荡项与 f、g 加权合并见ComputeAsymptoticF/ComputeAsymptoticG/ComputeAsymptoticBranch。阈值常量SMALL_SQ 2.5625f与 Cephes 原始实现一致。3. 特殊值处理HandleSpecialValues依次处理三类特殊输入负数利用奇函数性质恢复符号S(−x) −S(x)NaN通过Div(0/0)构造 NaN凡x ! x的位置结果覆盖为 NaN±InfS(∞) → 0.5S(−∞) → −0.5核函数先用Abs检测无穷再按符号选择 ±0.5。精度与类型处理DoCompute会将输入统一 Cast 为FP32 内部工作精度CALC_BUFFER_COUNT 8个 FP32 缓冲区全部中间计算在 FP32 下完成最后在FinalizeAndOutput中若目标类型为 float 直接拷贝否则CastRoundMode::CAST_ROUND到 FP16/BF16 输出从而在低精度类型上也获得较好的数值稳定性。Tiling 与多核调度Tiling 实现位于 math/fresnel_sin/op_host/arch35/fresnel_sin_tiling_arch35.cpp运行时将形状与硬件信息翻译为 Kernel 执行参数核心逻辑如下平台信息通过GetCoreNumAiv()获取 AIV 核数、GetCoreMemSize(UB)获取 UB 容量总元素数totalNum取输入GetStorageShape().GetShapeSize()并校验维度数 ≤ 8MAX_DIM_NUM 8核间切分blockFactor CeilAlign(CeilDiv(totalNum, coreNum), ubBlockSize / dtypeSize)即按 AIV 核数均分并向上对齐实际使用核数为usedCoreNum CeilDiv(totalNum, blockFactor)UB 循环切分每个核内按ubFactor分块循环。UB 预算按每元素字节数计算bytesPerElem 2·dtypeSize 8·4 31 输入 1 输出缓冲 8 个 FP32 计算缓冲 3 个 uint8 掩码缓冲ubFactor FloorAlign(FloorDiv(ubSize, bytesPerElem), cmpAlign)其中cmpAlign为CompareScalar要求的 256 字节对齐FP32 为 64 元素FP16/BF16 为 128 元素空张量保护totalIdx 0时直接SetBlockDim(1)返回Workspace当前实现申请 1 个大小为 0 的 workspace 占位GetWorkspaceSize即不依赖额外全局工作空间。Tiling 数据通过 math/fresnel_sin/op_kernel/arch35/fresnel_sin_tiling_data.h 中定义的FresnelSinTilingData结构体totalNum/blockFactor/ubFactor三个int64_t字段传递给核函数。Kernel 入口 math/fresnel_sin/op_kernel/fresnel_sin_apt.cpp 展示了 NPU 侧的最终执行形态__global__ __aicore__ void fresnel_sin(GM_ADDR x, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling)注册为AIV 核KERNEL_TASK_TYPE_DEFAULT(KERNEL_TYPE_AIV_ONLY)通过GET_TILING_DATA_WITH_STRUCT取回 Tiling 数据实例化模板算子NsFresnelSin::FresnelSinDTYPE_X后依次Init设置全局缓冲区偏移、按核号切分数据与Process按ubFactor循环搬运 → 计算 → 回写使用DataCopyPad处理边界对齐。Shape/DataType 推导与单元测试FresnelSin 为逐元素算子Shape 与数据类型推导规则十分简洁Shape 推导输出 Shape 与输入 Shape 完全一致。见 math/fresnel_sin/op_host/fresnel_sin_infershape.cpp 中InferShape4FresnelSin的*output_shape *input_shapeDataType 推导输出数据类型继承输入。见 math/fresnel_sin/op_graph/fresnel_sin_graph_infer.cpp 中InferDataTypeForFresnelSin的context-SetOutputDataType(0, xDataType)。仓库配套的单测 math/fresnel_sin/tests/ut/op_host/test_fresnel_sin_infershape.cpp 使用 gtest 覆盖了多种 Shape 场景验证输出 Shape 不变这一行为1D{1024}float32、2D{32,64}float16、3D{4,8,16}bfloat16、4D{2,3,4,5}bfloat160D 标量rank0、单元素{1}、大 Shape{8,16,32,64}动态 Shape含-1维度的{1,-1,-1,64}与空张量{0,4}等边界情况均期望返回与原输入一致的输出 Shape。总结FresnelSin 算子是 CANN ops-math 中实现成熟、链路完整的特殊函数算子功能逐元素计算 Fresnel 正弦积分 S(x)支持 BFLOAT16/FLOAT16/FLOATND 布局1D8D 动态 Shape精度内部统一 FP32 计算采用与 Cephes/TensorFlow 一致的 SN/SD/FN/FD/GN/GD 六组多项式系数按 x² 阈值2.5625在小参数区间走有理逼近、大参数区间走渐近展开并妥善处理 NaN、±Inf 与负号性能通过 AIV 多核切分blockFactor UB 分块流水ubFactor实现大规模张量加速计算且无需额外 workspace生态算子原型与 TensorFlowFresnelSin对齐math/fresnel_sin/framework/fresnel_sin_tf_plugin.cpp并提供完整的图模式调用示例与 Shape 推导单元测试开发者可直接参照 math/fresnel_sin/examples/test_geir_fresnel_sin.cpp 在支持的产品上开展调用与验证。【免费下载链接】ops-math本项目是CANN提供的数学类基础计算算子库实现网络在NPU上加速计算。项目地址: https://gitcode.com/cann/ops-math创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考