文件最后提交记录最后更新时间
CANN训练营第二季社区任务 floor,Add the readme for the floor operator Co-authored-by: xchencehn<xchencehn@163.com> # message auto-generated for no-merge-commit merge: !162 merge master into master CANN训练营第二季社区任务 floor Created-by: xchencehn Commit-by: xchencehn Merged-by: cann-robot Description: ### 1 背景介绍 cann训练营二期算子开发任务 参考版本内置Floor算子的TBE实现,在昇腾NPU上使用Ascend C编程语言实现相同功能的算子。 1. 参考内置算子实现,需实现相同功能,包含相同数据类型和相同数据格式,其中int64,double数据类型可暂不支持,广播操作可暂不支持。 2. 算子性能要求持平原有TBE实现算子,当前可暂只支持在使用所有核进行计算时性能需不低于原有TBE算子95%。 3. TBE参考实现: &emsp; kernel实现:/usr/local/Ascend/ascend-toolkit/latest/opp/built-in/op_impl/ai_core/tbe/impl/dynamic/ &emsp; API路径:/usr/local/Ascend/ascend-toolkit/latest/python/site-packages/tbe/dsl ### 2 Floor算子现状分析 当前Floor算子的TBE实现如下: ``` @register_operator_compute("Floor", op_mode="dynamic", support_fusion=True, support_bfp16=True) def floor_compute(input_x, output_y, kernel_name="floor"): dtype_x = input_x.dtype.lower() if not tbe_platform.api_check_support("tbe.dsl.floor", dtype_x): input_x = tbe.cast_to(input_x, "float16") if tbe_platform.api_check_support("tbe.dsl.floor", "f322f32"): x_f32 = tbe.cast_to(input_x, "float32") res = tbe.floor(x_f32, "float32") else: res = tbe.floor(input_x) res = tbe.cast_to(res, dtype_x) return res @register_operator("Floor") @para_check.check_op_params(para_check.REQUIRED_INPUT, para_check.REQUIRED_OUTPUT, para_check.KERNEL_NAME) def floor(input_x, output_y, kernel_name="floor"):     ... check_list = ("bfloat16", "float16", "float32") para_check.check_dtype(input_dtype, check_list, param_name="input_x")     ... ``` 支持 bfloat16 , float16 , float32 三中数据格式,计算逻辑如下: 1. 如果 输入的 bfloat16 ,就转成 float16 2. 然后看只要硬件支持 f322f32 floor ,就把输入转为 float32 调用tbe.floor,只有不支持 f322f32 floor 才使用 float16 调用tbe.floor 3. 计算完成后转回原来输入的数据类型 ```mermaid graph TD A["开始 floor_compute"] --> B{"输入类型 dtype_x == bfloat16 ?"} B -- 是 --> C["将输入 cast_to float16"] B -- 否 --> D["保持输入类型不变"] C --> E{"硬件支持 f32→f32 floor ?"} D --> E E -- 是 --> F["将输入 cast_to float32<br>执行 tbe.floor(float32)"] E -- 否 --> G["执行 tbe.floor(当前类型)<br>(如 float16)"] F --> H["结果 cast_to 原始 dtype_x"] G --> H H --> I["返回最终结果"] ``` ### 3 Ascend C 算子设计 产品支持: &emsp;&emsp; Atlas A2 训练系列产品/Atlas 800I A2推理产品 接口支持: &emsp;&emsp; 适配Aclnn接口和图模式调用 数据类型支持: | 名称 | 类别 | dtype | format | shape | 介绍 | | --- | --- | --- | --- | --- | --- | | Input | 输入 | bfloat16, float16, float32 | ND | all | 输出 | | y | 输出 | bfloat16, float16, float32 | ND | 同输入 | 输出 | Host侧设计: 不需要广播,算子计算过程不涉及数据的维度信息,故在host侧将数据视为一维向量,仅考虑数据个数,不考虑数据维度信息。 任务均分:coreNum 根据输入长度和块大小动态调整,确保每个核心处理的数据块数均匀。 批量搬运:tileBlockNum 和 tileDataNum 计算单次搬运的数据量,通过 finalSmallTileNum 和 finalBigTileNum 确定小核/大核的搬运次数,将多次搬运合并为批量操作,减少冗余开销。尾块的处理逻辑确保不完整块也能被合并到计算流程中,避免数据碎片。 1) 分核策略 Host 侧将输入视为一维向量,按总元素数切分; 每个核至少处理 512 个元素,且处理数据需满足 512B 对齐; 将对齐后的输入按 block 均分到各核,不能整除时前部分核会多分 1 个 block,形成大小核(big/small core); 每个核心内部根据 UB 大小计算单次可处理的 tile 大小,核心数据再分成若干 tile + 1 个尾块。 2) 数据分块和内存优化策略 开启double buffer; 根据UB内存大小和预定义的BLOCK_SIZE及BUFFER_NUM,计算出每个Tile块的数据数量; 将输入数据按照计算出的Tile块大小进行切分,计算出每个core需要处理的数据块数量和最后一个block的剩余数据量; 将计算出的切分参数(如每个core的数据量、Tile块大小等)设置到FloorTilingData对象中。 3) tilingkey规划策略 不涉及 Kernel侧设计: &emsp;&emsp; kernel执行分为Init和Process两个阶段,其中Process再分为CopyIn、Compute、CopyOut三步; &emsp;&emsp; AscendC::Floor支持float16、float32,将bfloat16转成float32进行计算, 其他直接计算; &emsp;&emsp; 开启double buffer,将流水并行,提高运算效率。 ```mermaid graph TD A["开始 floor_compute"] --> B{"输入类型 TYPE_X == float32 ?"} B -- 否 --> C[" Ascend::Cast 到 float32"] C --> E["执行 Ascend::Floor 运算"] E --> F[" Ascend::Cast 到TYPE_X"] B -- 是 --> H["执行 Ascend::Floor 运算"] F --> G["返回最终结果"] H --> G ``` ### 4 算子测试 采用aclnn调用测试 See merge request: cann/ops-math!1623 个月前