已合并
提交Ascend C实现的Cast算子 #646
skywang2创建于 1月4日
提交Ascend C实现的Cast算子 #646
已合并
共 13 个文件变更+2387-0
| @@ -0,0 +1,11 @@ | |||
| 1 | +# ---------------------------------------------------------------------------- | ||
| 2 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +# ---------------------------------------------------------------------------- | ||
| 10 | + | ||
| 11 | +add_all_modules_sources(OPTYPE cast ACLNNTYPE aclnn_exclude) | ||
| @@ -0,0 +1,38 @@ | |||
| 1 | +# Cast | ||
| 2 | +## 贡献说明 | ||
| 3 | +| 贡献者 | 贡献方 | 贡献算子 | 贡献时间 | 贡献内容 | | ||
| 4 | +|--------|------------------|-------|-----------|-----------| | ||
| 5 | +| skywang2 | 个人开发者 | Cast | 2025/12/31 | 新增Cast算子 | | ||
| 6 | + | ||
| 7 | +### 算子描述 | ||
| 8 | +`Cast`算子提供将tensor从源数据类型转换为目标数据类型的功能。 | ||
| 9 | + | ||
| 10 | +### 算子规格描述 | ||
| 11 | + | ||
| 12 | +<table> | ||
| 13 | +<tr><th align="center">算子类型(OpType)</th><th colspan="4" align="center">Cast</th></tr> | ||
| 14 | +<tr><td rowspan="2" align="center">算子输入</td><td align="center">name</td><td align="center">type</td><td align="center">data type</td><td align="center">format</td></tr> | ||
| 15 | +<tr><td align="center">x</td><td align="center">tensor</td><td align="center">float16, float32, int32, int8, uint8, bool, int64, bfloat16, int16</td><td align="center">ND</td></tr> | ||
| 16 | +<tr><td rowspan="1" align="center">算子输出</td><td align="center">out</td><td align="center">tensor</td><td align="center">float16, float32, int32, int8, uint8, bool, int64, bfloat16, int16</td><td align="center">ND</td></tr> | ||
| 17 | +<tr><td rowspan="1" align="center">算子属性</td><td align="center">dstType</td><td align="center">attr</td><td align="center">int64</td><td align="center">-</td></tr> | ||
| 18 | +<tr><td rowspan="1" align="center">核函数名</td><td colspan="4" align="center">cast</td></td></tr> | ||
| 19 | +</table> | ||
| 20 | + | ||
| 21 | +### 支持的产品型号 | ||
| 22 | +本样例支持如下产品型号: | ||
| 23 | +- Atlas A2训练系列产品 | ||
| 24 | +- Atlas 800I A2推理产品 | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +### 环境要求 | ||
| 28 | +编译运行此样例前,请参考[《CANN软件安装指南》](https://hiascend.com/document/redirect/CannCommunityInstSoftware)完成开发运行环境的部署。 | ||
| 29 | + | ||
| 30 | +### 算子调用 | ||
| 31 | +测试命令调用方式:[build.sh](../../../docs/zh/invocation/quick_op_invocation.md) | ||
| 32 | +<table> | ||
| 33 | + <th>目录</th><th>描述</th> | ||
| 34 | + <tr> | ||
| 35 | + <td><a href="./examples/test_aclnn_cast.cpp"> test_aclnn_cast.cpp</td><td>通过aclnn调用的方式调用Cast算子</td> | ||
| 36 | + </tr> | ||
| 37 | +</table> | ||
| 38 | + | ||
| @@ -0,0 +1,358 @@ | |||
| 1 | +# aclnnCast | ||
| 2 | + | ||
| 3 | + | ||
| 4 | +## 产品支持情况 | ||
| 5 | + | ||
| 6 | +| 产品 | 是否支持 | | ||
| 7 | +| :----------------------------------------------------------- | :------: | | ||
| 8 | +| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | √ | | ||
| 9 | + | ||
| 10 | +## 功能说明 | ||
| 11 | + | ||
| 12 | +将输入tensor转换为指定的dtype类型。 | ||
| 13 | + | ||
| 14 | +## 函数原型 | ||
| 15 | + | ||
| 16 | +每个算子分为[两段式接口](../../../../docs/zh/context/两段式接口.md),必须先调用“aclnnCastGetWorkspaceSize”接口获取计算所需workspace大小以及包含了算子计算流程的执行器,再调用“aclnnCast”接口执行计算。 | ||
| 17 | +```Cpp | ||
| 18 | +aclnnStatus aclnnCastGetWorkspaceSize( | ||
| 19 | + const aclTensor *self, | ||
| 20 | + const aclDataType dtype, | ||
| 21 | + aclTensor *out, | ||
| 22 | + uint64_t *workspaceSize, | ||
| 23 | + aclOpExecutor **executor) | ||
| 24 | +``` | ||
| 25 | +```Cpp | ||
| 26 | +aclnnStatus aclnnCast( | ||
| 27 | + void *workspace, | ||
| 28 | + uint64_t workspaceSize, | ||
| 29 | + aclOpExecutor *executor, | ||
| 30 | + aclrtStream stream) | ||
| 31 | +``` | ||
| 32 | +## aclnnCastGetWorkspaceSize | ||
| 33 | + | ||
| 34 | +- **参数说明:** | ||
| 35 | + | ||
| 36 | + <table style="undefined;table-layout: fixed; width: 1495px"><colgroup> | ||
| 37 | + <col style="width: 146px"> | ||
| 38 | + <col style="width: 110px"> | ||
| 39 | + <col style="width: 301px"> | ||
| 40 | + <col style="width: 219px"> | ||
| 41 | + <col style="width: 328px"> | ||
| 42 | + <col style="width: 101px"> | ||
| 43 | + <col style="width: 143px"> | ||
| 44 | + <col style="width: 147px"> | ||
| 45 | + </colgroup> | ||
| 46 | + <thead> | ||
| 47 | + <tr> | ||
| 48 | + <th>参数名</th> | ||
| 49 | + <th>输入/输出</th> | ||
| 50 | + <th>描述</th> | ||
| 51 | + <th>使用说明</th> | ||
| 52 | + <th>数据类型</th> | ||
| 53 | + <th>数据格式</th> | ||
| 54 | + <th>维度(shape)</th> | ||
| 55 | + <th>非连续Tensor</th> | ||
| 56 | + </tr></thead> | ||
| 57 | + <tbody> | ||
| 58 | + <tr> | ||
| 59 | + <td>self</td> | ||
| 60 | + <td>输入</td> | ||
| 61 | + <td>待进行cast计算的入参,Device侧的aclTensor。</td> | ||
| 62 | + <td>-</td> | ||
| 63 | + <td>FLOAT16、FLOAT、DOUBLE、INT8、UINT8、INT16、UINT16、INT32、UINT32、INT64、UINT64、BOOL、COMPLEX32、COMPLEX64、COMPLEX128、BFLOAT16、HIFLOAT8、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT4_E2M1、FLOAT4_E1M2</td> | ||
| 64 | + <td>ND</td> | ||
| 65 | + <td>0-8</td> | ||
| 66 | + <td>√</td> | ||
| 67 | + </tr> | ||
| 68 | + <tr> | ||
| 69 | + <td>dtype</td> | ||
| 70 | + <td>属性</td> | ||
| 71 | + <td>输入tensor要转换的目标dtype。</td> | ||
| 72 | + <td>-</td> | ||
| 73 | + <td>const aclDataType</td> | ||
| 74 | + <td>-</td> | ||
| 75 | + <td>-</td> | ||
| 76 | + <td>-</td> | ||
| 77 | + </tr> | ||
| 78 | + <tr> | ||
| 79 | + <td>out</td> | ||
| 80 | + <td>输出</td> | ||
| 81 | + <td>待进行cast计算的出参,Device侧的aclTensor。</td> | ||
| 82 | + <td>shape与self相同。</td> | ||
| 83 | + <td>FLOAT16、FLOAT、DOUBLE、INT8、UINT8、INT16、UINT16、INT32、UINT32、INT64、UINT64、BOOL、COMPLEX32、COMPLEX64、COMPLEX128、BFLOAT16、HIFLOAT8、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT4_E2M1、FLOAT4_E1M2、INT4(暂不支持非连续Tensor)</td> | ||
| 84 | + <td>ND</td> | ||
| 85 | + <td>0-8</td> | ||
| 86 | + <td>√</td> | ||
| 87 | + </tr> | ||
| 88 | + <tr> | ||
| 89 | + <td>workspaceSize</td> | ||
| 90 | + <td>输出</td> | ||
| 91 | + <td>返回需要在Device侧申请的workspace大小。</td> | ||
| 92 | + <td>-</td> | ||
| 93 | + <td>-</td> | ||
| 94 | + <td>-</td> | ||
| 95 | + <td>-</td> | ||
| 96 | + <td>-</td> | ||
| 97 | + </tr> | ||
| 98 | + <tr> | ||
| 99 | + <td>executor</td> | ||
| 100 | + <td>输出</td> | ||
| 101 | + <td>返回op执行器,包含了算子计算流程。</td> | ||
| 102 | + <td>-</td> | ||
| 103 | + <td>-</td> | ||
| 104 | + <td>-</td> | ||
| 105 | + <td>-</td> | ||
| 106 | + <td>-</td> | ||
| 107 | + </tr> | ||
| 108 | + </tbody></table> | ||
| 109 | + | ||
| 110 | + - <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term>:不支持COMPLEX32、HIFLOAT8、FLOAT8_E5M2、FLOAT8_E4M3FN、FLOAT4_E2M1、FLOAT4_E1M2、INT4。 | ||
| 111 | + | ||
| 112 | +- **返回值:** | ||
| 113 | + | ||
| 114 | + aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../../docs/zh/context/aclnn返回码.md)。 | ||
| 115 | + | ||
| 116 | + 第一段接口会完成入参校验,出现以下场景时报错: | ||
| 117 | + | ||
| 118 | + <table style="undefined;table-layout: fixed;width: 1155px"><colgroup> | ||
| 119 | + <col style="width: 319px"> | ||
| 120 | + <col style="width: 144px"> | ||
| 121 | + <col style="width: 671px"> | ||
| 122 | + </colgroup> | ||
| 123 | + <thead> | ||
| 124 | + <tr> | ||
| 125 | + <th>返回码</th> | ||
| 126 | + <th>错误码</th> | ||
| 127 | + <th>描述</th> | ||
| 128 | + </tr> | ||
| 129 | + </thead> | ||
| 130 | + <tbody> | ||
| 131 | + <tr> | ||
| 132 | + <td>ACLNN_ERR_PARAM_NULLPTR</td> | ||
| 133 | + <td>161001</td> | ||
| 134 | + <td>传入的tensor或out是空指针。</td> | ||
| 135 | + </tr> | ||
| 136 | + <tr> | ||
| 137 | + <td rowspan="5">ACLNN_ERR_PARAM_INVALID</td> | ||
| 138 | + <td rowspan="5">161002</td> | ||
| 139 | + <td>self的数据类型和数据格式不在支持的范围之内。</td> | ||
| 140 | + </tr> | ||
| 141 | + <tr> | ||
| 142 | + <td>self的数据格式与out的数据格式不同。</td> | ||
| 143 | + </tr> | ||
| 144 | + <tr> | ||
| 145 | + <td>self的shape与out的shape不同。</td> | ||
| 146 | + </tr> | ||
| 147 | + <tr> | ||
| 148 | + <td>参数dtype不在输出支持的数据格式范围之内。</td> | ||
| 149 | + </tr> | ||
| 150 | + <tr> | ||
| 151 | + <td>out的数据类型为INT4时,self为非连续Tensor。</td> | ||
| 152 | + </tr> | ||
| 153 | + <tr> | ||
| 154 | + <td>ACLNN_ERR_INNER_TILING_ERROR</td> | ||
| 155 | + <td>561002</td> | ||
| 156 | + <td>out的数据类型为INT4时,self的shape尾轴为奇数。</td> | ||
| 157 | + </tr> | ||
| 158 | + </tbody></table> | ||
| 159 | + | ||
| 160 | +## aclnnCast | ||
| 161 | + | ||
| 162 | +- **参数说明:** | ||
| 163 | + <table style="undefined;table-layout: fixed; width: 598px"><colgroup> | ||
| 164 | + <col style="width: 173px"> | ||
| 165 | + <col style="width: 173px"> | ||
| 166 | + <col style="width: 668px"> | ||
| 167 | + </colgroup> | ||
| 168 | + <thead> | ||
| 169 | + <tr> | ||
| 170 | + <th>参数名</th> | ||
| 171 | + <th>输入/输出</th> | ||
| 172 | + <th>描述</th> | ||
| 173 | + </tr></thead> | ||
| 174 | + <tbody> | ||
| 175 | + <tr> | ||
| 176 | + <td>workspace</td> | ||
| 177 | + <td>输入</td> | ||
| 178 | + <td>在Device侧申请的workspace内存地址。</td> | ||
| 179 | + </tr> | ||
| 180 | + <tr> | ||
| 181 | + <td>workspaceSize</td> | ||
| 182 | + <td>输入</td> | ||
| 183 | + <td>在Device侧申请的workspace大小,由第一段接口aclnnCastGetWorkspaceSize获取。</td> | ||
| 184 | + </tr> | ||
| 185 | + <tr> | ||
| 186 | + <td>executor</td> | ||
| 187 | + <td>输入</td> | ||
| 188 | + <td>op执行器,包含了算子计算流程。</td> | ||
| 189 | + </tr> | ||
| 190 | + <tr> | ||
| 191 | + <td>stream</td> | ||
| 192 | + <td>输入</td> | ||
| 193 | + <td>指定执行任务的Stream。</td> | ||
| 194 | + </tr> | ||
| 195 | + </tbody> | ||
| 196 | + </table> | ||
| 197 | + | ||
| 198 | + | ||
| 199 | +- **返回值:** | ||
| 200 | + | ||
| 201 | + aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../../docs/zh/context/aclnn返回码.md)。 | ||
| 202 | + | ||
| 203 | +## 约束说明 | ||
| 204 | + | ||
| 205 | +- 确定性计算: | ||
| 206 | + - aclnnCast默认确定性实现。 | ||
| 207 | + | ||
| 208 | +- 针对数据类型从浮点数转换为整型的场景: | ||
| 209 | + 输入数据中存在nan,则将nan转换为0。 | ||
| 210 | + | ||
| 211 | +- 针对输入数据类型为BOOL、COMPLEX32、COMPLEX64、COMPLEX128、FLOAT4_E2M1、FLOAT4_E1M2的场景: | ||
| 212 | + 不支持输入为非连续。 | ||
| 213 | + | ||
| 214 | +- <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term>: | ||
| 215 | + - 针对数据类型从int32转换为int8的场景: | ||
| 216 | + 只能保证输入数据在(-2048, 1920)范围内精度无误差。 | ||
| 217 | + - 针对数据类型从float64/complex64/complex128转换为uint8的场景: | ||
| 218 | + 只能保证输入数据为非负数精度无误差。 | ||
| 219 | + | ||
| 220 | + | ||
| 221 | + | ||
| 222 | +## 调用示例 | ||
| 223 | + | ||
| 224 | +示例代码如下,仅供参考,具体编译和执行过程请参考[编译与运行样例](../../../../docs/zh/context/编译与运行样例.md)。 | ||
| 225 | +```Cpp | ||
| 226 | +#include <iostream> | ||
| 227 | +#include <vector> | ||
| 228 | +#include "acl/acl.h" | ||
| 229 | +#include "aclnnop/aclnn_cast.h" | ||
| 230 | + | ||
| 231 | +#define CHECK_RET(cond, return_expr) \ | ||
| 232 | + do { \ | ||
| 233 | + if (!(cond)) { \ | ||
| 234 | + return_expr; \ | ||
| 235 | + } \ | ||
| 236 | + } while (0) | ||
| 237 | + | ||
| 238 | +#define LOG_PRINT(message, ...) \ | ||
| 239 | + do { \ | ||
| 240 | + printf(message, ##__VA_ARGS__); \ | ||
| 241 | + } while (0) | ||
| 242 | + | ||
| 243 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 244 | + int64_t shapeSize = 1; | ||
| 245 | + for (auto i : shape) { | ||
| 246 | + shapeSize *= i; | ||
| 247 | + } | ||
| 248 | + return shapeSize; | ||
| 249 | +} | ||
| 250 | + | ||
| 251 | +int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 252 | + // 固定写法,初始化 | ||
| 253 | + auto ret = aclInit(nullptr); | ||
| 254 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 255 | + ret = aclrtSetDevice(deviceId); | ||
| 256 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 257 | + ret = aclrtCreateStream(stream); | ||
| 258 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 259 | + return 0; | ||
| 260 | +} | ||
| 261 | + | ||
| 262 | +template <typename T> | ||
| 263 | +int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 264 | + aclDataType dataType, aclTensor** tensor) { | ||
| 265 | + auto size = GetShapeSize(shape) * sizeof(T); | ||
| 266 | + // 调用aclrtMalloc申请device侧内存 | ||
| 267 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 268 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 269 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 270 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 271 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 272 | + | ||
| 273 | + // 计算连续tensor的strides | ||
| 274 | + std::vector<int64_t> strides(shape.size(), 1); | ||
| 275 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 276 | + strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 277 | + } | ||
| 278 | + | ||
| 279 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 280 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 281 | + shape.data(), shape.size(), *deviceAddr); | ||
| 282 | + return 0; | ||
| 283 | +} | ||
| 284 | + | ||
| 285 | +int main() { | ||
| 286 | + // 1. (固定写法)device/stream初始化,参考acl API文档 | ||
| 287 | + // 根据自己的实际device填写deviceId | ||
| 288 | + int32_t deviceId = 0; | ||
| 289 | + aclrtStream stream; | ||
| 290 | + auto ret = Init(deviceId, &stream); | ||
| 291 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 292 | + | ||
| 293 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 294 | + std::vector<int64_t> selfShape = {4, 2}; | ||
| 295 | + std::vector<int64_t> outShape = {4, 2}; | ||
| 296 | + | ||
| 297 | + void* selfDeviceAddr = nullptr; | ||
| 298 | + void* outDeviceAddr = nullptr; | ||
| 299 | + aclTensor* self = nullptr; | ||
| 300 | + aclTensor* out = nullptr; | ||
| 301 | + | ||
| 302 | + std::vector<float> selfHostData = {0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1}; | ||
| 303 | + std::vector<double> outHostData = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; | ||
| 304 | + | ||
| 305 | + // 创建self aclTensor | ||
| 306 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 307 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 308 | + // 创建out aclTensor | ||
| 309 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_DOUBLE, &out); | ||
| 310 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 311 | + | ||
| 312 | + // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 313 | + uint64_t workspaceSize = 0; | ||
| 314 | + aclOpExecutor* executor; | ||
| 315 | + // 调用aclnnCast第一段接口 | ||
| 316 | + ret = aclnnCastGetWorkspaceSize(self, aclDataType::ACL_DOUBLE, out, &workspaceSize, &executor); | ||
| 317 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnCastGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 318 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 319 | + void* workspaceAddr = nullptr; | ||
| 320 | + if (workspaceSize > 0) { | ||
| 321 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 322 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 323 | + } | ||
| 324 | + // 调用aclnnCast第二段接口 | ||
| 325 | + ret = aclnnCast(workspaceAddr, workspaceSize, executor, stream); | ||
| 326 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnCast failed. ERROR: %d\n", ret); return ret); | ||
| 327 | + | ||
| 328 | + // 4. (固定写法)同步等待任务执行结束 | ||
| 329 | + ret = aclrtSynchronizeStream(stream); | ||
| 330 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 331 | + | ||
| 332 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 333 | + auto size = GetShapeSize(outShape); | ||
| 334 | + std::vector<double> resultData(size, 0); | ||
| 335 | + ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 336 | + size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 337 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 338 | + for (int64_t i = 0; i < size; i++) { | ||
| 339 | + LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 340 | + } | ||
| 341 | + | ||
| 342 | + // 6. 释放aclTensor,需要根据具体API的接口定义修改 | ||
| 343 | + aclDestroyTensor(self); | ||
| 344 | + aclDestroyTensor(out); | ||
| 345 | + | ||
| 346 | + // 7. 释放device 资源 | ||
| 347 | + aclrtFree(selfDeviceAddr); | ||
| 348 | + aclrtFree(outDeviceAddr); | ||
| 349 | + if (workspaceSize > 0) { | ||
| 350 | + aclrtFree(workspaceAddr); | ||
| 351 | + } | ||
| 352 | + aclrtDestroyStream(stream); | ||
| 353 | + aclrtResetDevice(deviceId); | ||
| 354 | + aclFinalize(); | ||
| 355 | + | ||
| 356 | + return 0; | ||
| 357 | +} | ||
| 358 | +``` | ||
| @@ -0,0 +1,142 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + do { \ | ||
| 18 | + if (!(cond)) { \ | ||
| 19 | + return_expr; \ | ||
| 20 | + } \ | ||
| 21 | + } while (0) | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + do { \ | ||
| 25 | + printf(message, ##__VA_ARGS__); \ | ||
| 26 | + } while (0) | ||
| 27 | + | ||
| 28 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 29 | + int64_t shapeSize = 1; | ||
| 30 | + for (auto i : shape) { | ||
| 31 | + shapeSize *= i; | ||
| 32 | + } | ||
| 33 | + return shapeSize; | ||
| 34 | +} | ||
| 35 | + | ||
| 36 | +int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 37 | + // 固定写法,初始化 | ||
| 38 | + auto ret = aclInit(nullptr); | ||
| 39 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 40 | + ret = aclrtSetDevice(deviceId); | ||
| 41 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 42 | + ret = aclrtCreateStream(stream); | ||
| 43 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 44 | + return 0; | ||
| 45 | +} | ||
| 46 | + | ||
| 47 | +template <typename T> | ||
| 48 | +int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 49 | + aclDataType dataType, aclTensor** tensor) { | ||
| 50 | + auto size = GetShapeSize(shape) * sizeof(T); | ||
| 51 | + // 调用aclrtMalloc申请device侧内存 | ||
| 52 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 53 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 54 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 55 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 56 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 57 | + | ||
| 58 | + // 计算连续tensor的strides | ||
| 59 | + std::vector<int64_t> strides(shape.size(), 1); | ||
| 60 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 61 | + strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 62 | + } | ||
| 63 | + | ||
| 64 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 65 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 66 | + shape.data(), shape.size(), *deviceAddr); | ||
| 67 | + return 0; | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +int main() { | ||
| 71 | + // 1. (固定写法)device/stream初始化,参考acl API文档 | ||
| 72 | + // 根据自己的实际device填写deviceId | ||
| 73 | + int32_t deviceId = 0; | ||
| 74 | + aclrtStream stream; | ||
| 75 | + auto ret = Init(deviceId, &stream); | ||
| 76 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 77 | + | ||
| 78 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 79 | + std::vector<int64_t> selfShape = {4, 2}; | ||
| 80 | + std::vector<int64_t> outShape = {4, 2}; | ||
| 81 | + | ||
| 82 | + void* selfDeviceAddr = nullptr; | ||
| 83 | + void* outDeviceAddr = nullptr; | ||
| 84 | + aclTensor* self = nullptr; | ||
| 85 | + aclTensor* out = nullptr; | ||
| 86 | + | ||
| 87 | + std::vector<float> selfHostData = {0.1, 1.1, 2.1, 3.1, 4.1, 5.1, 6.1, 7.1}; | ||
| 88 | + std::vector<double> outHostData = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0}; | ||
| 89 | + | ||
| 90 | + // 创建self aclTensor | ||
| 91 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 92 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 93 | + // 创建out aclTensor | ||
| 94 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_DOUBLE, &out); | ||
| 95 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 96 | + | ||
| 97 | + // 3. 调用CANN算子库API,需要修改为具体的Api名称 | ||
| 98 | + uint64_t workspaceSize = 0; | ||
| 99 | + aclOpExecutor* executor; | ||
| 100 | + // 调用aclnnCast第一段接口 | ||
| 101 | + ret = aclnnCastGetWorkspaceSize(self, aclDataType::ACL_DOUBLE, out, &workspaceSize, &executor); | ||
| 102 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnCastGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 103 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 104 | + void* workspaceAddr = nullptr; | ||
| 105 | + if (workspaceSize > static_cast<uint64_t>(0)) { | ||
| 106 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 107 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 108 | + } | ||
| 109 | + // 调用aclnnCast第二段接口 | ||
| 110 | + ret = aclnnCast(workspaceAddr, workspaceSize, executor, stream); | ||
| 111 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnCast failed. ERROR: %d\n", ret); return ret); | ||
| 112 | + | ||
| 113 | + // 4. (固定写法)同步等待任务执行结束 | ||
| 114 | + ret = aclrtSynchronizeStream(stream); | ||
| 115 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 116 | + | ||
| 117 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 118 | + auto size = GetShapeSize(outShape); | ||
| 119 | + std::vector<double> resultData(size, 0); | ||
| 120 | + ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 121 | + size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 122 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 123 | + for (int64_t i = 0; i < size; i++) { | ||
| 124 | + LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + // 6. 释放aclTensor,需要根据具体API的接口定义修改 | ||
| 128 | + aclDestroyTensor(self); | ||
| 129 | + aclDestroyTensor(out); | ||
| 130 | + | ||
| 131 | + // 7. 释放device 资源 | ||
| 132 | + aclrtFree(selfDeviceAddr); | ||
| 133 | + aclrtFree(outDeviceAddr); | ||
| 134 | + if (workspaceSize > static_cast<uint64_t>(0)) { | ||
| 135 | + aclrtFree(workspaceAddr); | ||
| 136 | + } | ||
| 137 | + aclrtDestroyStream(stream); | ||
| 138 | + aclrtResetDevice(deviceId); | ||
| 139 | + aclFinalize(); | ||
| 140 | + | ||
| 141 | + return 0; | ||
| 142 | +} | ||
| @@ -0,0 +1,176 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +using namespace op; | ||
| 26 | + | ||
| 27 | +extern "C" { | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +/* Cast 算子的完整计算流程如下: | ||
| 31 | + * self dtype | ||
| 32 | + * \ / | ||
| 33 | + * Contiguous(workspace_0) / | ||
| 34 | + * \ / | ||
| 35 | + * Cast(workspace_1) | ||
| 36 | + * | | ||
| 37 | + * ViewCopy | ||
| 38 | + * | | ||
| 39 | + * result | ||
| 40 | + */ | ||
| 41 | + | ||
| 42 | +static const size_t MAX_DIM = 8; | ||
| 43 | + | ||
| 44 | +// 根据API定义,需要列出所能支持的所有dtype | ||
| 45 | +static const std::initializer_list<op::DataType> ASCEND910_DTYPE_SUPPORT_LIST = { | ||
| 46 | + op::DataType::DT_FLOAT16, op::DataType::DT_FLOAT, op::DataType::DT_DOUBLE, op::DataType::DT_INT8, | ||
| 47 | + op::DataType::DT_UINT8, op::DataType::DT_INT16, op::DataType::DT_INT32, op::DataType::DT_INT64, | ||
| 48 | + op::DataType::DT_UINT16, op::DataType::DT_UINT32, op::DataType::DT_UINT64, op::DataType::DT_BOOL, | ||
| 49 | + op::DataType::DT_COMPLEX64, op::DataType::DT_COMPLEX128}; | ||
| 50 | +static const std::initializer_list<op::DataType> DTYPE_SUPPORT_LIST_DEFAULT = { | ||
| 51 | + op::DataType::DT_FLOAT16, op::DataType::DT_FLOAT, op::DataType::DT_DOUBLE, op::DataType::DT_INT8, | ||
| 52 | + op::DataType::DT_UINT8, op::DataType::DT_INT16, op::DataType::DT_INT32, op::DataType::DT_INT64, | ||
| 53 | + op::DataType::DT_UINT16, op::DataType::DT_UINT32, op::DataType::DT_UINT64, op::DataType::DT_BOOL, | ||
| 54 | + op::DataType::DT_COMPLEX64, op::DataType::DT_COMPLEX128, op::DataType::DT_BF16}; | ||
| 55 | +static const std::initializer_list<op::DataType> ASCEND950_DTYPE_SUPPORT_LIST = { | ||
| 56 | + op::DataType::DT_FLOAT16, op::DataType::DT_FLOAT, op::DataType::DT_DOUBLE, | ||
| 57 | + op::DataType::DT_INT8, op::DataType::DT_UINT8, op::DataType::DT_INT16, | ||
| 58 | + op::DataType::DT_INT32, op::DataType::DT_INT64, op::DataType::DT_UINT16, | ||
| 59 | + op::DataType::DT_UINT32, op::DataType::DT_UINT64, op::DataType::DT_BOOL, | ||
| 60 | + op::DataType::DT_COMPLEX64, op::DataType::DT_COMPLEX128, op::DataType::DT_BF16, | ||
| 61 | + op::DataType::DT_HIFLOAT8, op::DataType::DT_FLOAT8_E5M2, op::DataType::DT_FLOAT8_E4M3FN, | ||
| 62 | + op::DataType::DT_COMPLEX32, op::DataType::DT_FLOAT4_E1M2, op::DataType::DT_FLOAT4_E2M1}; | ||
| 63 | +static const std::initializer_list<op::DataType> ASCEND950_SELF_DTYPE_SUPPORT_LIST = { | ||
| 64 | + op::DataType::DT_FLOAT16, op::DataType::DT_FLOAT, op::DataType::DT_DOUBLE, | ||
| 65 | + op::DataType::DT_INT8, op::DataType::DT_UINT8, op::DataType::DT_INT16, | ||
| 66 | + op::DataType::DT_INT32, op::DataType::DT_INT64, op::DataType::DT_UINT16, | ||
| 67 | + op::DataType::DT_UINT32, op::DataType::DT_UINT64, op::DataType::DT_BOOL, | ||
| 68 | + op::DataType::DT_COMPLEX64, op::DataType::DT_COMPLEX128, op::DataType::DT_BF16, | ||
| 69 | + op::DataType::DT_HIFLOAT8, op::DataType::DT_FLOAT8_E5M2, op::DataType::DT_FLOAT8_E4M3FN, | ||
| 70 | + op::DataType::DT_COMPLEX32, op::DataType::DT_FLOAT4_E1M2, op::DataType::DT_FLOAT4_E2M1}; | ||
| 71 | + | ||
| 72 | +static bool CheckNotNull(const aclTensor* self, const aclTensor* out) | ||
| 73 | +{ | ||
| 74 | + OP_CHECK_NULL(self, return false); | ||
| 75 | + OP_CHECK_NULL(out, return false); | ||
| 76 | + return true; | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +static bool CheckDtypeValid(const aclTensor* self, const DataType dtype) | ||
| 80 | +{ | ||
| 81 | + // 检查self的数据类型是否在算子的支持列表内 | ||
| 82 | + bool isASCEND910B = (GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_2201); | ||
| 83 | + bool isASCEND910_93 = (GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_2201); | ||
| 84 | + bool isASCEND950 = (GetCurrentPlatformInfo().GetCurNpuArch() == NpuArch::DAV_3510); | ||
| 85 | + bool isAscend910BC = isASCEND910B || isASCEND910_93; | ||
| 86 | + | ||
| 87 | + auto supportList = ASCEND910_DTYPE_SUPPORT_LIST; | ||
| 88 | + auto selfSupportList = ASCEND910_DTYPE_SUPPORT_LIST; | ||
| 89 | + if (isAscend910BC) { | ||
| 90 | + supportList = DTYPE_SUPPORT_LIST_DEFAULT; | ||
| 91 | + selfSupportList = DTYPE_SUPPORT_LIST_DEFAULT; | ||
| 92 | + } else if (isASCEND950) { | ||
| 93 | + supportList = ASCEND950_DTYPE_SUPPORT_LIST; | ||
| 94 | + selfSupportList = ASCEND950_SELF_DTYPE_SUPPORT_LIST; | ||
| 95 | + } | ||
| 96 | + OP_CHECK_DTYPE_NOT_SUPPORT(self, selfSupportList, return false); | ||
| 97 | + bool isSupport = CheckType(dtype, supportList); | ||
| 98 | + // 检查参数dtype是否在Cast算子的输出数据类型支持列表内 | ||
| 99 | + if (!isSupport) { | ||
| 100 | + OP_LOGE( | ||
| 101 | + ACLNN_ERR_PARAM_INVALID, "The param dtype not implemented for %s, should be in dtype support list %s.", | ||
| 102 | + op::ToString(dtype).GetString(), op::ToString(supportList).GetString()); | ||
| 103 | + return false; | ||
| 104 | + } | ||
| 105 | + return true; | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +static inline bool CheckShape(const aclTensor* self, const aclTensor* out) | ||
| 109 | +{ | ||
| 110 | + OP_CHECK_MAX_DIM(self, MAX_DIM, return false); | ||
| 111 | + OP_CHECK_SHAPE_NOT_EQUAL(out, self, return false); | ||
| 112 | + return true; | ||
| 113 | +} | ||
| 114 | + | ||
| 115 | +static inline aclnnStatus CheckParams(const aclTensor* self, const DataType dtype, const aclTensor* out) | ||
| 116 | +{ | ||
| 117 | + // 1. 检查参数是否为空指针 | ||
| 118 | + CHECK_RET(CheckNotNull(self, out), ACLNN_ERR_PARAM_NULLPTR); | ||
| 119 | + | ||
| 120 | + // 2. 检查输入的数据类型是否在API支持的数据类型范围之内,需要根据api定义校验 | ||
| 121 | + CHECK_RET(CheckDtypeValid(self, dtype), ACLNN_ERR_PARAM_INVALID); | ||
| 122 | + | ||
| 123 | + // 3. 检查输入tensor的shape是否为异常,输出和输入的shape是否相同 | ||
| 124 | + CHECK_RET(CheckShape(self, out), ACLNN_ERR_PARAM_INVALID); | ||
| 125 | + | ||
| 126 | + return ACLNN_SUCCESS; | ||
| 127 | +} | ||
| 128 | + | ||
| 129 | +aclnnStatus aclnnCastGetWorkspaceSize( | ||
| 130 | + const aclTensor* self, const aclDataType dtype, aclTensor* out, uint64_t* workspaceSize, aclOpExecutor** executor) | ||
| 131 | +{ | ||
| 132 | + L2_DFX_PHASE_1(aclnnCast, DFX_IN(self, dtype), DFX_OUT(out)); | ||
| 133 | + | ||
| 134 | + // 固定写法,创建OpExecutor | ||
| 135 | + auto uniqueExecutor = CREATE_EXECUTOR(); | ||
| 136 | + CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); | ||
| 137 | + | ||
| 138 | + // 固定写法,参数检查 | ||
| 139 | + auto ret = CheckParams(self, op::ToOpDataType(dtype), out); | ||
| 140 | + CHECK_RET(ret == ACLNN_SUCCESS, ret); | ||
| 141 | + | ||
| 142 | + // 输入为空tensor时,直接返回dtype类型的空tensor | ||
| 143 | + if (self->IsEmpty()) { | ||
| 144 | + *workspaceSize = 0; | ||
| 145 | + uniqueExecutor.ReleaseTo(executor); | ||
| 146 | + return ACLNN_SUCCESS; | ||
| 147 | + } | ||
| 148 | + | ||
| 149 | + // 固定写法,将输入self转换成连续的tensor | ||
| 150 | + auto selfContiguous = l0op::Contiguous(self, uniqueExecutor.get()); | ||
| 151 | + CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 152 | + | ||
| 153 | + // 调用Cast算子kernel,将输入self的数据类型转换成指定的数据类型 | ||
| 154 | + auto castOut = l0op::Cast(selfContiguous, op::ToOpDataType(dtype), uniqueExecutor.get()); | ||
| 155 | + CHECK_RET(castOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 156 | + | ||
| 157 | + // 固定写法,将计算结果拷贝到输出out上,out可能是非连续的tensor | ||
| 158 | + auto viewCopyResult = l0op::ViewCopy(castOut, out, uniqueExecutor.get()); | ||
| 159 | + CHECK_RET(viewCopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 160 | + | ||
| 161 | + // 固定写法,获取计算过程中需要使用的workspace大小 | ||
| 162 | + *workspaceSize = uniqueExecutor->GetWorkspaceSize(); | ||
| 163 | + uniqueExecutor.ReleaseTo(executor); | ||
| 164 | + return ACLNN_SUCCESS; | ||
| 165 | +} | ||
| 166 | + | ||
| 167 | +aclnnStatus aclnnCast(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream) | ||
| 168 | +{ | ||
| 169 | + L2_DFX_PHASE_2(aclnnCast); | ||
| 170 | + // 固定写法,调用框架能力,完成计算 | ||
| 171 | + return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); | ||
| 172 | +} | ||
| 173 | + | ||
| 174 | + | ||
| 175 | +} | ||
| 176 | + | ||
| @@ -0,0 +1,57 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +extern "C" { | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +/** | ||
| 22 | + * @brief aclnnCast的第一段接口,根据具体的计算流程,计算workspace大小。 | ||
| 23 | + * @domain aclnn_math | ||
| 24 | + * | ||
| 25 | + * 算子功能:将输入tensor转换为指定的dtype类型。 | ||
| 26 | + * | ||
| 27 | + * @param [in] self: npu | ||
| 28 | + * device侧的aclTensor,数据类型支持FLOAT16、FLOAT、FlOAT64、INT8、UINT8、INT16、INT32、INT64、BOOL。 | ||
| 29 | + * 支持非连续的Tensor,数据格式支持ND。 | ||
| 30 | + * @param [in] dtype: host侧的aclDataType,输入tensor要转换的目标dtype。 | ||
| 31 | + * @param [in] out: npu | ||
| 32 | + * device侧的aclTensor,数据类型支持FLOAT16、FLOAT、FlOAT64、INT8、UINT8、INT16、INT32、INT64、BOOL、 | ||
| 33 | + * COMPLEX64、COMPLEX128。数据类型为dtype,shape与self相同,数据格式支持ND,且数据格式需要与self一致。 | ||
| 34 | + * @param [out] workspaceSize: 返回用户需要在npu device侧申请的workspace大小。 | ||
| 35 | + * @param [out] executor: 返回op执行器,包含算子计算流程。 | ||
| 36 | + * @return aclnnStatus: 返回状态码。 | ||
| 37 | + */ | ||
| 38 | +ACLNN_API aclnnStatus aclnnCastGetWorkspaceSize( | ||
| 39 | + const aclTensor* self, const aclDataType dtype, aclTensor* out, uint64_t* workspaceSize, aclOpExecutor** executor); | ||
| 40 | +/** | ||
| 41 | + * @brief aclnnCast的第二段接口,用于执行计算。 | ||
| 42 | + * | ||
| 43 | + * 算子功能:将输入tensor转换为指定的dtype类型。 | ||
| 44 | + * | ||
| 45 | + * @param [in] workspace: 在npu device侧申请的workspace内存起址。 | ||
| 46 | + * @param [in] workspaceSize: 在npu device侧申请的workspace大小,由第一段接口aclnnCastGetWorkspaceSize获取。 | ||
| 47 | + * @param [in] executor: op执行器,包含了算子计算流程。 | ||
| 48 | + * @param [in] stream: acl stream流。 | ||
| 49 | + * @return aclnnStatus: 返回状态码。 | ||
| 50 | + */ | ||
| 51 | +ACLNN_API aclnnStatus aclnnCast(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream); | ||
| 52 | + | ||
| 53 | + | ||
| 54 | +} | ||
| 55 | + | ||
| 56 | + | ||
| 57 | + | ||
| @@ -0,0 +1,31 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file cast_infershape.cpp | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +using namespace ge; | ||
| 19 | + | ||
| 20 | +namespace ops { | ||
| 21 | + | ||
| 22 | +static ge::graphStatus InferShapeCast(gert::InferShapeContext* context) | ||
| 23 | +{ | ||
| 24 | + const gert::Shape* x1_shape = context->GetInputShape(0); | ||
| 25 | + gert::Shape* y_shape = context->GetOutputShape(0); | ||
| 26 | + *y_shape = *x1_shape; | ||
| 27 | + return GRAPH_SUCCESS; | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | +IMPL_OP_INFERSHAPE(Cast).InferShape(InferShapeCast); | ||
| 31 | +} // namespace ops | ||
| @@ -0,0 +1,325 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file cast_tiling.cpp | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace optiling { | ||
| 24 | + | ||
| 25 | +const uint64_t BLOCK_SIZE = 32; | ||
| 26 | +const uint64_t BUFFER_NUM = 2; | ||
| 27 | +uint64_t ubDataNumMap[40][40] = {}; | ||
| 28 | +uint64_t tilingKeyMap[40][40] = {}; | ||
| 29 | +uint64_t minDataTypeLengthMap[40][40] = {}; | ||
| 30 | +void UbDataNumMapInit() | ||
| 31 | +{ | ||
| 32 | + // = InputBytes * BUFFER_NUM + OutputBytes * BUFFER_NUM + AlltmpBytes | ||
| 33 | + ubDataNumMap[ge::DT_FLOAT16][ge::DT_FLOAT] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 0; | ||
| 34 | + ubDataNumMap[ge::DT_FLOAT16][ge::DT_INT32] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 0; | ||
| 35 | + ubDataNumMap[ge::DT_FLOAT16][ge::DT_INT8] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 4; | ||
| 36 | + ubDataNumMap[ge::DT_FLOAT16][ge::DT_UINT8] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 4; | ||
| 37 | + ubDataNumMap[ge::DT_FLOAT16][ge::DT_BOOL] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 38 | + ubDataNumMap[ge::DT_FLOAT16][ge::DT_INT16] = 1 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 39 | + ubDataNumMap[ge::DT_FLOAT16][ge::DT_BF16] = 1 * BUFFER_NUM + 1 * BUFFER_NUM + 2; | ||
| 40 | + ubDataNumMap[ge::DT_FLOAT][ge::DT_FLOAT16] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 41 | + ubDataNumMap[ge::DT_FLOAT][ge::DT_BF16] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 42 | + ubDataNumMap[ge::DT_FLOAT][ge::DT_INT32] = 1 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 43 | + ubDataNumMap[ge::DT_FLOAT][ge::DT_INT64] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 0; | ||
| 44 | + ubDataNumMap[ge::DT_FLOAT][ge::DT_BOOL] = 4 * BUFFER_NUM + 1 * BUFFER_NUM + 4; | ||
| 45 | + ubDataNumMap[ge::DT_FLOAT][ge::DT_INT8] = 4 * BUFFER_NUM + 1 * BUFFER_NUM + 6; | ||
| 46 | + ubDataNumMap[ge::DT_FLOAT][ge::DT_UINT8] = 4 * BUFFER_NUM + 1 * BUFFER_NUM + 6; | ||
| 47 | + ubDataNumMap[ge::DT_FLOAT][ge::DT_INT16] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 48 | + ubDataNumMap[ge::DT_INT32][ge::DT_FLOAT] = 1 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 49 | + ubDataNumMap[ge::DT_INT32][ge::DT_FLOAT16] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 2; | ||
| 50 | + ubDataNumMap[ge::DT_INT32][ge::DT_BF16] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 2; | ||
| 51 | + ubDataNumMap[ge::DT_INT32][ge::DT_INT8] = 4 * BUFFER_NUM + 1 * BUFFER_NUM + 6; | ||
| 52 | + ubDataNumMap[ge::DT_INT32][ge::DT_UINT8] = 4 * BUFFER_NUM + 1 * BUFFER_NUM + 6; | ||
| 53 | + ubDataNumMap[ge::DT_INT32][ge::DT_INT16] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 54 | + ubDataNumMap[ge::DT_INT32][ge::DT_INT64] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 0; | ||
| 55 | + ubDataNumMap[ge::DT_INT32][ge::DT_BOOL] = 4 * BUFFER_NUM + 1 * BUFFER_NUM + 4; | ||
| 56 | + ubDataNumMap[ge::DT_INT8][ge::DT_FLOAT16] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 0; | ||
| 57 | + ubDataNumMap[ge::DT_INT8][ge::DT_FLOAT] = 1 * BUFFER_NUM + 4 * BUFFER_NUM + 2; | ||
| 58 | + ubDataNumMap[ge::DT_INT8][ge::DT_INT32] = 1 * BUFFER_NUM + 4 * BUFFER_NUM + 2; | ||
| 59 | + ubDataNumMap[ge::DT_INT8][ge::DT_UINT8] = 1 * BUFFER_NUM + 1 * BUFFER_NUM + 2; | ||
| 60 | + ubDataNumMap[ge::DT_INT8][ge::DT_BOOL] = 1 * BUFFER_NUM + 1 * BUFFER_NUM + 2; | ||
| 61 | + ubDataNumMap[ge::DT_INT8][ge::DT_INT16] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 2; | ||
| 62 | + ubDataNumMap[ge::DT_INT8][ge::DT_INT64] = 1 * BUFFER_NUM + 8 * BUFFER_NUM + 6; | ||
| 63 | + ubDataNumMap[ge::DT_INT8][ge::DT_BF16] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 6; | ||
| 64 | + ubDataNumMap[ge::DT_UINT8][ge::DT_FLOAT16] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 0; | ||
| 65 | + ubDataNumMap[ge::DT_UINT8][ge::DT_FLOAT] = 1 * BUFFER_NUM + 4 * BUFFER_NUM + 2; | ||
| 66 | + ubDataNumMap[ge::DT_UINT8][ge::DT_INT32] = 1 * BUFFER_NUM + 4 * BUFFER_NUM + 2; | ||
| 67 | + ubDataNumMap[ge::DT_UINT8][ge::DT_INT8] = 1 * BUFFER_NUM + 1 * BUFFER_NUM + 6; | ||
| 68 | + ubDataNumMap[ge::DT_UINT8][ge::DT_INT16] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 2; | ||
| 69 | + ubDataNumMap[ge::DT_UINT8][ge::DT_INT64] = 1 * BUFFER_NUM + 8 * BUFFER_NUM + 6; | ||
| 70 | + ubDataNumMap[ge::DT_UINT8][ge::DT_BF16] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 6; | ||
| 71 | + ubDataNumMap[ge::DT_BOOL][ge::DT_FLOAT16] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 0; | ||
| 72 | + ubDataNumMap[ge::DT_BOOL][ge::DT_FLOAT] = 1 * BUFFER_NUM + 4 * BUFFER_NUM + 2; | ||
| 73 | + ubDataNumMap[ge::DT_BOOL][ge::DT_INT32] = 1 * BUFFER_NUM + 4 * BUFFER_NUM + 2; | ||
| 74 | + ubDataNumMap[ge::DT_BOOL][ge::DT_UINT8] = 1 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 75 | + ubDataNumMap[ge::DT_BOOL][ge::DT_INT8] = 1 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 76 | + ubDataNumMap[ge::DT_BOOL][ge::DT_INT64] = 1 * BUFFER_NUM + 8 * BUFFER_NUM + 6; | ||
| 77 | + ubDataNumMap[ge::DT_BOOL][ge::DT_BF16] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 6; | ||
| 78 | + ubDataNumMap[ge::DT_INT64][ge::DT_FLOAT16] = 4 * BUFFER_NUM + 1 * BUFFER_NUM + 2; | ||
| 79 | + ubDataNumMap[ge::DT_INT64][ge::DT_FLOAT] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 80 | + ubDataNumMap[ge::DT_INT64][ge::DT_INT32] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 81 | + ubDataNumMap[ge::DT_INT64][ge::DT_UINT8] = 8 * BUFFER_NUM + 1 * BUFFER_NUM + 10; | ||
| 82 | + ubDataNumMap[ge::DT_INT64][ge::DT_INT8] = 8 * BUFFER_NUM + 1 * BUFFER_NUM + 10; | ||
| 83 | + ubDataNumMap[ge::DT_INT64][ge::DT_BOOL] = 8 * BUFFER_NUM + 1 * BUFFER_NUM + 6; | ||
| 84 | + ubDataNumMap[ge::DT_INT64][ge::DT_BF16] = 4 * BUFFER_NUM + 1 * BUFFER_NUM + 2; | ||
| 85 | + ubDataNumMap[ge::DT_INT64][ge::DT_INT16] = 4 * BUFFER_NUM + 1 * BUFFER_NUM + 2; | ||
| 86 | + ubDataNumMap[ge::DT_BF16][ge::DT_FLOAT16] = 1 * BUFFER_NUM + 1 * BUFFER_NUM + 2; | ||
| 87 | + ubDataNumMap[ge::DT_BF16][ge::DT_FLOAT] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 0; | ||
| 88 | + ubDataNumMap[ge::DT_BF16][ge::DT_INT32] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 0; | ||
| 89 | + ubDataNumMap[ge::DT_BF16][ge::DT_INT8] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 10; | ||
| 90 | + ubDataNumMap[ge::DT_BF16][ge::DT_UINT8] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 10; | ||
| 91 | + ubDataNumMap[ge::DT_BF16][ge::DT_BOOL] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 6; | ||
| 92 | + ubDataNumMap[ge::DT_INT16][ge::DT_FLOAT16] = 1 * BUFFER_NUM + 1 * BUFFER_NUM + 0; | ||
| 93 | + ubDataNumMap[ge::DT_INT16][ge::DT_FLOAT] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 0; | ||
| 94 | + ubDataNumMap[ge::DT_INT16][ge::DT_INT32] = 1 * BUFFER_NUM + 2 * BUFFER_NUM + 2; | ||
| 95 | + ubDataNumMap[ge::DT_INT16][ge::DT_INT8] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 4; | ||
| 96 | + ubDataNumMap[ge::DT_INT16][ge::DT_UINT8] = 2 * BUFFER_NUM + 1 * BUFFER_NUM + 4; | ||
| 97 | + ubDataNumMap[ge::DT_INT16][ge::DT_INT64] = 1 * BUFFER_NUM + 4 * BUFFER_NUM + 2; | ||
| 98 | +} | ||
| 99 | +void TilingKeyMapInit() | ||
| 100 | +{ | ||
| 101 | + // = Tiling Key | ||
| 102 | + tilingKeyMap[ge::DT_FLOAT16][ge::DT_FLOAT] = 1; | ||
| 103 | + tilingKeyMap[ge::DT_FLOAT16][ge::DT_INT32] = 1; | ||
| 104 | + tilingKeyMap[ge::DT_FLOAT16][ge::DT_INT8] = 3; | ||
| 105 | + tilingKeyMap[ge::DT_FLOAT16][ge::DT_UINT8] = 3; | ||
| 106 | + tilingKeyMap[ge::DT_FLOAT16][ge::DT_BOOL] = 1; | ||
| 107 | + tilingKeyMap[ge::DT_FLOAT16][ge::DT_INT16] = 1; | ||
| 108 | + tilingKeyMap[ge::DT_FLOAT16][ge::DT_BF16] = 2; | ||
| 109 | + tilingKeyMap[ge::DT_FLOAT][ge::DT_FLOAT16] = 1; | ||
| 110 | + tilingKeyMap[ge::DT_FLOAT][ge::DT_BF16] = 1; | ||
| 111 | + tilingKeyMap[ge::DT_FLOAT][ge::DT_INT32] = 1; | ||
| 112 | + tilingKeyMap[ge::DT_FLOAT][ge::DT_INT64] = 1; | ||
| 113 | + tilingKeyMap[ge::DT_FLOAT][ge::DT_BOOL] = 3; | ||
| 114 | + tilingKeyMap[ge::DT_FLOAT][ge::DT_INT8] = 4; | ||
| 115 | + tilingKeyMap[ge::DT_FLOAT][ge::DT_UINT8] = 4; | ||
| 116 | + tilingKeyMap[ge::DT_FLOAT][ge::DT_INT16] = 1; | ||
| 117 | + tilingKeyMap[ge::DT_INT32][ge::DT_FLOAT] = 1; | ||
| 118 | + tilingKeyMap[ge::DT_INT32][ge::DT_FLOAT16] = 2; | ||
| 119 | + tilingKeyMap[ge::DT_INT32][ge::DT_BF16] = 2; | ||
| 120 | + tilingKeyMap[ge::DT_INT32][ge::DT_INT8] = 4; | ||
| 121 | + tilingKeyMap[ge::DT_INT32][ge::DT_UINT8] = 4; | ||
| 122 | + tilingKeyMap[ge::DT_INT32][ge::DT_INT16] = 1; | ||
| 123 | + tilingKeyMap[ge::DT_INT32][ge::DT_INT64] = 1; | ||
| 124 | + tilingKeyMap[ge::DT_INT32][ge::DT_BOOL] = 3; | ||
| 125 | + tilingKeyMap[ge::DT_INT8][ge::DT_FLOAT16] = 1; | ||
| 126 | + tilingKeyMap[ge::DT_INT8][ge::DT_FLOAT] = 5; | ||
| 127 | + tilingKeyMap[ge::DT_INT8][ge::DT_INT32] = 5; | ||
| 128 | + tilingKeyMap[ge::DT_INT8][ge::DT_UINT8] = 8; | ||
| 129 | + tilingKeyMap[ge::DT_INT8][ge::DT_BOOL] = 5; | ||
| 130 | + tilingKeyMap[ge::DT_INT8][ge::DT_INT16] = 5; | ||
| 131 | + tilingKeyMap[ge::DT_INT8][ge::DT_INT64] = 6; | ||
| 132 | + tilingKeyMap[ge::DT_INT8][ge::DT_BF16] = 6; | ||
| 133 | + tilingKeyMap[ge::DT_UINT8][ge::DT_FLOAT16] = 1; | ||
| 134 | + tilingKeyMap[ge::DT_UINT8][ge::DT_FLOAT] = 5; | ||
| 135 | + tilingKeyMap[ge::DT_UINT8][ge::DT_INT32] = 5; | ||
| 136 | + tilingKeyMap[ge::DT_UINT8][ge::DT_INT8] = 8; | ||
| 137 | + tilingKeyMap[ge::DT_UINT8][ge::DT_INT16] = 5; | ||
| 138 | + tilingKeyMap[ge::DT_UINT8][ge::DT_INT64] = 6; | ||
| 139 | + tilingKeyMap[ge::DT_UINT8][ge::DT_BF16] = 6; | ||
| 140 | + tilingKeyMap[ge::DT_BOOL][ge::DT_FLOAT16] = 1; | ||
| 141 | + tilingKeyMap[ge::DT_BOOL][ge::DT_FLOAT] = 5; | ||
| 142 | + tilingKeyMap[ge::DT_BOOL][ge::DT_INT32] = 5; | ||
| 143 | + tilingKeyMap[ge::DT_BOOL][ge::DT_UINT8] = 8; | ||
| 144 | + tilingKeyMap[ge::DT_BOOL][ge::DT_INT8] = 8; | ||
| 145 | + tilingKeyMap[ge::DT_BOOL][ge::DT_INT64] = 6; | ||
| 146 | + tilingKeyMap[ge::DT_BOOL][ge::DT_BF16] = 6; | ||
| 147 | + tilingKeyMap[ge::DT_INT64][ge::DT_FLOAT16] = 2; | ||
| 148 | + tilingKeyMap[ge::DT_INT64][ge::DT_FLOAT] = 1; | ||
| 149 | + tilingKeyMap[ge::DT_INT64][ge::DT_INT32] = 1; | ||
| 150 | + tilingKeyMap[ge::DT_INT64][ge::DT_UINT8] = 7; | ||
| 151 | + tilingKeyMap[ge::DT_INT64][ge::DT_INT8] = 7; | ||
| 152 | + tilingKeyMap[ge::DT_INT64][ge::DT_BOOL] = 6; | ||
| 153 | + tilingKeyMap[ge::DT_INT64][ge::DT_BF16] = 2; | ||
| 154 | + tilingKeyMap[ge::DT_INT64][ge::DT_INT16] = 2; | ||
| 155 | + tilingKeyMap[ge::DT_BF16][ge::DT_FLOAT16] = 2; | ||
| 156 | + tilingKeyMap[ge::DT_BF16][ge::DT_FLOAT] = 1; | ||
| 157 | + tilingKeyMap[ge::DT_BF16][ge::DT_INT32] = 1; | ||
| 158 | + tilingKeyMap[ge::DT_BF16][ge::DT_INT8] = 7; | ||
| 159 | + tilingKeyMap[ge::DT_BF16][ge::DT_UINT8] = 7; | ||
| 160 | + tilingKeyMap[ge::DT_BF16][ge::DT_BOOL] = 6; | ||
| 161 | + tilingKeyMap[ge::DT_INT16][ge::DT_FLOAT16] = 1; | ||
| 162 | + tilingKeyMap[ge::DT_INT16][ge::DT_FLOAT] = 1; | ||
| 163 | + tilingKeyMap[ge::DT_INT16][ge::DT_INT32] = 2; | ||
| 164 | + tilingKeyMap[ge::DT_INT16][ge::DT_INT8] = 3; | ||
| 165 | + tilingKeyMap[ge::DT_INT16][ge::DT_UINT8] = 3; | ||
| 166 | + tilingKeyMap[ge::DT_INT16][ge::DT_INT64] = 2; | ||
| 167 | +} | ||
| 168 | +void MinDataTypeLengthMapInit() | ||
| 169 | +{ | ||
| 170 | + minDataTypeLengthMap[ge::DT_FLOAT16][ge::DT_FLOAT] = 2; | ||
| 171 | + minDataTypeLengthMap[ge::DT_FLOAT16][ge::DT_INT32] = 2; | ||
| 172 | + minDataTypeLengthMap[ge::DT_FLOAT16][ge::DT_INT8] = 1; | ||
| 173 | + minDataTypeLengthMap[ge::DT_FLOAT16][ge::DT_UINT8] = 1; | ||
| 174 | + minDataTypeLengthMap[ge::DT_FLOAT16][ge::DT_BOOL] = 1; | ||
| 175 | + minDataTypeLengthMap[ge::DT_FLOAT16][ge::DT_INT16] = 2; | ||
| 176 | + minDataTypeLengthMap[ge::DT_FLOAT16][ge::DT_BF16] = 2; | ||
| 177 | + minDataTypeLengthMap[ge::DT_FLOAT][ge::DT_FLOAT16] = 2; | ||
| 178 | + minDataTypeLengthMap[ge::DT_FLOAT][ge::DT_BF16] = 2; | ||
| 179 | + minDataTypeLengthMap[ge::DT_FLOAT][ge::DT_INT32] = 4; | ||
| 180 | + minDataTypeLengthMap[ge::DT_FLOAT][ge::DT_INT64] = 4; | ||
| 181 | + minDataTypeLengthMap[ge::DT_FLOAT][ge::DT_BOOL] = 1; | ||
| 182 | + minDataTypeLengthMap[ge::DT_FLOAT][ge::DT_INT8] = 1; | ||
| 183 | + minDataTypeLengthMap[ge::DT_FLOAT][ge::DT_UINT8] = 1; | ||
| 184 | + minDataTypeLengthMap[ge::DT_FLOAT][ge::DT_INT16] = 2; | ||
| 185 | + minDataTypeLengthMap[ge::DT_INT32][ge::DT_FLOAT] = 4; | ||
| 186 | + minDataTypeLengthMap[ge::DT_INT32][ge::DT_FLOAT16] = 2; | ||
| 187 | + minDataTypeLengthMap[ge::DT_INT32][ge::DT_BF16] = 2; | ||
| 188 | + minDataTypeLengthMap[ge::DT_INT32][ge::DT_INT8] = 1; | ||
| 189 | + minDataTypeLengthMap[ge::DT_INT32][ge::DT_UINT8] = 1; | ||
| 190 | + minDataTypeLengthMap[ge::DT_INT32][ge::DT_INT16] = 2; | ||
| 191 | + minDataTypeLengthMap[ge::DT_INT32][ge::DT_INT64] = 4; | ||
| 192 | + minDataTypeLengthMap[ge::DT_INT32][ge::DT_BOOL] = 1; | ||
| 193 | + minDataTypeLengthMap[ge::DT_INT8][ge::DT_FLOAT16] = 1; | ||
| 194 | + minDataTypeLengthMap[ge::DT_INT8][ge::DT_FLOAT] = 1; | ||
| 195 | + minDataTypeLengthMap[ge::DT_INT8][ge::DT_INT32] = 1; | ||
| 196 | + minDataTypeLengthMap[ge::DT_INT8][ge::DT_UINT8] = 1; | ||
| 197 | + minDataTypeLengthMap[ge::DT_INT8][ge::DT_BOOL] = 1; | ||
| 198 | + minDataTypeLengthMap[ge::DT_INT8][ge::DT_INT16] = 1; | ||
| 199 | + minDataTypeLengthMap[ge::DT_INT8][ge::DT_INT64] = 1; | ||
| 200 | + minDataTypeLengthMap[ge::DT_INT8][ge::DT_BF16] = 1; | ||
| 201 | + minDataTypeLengthMap[ge::DT_UINT8][ge::DT_FLOAT16] = 1; | ||
| 202 | + minDataTypeLengthMap[ge::DT_UINT8][ge::DT_FLOAT] = 1; | ||
| 203 | + minDataTypeLengthMap[ge::DT_UINT8][ge::DT_INT32] = 1; | ||
| 204 | + minDataTypeLengthMap[ge::DT_UINT8][ge::DT_INT8] = 1; | ||
| 205 | + minDataTypeLengthMap[ge::DT_UINT8][ge::DT_INT16] = 1; | ||
| 206 | + minDataTypeLengthMap[ge::DT_UINT8][ge::DT_INT64] = 1; | ||
| 207 | + minDataTypeLengthMap[ge::DT_UINT8][ge::DT_BF16] = 1; | ||
| 208 | + minDataTypeLengthMap[ge::DT_BOOL][ge::DT_FLOAT16] = 1; | ||
| 209 | + minDataTypeLengthMap[ge::DT_BOOL][ge::DT_FLOAT] = 1; | ||
| 210 | + minDataTypeLengthMap[ge::DT_BOOL][ge::DT_INT32] = 1; | ||
| 211 | + minDataTypeLengthMap[ge::DT_BOOL][ge::DT_UINT8] = 1; | ||
| 212 | + minDataTypeLengthMap[ge::DT_BOOL][ge::DT_INT8] = 1; | ||
| 213 | + minDataTypeLengthMap[ge::DT_BOOL][ge::DT_INT64] = 1; | ||
| 214 | + minDataTypeLengthMap[ge::DT_BOOL][ge::DT_BF16] = 1; | ||
| 215 | + minDataTypeLengthMap[ge::DT_INT64][ge::DT_FLOAT16] = 2; | ||
| 216 | + minDataTypeLengthMap[ge::DT_INT64][ge::DT_FLOAT] = 4; | ||
| 217 | + minDataTypeLengthMap[ge::DT_INT64][ge::DT_INT32] = 4; | ||
| 218 | + minDataTypeLengthMap[ge::DT_INT64][ge::DT_UINT8] = 1; | ||
| 219 | + minDataTypeLengthMap[ge::DT_INT64][ge::DT_INT8] = 1; | ||
| 220 | + minDataTypeLengthMap[ge::DT_INT64][ge::DT_BOOL] = 1; | ||
| 221 | + minDataTypeLengthMap[ge::DT_INT64][ge::DT_BF16] = 2; | ||
| 222 | + minDataTypeLengthMap[ge::DT_INT64][ge::DT_INT16] = 2; | ||
| 223 | + minDataTypeLengthMap[ge::DT_BF16][ge::DT_FLOAT16] = 2; | ||
| 224 | + minDataTypeLengthMap[ge::DT_BF16][ge::DT_FLOAT] = 2; | ||
| 225 | + minDataTypeLengthMap[ge::DT_BF16][ge::DT_INT32] = 2; | ||
| 226 | + minDataTypeLengthMap[ge::DT_BF16][ge::DT_INT8] = 1; | ||
| 227 | + minDataTypeLengthMap[ge::DT_BF16][ge::DT_UINT8] = 1; | ||
| 228 | + minDataTypeLengthMap[ge::DT_BF16][ge::DT_BOOL] = 1; | ||
| 229 | + minDataTypeLengthMap[ge::DT_INT16][ge::DT_FLOAT16] = 2; | ||
| 230 | + minDataTypeLengthMap[ge::DT_INT16][ge::DT_FLOAT] = 2; | ||
| 231 | + minDataTypeLengthMap[ge::DT_INT16][ge::DT_INT32] = 2; | ||
| 232 | + minDataTypeLengthMap[ge::DT_INT16][ge::DT_INT8] = 1; | ||
| 233 | + minDataTypeLengthMap[ge::DT_INT16][ge::DT_UINT8] = 1; | ||
| 234 | + minDataTypeLengthMap[ge::DT_INT16][ge::DT_INT64] = 2; | ||
| 235 | +} | ||
| 236 | + | ||
| 237 | +// tiling 分发入口 | ||
| 238 | +static ge::graphStatus CastTilingFunc(gert::TilingContext* context) | ||
| 239 | +{ | ||
| 240 | + CastTilingData* tiling = context->GetTilingData<CastTilingData>(); | ||
| 241 | + uint64_t ubSize; | ||
| 242 | + auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); | ||
| 243 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSize); | ||
| 244 | + auto coreNum = ascendcPlatform.GetCoreNum(); | ||
| 245 | + auto socVersion = ascendcPlatform.GetSocVersion(); | ||
| 246 | + if (socVersion != platform_ascendc::SocVersion::ASCEND910B && socVersion != platform_ascendc::SocVersion::ASCEND310P && context->GetInputDesc(0)->GetDataType() == ge::DT_BF16) { | ||
| 247 | + OP_LOGE(context, "socVersion is invalid"); | ||
| 248 | + return ge::GRAPH_FAILED; | ||
| 249 | + } | ||
| 250 | + const gert::RuntimeAttrs *attrs = context->GetAttrs(); | ||
| 251 | + const int32_t *dst_type = attrs->GetAttrPointer<int32_t>(0); | ||
| 252 | + if (*dst_type != context->GetOutputDesc(0)->GetDataType()) { | ||
| 253 | + OP_LOGE(context, "dst_type is invalid"); | ||
| 254 | + return ge::GRAPH_FAILED; | ||
| 255 | + } | ||
| 256 | + | ||
| 257 | + uint64_t inputNum = context->GetInputShape(0)->GetStorageShape().GetShapeSize(); | ||
| 258 | + if (inputNum == 0) { | ||
| 259 | + OP_LOGE(context, "inputNum is 0"); | ||
| 260 | + return ge::GRAPH_FAILED; | ||
| 261 | + } | ||
| 262 | + UbDataNumMapInit(); | ||
| 263 | + TilingKeyMapInit(); | ||
| 264 | + MinDataTypeLengthMapInit(); | ||
| 265 | + auto inputDatatype = context->GetInputDesc(0)->GetDataType(); | ||
| 266 | + auto outputDatatype = context->GetOutputDesc(0)->GetDataType(); | ||
| 267 | + uint64_t tilingKey = tilingKeyMap[inputDatatype][outputDatatype]; | ||
| 268 | + uint64_t typeLength = minDataTypeLengthMap[inputDatatype][outputDatatype]; | ||
| 269 | + uint64_t inputLength = inputNum * typeLength; | ||
| 270 | + uint64_t inputBytes = inputLength / inputNum; | ||
| 271 | + | ||
| 272 | + uint64_t ubDataNumber = ubDataNumMap[inputDatatype][outputDatatype]; | ||
| 273 | + uint64_t tileBlockNum = (ubSize / BLOCK_SIZE) / ubDataNumber; | ||
| 274 | + uint64_t tileDataNum = (tileBlockNum * BLOCK_SIZE) / inputBytes; | ||
| 275 | + | ||
| 276 | + uint64_t inputLengthAlgin32 = (((inputLength + BLOCK_SIZE - 1) / BLOCK_SIZE) * BLOCK_SIZE); | ||
| 277 | + | ||
| 278 | + if (inputNum <= tileDataNum) | ||
| 279 | + { | ||
| 280 | + coreNum = 1; | ||
| 281 | + } | ||
| 282 | + else | ||
| 283 | + { | ||
| 284 | + coreNum = (coreNum < inputLengthAlgin32 / BLOCK_SIZE) ? coreNum : inputLengthAlgin32 / BLOCK_SIZE; | ||
| 285 | + } | ||
| 286 | + if (coreNum == 0 || BLOCK_SIZE == 0) | ||
| 287 | + { | ||
| 288 | + OP_LOGE(context, "coreNum or BLOCK_SIZE is 0"); | ||
| 289 | + return ge::GRAPH_FAILED; | ||
| 290 | + } | ||
| 291 | + uint64_t everyCoreInputBlockNum = inputLengthAlgin32 / BLOCK_SIZE / coreNum; | ||
| 292 | + uint64_t tailBlockNum = (inputLengthAlgin32 / BLOCK_SIZE) % coreNum; | ||
| 293 | + | ||
| 294 | + uint64_t smallCoreDataNum = everyCoreInputBlockNum * BLOCK_SIZE / inputBytes; | ||
| 295 | + uint64_t smallTileNum = everyCoreInputBlockNum / tileBlockNum; | ||
| 296 | + uint64_t finalSmallTileNum = (everyCoreInputBlockNum % tileBlockNum) == 0 ? smallTileNum : smallTileNum + 1; | ||
| 297 | + uint64_t smallTailDataNum = smallCoreDataNum - (tileDataNum * smallTileNum); | ||
| 298 | + smallTailDataNum = smallTailDataNum == 0 ? tileDataNum : smallTailDataNum; | ||
| 299 | + | ||
| 300 | + everyCoreInputBlockNum += 1; | ||
| 301 | + uint64_t bigCoreDataNum = everyCoreInputBlockNum * BLOCK_SIZE / inputBytes; | ||
| 302 | + uint64_t bigTileNum = everyCoreInputBlockNum / tileBlockNum; | ||
| 303 | + uint64_t finalBigTileNum = (everyCoreInputBlockNum % tileBlockNum) == 0 ? bigTileNum : bigTileNum + 1; | ||
| 304 | + uint64_t bigTailDataNum = bigCoreDataNum - tileDataNum * bigTileNum; | ||
| 305 | + bigTailDataNum = bigTailDataNum == 0 ? tileDataNum : bigTailDataNum; | ||
| 306 | + | ||
| 307 | + tiling->smallCoreDataNum = smallCoreDataNum; | ||
| 308 | + tiling->bigCoreDataNum = bigCoreDataNum; | ||
| 309 | + tiling->tileDataNum = tileDataNum; | ||
| 310 | + tiling->smallTailDataNum = smallTailDataNum; | ||
| 311 | + tiling->bigTailDataNum = bigTailDataNum; | ||
| 312 | + tiling->finalSmallTileNum = finalSmallTileNum; | ||
| 313 | + tiling->finalBigTileNum = finalBigTileNum; | ||
| 314 | + tiling->tailBlockNum = tailBlockNum; | ||
| 315 | + | ||
| 316 | + context->SetBlockDim(coreNum); | ||
| 317 | + context->SetTilingKey(tilingKey); | ||
| 318 | + size_t *currentWorkspace = context->GetWorkspaceSizes(1); | ||
| 319 | + currentWorkspace[0] = 0; | ||
| 320 | + return ge::GRAPH_SUCCESS; | ||
| 321 | +} | ||
| 322 | + | ||
| 323 | +// tiling注册入口. | ||
| 324 | +IMPL_OP_OPTILING(Cast).Tiling(CastTilingFunc); | ||
| 325 | +} // namespace optiling | ||
| @@ -0,0 +1,189 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file cast.cpp | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +using namespace NsCast; | ||
| 19 | + | ||
| 20 | +template <uint32_t schMode> | ||
| 21 | +__global__ __aicore__ void cast(GM_ADDR x, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling) | ||
| 22 | +{ | ||
| 23 | + REGISTER_TILING_DEFAULT(CastTilingData); | ||
| 24 | + GET_TILING_DATA_WITH_STRUCT(CastTilingData, tiling_data, tiling); | ||
| 25 | + | ||
| 26 | + TPipe pipe; | ||
| 27 | + if (TILING_KEY_IS(1)) | ||
| 28 | + { | ||
| 29 | + if constexpr (std::is_same_v<DTYPE_X, bool>) | ||
| 30 | + { | ||
| 31 | + KernelCast0TBuf<int8_t, DTYPE_Y> op; | ||
| 32 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 33 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 34 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 35 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 36 | + tiling_data.tailBlockNum, &pipe); | ||
| 37 | + op.Process(); | ||
| 38 | + } | ||
| 39 | + else if constexpr (std::is_same_v<DTYPE_Y, bool>) | ||
| 40 | + { | ||
| 41 | + KernelCast0TBuf<DTYPE_X, int8_t> op; | ||
| 42 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 43 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 44 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 45 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 46 | + tiling_data.tailBlockNum, &pipe); | ||
| 47 | + op.Process(); | ||
| 48 | + } | ||
| 49 | + else | ||
| 50 | + { | ||
| 51 | + KernelCast0TBuf<DTYPE_X, DTYPE_Y> op; | ||
| 52 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 53 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 54 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 55 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 56 | + tiling_data.tailBlockNum, &pipe); | ||
| 57 | + op.Process(); | ||
| 58 | + } | ||
| 59 | + } | ||
| 60 | + else if (TILING_KEY_IS(2)) | ||
| 61 | + { | ||
| 62 | + KernelCast1TBuf4B<DTYPE_X, DTYPE_Y> op; | ||
| 63 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 64 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 65 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 66 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 67 | + tiling_data.tailBlockNum, &pipe); | ||
| 68 | + op.Process(); | ||
| 69 | + } | ||
| 70 | + else if (TILING_KEY_IS(3)) | ||
| 71 | + { | ||
| 72 | + if constexpr (std::is_same_v<DTYPE_Y, bool>) | ||
| 73 | + { | ||
| 74 | + KernelCast2TBuf2B<DTYPE_X, int8_t> op; | ||
| 75 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 76 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 77 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 78 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 79 | + tiling_data.tailBlockNum, &pipe); | ||
| 80 | + op.Process(); | ||
| 81 | + } | ||
| 82 | + else | ||
| 83 | + { | ||
| 84 | + KernelCast2TBuf2B<DTYPE_X, DTYPE_Y> op; | ||
| 85 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 86 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 87 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 88 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 89 | + tiling_data.tailBlockNum, &pipe); | ||
| 90 | + op.Process(); | ||
| 91 | + } | ||
| 92 | + } | ||
| 93 | + else if (TILING_KEY_IS(4)) | ||
| 94 | + { | ||
| 95 | + KernelCast3TBuf2B<DTYPE_X, DTYPE_Y> op; | ||
| 96 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 97 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 98 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 99 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 100 | + tiling_data.tailBlockNum, &pipe); | ||
| 101 | + op.Process(); | ||
| 102 | + } | ||
| 103 | + else if (TILING_KEY_IS(5)) | ||
| 104 | + { | ||
| 105 | + if constexpr (std::is_same_v<DTYPE_X, bool>) | ||
| 106 | + { | ||
| 107 | + KernelCast1TBuf2B<int8_t, DTYPE_Y> op; | ||
| 108 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 109 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 110 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 111 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 112 | + tiling_data.tailBlockNum, &pipe); | ||
| 113 | + op.Process(); | ||
| 114 | + } | ||
| 115 | + else if constexpr (std::is_same_v<DTYPE_Y, bool>) | ||
| 116 | + { | ||
| 117 | + KernelCast1TBuf2B<DTYPE_X, int8_t> op; | ||
| 118 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 119 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 120 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 121 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 122 | + tiling_data.tailBlockNum, &pipe); | ||
| 123 | + op.Process(); | ||
| 124 | + } | ||
| 125 | + else | ||
| 126 | + { | ||
| 127 | + KernelCast1TBuf2B<DTYPE_X, DTYPE_Y> op; | ||
| 128 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 129 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 130 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 131 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 132 | + tiling_data.tailBlockNum, &pipe); | ||
| 133 | + op.Process(); | ||
| 134 | + } | ||
| 135 | + } | ||
| 136 | + else if (TILING_KEY_IS(6)) | ||
| 137 | + { | ||
| 138 | + if constexpr (std::is_same_v<DTYPE_X, bool>) | ||
| 139 | + { | ||
| 140 | + KernelCast1TBuf2B1TBuf4B<int8_t, DTYPE_Y> op; | ||
| 141 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 142 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 143 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 144 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 145 | + tiling_data.tailBlockNum, &pipe); | ||
| 146 | + op.Process(); | ||
| 147 | + } | ||
| 148 | + else if constexpr (std::is_same_v<DTYPE_Y, bool>) | ||
| 149 | + { | ||
| 150 | + KernelCast1TBuf2B1TBuf4B<DTYPE_X, int8_t> op; | ||
| 151 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 152 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 153 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 154 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 155 | + tiling_data.tailBlockNum, &pipe); | ||
| 156 | + op.Process(); | ||
| 157 | + } | ||
| 158 | + else | ||
| 159 | + { | ||
| 160 | + KernelCast1TBuf2B1TBuf4B<DTYPE_X, DTYPE_Y> op; | ||
| 161 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 162 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 163 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 164 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 165 | + tiling_data.tailBlockNum, &pipe); | ||
| 166 | + op.Process(); | ||
| 167 | + } | ||
| 168 | + } | ||
| 169 | + else if (TILING_KEY_IS(7)) | ||
| 170 | + { | ||
| 171 | + KernelCast3TBuf2B1TBuf4B<DTYPE_X, DTYPE_Y> op; | ||
| 172 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 173 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 174 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 175 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 176 | + tiling_data.tailBlockNum, &pipe); | ||
| 177 | + op.Process(); | ||
| 178 | + } | ||
| 179 | + else if (TILING_KEY_IS(8)) | ||
| 180 | + { | ||
| 181 | + KernelCastTQueBind op; | ||
| 182 | + op.Init(x, y, tiling_data.smallCoreDataNum, | ||
| 183 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 184 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 185 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 186 | + tiling_data.tailBlockNum, &pipe); | ||
| 187 | + op.Process(); | ||
| 188 | + } | ||
| 189 | +} | ||
| @@ -0,0 +1,956 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file cast.h | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace NsCast { | ||
| 24 | + | ||
| 25 | +using namespace AscendC; | ||
| 26 | + | ||
| 27 | +constexpr int32_t BUFFER_NUM = 2; | ||
| 28 | +constexpr int16_t CONST_128 = 128; | ||
| 29 | +constexpr int16_t CONST_NE128 = -128; | ||
| 30 | +constexpr int16_t CONST_255 = 255; | ||
| 31 | +constexpr int16_t CONST_1 = 1; | ||
| 32 | +constexpr half HALF_ONE = 1.0; | ||
| 33 | + | ||
| 34 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 35 | +class BaseKernelCast | ||
| 36 | +{ | ||
| 37 | +public: | ||
| 38 | + __aicore__ inline BaseKernelCast() {} | ||
| 39 | + | ||
| 40 | +protected: | ||
| 41 | + __aicore__ inline void CopyIn(int32_t progress) | ||
| 42 | + { | ||
| 43 | + LocalTensor<TYPE_X> xLocal = inQueueX.AllocTensor<TYPE_X>(); | ||
| 44 | + DataCopy(xLocal, xGm[progress * this->tileDataNum], this->processDataNum); | ||
| 45 | + inQueueX.EnQue(xLocal); | ||
| 46 | + } | ||
| 47 | + __aicore__ inline void CopyOut(int32_t progress) | ||
| 48 | + { | ||
| 49 | + LocalTensor<TYPE_Y> yLocal = outQueueY.DeQue<TYPE_Y>(); | ||
| 50 | + DataCopy(yGm[progress * this->tileDataNum], yLocal, this->processDataNum); | ||
| 51 | + outQueueY.FreeTensor(yLocal); | ||
| 52 | + } | ||
| 53 | + | ||
| 54 | +protected: | ||
| 55 | + TPipe *pipe; | ||
| 56 | + TQue<QuePosition::VECIN, BUFFER_NUM> inQueueX; | ||
| 57 | + TQue<QuePosition::VECOUT, BUFFER_NUM> outQueueY; | ||
| 58 | + GlobalTensor<TYPE_X> xGm; | ||
| 59 | + GlobalTensor<TYPE_Y> yGm; | ||
| 60 | + uint32_t coreDataNum = 0; | ||
| 61 | + uint32_t tileNum = 0; | ||
| 62 | + uint32_t tileDataNum = 0; | ||
| 63 | + uint32_t tailDataNum = 0; | ||
| 64 | + uint32_t processDataNum = 0; | ||
| 65 | +}; | ||
| 66 | + | ||
| 67 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 68 | +class KernelCast0TBuf : public BaseKernelCast<TYPE_X, TYPE_Y> | ||
| 69 | +{ | ||
| 70 | + /* | ||
| 71 | + 无临时变量 | ||
| 72 | + half -> float | ||
| 73 | + half -> int32 (TRUNC) | ||
| 74 | + half -> bool (Abs) | ||
| 75 | + half -> int16 (TRUNC) | ||
| 76 | + float -> half | ||
| 77 | + float -> bfloat16 (RINT) | ||
| 78 | + float -> int32 (TRUNC) | ||
| 79 | + float -> int64 (TRUNC) | ||
| 80 | + float -> int16 (TRUNC) | ||
| 81 | + int32 -> float | ||
| 82 | + int32 -> int64 | ||
| 83 | + int32 -> int16 | ||
| 84 | + int8 -> half | ||
| 85 | + uint8 -> half | ||
| 86 | + bool -> half | ||
| 87 | + int64 -> float (ROUND) | ||
| 88 | + int64 -> int32 | ||
| 89 | + bfloat16 -> float | ||
| 90 | + bfloat16 -> int32 (TRUNC) | ||
| 91 | + int16 -> float | ||
| 92 | + int16 -> half | ||
| 93 | + */ | ||
| 94 | +public: | ||
| 95 | + __aicore__ inline KernelCast0TBuf() {} | ||
| 96 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, uint32_t smallCoreDataNum, | ||
| 97 | + uint32_t bigCoreDataNum, uint32_t finalBigTileNum, | ||
| 98 | + uint32_t finalSmallTileNum, uint32_t tileDataNum, | ||
| 99 | + uint32_t smallTailDataNum, uint32_t bigTailDataNum, | ||
| 100 | + uint32_t tailBlockNum, TPipe *pipeIn) | ||
| 101 | + { | ||
| 102 | + this->pipe = pipeIn; | ||
| 103 | + ASSERT(GetBlockNum() != 0 && "block dim can not be zero!"); | ||
| 104 | + uint32_t coreNum = GetBlockIdx(); | ||
| 105 | + uint32_t globalBufferIndex = bigCoreDataNum * GetBlockIdx(); | ||
| 106 | + this->tileDataNum = tileDataNum; | ||
| 107 | + if (coreNum < tailBlockNum) | ||
| 108 | + { | ||
| 109 | + this->coreDataNum = bigCoreDataNum; | ||
| 110 | + this->tileNum = finalBigTileNum; | ||
| 111 | + this->tailDataNum = bigTailDataNum; | ||
| 112 | + } | ||
| 113 | + else | ||
| 114 | + { | ||
| 115 | + this->coreDataNum = smallCoreDataNum; | ||
| 116 | + this->tileNum = finalSmallTileNum; | ||
| 117 | + this->tailDataNum = smallTailDataNum; | ||
| 118 | + globalBufferIndex -= (bigCoreDataNum - smallCoreDataNum) * (GetBlockIdx() - tailBlockNum); | ||
| 119 | + } | ||
| 120 | + this->xGm.SetGlobalBuffer((__gm__ TYPE_X *)x + globalBufferIndex, this->coreDataNum); | ||
| 121 | + this->yGm.SetGlobalBuffer((__gm__ TYPE_Y *)y + globalBufferIndex, this->coreDataNum); | ||
| 122 | + BufferInit(); | ||
| 123 | + } | ||
| 124 | + __aicore__ inline void Process() | ||
| 125 | + { | ||
| 126 | + int32_t loopCount = this->tileNum; | ||
| 127 | + this->processDataNum = this->tileDataNum; | ||
| 128 | + for (int32_t i = 0; i < loopCount - 1; i++) | ||
| 129 | + { | ||
| 130 | + this->CopyIn(i); | ||
| 131 | + Compute(i); | ||
| 132 | + this->CopyOut(i); | ||
| 133 | + } | ||
| 134 | + this->processDataNum = this->tailDataNum; | ||
| 135 | + this->CopyIn(loopCount - 1); | ||
| 136 | + Compute(loopCount - 1); | ||
| 137 | + this->CopyOut(loopCount - 1); | ||
| 138 | + } | ||
| 139 | + | ||
| 140 | +private: | ||
| 141 | + __aicore__ inline void BufferInit() | ||
| 142 | + { | ||
| 143 | + this->pipe->InitBuffer(this->inQueueX, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_X)); | ||
| 144 | + this->pipe->InitBuffer(this->outQueueY, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_Y)); | ||
| 145 | + } | ||
| 146 | + __aicore__ inline void Compute(int32_t progress) | ||
| 147 | + { | ||
| 148 | + LocalTensor<TYPE_X> xLocal = this->inQueueX.template DeQue<TYPE_X>(); | ||
| 149 | + LocalTensor<TYPE_Y> yLocal = this->outQueueY.template AllocTensor<TYPE_Y>(); | ||
| 150 | + if constexpr ((std::is_same_v<DTYPE_X, half> && std::is_same_v<DTYPE_Y, int32_t>) || | ||
| 151 | + (std::is_same_v<DTYPE_X, half> && std::is_same_v<DTYPE_Y, int16_t>) || | ||
| 152 | + (std::is_same_v<DTYPE_X, float> && std::is_same_v<DTYPE_Y, int32_t>) || | ||
| 153 | + (std::is_same_v<DTYPE_X, float> && std::is_same_v<DTYPE_Y, int16_t>) || | ||
| 154 | + (std::is_same_v<DTYPE_X, float> && std::is_same_v<DTYPE_Y, int64_t>) || | ||
| 155 | + (std::is_same_v<DTYPE_X, bfloat16_t> && std::is_same_v<DTYPE_Y, int32_t>)) | ||
| 156 | + { | ||
| 157 | + Cast(yLocal, xLocal, RoundMode::CAST_TRUNC, this->processDataNum); | ||
| 158 | + } | ||
| 159 | + else if constexpr ((std::is_same_v<DTYPE_X, int64_t> && std::is_same_v<DTYPE_Y, float>)) | ||
| 160 | + { | ||
| 161 | + Cast(yLocal, xLocal, RoundMode::CAST_ROUND, this->processDataNum); | ||
| 162 | + } | ||
| 163 | + else if constexpr ((std::is_same_v<DTYPE_X, half> && std::is_same_v<DTYPE_Y, bool>)) | ||
| 164 | + { | ||
| 165 | + Abs(xLocal, xLocal, this->processDataNum); | ||
| 166 | + Mins(xLocal, xLocal, HALF_ONE, this->processDataNum); | ||
| 167 | + Cast(yLocal, xLocal, RoundMode::CAST_CEIL, this->processDataNum); | ||
| 168 | + } | ||
| 169 | + else if constexpr ((std::is_same_v<DTYPE_X, half> && std::is_same_v<DTYPE_Y, float>) || | ||
| 170 | + (std::is_same_v<DTYPE_X, float> && std::is_same_v<DTYPE_Y, half>) || | ||
| 171 | + (std::is_same_v<DTYPE_X, int32_t> && std::is_same_v<DTYPE_Y, int16_t>) || | ||
| 172 | + (std::is_same_v<DTYPE_X, int32_t> && std::is_same_v<DTYPE_Y, int64_t>) || | ||
| 173 | + (std::is_same_v<DTYPE_X, int32_t> && std::is_same_v<DTYPE_Y, float>) || | ||
| 174 | + (std::is_same_v<DTYPE_X, int8_t> && std::is_same_v<DTYPE_Y, half>) || | ||
| 175 | + (std::is_same_v<DTYPE_X, uint8_t> && std::is_same_v<DTYPE_Y, half>) || | ||
| 176 | + (std::is_same_v<DTYPE_X, bool> && std::is_same_v<DTYPE_Y, half>) || | ||
| 177 | + (std::is_same_v<DTYPE_X, int64_t> && std::is_same_v<DTYPE_Y, int32_t>) || | ||
| 178 | + (std::is_same_v<DTYPE_X, bfloat16_t> && std::is_same_v<DTYPE_Y, float>) || | ||
| 179 | + (std::is_same_v<DTYPE_X, int16_t> && std::is_same_v<DTYPE_Y, half>) || | ||
| 180 | + (std::is_same_v<DTYPE_X, int16_t> && std::is_same_v<DTYPE_Y, float>)) | ||
| 181 | + { | ||
| 182 | + Cast(yLocal, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 183 | + } | ||
| 184 | + else if constexpr ((std::is_same_v<DTYPE_X, float> && std::is_same_v<DTYPE_Y, bfloat16_t>)) | ||
| 185 | + { | ||
| 186 | + Cast(yLocal, xLocal, RoundMode::CAST_RINT, this->processDataNum); | ||
| 187 | + } | ||
| 188 | + this->outQueueY.template EnQue<TYPE_Y>(yLocal); | ||
| 189 | + this->inQueueX.template FreeTensor(xLocal); | ||
| 190 | + } | ||
| 191 | +}; | ||
| 192 | + | ||
| 193 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 194 | +class KernelCast1TBuf4B : public BaseKernelCast<TYPE_X, TYPE_Y> | ||
| 195 | +{ | ||
| 196 | + /* | ||
| 197 | + 1个4Bytes的临时变量 | ||
| 198 | + half -> float ->(RINT) bfloat16 | ||
| 199 | + int32 -> float ->(RINT) bfloat16 | ||
| 200 | + int32 -> float -> half | ||
| 201 | + int64 ->(ROUND) float -> half | ||
| 202 | + int64 ->(ROUND) float ->(RINT) bfloat16 | ||
| 203 | + int64 -> int32 -> int16 | ||
| 204 | + bfloat16 -> float -> half | ||
| 205 | + int16 -> float ->(ROUND) int32 | ||
| 206 | + int16 -> float ->(ROUND) int64 | ||
| 207 | + */ | ||
| 208 | +public: | ||
| 209 | + __aicore__ inline KernelCast1TBuf4B() {} | ||
| 210 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, uint32_t smallCoreDataNum, | ||
| 211 | + uint32_t bigCoreDataNum, uint32_t finalBigTileNum, | ||
| 212 | + uint32_t finalSmallTileNum, uint32_t tileDataNum, | ||
| 213 | + uint32_t smallTailDataNum, uint32_t bigTailDataNum, | ||
| 214 | + uint32_t tailBlockNum, TPipe *pipeIn) | ||
| 215 | + { | ||
| 216 | + this->pipe = pipeIn; | ||
| 217 | + ASSERT(GetBlockNum() != 0 && "block dim can not be zero!"); | ||
| 218 | + uint32_t coreNum = GetBlockIdx(); | ||
| 219 | + uint32_t globalBufferIndex = bigCoreDataNum * GetBlockIdx(); | ||
| 220 | + this->tileDataNum = tileDataNum; | ||
| 221 | + if (coreNum < tailBlockNum) | ||
| 222 | + { | ||
| 223 | + this->coreDataNum = bigCoreDataNum; | ||
| 224 | + this->tileNum = finalBigTileNum; | ||
| 225 | + this->tailDataNum = bigTailDataNum; | ||
| 226 | + } | ||
| 227 | + else | ||
| 228 | + { | ||
| 229 | + this->coreDataNum = smallCoreDataNum; | ||
| 230 | + this->tileNum = finalSmallTileNum; | ||
| 231 | + this->tailDataNum = smallTailDataNum; | ||
| 232 | + globalBufferIndex -= (bigCoreDataNum - smallCoreDataNum) * (GetBlockIdx() - tailBlockNum); | ||
| 233 | + } | ||
| 234 | + this->xGm.SetGlobalBuffer((__gm__ TYPE_X *)x + globalBufferIndex, this->coreDataNum); | ||
| 235 | + this->yGm.SetGlobalBuffer((__gm__ TYPE_Y *)y + globalBufferIndex, this->coreDataNum); | ||
| 236 | + BufferInit(); | ||
| 237 | + } | ||
| 238 | + __aicore__ inline void Process() | ||
| 239 | + { | ||
| 240 | + int32_t loopCount = this->tileNum; | ||
| 241 | + this->processDataNum = this->tileDataNum; | ||
| 242 | + for (int32_t i = 0; i < loopCount - 1; i++) | ||
| 243 | + { | ||
| 244 | + this->CopyIn(i); | ||
| 245 | + Compute(i); | ||
| 246 | + this->CopyOut(i); | ||
| 247 | + } | ||
| 248 | + this->processDataNum = this->tailDataNum; | ||
| 249 | + this->CopyIn(loopCount - 1); | ||
| 250 | + Compute(loopCount - 1); | ||
| 251 | + this->CopyOut(loopCount - 1); | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | +private: | ||
| 255 | + __aicore__ inline void BufferInit() | ||
| 256 | + { | ||
| 257 | + this->pipe->InitBuffer(this->inQueueX, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_X)); | ||
| 258 | + this->pipe->InitBuffer(this->outQueueY, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_Y)); | ||
| 259 | + this->pipe->InitBuffer(tmp4Bytes1, this->tileDataNum * sizeof(float)); | ||
| 260 | + } | ||
| 261 | + __aicore__ inline void Compute(int32_t progress) | ||
| 262 | + { | ||
| 263 | + LocalTensor<TYPE_X> xLocal = this->inQueueX.template DeQue<TYPE_X>(); | ||
| 264 | + LocalTensor<TYPE_Y> yLocal = this->outQueueY.template AllocTensor<TYPE_Y>(); | ||
| 265 | + if constexpr ((std::is_same_v<DTYPE_X, half> && std::is_same_v<DTYPE_Y, bfloat16_t>) || | ||
| 266 | + (std::is_same_v<DTYPE_X, int32_t> && std::is_same_v<DTYPE_Y, bfloat16_t>) || | ||
| 267 | + (std::is_same_v<DTYPE_X, int32_t> && std::is_same_v<DTYPE_Y, half>) || | ||
| 268 | + (std::is_same_v<DTYPE_X, bfloat16_t> && std::is_same_v<DTYPE_Y, half>)) | ||
| 269 | + { | ||
| 270 | + LocalTensor<float> tmp1 = tmp4Bytes1.Get<float>(); | ||
| 271 | + Cast(tmp1, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 272 | + if constexpr (std::is_same_v<DTYPE_Y, half>) | ||
| 273 | + { | ||
| 274 | + Cast(yLocal, tmp1, RoundMode::CAST_NONE, this->processDataNum); | ||
| 275 | + } | ||
| 276 | + else if constexpr (std::is_same_v<DTYPE_Y, bfloat16_t>) | ||
| 277 | + { | ||
| 278 | + Cast(yLocal, tmp1, RoundMode::CAST_RINT, this->processDataNum); | ||
| 279 | + } | ||
| 280 | + } | ||
| 281 | + else if constexpr ((std::is_same_v<DTYPE_X, int64_t> && std::is_same_v<DTYPE_Y, half>) || | ||
| 282 | + (std::is_same_v<DTYPE_X, int64_t> && std::is_same_v<DTYPE_Y, bfloat16_t>)) | ||
| 283 | + { | ||
| 284 | + LocalTensor<float> tmp1 = tmp4Bytes1.Get<float>(); | ||
| 285 | + Cast(tmp1, xLocal, RoundMode::CAST_ROUND, this->processDataNum); | ||
| 286 | + if constexpr (std::is_same_v<DTYPE_Y, half>) | ||
| 287 | + { | ||
| 288 | + Cast(yLocal, tmp1, RoundMode::CAST_NONE, this->processDataNum); | ||
| 289 | + } | ||
| 290 | + else if constexpr (std::is_same_v<DTYPE_Y, bfloat16_t>) | ||
| 291 | + { | ||
| 292 | + Cast(yLocal, tmp1, RoundMode::CAST_RINT, this->processDataNum); | ||
| 293 | + } | ||
| 294 | + } | ||
| 295 | + else if constexpr ((std::is_same_v<DTYPE_X, int64_t> && std::is_same_v<DTYPE_Y, int16_t>)) | ||
| 296 | + { | ||
| 297 | + LocalTensor<int32_t> tmp1 = tmp4Bytes1.Get<int32_t>(); | ||
| 298 | + Cast(tmp1, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 299 | + Cast(yLocal, tmp1, RoundMode::CAST_NONE, this->processDataNum); | ||
| 300 | + } | ||
| 301 | + else if constexpr ((std::is_same_v<DTYPE_X, int16_t> && std::is_same_v<DTYPE_Y, int32_t>) || | ||
| 302 | + (std::is_same_v<DTYPE_X, int16_t> && std::is_same_v<DTYPE_Y, int64_t>)) | ||
| 303 | + { | ||
| 304 | + LocalTensor<float> tmp1 = tmp4Bytes1.Get<float>(); | ||
| 305 | + Cast(tmp1, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 306 | + Cast(yLocal, tmp1, RoundMode::CAST_ROUND, this->processDataNum); | ||
| 307 | + } | ||
| 308 | + this->outQueueY.template EnQue<TYPE_Y>(yLocal); | ||
| 309 | + this->inQueueX.template FreeTensor(xLocal); | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | +private: | ||
| 313 | + TBuf<QuePosition::VECCALC> tmp4Bytes1; | ||
| 314 | +}; | ||
| 315 | + | ||
| 316 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 317 | +class KernelCast2TBuf2B : public BaseKernelCast<TYPE_X, TYPE_Y> | ||
| 318 | +{ | ||
| 319 | + /* | ||
| 320 | + 2个2Bytes的临时变量 | ||
| 321 | + half -> int8 | ||
| 322 | + half -> uint8 | ||
| 323 | + float -> bool | ||
| 324 | + int32 -> bool | ||
| 325 | + int16 -> int8 | ||
| 326 | + int16 -> uint8 | ||
| 327 | + */ | ||
| 328 | +public: | ||
| 329 | + __aicore__ inline KernelCast2TBuf2B() {} | ||
| 330 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, uint32_t smallCoreDataNum, | ||
| 331 | + uint32_t bigCoreDataNum, uint32_t finalBigTileNum, | ||
| 332 | + uint32_t finalSmallTileNum, uint32_t tileDataNum, | ||
| 333 | + uint32_t smallTailDataNum, uint32_t bigTailDataNum, | ||
| 334 | + uint32_t tailBlockNum, TPipe *pipeIn) | ||
| 335 | + { | ||
| 336 | + this->pipe = pipeIn; | ||
| 337 | + ASSERT(GetBlockNum() != 0 && "block dim can not be zero!"); | ||
| 338 | + uint32_t coreNum = GetBlockIdx(); | ||
| 339 | + uint32_t globalBufferIndex = bigCoreDataNum * GetBlockIdx(); | ||
| 340 | + this->tileDataNum = tileDataNum; | ||
| 341 | + if (coreNum < tailBlockNum) | ||
| 342 | + { | ||
| 343 | + this->coreDataNum = bigCoreDataNum; | ||
| 344 | + this->tileNum = finalBigTileNum; | ||
| 345 | + this->tailDataNum = bigTailDataNum; | ||
| 346 | + } | ||
| 347 | + else | ||
| 348 | + { | ||
| 349 | + this->coreDataNum = smallCoreDataNum; | ||
| 350 | + this->tileNum = finalSmallTileNum; | ||
| 351 | + this->tailDataNum = smallTailDataNum; | ||
| 352 | + globalBufferIndex -= (bigCoreDataNum - smallCoreDataNum) * (GetBlockIdx() - tailBlockNum); | ||
| 353 | + } | ||
| 354 | + this->xGm.SetGlobalBuffer((__gm__ TYPE_X *)x + globalBufferIndex, this->coreDataNum); | ||
| 355 | + this->yGm.SetGlobalBuffer((__gm__ TYPE_Y *)y + globalBufferIndex, this->coreDataNum); | ||
| 356 | + BufferInit(); | ||
| 357 | + } | ||
| 358 | + __aicore__ inline void Process() | ||
| 359 | + { | ||
| 360 | + int32_t loopCount = this->tileNum; | ||
| 361 | + this->processDataNum = this->tileDataNum; | ||
| 362 | + for (int32_t i = 0; i < loopCount - 1; i++) | ||
| 363 | + { | ||
| 364 | + this->CopyIn(i); | ||
| 365 | + Compute(i); | ||
| 366 | + this->CopyOut(i); | ||
| 367 | + } | ||
| 368 | + this->processDataNum = this->tailDataNum; | ||
| 369 | + this->CopyIn(loopCount - 1); | ||
| 370 | + Compute(loopCount - 1); | ||
| 371 | + this->CopyOut(loopCount - 1); | ||
| 372 | + } | ||
| 373 | + | ||
| 374 | +private: | ||
| 375 | + __aicore__ inline void BufferInit() | ||
| 376 | + { | ||
| 377 | + this->pipe->InitBuffer(this->inQueueX, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_X)); | ||
| 378 | + this->pipe->InitBuffer(this->outQueueY, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_Y)); | ||
| 379 | + this->pipe->InitBuffer(tmp2Bytes1, this->tileDataNum * sizeof(half)); | ||
| 380 | + this->pipe->InitBuffer(tmp2Bytes2, this->tileDataNum * sizeof(half)); | ||
| 381 | + } | ||
| 382 | + __aicore__ inline void Compute(int32_t progress) | ||
| 383 | + { | ||
| 384 | + LocalTensor<TYPE_X> xLocal = this->inQueueX.template DeQue<TYPE_X>(); | ||
| 385 | + LocalTensor<TYPE_Y> yLocal = this->outQueueY.template AllocTensor<TYPE_Y>(); | ||
| 386 | + if constexpr ((std::is_same_v<DTYPE_X, half> && std::is_same_v<DTYPE_Y, int8_t>) || | ||
| 387 | + (std::is_same_v<DTYPE_X, half> && std::is_same_v<DTYPE_Y, uint8_t>)) | ||
| 388 | + { | ||
| 389 | + LocalTensor<int16_t> tmp1 = tmp2Bytes1.Get<int16_t>(); | ||
| 390 | + LocalTensor<int16_t> tmp2 = tmp2Bytes2.Get<int16_t>(); | ||
| 391 | + Cast(tmp1, xLocal, RoundMode::CAST_TRUNC, this->processDataNum); | ||
| 392 | + Duplicate(tmp2, CONST_255, this->processDataNum); | ||
| 393 | + And(tmp1, tmp1, tmp2, this->processDataNum); | ||
| 394 | + if constexpr (std::is_same_v<DTYPE_Y, int8_t>) | ||
| 395 | + { | ||
| 396 | + Adds(tmp1, tmp1, CONST_128, this->processDataNum); | ||
| 397 | + And(tmp1, tmp1, tmp2, this->processDataNum); | ||
| 398 | + Adds(tmp1, tmp1, CONST_NE128, this->processDataNum); | ||
| 399 | + } | ||
| 400 | + Cast(xLocal, tmp1, RoundMode::CAST_NONE, this->processDataNum); | ||
| 401 | + Cast(yLocal, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 402 | + } | ||
| 403 | + else if constexpr ((std::is_same_v<DTYPE_X, float> && std::is_same_v<DTYPE_Y, bool>)) | ||
| 404 | + { | ||
| 405 | + LocalTensor<int16_t> tmp1 = tmp2Bytes1.Get<int16_t>(); | ||
| 406 | + LocalTensor<half> tmp2 = tmp2Bytes2.Get<half>(); | ||
| 407 | + Abs(xLocal, xLocal, this->processDataNum); | ||
| 408 | + Cast(tmp1, xLocal, RoundMode::CAST_CEIL, this->processDataNum); | ||
| 409 | + Mins(tmp1, tmp1, CONST_1, this->processDataNum); | ||
| 410 | + Cast(tmp2, tmp1, RoundMode::CAST_NONE, this->processDataNum); | ||
| 411 | + Cast(yLocal, tmp2, RoundMode::CAST_NONE, this->processDataNum); | ||
| 412 | + } | ||
| 413 | + else if constexpr ((std::is_same_v<DTYPE_X, int32_t> && std::is_same_v<DTYPE_Y, bool>)) | ||
| 414 | + { | ||
| 415 | + LocalTensor<int16_t> tmp1 = tmp2Bytes1.Get<int16_t>(); | ||
| 416 | + LocalTensor<half> tmp2 = tmp2Bytes2.Get<half>(); | ||
| 417 | + Cast(tmp1, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 418 | + Cast(tmp2, tmp1, RoundMode::CAST_NONE, this->processDataNum); | ||
| 419 | + Abs(tmp2, tmp2, this->processDataNum); | ||
| 420 | + Mins(tmp2, tmp2, HALF_ONE, this->processDataNum); | ||
| 421 | + Cast(yLocal, tmp2, RoundMode::CAST_NONE, this->processDataNum); | ||
| 422 | + } | ||
| 423 | + else if constexpr ((std::is_same_v<DTYPE_X, int16_t> && std::is_same_v<DTYPE_Y, int8_t>) || | ||
| 424 | + (std::is_same_v<DTYPE_X, int16_t> && std::is_same_v<DTYPE_Y, uint8_t>)) | ||
| 425 | + { | ||
| 426 | + LocalTensor<int16_t> tmp1 = tmp2Bytes1.Get<int16_t>(); | ||
| 427 | + LocalTensor<half> tmp2 = tmp2Bytes2.Get<half>(); | ||
| 428 | + Duplicate(tmp1, CONST_255, this->processDataNum); | ||
| 429 | + And(xLocal, xLocal, tmp1, this->processDataNum); | ||
| 430 | + if constexpr (std::is_same_v<DTYPE_Y, int8_t>) | ||
| 431 | + { | ||
| 432 | + Adds(xLocal, xLocal, CONST_128, this->processDataNum); | ||
| 433 | + And(xLocal, xLocal, tmp1, this->processDataNum); | ||
| 434 | + Adds(xLocal, xLocal, CONST_NE128, this->processDataNum); | ||
| 435 | + } | ||
| 436 | + Cast(tmp2, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 437 | + Cast(yLocal, tmp2, RoundMode::CAST_NONE, this->processDataNum); | ||
| 438 | + } | ||
| 439 | + this->outQueueY.template EnQue<TYPE_Y>(yLocal); | ||
| 440 | + this->inQueueX.template FreeTensor(xLocal); | ||
| 441 | + } | ||
| 442 | + | ||
| 443 | +private: | ||
| 444 | + TBuf<QuePosition::VECCALC> tmp2Bytes1; | ||
| 445 | + TBuf<QuePosition::VECCALC> tmp2Bytes2; | ||
| 446 | +}; | ||
| 447 | + | ||
| 448 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 449 | +class KernelCast3TBuf2B : public BaseKernelCast<TYPE_X, TYPE_Y> | ||
| 450 | +{ | ||
| 451 | + /* | ||
| 452 | + 3个2Bytes的临时变量 | ||
| 453 | + float -> int8 | ||
| 454 | + float -> uint8 | ||
| 455 | + int32 -> int8 | ||
| 456 | + int32 -> uint8 | ||
| 457 | + */ | ||
| 458 | +public: | ||
| 459 | + __aicore__ inline KernelCast3TBuf2B() {} | ||
| 460 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, uint32_t smallCoreDataNum, | ||
| 461 | + uint32_t bigCoreDataNum, uint32_t finalBigTileNum, | ||
| 462 | + uint32_t finalSmallTileNum, uint32_t tileDataNum, | ||
| 463 | + uint32_t smallTailDataNum, uint32_t bigTailDataNum, | ||
| 464 | + uint32_t tailBlockNum, TPipe *pipeIn) | ||
| 465 | + { | ||
| 466 | + this->pipe = pipeIn; | ||
| 467 | + ASSERT(GetBlockNum() != 0 && "block dim can not be zero!"); | ||
| 468 | + uint32_t coreNum = GetBlockIdx(); | ||
| 469 | + uint32_t globalBufferIndex = bigCoreDataNum * GetBlockIdx(); | ||
| 470 | + this->tileDataNum = tileDataNum; | ||
| 471 | + if (coreNum < tailBlockNum) | ||
| 472 | + { | ||
| 473 | + this->coreDataNum = bigCoreDataNum; | ||
| 474 | + this->tileNum = finalBigTileNum; | ||
| 475 | + this->tailDataNum = bigTailDataNum; | ||
| 476 | + } | ||
| 477 | + else | ||
| 478 | + { | ||
| 479 | + this->coreDataNum = smallCoreDataNum; | ||
| 480 | + this->tileNum = finalSmallTileNum; | ||
| 481 | + this->tailDataNum = smallTailDataNum; | ||
| 482 | + globalBufferIndex -= (bigCoreDataNum - smallCoreDataNum) * (GetBlockIdx() - tailBlockNum); | ||
| 483 | + } | ||
| 484 | + this->xGm.SetGlobalBuffer((__gm__ TYPE_X *)x + globalBufferIndex, this->coreDataNum); | ||
| 485 | + this->yGm.SetGlobalBuffer((__gm__ TYPE_Y *)y + globalBufferIndex, this->coreDataNum); | ||
| 486 | + BufferInit(); | ||
| 487 | + } | ||
| 488 | + __aicore__ inline void Process() | ||
| 489 | + { | ||
| 490 | + int32_t loopCount = this->tileNum; | ||
| 491 | + this->processDataNum = this->tileDataNum; | ||
| 492 | + for (int32_t i = 0; i < loopCount - 1; i++) | ||
| 493 | + { | ||
| 494 | + this->CopyIn(i); | ||
| 495 | + Compute(i); | ||
| 496 | + this->CopyOut(i); | ||
| 497 | + } | ||
| 498 | + this->processDataNum = this->tailDataNum; | ||
| 499 | + this->CopyIn(loopCount - 1); | ||
| 500 | + Compute(loopCount - 1); | ||
| 501 | + this->CopyOut(loopCount - 1); | ||
| 502 | + } | ||
| 503 | + | ||
| 504 | +private: | ||
| 505 | + __aicore__ inline void BufferInit() | ||
| 506 | + { | ||
| 507 | + this->pipe->InitBuffer(this->inQueueX, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_X)); | ||
| 508 | + this->pipe->InitBuffer(this->outQueueY, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_Y)); | ||
| 509 | + this->pipe->InitBuffer(tmp2Bytes1, this->tileDataNum * sizeof(half)); | ||
| 510 | + this->pipe->InitBuffer(tmp2Bytes2, this->tileDataNum * sizeof(half)); | ||
| 511 | + this->pipe->InitBuffer(tmp2Bytes3, this->tileDataNum * sizeof(half)); | ||
| 512 | + } | ||
| 513 | + __aicore__ inline void Compute(int32_t progress) | ||
| 514 | + { | ||
| 515 | + LocalTensor<TYPE_X> xLocal = this->inQueueX.template DeQue<TYPE_X>(); | ||
| 516 | + LocalTensor<TYPE_Y> yLocal = this->outQueueY.template AllocTensor<TYPE_Y>(); | ||
| 517 | + if constexpr ((std::is_same_v<DTYPE_X, float> && std::is_same_v<DTYPE_Y, int8_t>) || | ||
| 518 | + (std::is_same_v<DTYPE_X, float> && std::is_same_v<DTYPE_Y, uint8_t>) || | ||
| 519 | + (std::is_same_v<DTYPE_X, int32_t> && std::is_same_v<DTYPE_Y, int8_t>) || | ||
| 520 | + (std::is_same_v<DTYPE_X, int32_t> && std::is_same_v<DTYPE_Y, uint8_t>)) | ||
| 521 | + { | ||
| 522 | + LocalTensor<int16_t> tmp1 = tmp2Bytes1.Get<int16_t>(); | ||
| 523 | + LocalTensor<int16_t> tmp2 = tmp2Bytes2.Get<int16_t>(); | ||
| 524 | + LocalTensor<half> tmp3 = tmp2Bytes3.Get<half>(); | ||
| 525 | + if constexpr (std::is_same_v<DTYPE_X, float>) | ||
| 526 | + { | ||
| 527 | + Cast(tmp1, xLocal, RoundMode::CAST_TRUNC, this->processDataNum); | ||
| 528 | + } | ||
| 529 | + else if constexpr (std::is_same_v<DTYPE_X, int32_t>) | ||
| 530 | + { | ||
| 531 | + Cast(tmp1, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 532 | + } | ||
| 533 | + Duplicate(tmp2, CONST_255, this->processDataNum); | ||
| 534 | + And(tmp1, tmp1, tmp2, this->processDataNum); | ||
| 535 | + if constexpr (std::is_same_v<DTYPE_Y, int8_t>) | ||
| 536 | + { | ||
| 537 | + Adds(tmp1, tmp1, CONST_128, this->processDataNum); | ||
| 538 | + And(tmp1, tmp1, tmp2, this->processDataNum); | ||
| 539 | + Adds(tmp1, tmp1, CONST_NE128, this->processDataNum); | ||
| 540 | + } | ||
| 541 | + Cast(tmp3, tmp1, RoundMode::CAST_NONE, this->processDataNum); | ||
| 542 | + Cast(yLocal, tmp3, RoundMode::CAST_NONE, this->processDataNum); | ||
| 543 | + } | ||
| 544 | + this->outQueueY.template EnQue<TYPE_Y>(yLocal); | ||
| 545 | + this->inQueueX.template FreeTensor(xLocal); | ||
| 546 | + } | ||
| 547 | + | ||
| 548 | +private: | ||
| 549 | + TBuf<QuePosition::VECCALC> tmp2Bytes1; | ||
| 550 | + TBuf<QuePosition::VECCALC> tmp2Bytes2; | ||
| 551 | + TBuf<QuePosition::VECCALC> tmp2Bytes3; | ||
| 552 | +}; | ||
| 553 | + | ||
| 554 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 555 | +class KernelCast1TBuf2B : public BaseKernelCast<TYPE_X, TYPE_Y> | ||
| 556 | +{ | ||
| 557 | + /* | ||
| 558 | + 1个2Bytes的临时变量 | ||
| 559 | + int8/uint8/bool -> float | ||
| 560 | + int8/uint8/bool -> int32 | ||
| 561 | + int8/uint8 -> int16 | ||
| 562 | + int8 -> bool | ||
| 563 | + */ | ||
| 564 | +public: | ||
| 565 | + __aicore__ inline KernelCast1TBuf2B() {} | ||
| 566 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, uint32_t smallCoreDataNum, | ||
| 567 | + uint32_t bigCoreDataNum, uint32_t finalBigTileNum, | ||
| 568 | + uint32_t finalSmallTileNum, uint32_t tileDataNum, | ||
| 569 | + uint32_t smallTailDataNum, uint32_t bigTailDataNum, | ||
| 570 | + uint32_t tailBlockNum, TPipe *pipeIn) | ||
| 571 | + { | ||
| 572 | + this->pipe = pipeIn; | ||
| 573 | + ASSERT(GetBlockNum() != 0 && "block dim can not be zero!"); | ||
| 574 | + uint32_t coreNum = GetBlockIdx(); | ||
| 575 | + uint32_t globalBufferIndex = bigCoreDataNum * GetBlockIdx(); | ||
| 576 | + this->tileDataNum = tileDataNum; | ||
| 577 | + if (coreNum < tailBlockNum) | ||
| 578 | + { | ||
| 579 | + this->coreDataNum = bigCoreDataNum; | ||
| 580 | + this->tileNum = finalBigTileNum; | ||
| 581 | + this->tailDataNum = bigTailDataNum; | ||
| 582 | + } | ||
| 583 | + else | ||
| 584 | + { | ||
| 585 | + this->coreDataNum = smallCoreDataNum; | ||
| 586 | + this->tileNum = finalSmallTileNum; | ||
| 587 | + this->tailDataNum = smallTailDataNum; | ||
| 588 | + globalBufferIndex -= (bigCoreDataNum - smallCoreDataNum) * (GetBlockIdx() - tailBlockNum); | ||
| 589 | + } | ||
| 590 | + this->xGm.SetGlobalBuffer((__gm__ TYPE_X *)x + globalBufferIndex, this->coreDataNum); | ||
| 591 | + this->yGm.SetGlobalBuffer((__gm__ TYPE_Y *)y + globalBufferIndex, this->coreDataNum); | ||
| 592 | + BufferInit(); | ||
| 593 | + } | ||
| 594 | + __aicore__ inline void Process() | ||
| 595 | + { | ||
| 596 | + int32_t loopCount = this->tileNum; | ||
| 597 | + this->processDataNum = this->tileDataNum; | ||
| 598 | + for (int32_t i = 0; i < loopCount - 1; i++) | ||
| 599 | + { | ||
| 600 | + this->CopyIn(i); | ||
| 601 | + Compute(i); | ||
| 602 | + this->CopyOut(i); | ||
| 603 | + } | ||
| 604 | + this->processDataNum = this->tailDataNum; | ||
| 605 | + this->CopyIn(loopCount - 1); | ||
| 606 | + Compute(loopCount - 1); | ||
| 607 | + this->CopyOut(loopCount - 1); | ||
| 608 | + } | ||
| 609 | + | ||
| 610 | +private: | ||
| 611 | + __aicore__ inline void BufferInit() | ||
| 612 | + { | ||
| 613 | + this->pipe->InitBuffer(this->inQueueX, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_X)); | ||
| 614 | + this->pipe->InitBuffer(this->outQueueY, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_Y)); | ||
| 615 | + this->pipe->InitBuffer(tmp2Bytes1, this->tileDataNum * sizeof(half)); | ||
| 616 | + } | ||
| 617 | + __aicore__ inline void Compute(int32_t progress) | ||
| 618 | + { | ||
| 619 | + LocalTensor<TYPE_X> xLocal = this->inQueueX.template DeQue<TYPE_X>(); | ||
| 620 | + LocalTensor<TYPE_Y> yLocal = this->outQueueY.template AllocTensor<TYPE_Y>(); | ||
| 621 | + if constexpr ((std::is_same_v<DTYPE_X, int8_t> && std::is_same_v<DTYPE_Y, float>) || | ||
| 622 | + (std::is_same_v<DTYPE_X, uint8_t> && std::is_same_v<DTYPE_Y, float>) || | ||
| 623 | + (std::is_same_v<DTYPE_X, bool> && std::is_same_v<DTYPE_Y, float>) || | ||
| 624 | + (std::is_same_v<DTYPE_X, int8_t> && std::is_same_v<DTYPE_Y, int32_t>) || | ||
| 625 | + (std::is_same_v<DTYPE_X, uint8_t> && std::is_same_v<DTYPE_Y, int32_t>) || | ||
| 626 | + (std::is_same_v<DTYPE_X, bool> && std::is_same_v<DTYPE_Y, int32_t>) || | ||
| 627 | + (std::is_same_v<DTYPE_X, int8_t> && std::is_same_v<DTYPE_Y, int16_t>) || | ||
| 628 | + (std::is_same_v<DTYPE_X, uint8_t> && std::is_same_v<DTYPE_Y, int16_t>) || | ||
| 629 | + (std::is_same_v<DTYPE_X, bool> && std::is_same_v<DTYPE_Y, uint8_t>)) | ||
| 630 | + { | ||
| 631 | + LocalTensor<half> tmp1 = tmp2Bytes1.Get<half>(); | ||
| 632 | + Cast(tmp1, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 633 | + if constexpr (std::is_same_v<DTYPE_Y, int32_t> || std::is_same_v<DTYPE_Y, int16_t> || std::is_same_v<DTYPE_Y, uint8_t>) | ||
| 634 | + { | ||
| 635 | + Cast(yLocal, tmp1, RoundMode::CAST_TRUNC, this->processDataNum); | ||
| 636 | + } | ||
| 637 | + else | ||
| 638 | + { | ||
| 639 | + Cast(yLocal, tmp1, RoundMode::CAST_NONE, this->processDataNum); | ||
| 640 | + } | ||
| 641 | + } | ||
| 642 | + else if constexpr ((std::is_same_v<DTYPE_X, int8_t> && std::is_same_v<DTYPE_Y, bool>)) | ||
| 643 | + { | ||
| 644 | + LocalTensor<half> tmp1 = tmp2Bytes1.Get<half>(); | ||
| 645 | + Cast(tmp1, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 646 | + Abs(tmp1, tmp1, this->processDataNum); | ||
| 647 | + Mins(tmp1, tmp1, HALF_ONE, this->processDataNum); | ||
| 648 | + Cast(yLocal, tmp1, RoundMode::CAST_NONE, this->processDataNum); | ||
| 649 | + } | ||
| 650 | + this->outQueueY.template EnQue<TYPE_Y>(yLocal); | ||
| 651 | + this->inQueueX.template FreeTensor(xLocal); | ||
| 652 | + } | ||
| 653 | + | ||
| 654 | +private: | ||
| 655 | + TBuf<QuePosition::VECCALC> tmp2Bytes1; | ||
| 656 | +}; | ||
| 657 | + | ||
| 658 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 659 | +class KernelCast1TBuf2B1TBuf4B : public BaseKernelCast<TYPE_X, TYPE_Y> | ||
| 660 | +{ | ||
| 661 | + /* | ||
| 662 | + 1个2Bytes,1个4Bytes的临时变量 | ||
| 663 | + int8/uint8/bool -> half ->(TRUNC) int32 -> int64 | ||
| 664 | + int8/uint8/bool -> half -> float -> bfloat16 | ||
| 665 | + int64 -> bool | ||
| 666 | + bfloat16 -> bool | ||
| 667 | + */ | ||
| 668 | +public: | ||
| 669 | + __aicore__ inline KernelCast1TBuf2B1TBuf4B() {} | ||
| 670 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, uint32_t smallCoreDataNum, | ||
| 671 | + uint32_t bigCoreDataNum, uint32_t finalBigTileNum, | ||
| 672 | + uint32_t finalSmallTileNum, uint32_t tileDataNum, | ||
| 673 | + uint32_t smallTailDataNum, uint32_t bigTailDataNum, | ||
| 674 | + uint32_t tailBlockNum, TPipe *pipeIn) | ||
| 675 | + { | ||
| 676 | + this->pipe = pipeIn; | ||
| 677 | + ASSERT(GetBlockNum() != 0 && "block dim can not be zero!"); | ||
| 678 | + uint32_t coreNum = GetBlockIdx(); | ||
| 679 | + uint32_t globalBufferIndex = bigCoreDataNum * GetBlockIdx(); | ||
| 680 | + this->tileDataNum = tileDataNum; | ||
| 681 | + if (coreNum < tailBlockNum) | ||
| 682 | + { | ||
| 683 | + this->coreDataNum = bigCoreDataNum; | ||
| 684 | + this->tileNum = finalBigTileNum; | ||
| 685 | + this->tailDataNum = bigTailDataNum; | ||
| 686 | + } | ||
| 687 | + else | ||
| 688 | + { | ||
| 689 | + this->coreDataNum = smallCoreDataNum; | ||
| 690 | + this->tileNum = finalSmallTileNum; | ||
| 691 | + this->tailDataNum = smallTailDataNum; | ||
| 692 | + globalBufferIndex -= (bigCoreDataNum - smallCoreDataNum) * (GetBlockIdx() - tailBlockNum); | ||
| 693 | + } | ||
| 694 | + this->xGm.SetGlobalBuffer((__gm__ TYPE_X *)x + globalBufferIndex, this->coreDataNum); | ||
| 695 | + this->yGm.SetGlobalBuffer((__gm__ TYPE_Y *)y + globalBufferIndex, this->coreDataNum); | ||
| 696 | + BufferInit(); | ||
| 697 | + } | ||
| 698 | + __aicore__ inline void Process() | ||
| 699 | + { | ||
| 700 | + int32_t loopCount = this->tileNum; | ||
| 701 | + this->processDataNum = this->tileDataNum; | ||
| 702 | + for (int32_t i = 0; i < loopCount - 1; i++) | ||
| 703 | + { | ||
| 704 | + this->CopyIn(i); | ||
| 705 | + Compute(i); | ||
| 706 | + this->CopyOut(i); | ||
| 707 | + } | ||
| 708 | + this->processDataNum = this->tailDataNum; | ||
| 709 | + this->CopyIn(loopCount - 1); | ||
| 710 | + Compute(loopCount - 1); | ||
| 711 | + this->CopyOut(loopCount - 1); | ||
| 712 | + } | ||
| 713 | + | ||
| 714 | +private: | ||
| 715 | + __aicore__ inline void BufferInit() | ||
| 716 | + { | ||
| 717 | + this->pipe->InitBuffer(this->inQueueX, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_X)); | ||
| 718 | + this->pipe->InitBuffer(this->outQueueY, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_Y)); | ||
| 719 | + this->pipe->InitBuffer(tmp2Bytes1, this->tileDataNum * sizeof(half)); | ||
| 720 | + this->pipe->InitBuffer(tmp4Bytes1, this->tileDataNum * sizeof(float)); | ||
| 721 | + } | ||
| 722 | + __aicore__ inline void Compute(int32_t progress) | ||
| 723 | + { | ||
| 724 | + LocalTensor<TYPE_X> xLocal = this->inQueueX.template DeQue<TYPE_X>(); | ||
| 725 | + LocalTensor<TYPE_Y> yLocal = this->outQueueY.template AllocTensor<TYPE_Y>(); | ||
| 726 | + if constexpr ((std::is_same_v<DTYPE_X, int8_t> && std::is_same_v<DTYPE_Y, int64_t>) || | ||
| 727 | + (std::is_same_v<DTYPE_X, uint8_t> && std::is_same_v<DTYPE_Y, int64_t>) || | ||
| 728 | + (std::is_same_v<DTYPE_X, bool> && std::is_same_v<DTYPE_Y, int64_t>)) | ||
| 729 | + { | ||
| 730 | + LocalTensor<half> tmp1 = tmp2Bytes1.Get<half>(); | ||
| 731 | + LocalTensor<int32_t> tmp2 = tmp4Bytes1.Get<int32_t>(); | ||
| 732 | + Cast(tmp1, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 733 | + Cast(tmp2, tmp1, RoundMode::CAST_TRUNC, this->processDataNum); | ||
| 734 | + Cast(yLocal, tmp2, RoundMode::CAST_NONE, this->processDataNum); | ||
| 735 | + } | ||
| 736 | + else if constexpr ((std::is_same_v<DTYPE_X, int8_t> && std::is_same_v<DTYPE_Y, bfloat16_t>) || | ||
| 737 | + (std::is_same_v<DTYPE_X, uint8_t> && std::is_same_v<DTYPE_Y, bfloat16_t>) || | ||
| 738 | + (std::is_same_v<DTYPE_X, bool> && std::is_same_v<DTYPE_Y, bfloat16_t>)) | ||
| 739 | + { | ||
| 740 | + LocalTensor<half> tmp1 = tmp2Bytes1.Get<half>(); | ||
| 741 | + LocalTensor<float> tmp2 = tmp4Bytes1.Get<float>(); | ||
| 742 | + Cast(tmp1, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 743 | + Cast(tmp2, tmp1, RoundMode::CAST_NONE, this->processDataNum); | ||
| 744 | + Cast(yLocal, tmp2, RoundMode::CAST_RINT, this->processDataNum); | ||
| 745 | + } | ||
| 746 | + else if constexpr ((std::is_same_v<DTYPE_X, int64_t> && std::is_same_v<DTYPE_Y, bool>) || | ||
| 747 | + (std::is_same_v<DTYPE_X, bfloat16_t> && std::is_same_v<DTYPE_Y, bool>)) | ||
| 748 | + { | ||
| 749 | + LocalTensor<half> tmp1 = tmp2Bytes1.Get<half>(); | ||
| 750 | + LocalTensor<float> tmp2 = tmp4Bytes1.Get<float>(); | ||
| 751 | + if constexpr (std::is_same_v<DTYPE_X, int64_t>) | ||
| 752 | + { | ||
| 753 | + Cast(tmp2, xLocal, RoundMode::CAST_ROUND, this->processDataNum); | ||
| 754 | + } | ||
| 755 | + else if constexpr (std::is_same_v<DTYPE_X, bfloat16_t>) | ||
| 756 | + { | ||
| 757 | + Cast(tmp2, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 758 | + } | ||
| 759 | + Cast(tmp1, tmp2, RoundMode::CAST_CEIL, this->processDataNum); | ||
| 760 | + Abs(tmp1, tmp1, this->processDataNum); | ||
| 761 | + Mins(tmp1, tmp1, HALF_ONE, this->processDataNum); | ||
| 762 | + Cast(yLocal, tmp1, RoundMode::CAST_CEIL, this->processDataNum); | ||
| 763 | + } | ||
| 764 | + this->outQueueY.template EnQue<TYPE_Y>(yLocal); | ||
| 765 | + this->inQueueX.template FreeTensor(xLocal); | ||
| 766 | + } | ||
| 767 | + | ||
| 768 | +private: | ||
| 769 | + TBuf<QuePosition::VECCALC> tmp2Bytes1; | ||
| 770 | + TBuf<QuePosition::VECCALC> tmp4Bytes1; | ||
| 771 | +}; | ||
| 772 | + | ||
| 773 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 774 | +class KernelCast3TBuf2B1TBuf4B : public BaseKernelCast<TYPE_X, TYPE_Y> | ||
| 775 | +{ | ||
| 776 | + /* | ||
| 777 | + 3个2Bytes,1个4Bytes的临时变量 | ||
| 778 | + int64 -> int8 | ||
| 779 | + int64 -> uint8 | ||
| 780 | + bfloat16 -> int8 | ||
| 781 | + bfloat16 -> uint8 | ||
| 782 | + */ | ||
| 783 | +public: | ||
| 784 | + __aicore__ inline KernelCast3TBuf2B1TBuf4B() {} | ||
| 785 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, uint32_t smallCoreDataNum, | ||
| 786 | + uint32_t bigCoreDataNum, uint32_t finalBigTileNum, | ||
| 787 | + uint32_t finalSmallTileNum, uint32_t tileDataNum, | ||
| 788 | + uint32_t smallTailDataNum, uint32_t bigTailDataNum, | ||
| 789 | + uint32_t tailBlockNum, TPipe *pipeIn) | ||
| 790 | + { | ||
| 791 | + this->pipe = pipeIn; | ||
| 792 | + ASSERT(GetBlockNum() != 0 && "block dim can not be zero!"); | ||
| 793 | + uint32_t coreNum = GetBlockIdx(); | ||
| 794 | + uint32_t globalBufferIndex = bigCoreDataNum * GetBlockIdx(); | ||
| 795 | + this->tileDataNum = tileDataNum; | ||
| 796 | + if (coreNum < tailBlockNum) | ||
| 797 | + { | ||
| 798 | + this->coreDataNum = bigCoreDataNum; | ||
| 799 | + this->tileNum = finalBigTileNum; | ||
| 800 | + this->tailDataNum = bigTailDataNum; | ||
| 801 | + } | ||
| 802 | + else | ||
| 803 | + { | ||
| 804 | + this->coreDataNum = smallCoreDataNum; | ||
| 805 | + this->tileNum = finalSmallTileNum; | ||
| 806 | + this->tailDataNum = smallTailDataNum; | ||
| 807 | + globalBufferIndex -= (bigCoreDataNum - smallCoreDataNum) * (GetBlockIdx() - tailBlockNum); | ||
| 808 | + } | ||
| 809 | + this->xGm.SetGlobalBuffer((__gm__ TYPE_X *)x + globalBufferIndex, this->coreDataNum); | ||
| 810 | + this->yGm.SetGlobalBuffer((__gm__ TYPE_Y *)y + globalBufferIndex, this->coreDataNum); | ||
| 811 | + BufferInit(); | ||
| 812 | + } | ||
| 813 | + __aicore__ inline void Process() | ||
| 814 | + { | ||
| 815 | + int32_t loopCount = this->tileNum; | ||
| 816 | + this->processDataNum = this->tileDataNum; | ||
| 817 | + for (int32_t i = 0; i < loopCount - 1; i++) | ||
| 818 | + { | ||
| 819 | + this->CopyIn(i); | ||
| 820 | + Compute(i); | ||
| 821 | + this->CopyOut(i); | ||
| 822 | + } | ||
| 823 | + this->processDataNum = this->tailDataNum; | ||
| 824 | + this->CopyIn(loopCount - 1); | ||
| 825 | + Compute(loopCount - 1); | ||
| 826 | + this->CopyOut(loopCount - 1); | ||
| 827 | + } | ||
| 828 | + | ||
| 829 | +private: | ||
| 830 | + __aicore__ inline void BufferInit() | ||
| 831 | + { | ||
| 832 | + this->pipe->InitBuffer(this->inQueueX, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_X)); | ||
| 833 | + this->pipe->InitBuffer(this->outQueueY, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_Y)); | ||
| 834 | + this->pipe->InitBuffer(tmp2Bytes1, this->tileDataNum * sizeof(half)); | ||
| 835 | + this->pipe->InitBuffer(tmp2Bytes2, this->tileDataNum * sizeof(half)); | ||
| 836 | + this->pipe->InitBuffer(tmp2Bytes3, this->tileDataNum * sizeof(half)); | ||
| 837 | + this->pipe->InitBuffer(tmp4Bytes1, this->tileDataNum * sizeof(float)); | ||
| 838 | + } | ||
| 839 | + __aicore__ inline void Compute(int32_t progress) | ||
| 840 | + { | ||
| 841 | + LocalTensor<TYPE_X> xLocal = this->inQueueX.template DeQue<TYPE_X>(); | ||
| 842 | + LocalTensor<TYPE_Y> yLocal = this->outQueueY.template AllocTensor<TYPE_Y>(); | ||
| 843 | + if constexpr ((std::is_same_v<DTYPE_X, int64_t> && std::is_same_v<DTYPE_Y, int8_t>) || | ||
| 844 | + (std::is_same_v<DTYPE_X, int64_t> && std::is_same_v<DTYPE_Y, uint8_t>) || | ||
| 845 | + (std::is_same_v<DTYPE_X, bfloat16_t> && std::is_same_v<DTYPE_Y, int8_t>) || | ||
| 846 | + (std::is_same_v<DTYPE_X, bfloat16_t> && std::is_same_v<DTYPE_Y, uint8_t>)) | ||
| 847 | + { | ||
| 848 | + LocalTensor<int16_t> tmp1 = tmp2Bytes1.Get<int16_t>(); | ||
| 849 | + LocalTensor<int16_t> tmp2 = tmp2Bytes2.Get<int16_t>(); | ||
| 850 | + LocalTensor<half> tmp3 = tmp2Bytes3.Get<half>(); | ||
| 851 | + LocalTensor<int32_t> tmp4 = tmp4Bytes1.Get<int32_t>(); | ||
| 852 | + if constexpr (std::is_same_v<DTYPE_X, int64_t>) | ||
| 853 | + { | ||
| 854 | + Cast(tmp4, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 855 | + } | ||
| 856 | + else if constexpr (std::is_same_v<DTYPE_X, bfloat16_t>) | ||
| 857 | + { | ||
| 858 | + Cast(tmp4, xLocal, RoundMode::CAST_TRUNC, this->processDataNum); | ||
| 859 | + } | ||
| 860 | + Cast(tmp1, tmp4, RoundMode::CAST_NONE, this->processDataNum); | ||
| 861 | + Duplicate(tmp2, CONST_255, this->processDataNum); | ||
| 862 | + And(tmp1, tmp1, tmp2, this->processDataNum); | ||
| 863 | + if constexpr (std::is_same_v<DTYPE_Y, int8_t>) | ||
| 864 | + { | ||
| 865 | + Adds(tmp1, tmp1, CONST_128, this->processDataNum); | ||
| 866 | + And(tmp1, tmp1, tmp2, this->processDataNum); | ||
| 867 | + Adds(tmp1, tmp1, CONST_NE128, this->processDataNum); | ||
| 868 | + } | ||
| 869 | + Cast(tmp3, tmp1, RoundMode::CAST_NONE, this->processDataNum); | ||
| 870 | + Cast(yLocal, tmp3, RoundMode::CAST_NONE, this->processDataNum); | ||
| 871 | + } | ||
| 872 | + this->outQueueY.template EnQue<TYPE_Y>(yLocal); | ||
| 873 | + this->inQueueX.template FreeTensor(xLocal); | ||
| 874 | + } | ||
| 875 | + | ||
| 876 | +private: | ||
| 877 | + TBuf<QuePosition::VECCALC> tmp2Bytes1; | ||
| 878 | + TBuf<QuePosition::VECCALC> tmp2Bytes2; | ||
| 879 | + TBuf<QuePosition::VECCALC> tmp2Bytes3; | ||
| 880 | + TBuf<QuePosition::VECCALC> tmp4Bytes1; | ||
| 881 | +}; | ||
| 882 | + | ||
| 883 | +class KernelCastTQueBind | ||
| 884 | +{ | ||
| 885 | + /* | ||
| 886 | + 使用TQueBind直接传输8bit的数据类型 | ||
| 887 | + bool -> int8/uint8 | ||
| 888 | + int8 -> uint8 | ||
| 889 | + uint8 -> int8 | ||
| 890 | + */ | ||
| 891 | +public: | ||
| 892 | + __aicore__ inline KernelCastTQueBind() {} | ||
| 893 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, uint32_t smallCoreDataNum, | ||
| 894 | + uint32_t bigCoreDataNum, uint32_t finalBigTileNum, | ||
| 895 | + uint32_t finalSmallTileNum, uint32_t tileDataNum, | ||
| 896 | + uint32_t smallTailDataNum, uint32_t bigTailDataNum, | ||
| 897 | + uint32_t tailBlockNum, TPipe *pipeIn) | ||
| 898 | + { | ||
| 899 | + pipe = pipeIn; | ||
| 900 | + ASSERT(GetBlockNum() != 0 && "block dim can not be zero!"); | ||
| 901 | + uint32_t coreNum = GetBlockIdx(); | ||
| 902 | + uint32_t globalBufferIndex = bigCoreDataNum * GetBlockIdx(); | ||
| 903 | + this->tileDataNum = tileDataNum; | ||
| 904 | + if (coreNum < tailBlockNum) | ||
| 905 | + { | ||
| 906 | + this->coreDataNum = bigCoreDataNum; | ||
| 907 | + this->tileNum = finalBigTileNum; | ||
| 908 | + this->tailDataNum = bigTailDataNum; | ||
| 909 | + } | ||
| 910 | + else | ||
| 911 | + { | ||
| 912 | + this->coreDataNum = smallCoreDataNum; | ||
| 913 | + this->tileNum = finalSmallTileNum; | ||
| 914 | + this->tailDataNum = smallTailDataNum; | ||
| 915 | + globalBufferIndex -= (bigCoreDataNum - smallCoreDataNum) * (GetBlockIdx() - tailBlockNum); | ||
| 916 | + } | ||
| 917 | + xGm.SetGlobalBuffer((__gm__ uint8_t *)x + globalBufferIndex, this->coreDataNum); | ||
| 918 | + yGm.SetGlobalBuffer((__gm__ uint8_t *)y + globalBufferIndex, this->coreDataNum); | ||
| 919 | + pipe->InitBuffer(queBind, BUFFER_NUM, this->tileDataNum * sizeof(uint8_t)); | ||
| 920 | + } | ||
| 921 | + __aicore__ inline void Process() | ||
| 922 | + { | ||
| 923 | + int32_t loopCount = this->tileNum; | ||
| 924 | + this->processDataNum = this->tileDataNum; | ||
| 925 | + for (int32_t i = 0; i < loopCount - 1; i++) | ||
| 926 | + { | ||
| 927 | + auto bindLocal = queBind.AllocTensor<uint8_t>(); | ||
| 928 | + DataCopy(bindLocal, xGm[i * this->tileDataNum], this->processDataNum); | ||
| 929 | + queBind.EnQue(bindLocal); | ||
| 930 | + bindLocal = queBind.DeQue<uint8_t>(); | ||
| 931 | + DataCopy(yGm[i * this->tileDataNum], bindLocal, this->processDataNum); | ||
| 932 | + queBind.FreeTensor(bindLocal); | ||
| 933 | + } | ||
| 934 | + this->processDataNum = this->tailDataNum; | ||
| 935 | + auto bindLocal = queBind.AllocTensor<uint8_t>(); | ||
| 936 | + DataCopy(bindLocal, xGm[(loopCount - 1) * this->tileDataNum], this->processDataNum); | ||
| 937 | + queBind.EnQue(bindLocal); | ||
| 938 | + bindLocal = queBind.DeQue<uint8_t>(); | ||
| 939 | + DataCopy(yGm[(loopCount - 1) * this->tileDataNum], bindLocal, this->processDataNum); | ||
| 940 | + queBind.FreeTensor(bindLocal); | ||
| 941 | + } | ||
| 942 | + | ||
| 943 | +private: | ||
| 944 | + TPipe *pipe; | ||
| 945 | + TQueBind<TPosition::VECIN, TPosition::VECOUT, BUFFER_NUM> queBind; | ||
| 946 | + GlobalTensor<uint8_t> xGm; | ||
| 947 | + GlobalTensor<uint8_t> yGm; | ||
| 948 | + uint32_t coreDataNum = 0; | ||
| 949 | + uint32_t tileNum = 0; | ||
| 950 | + uint32_t tileDataNum = 0; | ||
| 951 | + uint32_t tailDataNum = 0; | ||
| 952 | + uint32_t processDataNum = 0; | ||
| 953 | +}; | ||
| 954 | + | ||
| 955 | +} // namespace NsCast | ||
| 956 | + | ||
| @@ -0,0 +1,29 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file cast_tiling_data.h | ||
| 13 | + * \brief tiling data struct | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +struct CastTilingData { | ||
| 20 | + uint32_t smallCoreDataNum; | ||
| 21 | + uint32_t bigCoreDataNum; | ||
| 22 | + uint32_t finalBigTileNum; | ||
| 23 | + uint32_t finalSmallTileNum; | ||
| 24 | + uint32_t tileDataNum; | ||
| 25 | + uint32_t smallTailDataNum; | ||
| 26 | + uint32_t bigTailDataNum; | ||
| 27 | + uint32_t tailBlockNum; | ||
| 28 | +}; | ||
| 29 | + | ||
| @@ -0,0 +1,35 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | + * This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | + * CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | + * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | + */ | ||
| 10 | + | ||
| 11 | +/*! | ||
| 12 | + * \file cast_tiling_key.h | ||
| 13 | + * \brief cast tiling key declare | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +/* Mode场景定义 */ | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +/* 继续定义其他Mode场景... */ | ||
| 25 | + | ||
| 26 | +/* 模板参数 */ | ||
| 27 | +ASCENDC_TPL_ARGS_DECL( | ||
| 28 | + Cast, | ||
| 29 | + ASCENDC_TPL_UINT_DECL(schMode, 1, ASCENDC_TPL_UI_LIST, ELEMENTWISE_TPL_SCH_MODE_0, ELEMENTWISE_TPL_SCH_MODE_1)); | ||
| 30 | + | ||
| 31 | +/* 模板参数组合 */ | ||
| 32 | +ASCENDC_TPL_SEL(ASCENDC_TPL_ARGS_SEL( | ||
| 33 | + ASCENDC_TPL_UINT_SEL(schMode, ASCENDC_TPL_UI_LIST, ELEMENTWISE_TPL_SCH_MODE_0, ELEMENTWISE_TPL_SCH_MODE_1))); | ||
| 34 | + | ||
| 35 | + | ||


