已合并
Swish算子Ascend C实现 #4020
fulltower创建于 4月20日
Swish算子Ascend C实现 #4020
已合并
共 28 个文件变更+2461-0
| @@ -0,0 +1,19 @@ | |||
| 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 | +file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 12 | +if(NOT ENABLE_TEST AND NOT BENCHMARK) | ||
| 13 | + list(REMOVE_ITEM CURRENT_DIRS tests) | ||
| 14 | +endif() | ||
| 15 | +foreach(SUB_DIR ${CURRENT_DIRS}) | ||
| 16 | + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | ||
| 17 | + add_subdirectory(${SUB_DIR}) | ||
| 18 | + endif() | ||
| 19 | +endforeach() | ||
| @@ -0,0 +1,51 @@ | |||
| 1 | +# Swish | ||
| 2 | +## 贡献说明 | ||
| 3 | +| 贡献者 | 贡献方 | 贡献算子 | 贡献时间 | 贡献内容 | | ||
| 4 | +|--------|------------------|-------|-----------|-----------| | ||
| 5 | +| skywang2 | 个人开发者 | Swish | 2025/12/31 | 新增Swish算子 | | ||
| 6 | + | ||
| 7 | +## 支持的产品型号 | ||
| 8 | + | ||
| 9 | +- Atlas A2训练系列产品 | ||
| 10 | + | ||
| 11 | +产品形态详细说明请参见[昇腾产品形态说明](http://www.hiascend.com/document/redirect/CannCommunityProductForm) | ||
| 12 | + | ||
| 13 | +## 算子描述 | ||
| 14 | +- 功能描述 | ||
| 15 | + | ||
| 16 | + `Swish`算子实现Swish激活函数,是一种由输入与其经过Sigmoid函数结果相乘得到的平滑、非线性函数。 | ||
| 17 | + | ||
| 18 | +- 原型信息 | ||
| 19 | + | ||
| 20 | + <table> | ||
| 21 | + <tr><th align="center">算子类型(OpType)</th><th colspan="4" align="center">Swish</th></tr> | ||
| 22 | + <tr><td 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> | ||
| 23 | + <tr><td rowspan="2" align="center">算子输入</td> | ||
| 24 | + | ||
| 25 | + <tr><td align="center">x</td><td align="center">tensor</td><td align="center">float32,float16,bfloat16</td><td align="center">ND</td></tr> | ||
| 26 | + | ||
| 27 | + <tr><td rowspan="1" align="center">算子输出</td> | ||
| 28 | + <td align="center">y</td><td align="center">tensor</td><td align="center">float32,float16,bfloat16</td><td align="center">ND</td></tr> | ||
| 29 | + <tr><td rowspan="1" align="center">算子属性</td> | ||
| 30 | + <td align="center">scale</td><td align="center">scalar</td><td align="center">float</td><td align="center">-</td></tr> | ||
| 31 | + <tr><td rowspan="1" align="center">核函数名</td><td colspan="4" align="center">swish</td></tr> | ||
| 32 | + </table> | ||
| 33 | + | ||
| 34 | +## 约束与限制 | ||
| 35 | +- x,y的数据类型仅支持float32,float16,bfloat1,数据格式仅支持ND | ||
| 36 | + | ||
| 37 | +### 运行验证 | ||
| 38 | +编译 | ||
| 39 | +```bash | ||
| 40 | +bash build.sh --pkg --soc=ascend910b --experimental --ops=swish | ||
| 41 | +``` | ||
| 42 | +运行 | ||
| 43 | +```bash | ||
| 44 | +bash build.sh --run_example swish eager cust --vendor_name=custom --experimental | ||
| 45 | +``` | ||
| 46 | +<table> | ||
| 47 | + <th>目录</th><th>描述</th> | ||
| 48 | + <tr> | ||
| 49 | + <td><a href="./examples/test_aclnn_swish.cpp">test_aclnn_swish.cpp</td><td>通过aclnn调用的方式调用Swish算子。</td> | ||
| 50 | + </tr> | ||
| 51 | +</table> | ||
| @@ -0,0 +1,327 @@ | |||
| 1 | +# aclnnSilu | ||
| 2 | + | ||
| 3 | +## 产品支持情况 | ||
| 4 | + | ||
| 5 | +|产品 | 是否支持 | | ||
| 6 | +|:-------------------------|:----------:| | ||
| 7 | +| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | √ | | ||
| 8 | + | ||
| 9 | +## 功能说明 | ||
| 10 | + | ||
| 11 | +- 接口功能:该算子也被称为Swish函数($\beta = 1$),对输入tensor逐元素进行Silu函数运算并输出结果tensor。 | ||
| 12 | + | ||
| 13 | +- 计算公式: | ||
| 14 | + | ||
| 15 | + $$ | ||
| 16 | + out_i = \frac {self_i} {1 + e^{-self_i}} | ||
| 17 | + $$ | ||
| 18 | + | ||
| 19 | +## 函数原型 | ||
| 20 | + | ||
| 21 | + 每个算子分为[两段式接口](../../../../docs/zh/context/两段式接口.md),必须先调用“aclnnSiluGetWorkspaceSize”接口获取计算所需workspace大小以及包含了算子计算流程的执行器,再调用“aclnnSilu”接口执行计算。 | ||
| 22 | + | ||
| 23 | +```Cpp | ||
| 24 | +aclnnStatus aclnnSiluGetWorkspaceSize( | ||
| 25 | + const aclTensor* self, | ||
| 26 | + aclTensor* out, | ||
| 27 | + uint64_t* workspaceSize, | ||
| 28 | + aclOpExecutor** executor) | ||
| 29 | +``` | ||
| 30 | + | ||
| 31 | +```Cpp | ||
| 32 | +aclnnStatus aclnnSilu( | ||
| 33 | + void* workspace, | ||
| 34 | + uint64_t workspaceSize, | ||
| 35 | + aclOpExecutor* executor, | ||
| 36 | + aclrtStream stream) | ||
| 37 | +``` | ||
| 38 | + | ||
| 39 | +## aclnnSiluGetWorkspaceSize | ||
| 40 | + | ||
| 41 | +- **参数说明:** | ||
| 42 | + | ||
| 43 | + <table style="undefined;table-layout: fixed; width: 1390px"><colgroup> | ||
| 44 | + <col style="width: 271px"> | ||
| 45 | + <col style="width: 115px"> | ||
| 46 | + <col style="width: 200px"> | ||
| 47 | + <col style="width: 240px"> | ||
| 48 | + <col style="width: 177px"> | ||
| 49 | + <col style="width: 104px"> | ||
| 50 | + <col style="width: 138px"> | ||
| 51 | + <col style="width: 145px"> | ||
| 52 | + </colgroup> | ||
| 53 | + <thead> | ||
| 54 | + <tr> | ||
| 55 | + <th>参数名</th> | ||
| 56 | + <th>输入/输出</th> | ||
| 57 | + <th>描述</th> | ||
| 58 | + <th>使用说明</th> | ||
| 59 | + <th>数据类型</th> | ||
| 60 | + <th>数据格式</th> | ||
| 61 | + <th>维度(shape)</th> | ||
| 62 | + <th>非连续Tensor</th> | ||
| 63 | + </tr></thead> | ||
| 64 | + <tbody> | ||
| 65 | + <tr> | ||
| 66 | + <td>self(aclTensor*)</td> | ||
| 67 | + <td>输入</td> | ||
| 68 | + <td>待进行Silu计算的入参,公式中的输入self。</td> | ||
| 69 | + <td><ul><li>支持空Tensor。</li><li>数据类型和shape需要与out一致。</li></ul></td> | ||
| 70 | + <td>FLOAT16、FLOAT、BFLOAT16</td> | ||
| 71 | + <td>ND</td> | ||
| 72 | + <td>0-8</td> | ||
| 73 | + <td>√</td> | ||
| 74 | + </tr> | ||
| 75 | + <tr> | ||
| 76 | + <td>out(aclTensor*)</td> | ||
| 77 | + <td>输出</td> | ||
| 78 | + <td>计算的出参,公式中的out。</td> | ||
| 79 | + <td>数据类型和shape需要与self一致。</td> | ||
| 80 | + <td>FLOAT16、FLOAT、BFLOAT16</td> | ||
| 81 | + <td>ND</td> | ||
| 82 | + <td>0-8</td> | ||
| 83 | + <td>√</td> | ||
| 84 | + </tr> | ||
| 85 | + <tr> | ||
| 86 | + <td>workspaceSize(uint64_t*)</td> | ||
| 87 | + <td>输出</td> | ||
| 88 | + <td>返回需要在Device侧申请的workspace大小。</td> | ||
| 89 | + <td>-</td> | ||
| 90 | + <td>-</td> | ||
| 91 | + <td>-</td> | ||
| 92 | + <td>-</td> | ||
| 93 | + <td>-</td> | ||
| 94 | + </tr> | ||
| 95 | + <tr> | ||
| 96 | + <td>executor(aclOpExecutor**)</td> | ||
| 97 | + <td>输出</td> | ||
| 98 | + <td>返回op执行器,包含了算子计算流程。</td> | ||
| 99 | + <td>-</td> | ||
| 100 | + <td>-</td> | ||
| 101 | + <td>-</td> | ||
| 102 | + <td>-</td> | ||
| 103 | + <td>-</td> | ||
| 104 | + </tr> | ||
| 105 | + </tbody> | ||
| 106 | + </table> | ||
| 107 | + | ||
| 108 | + - <term>Atlas 推理系列产品</term>、<term>Atlas 训练系列产品</term>:数据类型支持FLOAT16、FLOAT。 | ||
| 109 | + | ||
| 110 | +- **返回值:** | ||
| 111 | + | ||
| 112 | + aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../../docs/zh/context/aclnn返回码.md)。 | ||
| 113 | + | ||
| 114 | + 第一段接口会完成入参校验,出现以下场景时报错: | ||
| 115 | + | ||
| 116 | + <table style="undefined;table-layout: fixed;width: 979px"><colgroup> | ||
| 117 | + <col style="width: 272px"> | ||
| 118 | + <col style="width: 103px"> | ||
| 119 | + <col style="width: 604px"> | ||
| 120 | + </colgroup> | ||
| 121 | + <thead> | ||
| 122 | + <tr> | ||
| 123 | + <th>返回码</th> | ||
| 124 | + <th>错误码</th> | ||
| 125 | + <th>描述</th> | ||
| 126 | + </tr> | ||
| 127 | + </thead> | ||
| 128 | + <tbody> | ||
| 129 | + <tr> | ||
| 130 | + <td>ACLNN_ERR_PARAM_NULLPTR</td> | ||
| 131 | + <td>161001</td> | ||
| 132 | + <td>传入的self或out是空指针。</td> | ||
| 133 | + </tr> | ||
| 134 | + <tr> | ||
| 135 | + <td rowspan="8">ACLNN_ERR_PARAM_INVALID</td> | ||
| 136 | + <td rowspan="8">161002</td> | ||
| 137 | + <td>self和out的数据类型不在支持的范围内。</td> | ||
| 138 | + </tr> | ||
| 139 | + <tr> | ||
| 140 | + <td>self和out的数据类型不一致。</td> | ||
| 141 | + </tr> | ||
| 142 | + <tr> | ||
| 143 | + <td>self和out的shape不一致。</td> | ||
| 144 | + </tr> | ||
| 145 | + </tbody></table> | ||
| 146 | + | ||
| 147 | +## aclnnSilu | ||
| 148 | + | ||
| 149 | +- **参数说明:** | ||
| 150 | + | ||
| 151 | + <table style="undefined;table-layout: fixed; width: 953px"><colgroup> | ||
| 152 | + <col style="width: 173px"> | ||
| 153 | + <col style="width: 112px"> | ||
| 154 | + <col style="width: 668px"> | ||
| 155 | + </colgroup> | ||
| 156 | + <thead> | ||
| 157 | + <tr> | ||
| 158 | + <th>参数名</th> | ||
| 159 | + <th>输入/输出</th> | ||
| 160 | + <th>描述</th> | ||
| 161 | + </tr></thead> | ||
| 162 | + <tbody> | ||
| 163 | + <tr> | ||
| 164 | + <td>workspace</td> | ||
| 165 | + <td>输入</td> | ||
| 166 | + <td>在Device侧申请的workspace内存地址。</td> | ||
| 167 | + </tr> | ||
| 168 | + <tr> | ||
| 169 | + <td>workspaceSize</td> | ||
| 170 | + <td>输入</td> | ||
| 171 | + <td>在Device侧申请的workspace大小,由第一段接口aclnnSiluGetWorkspaceSize获取。</td> | ||
| 172 | + </tr> | ||
| 173 | + <tr> | ||
| 174 | + <td>executor</td> | ||
| 175 | + <td>输入</td> | ||
| 176 | + <td>op执行器,包含了算子计算流程。</td> | ||
| 177 | + </tr> | ||
| 178 | + <tr> | ||
| 179 | + <td>stream</td> | ||
| 180 | + <td>输入</td> | ||
| 181 | + <td>指定执行任务的Stream。</td> | ||
| 182 | + </tr> | ||
| 183 | + </tbody> | ||
| 184 | + </table> | ||
| 185 | + | ||
| 186 | +- **返回值:** | ||
| 187 | + | ||
| 188 | + aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../../docs/zh/context/aclnn返回码.md)。 | ||
| 189 | + | ||
| 190 | +## 约束说明 | ||
| 191 | + | ||
| 192 | +- 确定性计算: | ||
| 193 | + - aclnnSilu默认确定性实现。 | ||
| 194 | + | ||
| 195 | +## 调用示例 | ||
| 196 | + | ||
| 197 | +示例代码如下,仅供参考,具体编译和执行过程请参考[编译与运行样例](../../../../docs/zh/context/编译与运行样例.md)。 | ||
| 198 | + | ||
| 199 | +```Cpp | ||
| 200 | +#include <iostream> | ||
| 201 | +#include <vector> | ||
| 202 | +#include "acl/acl.h" | ||
| 203 | +#include "aclnnop/aclnn_silu.h" | ||
| 204 | + | ||
| 205 | +#define CHECK_RET(cond, return_expr) \ | ||
| 206 | + do { \ | ||
| 207 | + if (!(cond)) { \ | ||
| 208 | + return_expr; \ | ||
| 209 | + } \ | ||
| 210 | + } while (0) | ||
| 211 | + | ||
| 212 | +#define LOG_PRINT(message, ...) \ | ||
| 213 | + do { \ | ||
| 214 | + printf(message, ##__VA_ARGS__); \ | ||
| 215 | + } while (0) | ||
| 216 | + | ||
| 217 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 218 | + int64_t shape_size = 1; | ||
| 219 | + for (auto i : shape) { | ||
| 220 | + shape_size *= i; | ||
| 221 | + } | ||
| 222 | + return shape_size; | ||
| 223 | +} | ||
| 224 | + | ||
| 225 | +int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 226 | + // 固定写法,资源初始化 | ||
| 227 | + auto ret = aclInit(nullptr); | ||
| 228 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 229 | + ret = aclrtSetDevice(deviceId); | ||
| 230 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 231 | + ret = aclrtCreateStream(stream); | ||
| 232 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 233 | + return 0; | ||
| 234 | +} | ||
| 235 | + | ||
| 236 | +template <typename T> | ||
| 237 | +int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 238 | + aclDataType dataType, aclTensor** tensor) { | ||
| 239 | + auto size = GetShapeSize(shape) * sizeof(T); | ||
| 240 | + // 调用aclrtMalloc申请device侧内存 | ||
| 241 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 242 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 243 | + | ||
| 244 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 245 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 246 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 247 | + | ||
| 248 | + // 计算连续tensor的strides | ||
| 249 | + std::vector<int64_t> strides(shape.size(), 1); | ||
| 250 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 251 | + strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 252 | + } | ||
| 253 | + | ||
| 254 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 255 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 256 | + shape.data(), shape.size(), *deviceAddr); | ||
| 257 | + return 0; | ||
| 258 | +} | ||
| 259 | + | ||
| 260 | +int main() { | ||
| 261 | + // 1. (固定写法)device/stream初始化, 参考acl API手册 | ||
| 262 | + // 根据自己的实际device填写deviceId | ||
| 263 | + int32_t deviceId = 0; | ||
| 264 | + aclrtStream stream; | ||
| 265 | + auto ret = Init(deviceId, &stream); | ||
| 266 | + // check根据自己的需要处理 | ||
| 267 | + CHECK_RET(ret == 0, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 268 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 269 | + std::vector<int64_t> selfShape = {4, 2}; | ||
| 270 | + std::vector<int64_t> outShape = {4, 2}; | ||
| 271 | + void* selfDeviceAddr = nullptr; | ||
| 272 | + void* outDeviceAddr = nullptr; | ||
| 273 | + aclTensor* self = nullptr; | ||
| 274 | + aclTensor* out = nullptr; | ||
| 275 | + std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
| 276 | + std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 277 | + // 创建self aclTensor | ||
| 278 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 279 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 280 | + // 创建out aclTensor | ||
| 281 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 282 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 283 | + | ||
| 284 | + // 3. 调用CANN算子库API,需要修改为具体的API | ||
| 285 | + uint64_t workspaceSize = 0; | ||
| 286 | + aclOpExecutor* executor; | ||
| 287 | + // 调用aclnnSilu第一段接口 | ||
| 288 | + ret = aclnnSiluGetWorkspaceSize(self, out, &workspaceSize, &executor); | ||
| 289 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSiluGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 290 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 291 | + void* workspaceAddr = nullptr; | ||
| 292 | + if (workspaceSize > 0) { | ||
| 293 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 294 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret;); | ||
| 295 | + } | ||
| 296 | + // 调用aclnnSilu第二段接口 | ||
| 297 | + ret = aclnnSilu(workspaceAddr, workspaceSize, executor, stream); | ||
| 298 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSilu failed. ERROR: %d\n", ret); return ret); | ||
| 299 | + // 4. (固定写法)同步等待任务执行结束 | ||
| 300 | + ret = aclrtSynchronizeStream(stream); | ||
| 301 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 302 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 303 | + auto size = GetShapeSize(outShape); | ||
| 304 | + std::vector<float> resultData(size, 0); | ||
| 305 | + ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, size * sizeof(float), | ||
| 306 | + ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 307 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 308 | + for (int64_t i = 0; i < size; i++) { | ||
| 309 | + LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 310 | + } | ||
| 311 | + | ||
| 312 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 313 | + aclDestroyTensor(self); | ||
| 314 | + aclDestroyTensor(out); | ||
| 315 | + | ||
| 316 | + // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 317 | + aclrtFree(selfDeviceAddr); | ||
| 318 | + aclrtFree(outDeviceAddr); | ||
| 319 | + if (workspaceSize > 0) { | ||
| 320 | + aclrtFree(workspaceAddr); | ||
| 321 | + } | ||
| 322 | + aclrtDestroyStream(stream); | ||
| 323 | + aclrtResetDevice(deviceId); | ||
| 324 | + aclFinalize(); | ||
| 325 | + return 0; | ||
| 326 | +} | ||
| 327 | +``` | ||
| @@ -0,0 +1,353 @@ | |||
| 1 | +# aclnnSwish | ||
| 2 | + | ||
| 3 | +## 产品支持情况 | ||
| 4 | + | ||
| 5 | +|产品 | 是否支持 | | ||
| 6 | +|:-------------------------|:----------:| | ||
| 7 | +| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | √ | | ||
| 8 | + | ||
| 9 | +## 功能说明 | ||
| 10 | + | ||
| 11 | +- 接口功能:Swish激活函数,对输入Tensor逐元素进行Swish函数运算并输出结果Tensor。 | ||
| 12 | + | ||
| 13 | +- 计算公式: | ||
| 14 | + | ||
| 15 | + $$ | ||
| 16 | + s(x) = x*\sigma(\beta x) | ||
| 17 | + $$ | ||
| 18 | + | ||
| 19 | + $$ | ||
| 20 | + \sigma(x) = {\frac{1} {1+{e}^{-x}}} | ||
| 21 | + $$ | ||
| 22 | + | ||
| 23 | + 其中$\sigma(x)$为sigmoid函数。 | ||
| 24 | + | ||
| 25 | +## 函数原型 | ||
| 26 | + | ||
| 27 | + 每个算子分为[两段式接口](../../../../docs/zh/context/两段式接口.md),必须先调用“aclnnSwishGetWorkspaceSize”接口获取计算所需workspace大小以及包含了算子计算流程的执行器,再调用“aclnnSwish”接口执行计算。 | ||
| 28 | + | ||
| 29 | +```Cpp | ||
| 30 | +aclnnStatus aclnnSwishGetWorkspaceSize( | ||
| 31 | + const aclTensor* self, | ||
| 32 | + const aclScalar* betaOptional, | ||
| 33 | + aclTensor* out, | ||
| 34 | + uint64_t* workspaceSize, | ||
| 35 | + aclOpExecutor** executor) | ||
| 36 | +``` | ||
| 37 | + | ||
| 38 | +```Cpp | ||
| 39 | +aclnnStatus aclnnSwish( | ||
| 40 | + void* workspace, | ||
| 41 | + uint64_t workspaceSize, | ||
| 42 | + aclOpExecutor* executor, | ||
| 43 | + aclrtStream stream) | ||
| 44 | +``` | ||
| 45 | + | ||
| 46 | +## aclnnSwishGetWorkspaceSize | ||
| 47 | + | ||
| 48 | +- **参数说明:** | ||
| 49 | + | ||
| 50 | + <table style="undefined;table-layout: fixed; width: 1420px"><colgroup> | ||
| 51 | + <col style="width: 271px"> | ||
| 52 | + <col style="width: 115px"> | ||
| 53 | + <col style="width: 230px"> | ||
| 54 | + <col style="width: 240px"> | ||
| 55 | + <col style="width: 177px"> | ||
| 56 | + <col style="width: 104px"> | ||
| 57 | + <col style="width: 138px"> | ||
| 58 | + <col style="width: 145px"> | ||
| 59 | + </colgroup> | ||
| 60 | + <thead> | ||
| 61 | + <tr> | ||
| 62 | + <th>参数名</th> | ||
| 63 | + <th>输入/输出</th> | ||
| 64 | + <th>描述</th> | ||
| 65 | + <th>使用说明</th> | ||
| 66 | + <th>数据类型</th> | ||
| 67 | + <th>数据格式</th> | ||
| 68 | + <th>维度(shape)</th> | ||
| 69 | + <th>非连续Tensor</th> | ||
| 70 | + </tr></thead> | ||
| 71 | + <tbody> | ||
| 72 | + <tr> | ||
| 73 | + <td>self(aclTensor*)</td> | ||
| 74 | + <td>输入</td> | ||
| 75 | + <td>表示用于计算激活函数的张量,公式中的x。</td> | ||
| 76 | + <td><ul><li>支持空Tensor。</li><li>self的shape和数据类型与out的一致。</li></ul></td> | ||
| 77 | + <td>BFLOAT16、FLOAT16、FLOAT</td> | ||
| 78 | + <td>ND</td> | ||
| 79 | + <td>0-8</td> | ||
| 80 | + <td>√</td> | ||
| 81 | + </tr> | ||
| 82 | + <tr> | ||
| 83 | + <td>betaOptional(aclScalar*)</td> | ||
| 84 | + <td>输入</td> | ||
| 85 | + <td>表示可调节参数,用于控制Swish函数的形状和斜率的标量,公式中的β。</td> | ||
| 86 | + <td><ul><li>数据类型需要是可转换为FLOAT的数据类型(参见<a href="../../../../docs/zh/context/互转换关系.md" target="_blank">互转换关系</a>)。</li><li>当betaOptional为空指针时,接口以1.0进行计算。</li></ul></td> | ||
| 87 | + <td>-</td> | ||
| 88 | + <td>-</td> | ||
| 89 | + <td>-</td> | ||
| 90 | + <td>-</td> | ||
| 91 | + </tr> | ||
| 92 | + <tr> | ||
| 93 | + <td>out(aclTensor*)</td> | ||
| 94 | + <td>输出</td> | ||
| 95 | + <td>表示Swish函数的输出,公式中的s(x)。</td> | ||
| 96 | + <td><ul><li>支持空Tensor。</li><li>out的shape和数据类型与self的一致。</li></ul></td> | ||
| 97 | + <td>BFLOAT16、FLOAT16、FLOAT</td> | ||
| 98 | + <td>ND</td> | ||
| 99 | + <td>0-8</td> | ||
| 100 | + <td>√</td> | ||
| 101 | + </tr> | ||
| 102 | + <tr> | ||
| 103 | + <td>workspaceSize(uint64_t*)</td> | ||
| 104 | + <td>输出</td> | ||
| 105 | + <td>返回需要在Device侧申请的workspace大小。</td> | ||
| 106 | + <td>-</td> | ||
| 107 | + <td>-</td> | ||
| 108 | + <td>-</td> | ||
| 109 | + <td>-</td> | ||
| 110 | + <td>-</td> | ||
| 111 | + </tr> | ||
| 112 | + <tr> | ||
| 113 | + <td>executor(aclOpExecutor**)</td> | ||
| 114 | + <td>输出</td> | ||
| 115 | + <td>返回op执行器,包含了算子计算流程。</td> | ||
| 116 | + <td>-</td> | ||
| 117 | + <td>-</td> | ||
| 118 | + <td>-</td> | ||
| 119 | + <td>-</td> | ||
| 120 | + <td>-</td> | ||
| 121 | + </tr> | ||
| 122 | + </tbody> | ||
| 123 | + </table> | ||
| 124 | + | ||
| 125 | + - <term>Atlas 推理系列产品</term>、<term>Atlas 训练系列产品</term>:数据类型支持FLOAT16、FLOAT。 | ||
| 126 | + | ||
| 127 | +- **返回值:** | ||
| 128 | + | ||
| 129 | + aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../../docs/zh/context/aclnn返回码.md)。 | ||
| 130 | + | ||
| 131 | + 第一段接口会完成入参校验,出现以下场景时报错: | ||
| 132 | + | ||
| 133 | + <table style="undefined;table-layout: fixed;width: 979px"><colgroup> | ||
| 134 | + <col style="width: 272px"> | ||
| 135 | + <col style="width: 103px"> | ||
| 136 | + <col style="width: 604px"> | ||
| 137 | + </colgroup> | ||
| 138 | + <thead> | ||
| 139 | + <tr> | ||
| 140 | + <th>返回码</th> | ||
| 141 | + <th>错误码</th> | ||
| 142 | + <th>描述</th> | ||
| 143 | + </tr> | ||
| 144 | + </thead> | ||
| 145 | + <tbody> | ||
| 146 | + <tr> | ||
| 147 | + <td>ACLNN_ERR_PARAM_NULLPTR</td> | ||
| 148 | + <td>161001</td> | ||
| 149 | + <td>传入的self或out是空指针。</td> | ||
| 150 | + </tr> | ||
| 151 | + <tr> | ||
| 152 | + <td rowspan="8">ACLNN_ERR_PARAM_INVALID</td> | ||
| 153 | + <td rowspan="8">161002</td> | ||
| 154 | + <td>self、betaOptional或out的数据类型不在支持的范围内。</td> | ||
| 155 | + </tr> | ||
| 156 | + <tr> | ||
| 157 | + <td>self和out的数据类型不一致。</td> | ||
| 158 | + </tr> | ||
| 159 | + <tr> | ||
| 160 | + <td>self和out的shape不一致。</td> | ||
| 161 | + </tr> | ||
| 162 | + </tbody></table> | ||
| 163 | + | ||
| 164 | +## aclnnSwish | ||
| 165 | + | ||
| 166 | +- **参数说明:** | ||
| 167 | + | ||
| 168 | + <table style="undefined;table-layout: fixed; width: 953px"><colgroup> | ||
| 169 | + <col style="width: 173px"> | ||
| 170 | + <col style="width: 112px"> | ||
| 171 | + <col style="width: 668px"> | ||
| 172 | + </colgroup> | ||
| 173 | + <thead> | ||
| 174 | + <tr> | ||
| 175 | + <th>参数名</th> | ||
| 176 | + <th>输入/输出</th> | ||
| 177 | + <th>描述</th> | ||
| 178 | + </tr></thead> | ||
| 179 | + <tbody> | ||
| 180 | + <tr> | ||
| 181 | + <td>workspace</td> | ||
| 182 | + <td>输入</td> | ||
| 183 | + <td>在Device侧申请的workspace内存地址。</td> | ||
| 184 | + </tr> | ||
| 185 | + <tr> | ||
| 186 | + <td>workspaceSize</td> | ||
| 187 | + <td>输入</td> | ||
| 188 | + <td>在Device侧申请的workspace大小,由第一段接口aclnnSwishGetWorkspaceSize获取。</td> | ||
| 189 | + </tr> | ||
| 190 | + <tr> | ||
| 191 | + <td>executor</td> | ||
| 192 | + <td>输入</td> | ||
| 193 | + <td>op执行器,包含了算子计算流程。</td> | ||
| 194 | + </tr> | ||
| 195 | + <tr> | ||
| 196 | + <td>stream</td> | ||
| 197 | + <td>输入</td> | ||
| 198 | + <td>指定执行任务的Stream。</td> | ||
| 199 | + </tr> | ||
| 200 | + </tbody> | ||
| 201 | + </table> | ||
| 202 | + | ||
| 203 | +- **返回值:** | ||
| 204 | + | ||
| 205 | + aclnnStatus:返回状态码,具体参见[aclnn返回码](../../../../docs/zh/context/aclnn返回码.md)。 | ||
| 206 | + | ||
| 207 | +## 约束说明 | ||
| 208 | + | ||
| 209 | +- 确定性计算: | ||
| 210 | + - aclnnSwish默认确定性实现。 | ||
| 211 | + | ||
| 212 | +## 调用示例 | ||
| 213 | + | ||
| 214 | +示例代码如下,仅供参考,具体编译和执行过程请参考[编译与运行样例](../../../../docs/zh/context/编译与运行样例.md)。 | ||
| 215 | + | ||
| 216 | +```Cpp | ||
| 217 | +#include <iostream> | ||
| 218 | +#include <vector> | ||
| 219 | +#include "acl/acl.h" | ||
| 220 | +#include "aclnnop/aclnn_swish.h" | ||
| 221 | + | ||
| 222 | +#define CHECK_RET(cond, return_expr) \ | ||
| 223 | + do { \ | ||
| 224 | + if (!(cond)) { \ | ||
| 225 | + return_expr; \ | ||
| 226 | + } \ | ||
| 227 | + } while (0) | ||
| 228 | + | ||
| 229 | +#define LOG_PRINT(message, ...) \ | ||
| 230 | + do { \ | ||
| 231 | + printf(message, ##__VA_ARGS__); \ | ||
| 232 | + } while (0) | ||
| 233 | + | ||
| 234 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 235 | + int64_t shape_size = 1; | ||
| 236 | + for (auto i : shape) { | ||
| 237 | + shape_size *= i; | ||
| 238 | + } | ||
| 239 | + return shape_size; | ||
| 240 | +} | ||
| 241 | + | ||
| 242 | +int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 243 | + // 固定写法,资源初始化 | ||
| 244 | + auto ret = aclInit(nullptr); | ||
| 245 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 246 | + ret = aclrtSetDevice(deviceId); | ||
| 247 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 248 | + ret = aclrtCreateStream(stream); | ||
| 249 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 250 | + return 0; | ||
| 251 | +} | ||
| 252 | + | ||
| 253 | +template <typename T> | ||
| 254 | +int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 255 | + aclDataType dataType, aclTensor** tensor) { | ||
| 256 | + auto size = GetShapeSize(shape) * sizeof(T); | ||
| 257 | + // 调用aclrtMalloc申请device侧内存 | ||
| 258 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 259 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 260 | + | ||
| 261 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 262 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 263 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 264 | + | ||
| 265 | + // 计算连续tensor的strides | ||
| 266 | + std::vector<int64_t> strides(shape.size(), 1); | ||
| 267 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 268 | + strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 269 | + } | ||
| 270 | + | ||
| 271 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 272 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 273 | + shape.data(), shape.size(), *deviceAddr); | ||
| 274 | + return 0; | ||
| 275 | +} | ||
| 276 | + | ||
| 277 | +int main() { | ||
| 278 | + // 1. (固定写法)device/stream初始化, 参考acl API手册 | ||
| 279 | + // 根据自己的实际device填写deviceId | ||
| 280 | + int32_t deviceId = 0; | ||
| 281 | + aclrtStream stream; | ||
| 282 | + auto ret = Init(deviceId, &stream); | ||
| 283 | + CHECK_RET(ret == 0, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 284 | + | ||
| 285 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 286 | + std::vector<int64_t> selfShape = {4, 2}; | ||
| 287 | + std::vector<int64_t> outShape = {4, 2}; | ||
| 288 | + void* selfDeviceAddr = nullptr; | ||
| 289 | + void* outDeviceAddr = nullptr; | ||
| 290 | + aclTensor* self = nullptr; | ||
| 291 | + aclScalar* betaOptional = nullptr; | ||
| 292 | + aclTensor* out = nullptr; | ||
| 293 | + std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
| 294 | + std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 295 | + float betaValue = 1.1f; | ||
| 296 | + | ||
| 297 | + // 创建self aclTensor | ||
| 298 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 299 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 300 | + | ||
| 301 | + // 创建betaOptional aclScalar | ||
| 302 | + betaOptional = aclCreateScalar(&betaValue, aclDataType::ACL_FLOAT); | ||
| 303 | + CHECK_RET(betaOptional != nullptr, return ret); | ||
| 304 | + | ||
| 305 | + // 创建out aclTensor | ||
| 306 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 307 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 308 | + | ||
| 309 | + // 3. 调用CANN算子库API,需要修改为具体的API | ||
| 310 | + uint64_t workspaceSize = 0; | ||
| 311 | + aclOpExecutor* executor; | ||
| 312 | + // 调用aclnnSwish第一段接口 | ||
| 313 | + ret = aclnnSwishGetWorkspaceSize(self, betaOptional, out, &workspaceSize, &executor); | ||
| 314 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSwishGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 315 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 316 | + void* workspaceAddr = nullptr; | ||
| 317 | + if (workspaceSize > 0) { | ||
| 318 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 319 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret;); | ||
| 320 | + } | ||
| 321 | + // 调用aclnnSwish第二段接口 | ||
| 322 | + ret = aclnnSwish(workspaceAddr, workspaceSize, executor, stream); | ||
| 323 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSwish failed. ERROR: %d\n", ret); return ret); | ||
| 324 | + // 4. (固定写法)同步等待任务执行结束 | ||
| 325 | + ret = aclrtSynchronizeStream(stream); | ||
| 326 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 327 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 328 | + auto size = GetShapeSize(outShape); | ||
| 329 | + std::vector<float> resultData(size, 0); | ||
| 330 | + ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, size * sizeof(float), | ||
| 331 | + ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 332 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 333 | + for (int64_t i = 0; i < size; i++) { | ||
| 334 | + LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 335 | + } | ||
| 336 | + | ||
| 337 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 338 | + aclDestroyTensor(self); | ||
| 339 | + aclDestroyScalar(betaOptional); | ||
| 340 | + aclDestroyTensor(out); | ||
| 341 | + | ||
| 342 | + // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 343 | + aclrtFree(selfDeviceAddr); | ||
| 344 | + aclrtFree(outDeviceAddr); | ||
| 345 | + if (workspaceSize > 0) { | ||
| 346 | + aclrtFree(workspaceAddr); | ||
| 347 | + } | ||
| 348 | + aclrtDestroyStream(stream); | ||
| 349 | + aclrtResetDevice(deviceId); | ||
| 350 | + aclFinalize(); | ||
| 351 | + return 0; | ||
| 352 | +} | ||
| 353 | +``` | ||
| @@ -0,0 +1,141 @@ | |||
| 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 | + do { \ | ||
| 17 | + if (!(cond)) { \ | ||
| 18 | + return_expr; \ | ||
| 19 | + } \ | ||
| 20 | + } while (0) | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + do { \ | ||
| 24 | + printf(message, ##__VA_ARGS__); \ | ||
| 25 | + } while (0) | ||
| 26 | + | ||
| 27 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 28 | + int64_t shape_size = 1; | ||
| 29 | + for (auto i : shape) { | ||
| 30 | + shape_size *= i; | ||
| 31 | + } | ||
| 32 | + return shape_size; | ||
| 33 | +} | ||
| 34 | + | ||
| 35 | +int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 36 | + // 固定写法,资源初始化 | ||
| 37 | + auto ret = aclInit(nullptr); | ||
| 38 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 39 | + ret = aclrtSetDevice(deviceId); | ||
| 40 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 41 | + ret = aclrtCreateStream(stream); | ||
| 42 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 43 | + return 0; | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +template <typename T> | ||
| 47 | +int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 48 | + aclDataType dataType, aclTensor** tensor) { | ||
| 49 | + auto size = GetShapeSize(shape) * sizeof(T); | ||
| 50 | + // 调用aclrtMalloc申请device侧内存 | ||
| 51 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 52 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 53 | + | ||
| 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 == 0, 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 | + void* selfDeviceAddr = nullptr; | ||
| 82 | + void* outDeviceAddr = nullptr; | ||
| 83 | + aclTensor* self = nullptr; | ||
| 84 | + aclTensor* out = nullptr; | ||
| 85 | + std::vector<float> selfHostData = {0, 1, 2, 3, 4, 5, 6, 7}; | ||
| 86 | + std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 87 | + float scaleValue = 1.1f; | ||
| 88 | + aclScalar* scale = aclCreateScalar(&scaleValue, aclDataType::ACL_FLOAT); | ||
| 89 | + | ||
| 90 | + // 创建self aclTensor | ||
| 91 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 92 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 93 | + | ||
| 94 | + // 创建out aclTensor | ||
| 95 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 96 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 97 | + | ||
| 98 | + // 3. 调用CANN算子库API,需要修改为具体的API | ||
| 99 | + uint64_t workspaceSize = 0; | ||
| 100 | + aclOpExecutor* executor; | ||
| 101 | + // 调用aclnnSwish第一段接口 | ||
| 102 | + ret = aclnnSwishGetWorkspaceSize(self, scale, out, &workspaceSize, &executor); | ||
| 103 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSwishGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 104 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 105 | + void* workspaceAddr = nullptr; | ||
| 106 | + if (workspaceSize > 0) { | ||
| 107 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 108 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret;); | ||
| 109 | + } | ||
| 110 | + // 调用aclnnSwish第二段接口 | ||
| 111 | + ret = aclnnSwish(workspaceAddr, workspaceSize, executor, stream); | ||
| 112 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSwish failed. ERROR: %d\n", ret); return ret); | ||
| 113 | + // 4. (固定写法)同步等待任务执行结束 | ||
| 114 | + ret = aclrtSynchronizeStream(stream); | ||
| 115 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 116 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 117 | + auto size = GetShapeSize(outShape); | ||
| 118 | + std::vector<float> resultData(size, 0); | ||
| 119 | + ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, size * sizeof(float), | ||
| 120 | + ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 121 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 122 | + for (int64_t i = 0; i < size; i++) { | ||
| 123 | + LOG_PRINT("aclnnSwish result[%ld] is: %f\n", i, resultData[i]); | ||
| 124 | + } | ||
| 125 | + | ||
| 126 | + // 6. 释放aclTensor,需要根据具体API的接口定义修改 | ||
| 127 | + aclDestroyTensor(self); | ||
| 128 | + aclDestroyTensor(out); | ||
| 129 | + aclDestroyScalar(scale); | ||
| 130 | + | ||
| 131 | + // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 132 | + aclrtFree(selfDeviceAddr); | ||
| 133 | + aclrtFree(outDeviceAddr); | ||
| 134 | + if (workspaceSize > 0) { | ||
| 135 | + aclrtFree(workspaceAddr); | ||
| 136 | + } | ||
| 137 | + aclrtDestroyStream(stream); | ||
| 138 | + aclrtResetDevice(deviceId); | ||
| 139 | + aclFinalize(); | ||
| 140 | + return 0; | ||
| 141 | +} | ||
| @@ -0,0 +1,44 @@ | |||
| 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 | + * \file swish_proto.h | ||
| 14 | + * \brief use for graph | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace ge { | ||
| 22 | +/** | ||
| 23 | +*@brief Computes the Swish activation function for input tensor x . | ||
| 24 | + | ||
| 25 | +*@par Inputs: | ||
| 26 | +*One input, including: | ||
| 27 | +* x: A tensor, which supports 1D-8D defaultly and must be one of the following types: float16, bfloat16, float32. \n | ||
| 28 | + | ||
| 29 | +*@par Outputs: | ||
| 30 | +* y: A tensor of the same type, shape and format as "x", and y = x / (1 + exp(-scale * x)). \n | ||
| 31 | + | ||
| 32 | +*@par Attributes: | ||
| 33 | +* scale: scalar parameter, the multiplier of x. Must be of type float. Default value = 1.0. \n | ||
| 34 | + | ||
| 35 | +*@par Third-party framework compatibility | ||
| 36 | +*Compatible with the Torch operator Swish | ||
| 37 | +*/ | ||
| 38 | +REG_OP(Swish) | ||
| 39 | + .INPUT(x, TensorType({DT_FLOAT16, DT_FLOAT, DT_BF16})) | ||
| 40 | + .OUTPUT(y, TensorType({DT_FLOAT16, DT_FLOAT, DT_BF16})) | ||
| 41 | + .ATTR(scale, Float, 1.0) | ||
| 42 | + .OP_END_FACTORY_REG(Swish) | ||
| 43 | +} // namespace ge | ||
| 44 | + | ||
| @@ -0,0 +1,10 @@ | |||
| 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 | +add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE swish ACLNNTYPE aclnn_exclude) | ||
| @@ -0,0 +1,120 @@ | |||
| 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 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +using namespace op; | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +extern "C" { | ||
| 34 | + | ||
| 35 | + | ||
| 36 | +static const std::initializer_list<op::DataType> ASCEND910_DTYPE_SUPPORT_LIST = { | ||
| 37 | + op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16}; | ||
| 38 | + | ||
| 39 | +static const std::initializer_list<op::DataType> ASCEND910B_DTYPE_SUPPORT_LIST = { | ||
| 40 | + op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16, op::DataType::DT_BF16}; | ||
| 41 | + | ||
| 42 | +static inline bool CheckNotNull(const aclTensor* self, const aclTensor* out) | ||
| 43 | +{ | ||
| 44 | + OP_CHECK_NULL(self, return false); | ||
| 45 | + OP_CHECK_NULL(out, return false); | ||
| 46 | + return true; | ||
| 47 | +} | ||
| 48 | + | ||
| 49 | +static aclnnStatus CheckParams(const aclTensor *self, const aclTensor *out) { | ||
| 50 | + CHECK_RET(CheckNotNull(self, out), ACLNN_ERR_PARAM_NULLPTR); | ||
| 51 | + | ||
| 52 | + auto supportList = GetDtypeSupportListV2(ASCEND910B_DTYPE_SUPPORT_LIST, ASCEND910_DTYPE_SUPPORT_LIST); | ||
| 53 | + CHECK_RET(CheckDtypeValidActivation(self, out, supportList), ACLNN_ERR_PARAM_INVALID); | ||
| 54 | + | ||
| 55 | + CHECK_RET(CheckSameShapeNotlimit1In1Out(self, out), ACLNN_ERR_PARAM_INVALID); | ||
| 56 | + | ||
| 57 | + return ACLNN_SUCCESS; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +aclnnStatus aclnnSiluGetWorkspaceSize(const aclTensor* self, aclTensor* out, uint64_t* workspaceSize, | ||
| 61 | + aclOpExecutor** executor) { | ||
| 62 | + OP_CHECK_COMM_INPUT(workspaceSize, executor); | ||
| 63 | + | ||
| 64 | + L2_DFX_PHASE_1(aclnnSilu, DFX_IN(self), DFX_OUT(out)); | ||
| 65 | + | ||
| 66 | + auto uniqueExecutor = CREATE_EXECUTOR(); | ||
| 67 | + CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); | ||
| 68 | + | ||
| 69 | + auto ret = CheckParams(self, out); | ||
| 70 | + CHECK_RET(ret == ACLNN_SUCCESS, ret); | ||
| 71 | + | ||
| 72 | + if (self->IsEmpty() || out->IsEmpty()) { | ||
| 73 | + *workspaceSize = 0; | ||
| 74 | + uniqueExecutor.ReleaseTo(executor); | ||
| 75 | + return ACLNN_SUCCESS; | ||
| 76 | + } | ||
| 77 | + | ||
| 78 | + auto selfContiguous = l0op::Contiguous(self, uniqueExecutor.get()); | ||
| 79 | + CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 80 | + | ||
| 81 | + auto shapeOri = self->GetViewShape(); | ||
| 82 | + int64_t dimSize = self->GetViewShape().GetDimNum(); | ||
| 83 | + auto shapeOriDetail = GetTensorShapeActivation(selfContiguous, uniqueExecutor.get()); | ||
| 84 | + auto reshapeSelf = selfContiguous; | ||
| 85 | + | ||
| 86 | + if (dimSize > (int64_t)MAX_SUPPORT_DIMS_NUMS) { | ||
| 87 | + int64_t allDimValue = 1; | ||
| 88 | + for (int i = 0; i < dimSize; i++) { | ||
| 89 | + allDimValue *= shapeOri[i]; | ||
| 90 | + } | ||
| 91 | + int64_t AllDim[1] = {allDimValue}; | ||
| 92 | + auto shape1d = (uniqueExecutor)->AllocIntArray(AllDim, 1); | ||
| 93 | + reshapeSelf = ReshapeLongTensorActivation(selfContiguous, uniqueExecutor.get(), dimSize, shape1d); | ||
| 94 | + } | ||
| 95 | + | ||
| 96 | + float scale = 1.0; | ||
| 97 | + auto siluOut = l0op::Swish(reshapeSelf, scale, uniqueExecutor.get()); | ||
| 98 | + CHECK_RET(siluOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 99 | + | ||
| 100 | + auto reshapeSiluOut = siluOut; | ||
| 101 | + if (dimSize > (int64_t)MAX_SUPPORT_DIMS_NUMS) { | ||
| 102 | + reshapeSiluOut = ReshapeLongTensorActivation(siluOut, uniqueExecutor.get(), dimSize, shapeOriDetail); | ||
| 103 | + } | ||
| 104 | + | ||
| 105 | + auto viewCopyOut = l0op::ViewCopy(reshapeSiluOut, out, uniqueExecutor.get()); | ||
| 106 | + CHECK_RET(viewCopyOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 107 | + | ||
| 108 | + *workspaceSize = uniqueExecutor->GetWorkspaceSize(); | ||
| 109 | + uniqueExecutor.ReleaseTo(executor); | ||
| 110 | + return ACLNN_SUCCESS; | ||
| 111 | +} | ||
| 112 | + | ||
| 113 | +aclnnStatus aclnnSilu(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream) { | ||
| 114 | + L2_DFX_PHASE_2(aclnnSilu); | ||
| 115 | + return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | + | ||
| 119 | +} | ||
| 120 | + | ||
| @@ -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 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +extern "C" { | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +ACLNN_API aclnnStatus aclnnSiluGetWorkspaceSize(const aclTensor* self, aclTensor* out, uint64_t* workspaceSize, | ||
| 22 | + aclOpExecutor** executor); | ||
| 23 | + | ||
| 24 | +ACLNN_API aclnnStatus aclnnSilu(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, | ||
| 25 | + aclrtStream stream); | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| @@ -0,0 +1,134 @@ | |||
| 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 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +using namespace op; | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +extern "C" { | ||
| 34 | + | ||
| 35 | + | ||
| 36 | +static const std::initializer_list<op::DataType> ASCEND910_DTYPE_SUPPORT_LIST = { | ||
| 37 | + op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16}; | ||
| 38 | + | ||
| 39 | +static const std::initializer_list<op::DataType> ASCEND910B_DTYPE_SUPPORT_LIST = { | ||
| 40 | + op::DataType::DT_FLOAT, op::DataType::DT_FLOAT16, op::DataType::DT_BF16}; | ||
| 41 | + | ||
| 42 | +static bool CheckDtypeValidBetaToFloat(const aclScalar* betaOptional) { | ||
| 43 | + if (betaOptional != nullptr && !CanCast(betaOptional->GetDataType(), DataType::DT_FLOAT)) { | ||
| 44 | + OP_LOGE(ACLNN_ERR_PARAM_INVALID, "betaOptional dtype %s can not cast to float32.", | ||
| 45 | + ToString(betaOptional->GetDataType()).GetString()); | ||
| 46 | + return false; | ||
| 47 | + } | ||
| 48 | + return true; | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +static bool CheckDim(const aclTensor *self, const aclTensor *out) { | ||
| 52 | + OP_CHECK_MAX_DIM(self, MAX_SUPPORT_DIMS_NUMS, return false); | ||
| 53 | + OP_CHECK_MAX_DIM(out, MAX_SUPPORT_DIMS_NUMS, return false); | ||
| 54 | + return true; | ||
| 55 | +} | ||
| 56 | + | ||
| 57 | +static aclnnStatus CheckParams(const aclTensor *self, const aclScalar* betaOptional, const aclTensor *out) { | ||
| 58 | + CHECK_RET(CheckNotNull2Tensor(self, out), ACLNN_ERR_PARAM_NULLPTR); | ||
| 59 | + | ||
| 60 | + auto supportList = GetDtypeSupportListV1(ASCEND910B_DTYPE_SUPPORT_LIST, ASCEND910_DTYPE_SUPPORT_LIST); | ||
| 61 | + CHECK_RET(CheckDtypeValidActivation(self, out, supportList), ACLNN_ERR_PARAM_INVALID); | ||
| 62 | + CHECK_RET(CheckDtypeValidBetaToFloat(betaOptional), ACLNN_ERR_PARAM_INVALID); | ||
| 63 | + | ||
| 64 | + CHECK_RET(CheckDim(self, out), ACLNN_ERR_PARAM_INVALID); | ||
| 65 | + CHECK_RET(CheckSameShapeNotlimit1In1Out(self, out), ACLNN_ERR_PARAM_INVALID); | ||
| 66 | + | ||
| 67 | + return ACLNN_SUCCESS; | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +static const aclTensor *reshapeLongTensor(const aclTensor *x, aclOpExecutor *executor, size_t originalDimSize, | ||
| 71 | + aclIntArray *valuePerm = nullptr) { | ||
| 72 | + size_t dimSize = x->GetViewShape().GetDimNum(); | ||
| 73 | + if (originalDimSize == dimSize && dimSize <= MAX_SUPPORT_DIMS_NUMS) { | ||
| 74 | + return x; | ||
| 75 | + } | ||
| 76 | + | ||
| 77 | + auto reshapeSelf = l0op::Reshape(x, valuePerm, executor); | ||
| 78 | + return reshapeSelf; | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +aclnnStatus aclnnSwishGetWorkspaceSize(const aclTensor* self, const aclScalar* betaOptional, aclTensor* out, uint64_t* workspaceSize, | ||
| 82 | + aclOpExecutor** executor) { | ||
| 83 | + OP_CHECK_COMM_INPUT(workspaceSize, executor); | ||
| 84 | + | ||
| 85 | + L2_DFX_PHASE_1(aclnnSwish, DFX_IN(self, betaOptional), DFX_OUT(out)); | ||
| 86 | + | ||
| 87 | + auto uniqueExecutor = CREATE_EXECUTOR(); | ||
| 88 | + CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); | ||
| 89 | + | ||
| 90 | + auto ret = CheckParams(self, betaOptional, out); | ||
| 91 | + CHECK_RET(ret == ACLNN_SUCCESS, ret); | ||
| 92 | + | ||
| 93 | + if (self->IsEmpty() || out->IsEmpty()) { | ||
| 94 | + *workspaceSize = 0; | ||
| 95 | + uniqueExecutor.ReleaseTo(executor); | ||
| 96 | + return ACLNN_SUCCESS; | ||
| 97 | + } | ||
| 98 | + | ||
| 99 | + auto selfContiguous = l0op::Contiguous(self, uniqueExecutor.get()); | ||
| 100 | + CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 101 | + | ||
| 102 | + size_t dimSize = self->GetViewShape().GetDimNum(); | ||
| 103 | + auto shapeOriDetial = GetTensorShapeActivation(selfContiguous, uniqueExecutor.get()); | ||
| 104 | + auto reshapeSelf = ReshapeSelfValueGetActivation(self, dimSize, selfContiguous, uniqueExecutor); | ||
| 105 | + | ||
| 106 | + float scale = 1.0f; | ||
| 107 | + if (betaOptional != nullptr) { | ||
| 108 | + scale = betaOptional->ToFloat(); | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + auto swishOut = l0op::Swish(reshapeSelf, scale, uniqueExecutor.get()); | ||
| 112 | + CHECK_RET(swishOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 113 | + | ||
| 114 | + auto reshapeSwishOut = swishOut; | ||
| 115 | + if (dimSize > MAX_SUPPORT_DIMS_NUMS) { | ||
| 116 | + reshapeSwishOut = reshapeLongTensor(swishOut, uniqueExecutor.get(), dimSize, shapeOriDetial); | ||
| 117 | + } | ||
| 118 | + | ||
| 119 | + auto viewCopyOut = l0op::ViewCopy(reshapeSwishOut, out, uniqueExecutor.get()); | ||
| 120 | + CHECK_RET(viewCopyOut != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 121 | + | ||
| 122 | + *workspaceSize = uniqueExecutor->GetWorkspaceSize(); | ||
| 123 | + uniqueExecutor.ReleaseTo(executor); | ||
| 124 | + return ACLNN_SUCCESS; | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +aclnnStatus aclnnSwish(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream) { | ||
| 128 | + L2_DFX_PHASE_2(aclnnSwish); | ||
| 129 | + return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); | ||
| 130 | +} | ||
| 131 | + | ||
| 132 | + | ||
| 133 | +} | ||
| 134 | + | ||
| @@ -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 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +extern "C" { | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +ACLNN_API aclnnStatus aclnnSwishGetWorkspaceSize(const aclTensor* self, const aclScalar* betaOptional, aclTensor* out, | ||
| 22 | + uint64_t* workspaceSize, aclOpExecutor** executor); | ||
| 23 | + | ||
| 24 | +ACLNN_API aclnnStatus aclnnSwish(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, | ||
| 25 | + aclrtStream stream); | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +} | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| @@ -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 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +using namespace op; | ||
| 20 | +namespace l0op { | ||
| 21 | +OP_TYPE_REGISTER(Swish); | ||
| 22 | + | ||
| 23 | +static const aclTensor *SwishAiCore(const aclTensor *x, aclTensor *y, float scale, aclOpExecutor *executor) { | ||
| 24 | + L0_DFX(SwishAiCore, x, y); | ||
| 25 | + auto ret = ADD_TO_LAUNCHER_LIST_AICORE(Swish, OP_INPUT(x), OP_OUTPUT(y), OP_ATTR(scale)); | ||
| 26 | + OP_CHECK(ret == ACLNN_SUCCESS, OP_LOGE(ACLNN_ERR_INNER_NULLPTR, "SwishAiCore ADD_TO_LAUNCHER_LIST_AICORE failed."), | ||
| 27 | + return nullptr); | ||
| 28 | + return y; | ||
| 29 | +} | ||
| 30 | + | ||
| 31 | +const aclTensor *Swish(const aclTensor *x, float scale, aclOpExecutor *executor) { | ||
| 32 | + auto out = executor->AllocTensor(x->GetViewShape(), x->GetDataType()); | ||
| 33 | + return SwishAiCore(x, out, scale, executor); | ||
| 34 | +} | ||
| 35 | +} // namespace l0op | ||
| @@ -0,0 +1,20 @@ | |||
| 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 | +namespace l0op { | ||
| 17 | +const aclTensor *Swish(const aclTensor *self, float scale, aclOpExecutor *executor); | ||
| 18 | +} // namespace l0op | ||
| 19 | + | ||
| 20 | + | ||
| @@ -0,0 +1,46 @@ | |||
| 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 swish.cpp | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +namespace ops { | ||
| 18 | +class Swish : public OpDef { | ||
| 19 | +public: | ||
| 20 | + explicit Swish(const char* name) : OpDef(name) | ||
| 21 | + { | ||
| 22 | + this->Input("x") | ||
| 23 | + .ParamType(REQUIRED) | ||
| 24 | + .DataType({ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16}) | ||
| 25 | + .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 26 | + .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}); | ||
| 27 | + this->Output("y") | ||
| 28 | + .ParamType(REQUIRED) | ||
| 29 | + .DataType({ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16}) | ||
| 30 | + .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 31 | + .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}); | ||
| 32 | + this->Attr("scale").AttrType(OPTIONAL).Float(1.0); | ||
| 33 | + | ||
| 34 | + OpAICoreConfig aicoreConfig; | ||
| 35 | + aicoreConfig.DynamicCompileStaticFlag(true) | ||
| 36 | + .DynamicFormatFlag(false) | ||
| 37 | + .DynamicRankSupportFlag(true) | ||
| 38 | + .DynamicShapeSupportFlag(true) | ||
| 39 | + .NeedCheckSupportFlag(false) | ||
| 40 | + .PrecisionReduceFlag(true) | ||
| 41 | + .ExtendCfgInfo("opFile.value", "swish"); | ||
| 42 | + this->AICore().AddConfig("ascend910b", aicoreConfig); | ||
| 43 | + } | ||
| 44 | +}; | ||
| 45 | +OP_ADD(Swish); | ||
| 46 | +} // namespace ops | ||
| @@ -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 swish_infer.cpp | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +using namespace ge; | ||
| 19 | + | ||
| 20 | +namespace ops { | ||
| 21 | + | ||
| 22 | +static ge::graphStatus InferShapeSwish(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(Swish).InferShape(InferShapeSwish); | ||
| 31 | +} // namespace ops | ||
| @@ -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 | + * \file swish_tiling.cpp | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +namespace optiling { | ||
| 27 | + | ||
| 28 | +struct SwishCompileInfo {}; | ||
| 29 | + | ||
| 30 | +const uint64_t BUFFER_NUM = 2; | ||
| 31 | + | ||
| 32 | +// tiling 分发入口 | ||
| 33 | +static ge::graphStatus SwishTilingFunc(gert::TilingContext* context) | ||
| 34 | +{ | ||
| 35 | + uint64_t blockSize = 0; | ||
| 36 | + uint64_t ubSize = 0; | ||
| 37 | + | ||
| 38 | + blockSize = Ops::Base::GetUbBlockSize(context); | ||
| 39 | + OP_CHECK_IF(blockSize == 0, OP_LOGE(context, "blockSize is 0"), return ge::GRAPH_FAILED); | ||
| 40 | + | ||
| 41 | + SwishTilingData* tiling = context->GetTilingData<SwishTilingData>(); | ||
| 42 | + fe::PlatFormInfos* platformInfoPtr = context->GetPlatformInfo(); | ||
| 43 | + OP_CHECK_NULL_WITH_CONTEXT(context, platformInfoPtr); | ||
| 44 | + auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfoPtr); | ||
| 45 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSize); | ||
| 46 | + auto coreNum = ascendcPlatform.GetCoreNum(); | ||
| 47 | + auto socVersion = ascendcPlatform.GetSocVersion(); | ||
| 48 | + if (socVersion != platform_ascendc::SocVersion::ASCEND910B && socVersion != platform_ascendc::SocVersion::ASCEND310B && context->GetInputDesc(0)->GetDataType() == ge::DT_BF16) { | ||
| 49 | + OP_LOGE(context, "socVersion error."); | ||
| 50 | + return ge::GRAPH_FAILED; | ||
| 51 | + } | ||
| 52 | + | ||
| 53 | + auto inputShape = context->GetInputShape(0); | ||
| 54 | + OP_CHECK_NULL_WITH_CONTEXT(context, inputShape); | ||
| 55 | + uint64_t inputNum = inputShape->GetStorageShape().GetShapeSize(); | ||
| 56 | + OP_CHECK_IF(inputNum == 0, OP_LOGE(context, "inputNum is 0"), return ge::GRAPH_FAILED); | ||
| 57 | + | ||
| 58 | + auto inputDesc = context->GetInputDesc(0); | ||
| 59 | + OP_CHECK_NULL_WITH_CONTEXT(context, inputDesc); | ||
| 60 | + ge::DataType dataType = inputDesc->GetDataType(); | ||
| 61 | + uint32_t typeLength = 0; | ||
| 62 | + ge::TypeUtils::GetDataTypeLength(dataType, typeLength); | ||
| 63 | + | ||
| 64 | + uint64_t inputLength = inputNum * typeLength; | ||
| 65 | + uint64_t inputBytes = inputLength / inputNum; | ||
| 66 | + OP_CHECK_IF(inputNum == 0, OP_LOGE(context, "inputNum is 0"), return ge::GRAPH_FAILED); | ||
| 67 | + | ||
| 68 | + uint64_t ubDataNumber = (dataType == ge::DT_FLOAT) ? 2 : 4; | ||
| 69 | + uint64_t tileBlockNum = (ubSize / blockSize / BUFFER_NUM) / ubDataNumber; | ||
| 70 | + uint64_t tileDataNum = (tileBlockNum * blockSize) / inputBytes; | ||
| 71 | + | ||
| 72 | + uint64_t inputLengthAlgin32 = (((inputLength + blockSize - 1) / blockSize) * blockSize); | ||
| 73 | + if(tileDataNum >= inputNum) | ||
| 74 | + { | ||
| 75 | + coreNum=1; | ||
| 76 | + } | ||
| 77 | + else | ||
| 78 | + { | ||
| 79 | + // There is at least 32B of data on each core, satisfying several settings for several cores. The maximum number of audits is the actual number of audits | ||
| 80 | + coreNum = (coreNum < inputLengthAlgin32 / blockSize) ? coreNum : inputLengthAlgin32 / blockSize; | ||
| 81 | + } | ||
| 82 | + OP_CHECK_IF(coreNum == 0, OP_LOGE(context, "coreNum is 0"), return ge::GRAPH_FAILED); | ||
| 83 | + OP_CHECK_IF(inputBytes == 0, OP_LOGE(context, "inputBytes is 0"), return ge::GRAPH_FAILED); | ||
| 84 | + | ||
| 85 | + uint64_t everyCoreInputBlockNum = inputLengthAlgin32 / blockSize / coreNum; | ||
| 86 | + uint64_t tailBlockNum = (inputLengthAlgin32 / blockSize) % coreNum; | ||
| 87 | + | ||
| 88 | + uint64_t smallCoreDataNum = everyCoreInputBlockNum * blockSize / inputBytes; | ||
| 89 | + uint64_t smallTileNum = everyCoreInputBlockNum / tileBlockNum; | ||
| 90 | + uint64_t finalSmallTileNum = (everyCoreInputBlockNum % tileBlockNum) == 0 ? smallTileNum : smallTileNum + 1; | ||
| 91 | + uint64_t smallTailDataNum = smallCoreDataNum - (tileDataNum * smallTileNum); | ||
| 92 | + smallTailDataNum = smallTailDataNum == 0 ? tileDataNum : smallTailDataNum; | ||
| 93 | + | ||
| 94 | + everyCoreInputBlockNum += 1; | ||
| 95 | + uint64_t bigCoreDataNum = everyCoreInputBlockNum * blockSize / inputBytes; | ||
| 96 | + uint64_t bigTileNum = everyCoreInputBlockNum / tileBlockNum; | ||
| 97 | + uint64_t finalBigTileNum = (everyCoreInputBlockNum % tileBlockNum) == 0 ? bigTileNum : bigTileNum + 1; | ||
| 98 | + uint64_t bigTailDataNum = bigCoreDataNum - tileDataNum * bigTileNum; | ||
| 99 | + bigTailDataNum = bigTailDataNum == 0 ? tileDataNum : bigTailDataNum; | ||
| 100 | + | ||
| 101 | + tiling->smallCoreDataNum = (uint32_t)smallCoreDataNum; | ||
| 102 | + tiling->bigCoreDataNum = (uint32_t)bigCoreDataNum; | ||
| 103 | + tiling->tileDataNum = (uint32_t)tileDataNum; | ||
| 104 | + tiling->smallTailDataNum = (uint32_t)smallTailDataNum; | ||
| 105 | + tiling->bigTailDataNum = (uint32_t)bigTailDataNum; | ||
| 106 | + tiling->finalSmallTileNum = (uint32_t)finalSmallTileNum; | ||
| 107 | + tiling->finalBigTileNum = (uint32_t)finalBigTileNum; | ||
| 108 | + tiling->tailBlockNum = (uint32_t)tailBlockNum; | ||
| 109 | + | ||
| 110 | + auto attrs = context->GetAttrs(); | ||
| 111 | + OP_CHECK_NULL_WITH_CONTEXT(context, attrs); | ||
| 112 | + const float* scaleValueAttr = attrs->GetAttrPointer<float>(0); | ||
| 113 | + float scale = scaleValueAttr == nullptr ? 1.0f : *scaleValueAttr; | ||
| 114 | + tiling->scale = scale; | ||
| 115 | + | ||
| 116 | + uint64_t attrWork = TPL_SCALE_OTHER; | ||
| 117 | + constexpr float NEG_ONE = -1.0f; | ||
| 118 | + constexpr float ZERO = 0.0f; | ||
| 119 | + if (scale == NEG_ONE) { | ||
| 120 | + attrWork = TPL_SCALE_NEG_ONE; | ||
| 121 | + } else if (scale == ZERO) { | ||
| 122 | + attrWork = TPL_SCALE_ZERO; | ||
| 123 | + } else { | ||
| 124 | + attrWork = TPL_SCALE_OTHER; | ||
| 125 | + } | ||
| 126 | + | ||
| 127 | + context->SetBlockDim(coreNum); | ||
| 128 | + context->SetTilingKey(GET_TPL_TILING_KEY(TPL_SCH_MODE_0, attrWork)); | ||
| 129 | + uint32_t sysWorkspaceSize = ascendcPlatform.GetLibApiWorkSpaceSize(); | ||
| 130 | + size_t *currentWorkspace = context->GetWorkspaceSizes(1); | ||
| 131 | + currentWorkspace[0] = sysWorkspaceSize; | ||
| 132 | + return ge::GRAPH_SUCCESS; | ||
| 133 | +} | ||
| 134 | + | ||
| 135 | +// tiling注册入口. | ||
| 136 | +static ge::graphStatus TilingPrepare4Swish([[maybe_unused]] gert::TilingParseContext* context) | ||
| 137 | +{ | ||
| 138 | + return ge::GRAPH_SUCCESS; | ||
| 139 | +} | ||
| 140 | + | ||
| 141 | +IMPL_OP_OPTILING(Swish).Tiling(SwishTilingFunc).TilingParse<SwishCompileInfo>(TilingPrepare4Swish); | ||
| 142 | +} // namespace optiling | ||
| @@ -0,0 +1,33 @@ | |||
| 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 swish.cpp | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +using namespace NsSwish; | ||
| 19 | + | ||
| 20 | +template <uint64_t schMode, uint64_t attrWork> | ||
| 21 | +__global__ __aicore__ void swish(GM_ADDR x, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling) | ||
| 22 | +{ | ||
| 23 | + REGISTER_TILING_DEFAULT(SwishTilingData); | ||
| 24 | + GET_TILING_DATA_WITH_STRUCT(SwishTilingData, tiling_data, tiling); | ||
| 25 | + | ||
| 26 | + KernelSwish<DTYPE_X, DTYPE_X> op; | ||
| 27 | + op.Init(x, tiling_data.scale, y, tiling_data.smallCoreDataNum, | ||
| 28 | + tiling_data.bigCoreDataNum, tiling_data.finalBigTileNum, | ||
| 29 | + tiling_data.finalSmallTileNum, tiling_data.tileDataNum, | ||
| 30 | + tiling_data.smallTailDataNum, tiling_data.bigTailDataNum, | ||
| 31 | + tiling_data.tailBlockNum); | ||
| 32 | + op.Process(); | ||
| 33 | +} | ||
| @@ -0,0 +1,139 @@ | |||
| 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 swish.h | ||
| 13 | + * \brief | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace NsSwish { | ||
| 24 | + | ||
| 25 | +using namespace AscendC; | ||
| 26 | + | ||
| 27 | +constexpr int32_t BUFFER_NUM = 2; | ||
| 28 | + | ||
| 29 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 30 | +class KernelSwish | ||
| 31 | +{ | ||
| 32 | +public: | ||
| 33 | + __aicore__ inline KernelSwish() {} | ||
| 34 | + __aicore__ inline void Init(GM_ADDR x, float scale, GM_ADDR y, uint32_t smallCoreDataNum, | ||
| 35 | + uint32_t bigCoreDataNum, uint32_t finalBigTileNum, | ||
| 36 | + uint32_t finalSmallTileNum, uint32_t tileDataNum, | ||
| 37 | + uint32_t smallTailDataNum, uint32_t bigTailDataNum, | ||
| 38 | + uint32_t tailBlockNum) | ||
| 39 | + { | ||
| 40 | + ASSERT(GetBlockNum() != 0 && "block dim can not be zero!"); | ||
| 41 | + uint32_t coreNum = GetBlockIdx(); | ||
| 42 | + uint32_t globalBufferIndex = bigCoreDataNum * GetBlockIdx(); | ||
| 43 | + this->tileDataNum = tileDataNum; | ||
| 44 | + if (coreNum < tailBlockNum) | ||
| 45 | + { | ||
| 46 | + this->coreDataNum = bigCoreDataNum; | ||
| 47 | + this->tileNum = finalBigTileNum; | ||
| 48 | + this->tailDataNum = bigTailDataNum; | ||
| 49 | + } | ||
| 50 | + else | ||
| 51 | + { | ||
| 52 | + this->coreDataNum = smallCoreDataNum; | ||
| 53 | + this->tileNum = finalSmallTileNum; | ||
| 54 | + this->tailDataNum = smallTailDataNum; | ||
| 55 | + globalBufferIndex -= (bigCoreDataNum - smallCoreDataNum) * (GetBlockIdx() - tailBlockNum); | ||
| 56 | + } | ||
| 57 | + xGm.SetGlobalBuffer((__gm__ TYPE_X *)x + globalBufferIndex, this->coreDataNum); | ||
| 58 | + yGm.SetGlobalBuffer((__gm__ TYPE_Y *)y + globalBufferIndex, this->coreDataNum); | ||
| 59 | + | ||
| 60 | + this->scale = -1.0f * scale; | ||
| 61 | + pipe.InitBuffer(inQueueX, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_X)); | ||
| 62 | + pipe.InitBuffer(outQueueY, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_Y)); | ||
| 63 | + if constexpr (!std::is_same_v<TYPE_X, float>) | ||
| 64 | + { | ||
| 65 | + pipe.InitBuffer(calcBuf1, this->tileDataNum * sizeof(float)); | ||
| 66 | + pipe.InitBuffer(calcBuf2, this->tileDataNum * sizeof(float)); | ||
| 67 | + } | ||
| 68 | + } | ||
| 69 | + __aicore__ inline void Process() | ||
| 70 | + { | ||
| 71 | + int32_t loopCount = this->tileNum; | ||
| 72 | + this->processDataNum = this->tileDataNum; | ||
| 73 | + for (int32_t i = 0; i < loopCount-1; i++) | ||
| 74 | + { | ||
| 75 | + CopyIn(i); | ||
| 76 | + Compute(i); | ||
| 77 | + CopyOut(i); | ||
| 78 | + } | ||
| 79 | + this->processDataNum = this->tailDataNum; | ||
| 80 | + CopyIn(loopCount-1); | ||
| 81 | + Compute(loopCount-1); | ||
| 82 | + CopyOut(loopCount-1); | ||
| 83 | + } | ||
| 84 | + | ||
| 85 | +private: | ||
| 86 | + __aicore__ inline void CopyIn(int32_t progress) | ||
| 87 | + { | ||
| 88 | + LocalTensor<TYPE_X> xLocal = inQueueX.AllocTensor<TYPE_X>(); | ||
| 89 | + DataCopy(xLocal, xGm[progress * this->tileDataNum], this->processDataNum); | ||
| 90 | + inQueueX.EnQue(xLocal); | ||
| 91 | + } | ||
| 92 | + __aicore__ inline void Compute(int32_t progress) | ||
| 93 | + { | ||
| 94 | + LocalTensor<TYPE_X> xLocal = inQueueX.DeQue<TYPE_X>(); | ||
| 95 | + LocalTensor<TYPE_Y> yLocal = outQueueY.AllocTensor<TYPE_Y>(); | ||
| 96 | + if constexpr (std::is_same_v<TYPE_X, float>){ | ||
| 97 | + Muls(yLocal, xLocal, this->scale, this->processDataNum); | ||
| 98 | + Exp(yLocal, yLocal, this->processDataNum); | ||
| 99 | + Adds(yLocal, yLocal, (TYPE_X)1.0f, this->processDataNum); | ||
| 100 | + Div(yLocal, xLocal, yLocal, this->processDataNum); | ||
| 101 | + }else if constexpr (!std::is_same_v<TYPE_X, float>){ | ||
| 102 | + LocalTensor<float> xLocalFp32 = calcBuf1.Get<float>(); | ||
| 103 | + LocalTensor<float> yLocalFp32 = calcBuf2.Get<float>(); | ||
| 104 | + | ||
| 105 | + Cast(xLocalFp32, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 106 | + Muls(yLocalFp32, xLocalFp32, this->scale, this->processDataNum); | ||
| 107 | + Exp(yLocalFp32, yLocalFp32, this->processDataNum); | ||
| 108 | + Adds(yLocalFp32, yLocalFp32, 1.0f, this->processDataNum); | ||
| 109 | + Div(yLocalFp32, xLocalFp32, yLocalFp32, this->processDataNum); | ||
| 110 | + Cast(yLocal, yLocalFp32, RoundMode::CAST_ROUND, this->processDataNum); | ||
| 111 | + } | ||
| 112 | + outQueueY.EnQue<TYPE_Y>(yLocal); | ||
| 113 | + inQueueX.FreeTensor(xLocal); | ||
| 114 | + } | ||
| 115 | + __aicore__ inline void CopyOut(int32_t progress) | ||
| 116 | + { | ||
| 117 | + LocalTensor<TYPE_Y> yLocal = outQueueY.DeQue<TYPE_Y>(); | ||
| 118 | + DataCopy(yGm[progress * this->tileDataNum], yLocal, this->processDataNum); | ||
| 119 | + outQueueY.FreeTensor(yLocal); | ||
| 120 | + } | ||
| 121 | + | ||
| 122 | +private: | ||
| 123 | + TPipe pipe; | ||
| 124 | + TQue<QuePosition::VECIN, BUFFER_NUM> inQueueX; | ||
| 125 | + TQue<QuePosition::VECOUT, BUFFER_NUM> outQueueY; | ||
| 126 | + TBuf<QuePosition::VECCALC> calcBuf1; | ||
| 127 | + TBuf<QuePosition::VECCALC> calcBuf2; | ||
| 128 | + GlobalTensor<TYPE_X> xGm; | ||
| 129 | + GlobalTensor<TYPE_Y> yGm; | ||
| 130 | + uint32_t coreDataNum; | ||
| 131 | + uint32_t tileNum; | ||
| 132 | + uint32_t tileDataNum; | ||
| 133 | + uint32_t tailDataNum; | ||
| 134 | + uint32_t processDataNum; | ||
| 135 | + float scale; | ||
| 136 | +}; | ||
| 137 | + | ||
| 138 | +} // namespace NsSwish | ||
| 139 | + | ||
| @@ -0,0 +1,30 @@ | |||
| 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 swish_tiling_data.h | ||
| 13 | + * \brief tiling data struct | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +struct SwishTilingData { | ||
| 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 | + float scale; | ||
| 29 | +}; | ||
| 30 | + | ||
| @@ -0,0 +1,44 @@ | |||
| 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 swish_tiling_key.h | ||
| 13 | + * \brief swish tiling key declare | ||
| 14 | + */ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +namespace SwishOp { | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | +ASCENDC_TPL_ARGS_DECL(Swish, | ||
| 30 | + ASCENDC_TPL_UINT_DECL(schMode, 1, ASCENDC_TPL_UI_LIST, TPL_SCH_MODE_0, TPL_SCH_MODE_1), | ||
| 31 | + ASCENDC_TPL_DTYPE_DECL(dType, TPL_SCALE_NEG_ONE, TPL_SCALE_ZERO, TPL_SCALE_OTHER) | ||
| 32 | +); | ||
| 33 | + | ||
| 34 | +ASCENDC_TPL_SEL( | ||
| 35 | + ASCENDC_TPL_ARGS_SEL( | ||
| 36 | + ASCENDC_TPL_UINT_SEL(schMode, ASCENDC_TPL_UI_LIST, TPL_SCH_MODE_0, TPL_SCH_MODE_1), | ||
| 37 | + ASCENDC_TPL_DTYPE_SEL(dType, TPL_SCALE_NEG_ONE, TPL_SCALE_ZERO, TPL_SCALE_OTHER) | ||
| 38 | + ) | ||
| 39 | +); | ||
| 40 | +} // namespace SwishOp | ||
| 41 | + | ||
| 42 | +using namespace SwishOp; | ||
| 43 | + | ||
| 44 | + | ||
| @@ -0,0 +1,17 @@ | |||
| 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 | +file(GLOB CURRENT_SOURCE_DIRS LIST_DIRECTORIES true ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 12 | +message(STATUS "=== Debug: CURRENT_SOURCE_DIRS =${CURRENT_SOURCE_DIRS} ") | ||
| 13 | +foreach(SUB_DIR ${CURRENT_SOURCE_DIRS}) | ||
| 14 | + if(EXISTS "${SUB_DIR}/CMakeLists.txt") | ||
| 15 | + add_subdirectory(${SUB_DIR}) | ||
| 16 | + endif() | ||
| 17 | +endforeach() | ||
| @@ -0,0 +1,17 @@ | |||
| 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 | +file(GLOB CURRENT_SOURCE_DIRS LIST_DIRECTORIES true ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 12 | +message(STATUS "=== Debug: CURRENT_SOURCE_DIRS =${CURRENT_SOURCE_DIRS} ") | ||
| 13 | +foreach(SUB_DIR ${CURRENT_SOURCE_DIRS}) | ||
| 14 | + if(EXISTS "${SUB_DIR}/CMakeLists.txt") | ||
| 15 | + add_subdirectory(${SUB_DIR}) | ||
| 16 | + endif() | ||
| 17 | +endforeach() | ||
| @@ -0,0 +1,14 @@ | |||
| 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 | +file(GLOB CURRENT_DIR RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 12 | +if(UT_TEST_ALL OR OP_API_UT) | ||
| 13 | + add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | +endif() | ||
| @@ -0,0 +1,180 @@ | |||
| 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 | +using namespace std; | ||
| 23 | + | ||
| 24 | +class silu_test : public testing::Test { | ||
| 25 | + protected: | ||
| 26 | + static void SetUpTestCase() { cout << "sign_test SetUp" << endl; } | ||
| 27 | + | ||
| 28 | + static void TearDownTestCase() { cout << "sign_test TeastDown" << endl; } | ||
| 29 | +}; | ||
| 30 | + | ||
| 31 | +TEST_F(silu_test, test_silu_dataType_error) { | ||
| 32 | + vector<aclDataType> ValidList = {ACL_DT_UNDEFINED, ACL_INT8, ACL_INT16, ACL_INT32, ACL_INT64, | ||
| 33 | + ACL_UINT8, ACL_UINT16, ACL_UINT32, ACL_UINT64, ACL_DOUBLE, | ||
| 34 | + ACL_BOOL, ACL_STRING, ACL_COMPLEX64, ACL_COMPLEX128, ACL_BF16}; | ||
| 35 | + | ||
| 36 | + int length = ValidList.size(); | ||
| 37 | + vector<int64_t> input_dim = {2, 16, 32, 16}; | ||
| 38 | + vector<int64_t> result_dim = {2, 16, 32, 16}; | ||
| 39 | + | ||
| 40 | + for (int i = 0; i < length; i++) { | ||
| 41 | + auto inputDesc = TensorDesc(input_dim, ValidList[i], ACL_FORMAT_ND).ValueRange(-2, 2); | ||
| 42 | + auto outDesc = TensorDesc(result_dim, ValidList[i], ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 43 | + | ||
| 44 | + auto ut = OP_API_UT(aclnnSilu, INPUT(inputDesc), OUTPUT(outDesc)); | ||
| 45 | + uint64_t workspaceSize = 0; | ||
| 46 | + aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 47 | + } | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +TEST_F(silu_test, test_silu_format) { | ||
| 51 | + vector<aclFormat> ValidList = { | ||
| 52 | + ACL_FORMAT_UNDEFINED, ACL_FORMAT_NCHW, ACL_FORMAT_NHWC, ACL_FORMAT_ND, ACL_FORMAT_NC1HWC0, | ||
| 53 | + ACL_FORMAT_FRACTAL_Z, ACL_FORMAT_NC1HWC0_C04, ACL_FORMAT_HWCN, ACL_FORMAT_NDHWC, ACL_FORMAT_FRACTAL_NZ, | ||
| 54 | + ACL_FORMAT_NCDHW, ACL_FORMAT_NDC1HWC0, ACL_FRACTAL_Z_3D, ACL_FORMAT_NC, ACL_FORMAT_NCL}; | ||
| 55 | + | ||
| 56 | + int length = ValidList.size(); | ||
| 57 | + vector<int64_t> input_dim = {2, 16, 32, 16}; | ||
| 58 | + vector<int64_t> result_dim = {2, 16, 32, 16}; | ||
| 59 | + | ||
| 60 | + for (int i = 0; i < length; i++) { | ||
| 61 | + auto inputDesc = TensorDesc(input_dim, ACL_FLOAT, ValidList[i]).ValueRange(-1, 1); | ||
| 62 | + auto outDesc = TensorDesc(result_dim, ACL_FLOAT, ValidList[i]).Precision(0.0001, 0.0001); | ||
| 63 | + | ||
| 64 | + auto ut = OP_API_UT(aclnnSilu, INPUT(inputDesc), OUTPUT(outDesc)); | ||
| 65 | + uint64_t workspaceSize = 0; | ||
| 66 | + aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 67 | + EXPECT_EQ(aclRet, ACLNN_SUCCESS); | ||
| 68 | + ut.TestPrecision(); | ||
| 69 | + } | ||
| 70 | +} | ||
| 71 | + | ||
| 72 | +TEST_F(silu_test, test_silu_inconsistent_shape) { | ||
| 73 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 74 | + auto outDesc = TensorDesc({2, 16, 32, 18}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 75 | + | ||
| 76 | + auto ut = OP_API_UT(aclnnSilu, INPUT(inputDesc), OUTPUT(outDesc)); | ||
| 77 | + | ||
| 78 | + uint64_t workspaceSize = 0; | ||
| 79 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 80 | + EXPECT_EQ(getWorkspaceout, ACLNN_ERR_PARAM_INVALID); | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +TEST_F(silu_test, test_silu_inconsistent_dtype) { | ||
| 84 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 85 | + auto outDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT16, ACL_FORMAT_ND); | ||
| 86 | + | ||
| 87 | + auto ut = OP_API_UT(aclnnSilu, INPUT(inputDesc), OUTPUT(outDesc)); | ||
| 88 | + | ||
| 89 | + uint64_t workspaceSize = 0; | ||
| 90 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 91 | + EXPECT_EQ(getWorkspaceout, ACLNN_ERR_PARAM_INVALID); | ||
| 92 | +} | ||
| 93 | + | ||
| 94 | +TEST_F(silu_test, test_silu_empty_input) { | ||
| 95 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 96 | + auto outDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 97 | + | ||
| 98 | + auto ut = OP_API_UT(aclnnSilu, INPUT(inputDesc), OUTPUT(outDesc)); | ||
| 99 | + | ||
| 100 | + uint64_t workspaceSize = 0; | ||
| 101 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 102 | + EXPECT_EQ(getWorkspaceout, ACLNN_SUCCESS); | ||
| 103 | + ut.TestPrecision(); | ||
| 104 | +} | ||
| 105 | + | ||
| 106 | +TEST_F(silu_test, test_silu_nullptr_input) { | ||
| 107 | + auto outDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 108 | + | ||
| 109 | + auto ut = OP_API_UT(aclnnSilu, INPUT((aclTensor *)nullptr), OUTPUT(outDesc)); | ||
| 110 | + | ||
| 111 | + uint64_t workspaceSize = 0; | ||
| 112 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 113 | + EXPECT_EQ(getWorkspaceout, ACLNN_ERR_PARAM_NULLPTR); | ||
| 114 | +} | ||
| 115 | + | ||
| 116 | +TEST_F(silu_test, test_silu_nullptr_out) { | ||
| 117 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 118 | + | ||
| 119 | + auto ut = OP_API_UT(aclnnSilu, INPUT(inputDesc), OUTPUT((aclTensor *)nullptr)); | ||
| 120 | + | ||
| 121 | + uint64_t workspaceSize = 0; | ||
| 122 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 123 | + EXPECT_EQ(getWorkspaceout, ACLNN_ERR_PARAM_NULLPTR); | ||
| 124 | +} | ||
| 125 | + | ||
| 126 | +TEST_F(silu_test, test_silu_FP32) { | ||
| 127 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 128 | + auto outDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 129 | + | ||
| 130 | + auto ut = OP_API_UT(aclnnSilu, INPUT(inputDesc), OUTPUT(outDesc)); | ||
| 131 | + | ||
| 132 | + uint64_t workspaceSize = 0; | ||
| 133 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 134 | + EXPECT_EQ(getWorkspaceout, ACLNN_SUCCESS); | ||
| 135 | + ut.TestPrecision(); | ||
| 136 | +} | ||
| 137 | + | ||
| 138 | +TEST_F(silu_test, test_silu_FP16) { | ||
| 139 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 140 | + auto outDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 141 | + | ||
| 142 | + auto ut = OP_API_UT(aclnnSilu, INPUT(inputDesc), OUTPUT(outDesc)); | ||
| 143 | + | ||
| 144 | + uint64_t workspaceSize = 0; | ||
| 145 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 146 | + EXPECT_EQ(getWorkspaceout, ACLNN_SUCCESS); | ||
| 147 | + ut.TestPrecision(); | ||
| 148 | +} | ||
| 149 | + | ||
| 150 | +TEST_F(silu_test, test_silu_uncontiguous) { | ||
| 151 | + auto inputDesc = TensorDesc({2, 16}, ACL_FLOAT, ACL_FORMAT_ND, {1, 2}, 0, {16, 2}).ValueRange(-1, 1); | ||
| 152 | + auto outDesc = TensorDesc({2, 16}, ACL_FLOAT, ACL_FORMAT_ND, {1, 2}, 0, {16, 2}).Precision(0.0001, 0.0001); | ||
| 153 | + | ||
| 154 | + auto ut = OP_API_UT(aclnnSilu, INPUT(inputDesc), OUTPUT(outDesc)); | ||
| 155 | + | ||
| 156 | + uint64_t workspaceSize = 0; | ||
| 157 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 158 | + EXPECT_EQ(getWorkspaceout, ACLNN_SUCCESS); | ||
| 159 | + ut.TestPrecision(); | ||
| 160 | +} | ||
| 161 | + | ||
| 162 | +TEST_F(silu_test, test_silu_shape_larger_8) { | ||
| 163 | + vector<aclFormat> ValidList = { | ||
| 164 | + ACL_FORMAT_UNDEFINED, ACL_FORMAT_NCHW, ACL_FORMAT_NHWC, ACL_FORMAT_ND, ACL_FORMAT_NC1HWC0, | ||
| 165 | + ACL_FORMAT_FRACTAL_Z, ACL_FORMAT_NC1HWC0_C04, ACL_FORMAT_HWCN, ACL_FORMAT_NDHWC, ACL_FORMAT_FRACTAL_NZ, | ||
| 166 | + ACL_FORMAT_NCDHW, ACL_FORMAT_NDC1HWC0, ACL_FRACTAL_Z_3D, ACL_FORMAT_NC, ACL_FORMAT_NCL}; | ||
| 167 | + | ||
| 168 | + int length = ValidList.size(); | ||
| 169 | + | ||
| 170 | + for (int i = 0; i < length; i++) { | ||
| 171 | + auto inputDesc = TensorDesc({1, 1, 1, 1, 2, 1, 1, 1, 2}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 172 | + auto resultDesc = TensorDesc({1, 1, 1, 1, 2, 1, 1, 1, 2}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 173 | + auto ut = OP_API_UT(aclnnSilu, INPUT(inputDesc), OUTPUT(resultDesc)); | ||
| 174 | + | ||
| 175 | + uint64_t workspaceSize = 0; | ||
| 176 | + aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 177 | + EXPECT_EQ(aclRet, ACLNN_SUCCESS); | ||
| 178 | + // ut.TestPrecision(); // comment bcz of timeout in model tests (986327 ms) | ||
| 179 | + } | ||
| 180 | +} | ||
| @@ -0,0 +1,216 @@ | |||
| 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 | +using namespace std; | ||
| 23 | + | ||
| 24 | +class swish_test : public testing::Test { | ||
| 25 | + protected: | ||
| 26 | + static void SetUpTestCase() { cout << "sign_test SetUp" << endl; } | ||
| 27 | + | ||
| 28 | + static void TearDownTestCase() { cout << "sign_test TeastDown" << endl; } | ||
| 29 | +}; | ||
| 30 | + | ||
| 31 | +TEST_F(swish_test, test_swish_dataType_error) { | ||
| 32 | + vector<aclDataType> ValidList = {ACL_DT_UNDEFINED, ACL_INT8, ACL_INT16, ACL_INT32, ACL_INT64, | ||
| 33 | + ACL_UINT8, ACL_UINT16, ACL_UINT32, ACL_UINT64, ACL_DOUBLE, | ||
| 34 | + ACL_BOOL, ACL_STRING, ACL_COMPLEX64, ACL_COMPLEX128, ACL_BF16}; | ||
| 35 | + | ||
| 36 | + int length = ValidList.size(); | ||
| 37 | + vector<int64_t> input_dim = {2, 16, 32, 16}; | ||
| 38 | + vector<int64_t> result_dim = {2, 16, 32, 16}; | ||
| 39 | + | ||
| 40 | + for (int i = 0; i < length; i++) { | ||
| 41 | + auto inputDesc = TensorDesc(input_dim, ValidList[i], ACL_FORMAT_ND).ValueRange(-2, 2); | ||
| 42 | + auto betaDesc = ScalarDesc(static_cast<bool>(false)); | ||
| 43 | + auto outDesc = TensorDesc(result_dim, ValidList[i], ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 44 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(outDesc)); | ||
| 45 | + | ||
| 46 | + uint64_t workspaceSize = 0; | ||
| 47 | + aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 48 | + } | ||
| 49 | +} | ||
| 50 | + | ||
| 51 | +TEST_F(swish_test, test_swish_format) { | ||
| 52 | + vector<aclFormat> ValidList = { | ||
| 53 | + ACL_FORMAT_UNDEFINED, ACL_FORMAT_NCHW, ACL_FORMAT_NHWC, ACL_FORMAT_ND, ACL_FORMAT_NC1HWC0, | ||
| 54 | + ACL_FORMAT_FRACTAL_Z, ACL_FORMAT_NC1HWC0_C04, ACL_FORMAT_HWCN, ACL_FORMAT_NDHWC, ACL_FORMAT_FRACTAL_NZ, | ||
| 55 | + ACL_FORMAT_NCDHW, ACL_FORMAT_NDC1HWC0, ACL_FRACTAL_Z_3D, ACL_FORMAT_NC, ACL_FORMAT_NCL}; | ||
| 56 | + | ||
| 57 | + int length = ValidList.size(); | ||
| 58 | + vector<int64_t> input_dim = {2, 16, 32, 16}; | ||
| 59 | + vector<int64_t> result_dim = {2, 16, 32, 16}; | ||
| 60 | + | ||
| 61 | + for (int i = 0; i < length; i++) { | ||
| 62 | + auto inputDesc = TensorDesc(input_dim, ACL_FLOAT, ValidList[i]).ValueRange(-1, 1); | ||
| 63 | + auto betaDesc = ScalarDesc(static_cast<double>(0.0)); | ||
| 64 | + auto outDesc = TensorDesc(result_dim, ACL_FLOAT, ValidList[i]).Precision(0.0001, 0.0001); | ||
| 65 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(outDesc)); | ||
| 66 | + | ||
| 67 | + uint64_t workspaceSize = 0; | ||
| 68 | + aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 69 | + EXPECT_EQ(aclRet, ACLNN_SUCCESS); | ||
| 70 | + ut.TestPrecision(); | ||
| 71 | + } | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +TEST_F(swish_test, test_swish_inconsistent_shape) { | ||
| 75 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 76 | + auto betaDesc = ScalarDesc(1.1f, ACL_FLOAT); | ||
| 77 | + auto outDesc = TensorDesc({2, 16, 32, 18}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 78 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(outDesc)); | ||
| 79 | + | ||
| 80 | + uint64_t workspaceSize = 0; | ||
| 81 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 82 | + EXPECT_EQ(getWorkspaceout, ACLNN_ERR_PARAM_INVALID); | ||
| 83 | +} | ||
| 84 | + | ||
| 85 | +TEST_F(swish_test, test_swish_inconsistent_dtype) { | ||
| 86 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 87 | + auto betaDesc = ScalarDesc(1.1f, ACL_FLOAT); | ||
| 88 | + auto outDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT16, ACL_FORMAT_ND); | ||
| 89 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(outDesc)); | ||
| 90 | + | ||
| 91 | + uint64_t workspaceSize = 0; | ||
| 92 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 93 | + EXPECT_EQ(getWorkspaceout, ACLNN_ERR_PARAM_INVALID); | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +TEST_F(swish_test, test_swish_empty_input) { | ||
| 97 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 98 | + auto betaDesc = ScalarDesc(static_cast<uint8_t>(0)); | ||
| 99 | + auto outDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 100 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(outDesc)); | ||
| 101 | + | ||
| 102 | + uint64_t workspaceSize = 0; | ||
| 103 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 104 | + EXPECT_EQ(getWorkspaceout, ACLNN_SUCCESS); | ||
| 105 | + ut.TestPrecision(); | ||
| 106 | +} | ||
| 107 | + | ||
| 108 | +TEST_F(swish_test, test_swish_nullptr_input) { | ||
| 109 | + auto betaDesc = ScalarDesc(1.1f, ACL_FLOAT); | ||
| 110 | + auto outDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 111 | + auto ut = OP_API_UT(aclnnSwish, INPUT((aclTensor *)nullptr, betaDesc), OUTPUT(outDesc)); | ||
| 112 | + | ||
| 113 | + uint64_t workspaceSize = 0; | ||
| 114 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 115 | + EXPECT_EQ(getWorkspaceout, ACLNN_ERR_PARAM_NULLPTR); | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +TEST_F(swish_test, test_swish_nullptr_out) { | ||
| 119 | + auto betaDesc = ScalarDesc(1.1f, ACL_FLOAT); | ||
| 120 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 121 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT((aclTensor *)nullptr)); | ||
| 122 | + | ||
| 123 | + uint64_t workspaceSize = 0; | ||
| 124 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 125 | + EXPECT_EQ(getWorkspaceout, ACLNN_ERR_PARAM_NULLPTR); | ||
| 126 | +} | ||
| 127 | + | ||
| 128 | +TEST_F(swish_test, test_swish_nullptr_beta) { | ||
| 129 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 130 | + auto betaDesc = (aclScalar*)nullptr; | ||
| 131 | + auto outDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 132 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(outDesc)); | ||
| 133 | + | ||
| 134 | + uint64_t workspaceSize = 0; | ||
| 135 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 136 | + EXPECT_EQ(getWorkspaceout, ACLNN_SUCCESS); | ||
| 137 | +} | ||
| 138 | + | ||
| 139 | +TEST_F(swish_test, test_swish_FP32) { | ||
| 140 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 141 | + auto betaDesc = ScalarDesc(1.1f, ACL_FLOAT); | ||
| 142 | + auto outDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 143 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(outDesc)); | ||
| 144 | + | ||
| 145 | + uint64_t workspaceSize = 0; | ||
| 146 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 147 | + EXPECT_EQ(getWorkspaceout, ACLNN_SUCCESS); | ||
| 148 | + ut.TestPrecision(); | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +TEST_F(swish_test, test_swish_FP16) { | ||
| 152 | + auto inputDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT16, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 153 | + auto betaDesc = ScalarDesc(0.01f, ACL_FLOAT16); | ||
| 154 | + auto outDesc = TensorDesc({2, 16, 32, 16}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 155 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(outDesc)); | ||
| 156 | + | ||
| 157 | + uint64_t workspaceSize = 0; | ||
| 158 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 159 | + EXPECT_EQ(getWorkspaceout, ACLNN_SUCCESS); | ||
| 160 | + ut.TestPrecision(); | ||
| 161 | +} | ||
| 162 | + | ||
| 163 | +TEST_F(swish_test, test_swish_uncontiguous) { | ||
| 164 | + auto inputDesc = TensorDesc({2, 16}, ACL_FLOAT, ACL_FORMAT_ND, {1, 2}, 0, {16, 2}).ValueRange(-1, 1); | ||
| 165 | + auto betaDesc = ScalarDesc(static_cast<int8_t>(-1)); | ||
| 166 | + auto outDesc = TensorDesc({2, 16}, ACL_FLOAT, ACL_FORMAT_ND, {1, 2}, 0, {16, 2}).Precision(0.0001, 0.0001); | ||
| 167 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(outDesc)); | ||
| 168 | + | ||
| 169 | + uint64_t workspaceSize = 0; | ||
| 170 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 171 | + EXPECT_EQ(getWorkspaceout, ACLNN_SUCCESS); | ||
| 172 | + ut.TestPrecision(); | ||
| 173 | +} | ||
| 174 | + | ||
| 175 | +TEST_F(swish_test, test_swish_shape_larger_8) { | ||
| 176 | + vector<aclFormat> ValidList = { | ||
| 177 | + ACL_FORMAT_UNDEFINED, ACL_FORMAT_NCHW, ACL_FORMAT_NHWC, ACL_FORMAT_ND, ACL_FORMAT_NC1HWC0, | ||
| 178 | + ACL_FORMAT_FRACTAL_Z, ACL_FORMAT_NC1HWC0_C04, ACL_FORMAT_HWCN, ACL_FORMAT_NDHWC, ACL_FORMAT_FRACTAL_NZ, | ||
| 179 | + ACL_FORMAT_NCDHW, ACL_FORMAT_NDC1HWC0, ACL_FRACTAL_Z_3D, ACL_FORMAT_NC, ACL_FORMAT_NCL}; | ||
| 180 | + | ||
| 181 | + int length = ValidList.size(); | ||
| 182 | + | ||
| 183 | + for (int i = 0; i < length; i++) { | ||
| 184 | + auto inputDesc = TensorDesc({1, 1, 1, 1, 2, 1, 1, 1, 2}, ACL_FLOAT, ACL_FORMAT_ND).ValueRange(-1, 1); | ||
| 185 | + auto betaDesc = ScalarDesc(1.1f, ACL_FLOAT); | ||
| 186 | + auto resultDesc = TensorDesc({1, 1, 1, 1, 2, 1, 1, 1, 2}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001); | ||
| 187 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(resultDesc)); | ||
| 188 | + | ||
| 189 | + uint64_t workspaceSize = 0; | ||
| 190 | + aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 191 | + EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID); | ||
| 192 | + // ut.TestPrecision(); // comment bcz of timeout in model tests (986327 ms) | ||
| 193 | + } | ||
| 194 | +} | ||
| 195 | + | ||
| 196 | +TEST_F(swish_test, test_swish_input_invalid_dim) { | ||
| 197 | + auto inputDesc = TensorDesc({1, 2, 3, 4, 5, 6, 7, 8, 9}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 198 | + auto betaDesc = ScalarDesc(1.1f, ACL_FLOAT); | ||
| 199 | + auto outDesc = TensorDesc({1, 2, 3, 4}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 200 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(outDesc)); | ||
| 201 | + | ||
| 202 | + uint64_t workspaceSize = 0; | ||
| 203 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 204 | + EXPECT_EQ(getWorkspaceout, ACLNN_ERR_PARAM_INVALID); | ||
| 205 | +} | ||
| 206 | + | ||
| 207 | +TEST_F(swish_test, test_swish_output_invalid_dim) { | ||
| 208 | + auto inputDesc = TensorDesc({1, 2, 3, 4}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 209 | + auto betaDesc = ScalarDesc(1.1f, ACL_FLOAT); | ||
| 210 | + auto outDesc = TensorDesc({1, 2, 3, 4, 5, 6, 7, 8, 9}, ACL_FLOAT, ACL_FORMAT_ND); | ||
| 211 | + auto ut = OP_API_UT(aclnnSwish, INPUT(inputDesc, betaDesc), OUTPUT(outDesc)); | ||
| 212 | + | ||
| 213 | + uint64_t workspaceSize = 0; | ||
| 214 | + aclnnStatus getWorkspaceout = ut.TestGetWorkspaceSize(&workspaceSize); | ||
| 215 | + EXPECT_EQ(getWorkspaceout, ACLNN_ERR_PARAM_INVALID); | ||
| 216 | +} | ||
| @@ -0,0 +1,17 @@ | |||
| 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 | +file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 12 | + | ||
| 13 | +if(UT_TEST_ALL OR OP_HOST_UT) | ||
| 14 | + add_modules_ut_sources(HOSTNAME ${OP_TILING_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 15 | + add_modules_ut_sources(HOSTNAME ${OP_INFERSHAPE_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 16 | +endif() | ||
| 17 | + | ||
| @@ -0,0 +1,62 @@ | |||
| 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 test_swish_infershape.cpp | ||
| 13 | +* \brief | ||
| 14 | +*/ | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +class Swish : public testing::Test { | ||
| 25 | +protected: | ||
| 26 | + static void SetUpTestCase() | ||
| 27 | + { | ||
| 28 | + std::cout << "Swish Proto Test SetUp" << std::endl; | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + static void TearDownTestCase() { | ||
| 32 | + std::cout << "Swish Proto Test TearDown" << std::endl; | ||
| 33 | + } | ||
| 34 | +}; | ||
| 35 | + | ||
| 36 | +TEST_F(Swish, swish_infershape_test0) | ||
| 37 | +{ | ||
| 38 | + fe::PlatformInfo platformInfo; | ||
| 39 | + fe::OptionalInfo optiCompilationInfo; | ||
| 40 | + platformInfo.soc_info.ai_core_cnt = 64; | ||
| 41 | + platformInfo.str_info.short_soc_version = "Ascend910_95"; | ||
| 42 | + optiCompilationInfo.soc_version = "Ascend910_95"; | ||
| 43 | + fe::PlatformInfoManager::Instance().platform_info_map_["Ascend910_95"] = platformInfo; | ||
| 44 | + fe::PlatformInfoManager::Instance().SetOptionalCompilationInfo(optiCompilationInfo); | ||
| 45 | + | ||
| 46 | + auto inferShapeFunc = gert::OpImplRegistry::GetInstance().GetOpImpl("Swish")->infer_shape; | ||
| 47 | + gert::Shape xShape = {3, 4, 5}; | ||
| 48 | + gert::Shape output_shape = {}; | ||
| 49 | + | ||
| 50 | + auto holder = gert::InferShapeContextFaker() | ||
| 51 | + .NodeIoNum(1, 1) | ||
| 52 | + .IrInstanceNum({1}) | ||
| 53 | + .InputShapes({&xShape}) | ||
| 54 | + .OutputShapes({&output_shape}) | ||
| 55 | + .NodeAttrs( | ||
| 56 | + {{"scale", Ops::NN::AnyValue::CreateFrom<float>(1.0f)}}) | ||
| 57 | + .NodeInputTd(0, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 58 | + .NodeOutputTd(0, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 59 | + .Build(); | ||
| 60 | + | ||
| 61 | + ASSERT_EQ(inferShapeFunc(holder.GetContext<gert::InferShapeContext>()), ge::GRAPH_SUCCESS); | ||
| 62 | +} | ||
| @@ -0,0 +1,157 @@ | |||
| 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 | +using namespace ut_util; | ||
| 25 | +using namespace std; | ||
| 26 | +using namespace ge; | ||
| 27 | + | ||
| 28 | +class SwishTiling : public testing::Test { | ||
| 29 | +protected: | ||
| 30 | + static void SetUpTestCase() | ||
| 31 | + { | ||
| 32 | + std::cout << "SwishTiling SetUp" << std::endl; | ||
| 33 | + } | ||
| 34 | + | ||
| 35 | + static void TearDownTestCase() | ||
| 36 | + { | ||
| 37 | + std::cout << "SwishTiling TearDown" << std::endl; | ||
| 38 | + } | ||
| 39 | +}; | ||
| 40 | + | ||
| 41 | +TEST_F(SwishTiling, swish_float32_success) { | ||
| 42 | + gert::StorageShape x_shape = {{1, 2, 8, 16}, {1, 2, 8, 16}}; | ||
| 43 | + gert::StorageShape y_shape = {{1, 2, 8, 16}, {1, 2, 8, 16}}; | ||
| 44 | + string compile_info_string = R"({ | ||
| 45 | + "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1", | ||
| 46 | + "Intrinsic_fix_pipe_l0c2out": false, "Intrinsic_data_move_l12ub": true, "Intrinsic_data_move_l0c2ub": true, "Intrinsic_data_move_out2l1_nd2nz": false, | ||
| 47 | + "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288, | ||
| 48 | + "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072, | ||
| 49 | + "CORE_NUM": 48} | ||
| 50 | + })"; | ||
| 51 | + map<string, string> soc_infos; | ||
| 52 | + map<string, string> aicore_spec; | ||
| 53 | + map<string, string> intrinsics; | ||
| 54 | + GetPlatFormInfos(compile_info_string.c_str(), soc_infos, aicore_spec, intrinsics); | ||
| 55 | + | ||
| 56 | + fe::PlatFormInfos platform_info; | ||
| 57 | + platform_info.Init(); | ||
| 58 | + | ||
| 59 | + struct SwishCompileInfo {}; | ||
| 60 | + SwishCompileInfo compile_info; | ||
| 61 | + | ||
| 62 | + std::string op_type("Swish"); | ||
| 63 | + auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling; | ||
| 64 | + | ||
| 65 | + auto kernel_holder = | ||
| 66 | + gert::KernelRunContextFaker() | ||
| 67 | + .KernelIONum(3, 1) | ||
| 68 | + .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)}) | ||
| 69 | + .Outputs({&compile_info}) | ||
| 70 | + .Build(); | ||
| 71 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos); | ||
| 72 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec); | ||
| 73 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore"); | ||
| 74 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", | ||
| 75 | + intrinsics); | ||
| 76 | + | ||
| 77 | + auto param = gert::TilingData::CreateCap(4096); | ||
| 78 | + auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(4096); | ||
| 79 | + auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get()); | ||
| 80 | + ASSERT_NE(param, nullptr); | ||
| 81 | + auto holder = gert::TilingContextFaker() | ||
| 82 | + .SetOpType("Swish") | ||
| 83 | + .NodeIoNum(1, 1) | ||
| 84 | + .IrInstanceNum({1}) | ||
| 85 | + .InputShapes({&x_shape}) | ||
| 86 | + .OutputShapes({&y_shape}) | ||
| 87 | + .CompileInfo(&compile_info) | ||
| 88 | + .PlatformInfo(reinterpret_cast<char*>(&platform_info)) | ||
| 89 | + .NodeAttrs({{"scale", Ops::NN::AnyValue::CreateFrom<float>(1.0f)}}) | ||
| 90 | + .NodeInputTd(0, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 91 | + .NodeOutputTd(0, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 92 | + .TilingData(param.get()) | ||
| 93 | + .Workspace(ws_size) | ||
| 94 | + .Build(); | ||
| 95 | + gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>(); | ||
| 96 | + ASSERT_NE(tiling_context, nullptr); | ||
| 97 | + EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS); | ||
| 98 | +} | ||
| 99 | + | ||
| 100 | +TEST_F(SwishTiling, swish_float16_success) { | ||
| 101 | + gert::StorageShape x_shape = {{1, 2, 8, 16}, {1, 2, 8, 16}}; | ||
| 102 | + gert::StorageShape y_shape = {{1, 2, 8, 16}, {1, 2, 8, 16}}; | ||
| 103 | + string compile_info_string = R"({ | ||
| 104 | + "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1", | ||
| 105 | + "Intrinsic_fix_pipe_l0c2out": false, "Intrinsic_data_move_l12ub": true, "Intrinsic_data_move_l0c2ub": true, "Intrinsic_data_move_out2l1_nd2nz": false, | ||
| 106 | + "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288, | ||
| 107 | + "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072, | ||
| 108 | + "CORE_NUM": 48} | ||
| 109 | + })"; | ||
| 110 | + map<string, string> soc_infos; | ||
| 111 | + map<string, string> aicore_spec; | ||
| 112 | + map<string, string> intrinsics; | ||
| 113 | + GetPlatFormInfos(compile_info_string.c_str(), soc_infos, aicore_spec, intrinsics); | ||
| 114 | + | ||
| 115 | + fe::PlatFormInfos platform_info; | ||
| 116 | + platform_info.Init(); | ||
| 117 | + | ||
| 118 | + struct SwishCompileInfo {}; | ||
| 119 | + SwishCompileInfo compile_info; | ||
| 120 | + | ||
| 121 | + std::string op_type("Swish"); | ||
| 122 | + auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling; | ||
| 123 | + | ||
| 124 | + auto kernel_holder = | ||
| 125 | + gert::KernelRunContextFaker() | ||
| 126 | + .KernelIONum(3, 1) | ||
| 127 | + .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)}) | ||
| 128 | + .Outputs({&compile_info}) | ||
| 129 | + .Build(); | ||
| 130 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos); | ||
| 131 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec); | ||
| 132 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore"); | ||
| 133 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", | ||
| 134 | + intrinsics); | ||
| 135 | + | ||
| 136 | + auto param = gert::TilingData::CreateCap(4096); | ||
| 137 | + auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(4096); | ||
| 138 | + auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get()); | ||
| 139 | + ASSERT_NE(param, nullptr); | ||
| 140 | + auto holder = gert::TilingContextFaker() | ||
| 141 | + .SetOpType("Swish") | ||
| 142 | + .NodeIoNum(1, 1) | ||
| 143 | + .IrInstanceNum({1}) | ||
| 144 | + .InputShapes({&x_shape}) | ||
| 145 | + .OutputShapes({&y_shape}) | ||
| 146 | + .CompileInfo(&compile_info) | ||
| 147 | + .PlatformInfo(reinterpret_cast<char*>(&platform_info)) | ||
| 148 | + .NodeAttrs({{"scale", Ops::NN::AnyValue::CreateFrom<float>(1.0f)}}) | ||
| 149 | + .NodeInputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 150 | + .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 151 | + .TilingData(param.get()) | ||
| 152 | + .Workspace(ws_size) | ||
| 153 | + .Build(); | ||
| 154 | + gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>(); | ||
| 155 | + ASSERT_NE(tiling_context, nullptr); | ||
| 156 | + EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS); | ||
| 157 | +} | ||
experimental/activation/swish/op_graph/swish_proto.h此评论由代码审查工具自动生成