代码结构与可维护性: 输入数据类型列表存在明显的重复模式,代码可读性差且难以维护。从代码可以看出,同一数据类型(如ge::DT_FLOAT16)在列表中重复出现了7次,ge::DT_FLOAT重复了8次,ge::DT_INT32重复了8次等。这种硬编码的重复列表不仅难以阅读,也容易在修改时出错。应该使用更清晰的数据结构或生成方式来定义这些类型映射关系。
问题类型: 代码结构与可维护性 文件路径:
experimental/math/cast/op_host/cast_def.cpp行号: 25 问题代码:.DataType({ ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT16 , ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT , ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32 , ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_INT8, ge::DT_INT8 , ge::DT_UINT8, ge::DT_UINT8, ge::DT_UINT8, ge::DT_UINT8, ge::DT_UINT8, ge::DT_UINT8, ge::DT_UINT8 , ge::DT_BOOL, ge::DT_BOOL, ge::DT_BOOL, ge::DT_BOOL, ge::DT_BOOL, ge::DT_BOOL, ge::DT_BOOL , ge::DT_INT64, ge::DT_INT64, ge::DT_INT64, ge::DT_INT64, ge::DT_INT64, ge::DT_INT64, ge::DT_INT64, ge::DT_INT64 , ge::DT_BF16, ge::DT_BF16, ge::DT_BF16, ge::DT_BF16, ge::DT_BF16, ge::DT_BF16 , ge::DT_INT16, ge::DT_INT16, ge::DT_INT16, ge::DT_INT16, ge::DT_INT16, ge::DT_INT16 })修改建议:
此评论由代码审查工具自动生成