已合并
【CANN训练营第二季社区任务】Mish算子开发-算子提交 #490
wenyidylan创建于 2025年12月24日
【CANN训练营第二季社区任务】Mish算子开发-算子提交 #490
已合并
共 23 个文件变更+1774-0
| @@ -0,0 +1,19 @@ | |||
| 1 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 2 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 3 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 4 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 5 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 6 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +#/ | ||
| 9 | + | ||
| 10 | +message(STATUS "=== Debug: start ops.activation.mish.CMakeLists.txt ") | ||
| 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,71 @@ | |||
| 1 | +# Mish | ||
| 2 | + | ||
| 3 | +## 产品支持情况 | ||
| 4 | + | ||
| 5 | +| 产品 | 是否支持 | | ||
| 6 | +| :----------------------------------------------------------- | :------: | | ||
| 7 | +| <term>Atlas A2 训练系列产品/Atlas 800I A2推理产品</term> | √ | | ||
| 8 | + | ||
| 9 | +## 功能说明 | ||
| 10 | + | ||
| 11 | +- 算子功能:逐元素计算张量的Mish激活函数。 | ||
| 12 | +- SUPER_PERFORMANCE模式的计算公式为: | ||
| 13 | +$$y = x*(1-2/(1+(1+(1+x/64)^{64})^2))$$ | ||
| 14 | +其他模式的计算公式为: | ||
| 15 | +$$y = | ||
| 16 | +\begin{cases} | ||
| 17 | +x*(2e^{-x} + 1) / (2e^{-2x} + 2e^{-x} + 1), & \text{if $x > 0$} \\ | ||
| 18 | +x*(2e^x + e^{2x}) / (2 + 2e^x + e^{2x}), & \text{if $x \leq 0$} | ||
| 19 | +\end{cases}$$ | ||
| 20 | + | ||
| 21 | +## 参数说明 | ||
| 22 | + | ||
| 23 | +<table style="undefined;table-layout: fixed; width: 820px"><colgroup> | ||
| 24 | + <col style="width: 100px"> | ||
| 25 | + <col style="width: 150px"> | ||
| 26 | + <col style="width: 190px"> | ||
| 27 | + <col style="width: 260px"> | ||
| 28 | + <col style="width: 120px"> | ||
| 29 | + </colgroup> | ||
| 30 | + <thead> | ||
| 31 | + <tr> | ||
| 32 | + <th>参数名</th> | ||
| 33 | + <th>输入/输出/属性</th> | ||
| 34 | + <th>描述</th> | ||
| 35 | + <th>数据类型</th> | ||
| 36 | + <th>数据格式</th> | ||
| 37 | + </tr></thead> | ||
| 38 | + <tbody> | ||
| 39 | + <tr> | ||
| 40 | + <td>x</td> | ||
| 41 | + <td>输入</td> | ||
| 42 | + <td>公式中的输入张量x</td> | ||
| 43 | + <td>FLOAT、FLOAT16、BFLOAT16</td> | ||
| 44 | + <td>ND</td> | ||
| 45 | + </tr> | ||
| 46 | + <tr> | ||
| 47 | + <td>y</td> | ||
| 48 | + <td>输出</td> | ||
| 49 | + <td>公式中的输出张量y</td> | ||
| 50 | + <td>FLOAT、FLOAT16、BFLOAT16</td> | ||
| 51 | + <td>ND</td> | ||
| 52 | + </tr> | ||
| 53 | + </tbody></table> | ||
| 54 | + | ||
| 55 | +## 约束说明 | ||
| 56 | + | ||
| 57 | + | ||
| 58 | +## 调用说明 | ||
| 59 | + | ||
| 60 | +| 调用方式 | 调用样例 | 说明 | | ||
| 61 | +|--------------|------------------------------------------------------------------------|----------------------------------------------------------------| | ||
| 62 | +| aclnn调用 | [test_aclnn_mish](./examples/test_aclnn_mish.cpp) | 通过aclnnMish接口方式调用Mish算子。 | | ||
| 63 | + | ||
| 64 | + | ||
| 65 | +## 贡献说明 | ||
| 66 | + | ||
| 67 | +| 贡献者 | 贡献方 | 贡献算子 | 贡献时间 | 贡献内容 | | ||
| 68 | +| ---- | ---- | ---- | ---- | ---- | | ||
| 69 | +| 闻毅 | 个人开发者 | Mish | 2025/12/23 | Mish算子适配开源仓 | | ||
| 70 | + | ||
| 71 | + | ||
| @@ -0,0 +1,119 @@ | |||
| 1 | + | ||
| 2 | + | ||
| 3 | + | ||
| 4 | + | ||
| 5 | + | ||
| 6 | + | ||
| 7 | + do { \ | ||
| 8 | + if (!(cond)) { \ | ||
| 9 | + return_expr; \ | ||
| 10 | + } \ | ||
| 11 | + } while (0) | ||
| 12 | + | ||
| 13 | + do { \ | ||
| 14 | + printf(message, ##__VA_ARGS__); \ | ||
| 15 | + } while (0) | ||
| 16 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 17 | + int64_t shapeSize = 1; | ||
| 18 | + for (auto i : shape) { | ||
| 19 | + shapeSize *= i; | ||
| 20 | + } | ||
| 21 | + return shapeSize; | ||
| 22 | +} | ||
| 23 | +int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 24 | + // 固定写法,资源初始化 | ||
| 25 | + auto ret = aclInit(nullptr); | ||
| 26 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 27 | + ret = aclrtSetDevice(deviceId); | ||
| 28 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 29 | + ret = aclrtCreateStream(stream); | ||
| 30 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 31 | + return 0; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +template <typename T> | ||
| 35 | +int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 36 | + aclDataType dataType, aclTensor** tensor) { | ||
| 37 | + auto size = GetShapeSize(shape) * sizeof(T); | ||
| 38 | + // 调用aclrtMalloc申请device侧内存 | ||
| 39 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 40 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 41 | + // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上 | ||
| 42 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 43 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 44 | + // 计算连续tensor的strides | ||
| 45 | + std::vector<int64_t> strides(shape.size(), 1); | ||
| 46 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 47 | + strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 48 | + } | ||
| 49 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 50 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 51 | + shape.data(), shape.size(), *deviceAddr); | ||
| 52 | + return 0; | ||
| 53 | +} | ||
| 54 | +int main() { | ||
| 55 | + // 1. (固定写法)device/stream初始化,参考acl API手册 | ||
| 56 | + // 根据自己的实际device填写deviceId | ||
| 57 | + int32_t deviceId = 0; | ||
| 58 | + aclrtStream stream; | ||
| 59 | + auto ret = Init(deviceId, &stream); | ||
| 60 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 61 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 62 | + std::vector<int64_t> selfShape = {2, 2}; | ||
| 63 | + std::vector<int64_t> outShape = {2, 2}; | ||
| 64 | + void* selfDeviceAddr = nullptr; | ||
| 65 | + void* outDeviceAddr = nullptr; | ||
| 66 | + aclTensor* self = nullptr; | ||
| 67 | + aclTensor* out = nullptr; | ||
| 68 | + std::vector<float> selfHostData = {0, 1, 2, 3}; | ||
| 69 | + std::vector<float> outHostData = {0, 0, 0, 0}; | ||
| 70 | + // 创建self aclTensor | ||
| 71 | + ret = CreateAclTensor(selfHostData, selfShape, &selfDeviceAddr, aclDataType::ACL_FLOAT, &self); | ||
| 72 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 73 | + // 创建out aclTensor | ||
| 74 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 75 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 76 | + // 3. 调用CANN算子库API,需要修改为具体的API名称 | ||
| 77 | + // aclnnMish接口调用示例 | ||
| 78 | + uint64_t workspaceSize = 0; | ||
| 79 | + aclOpExecutor* executor; | ||
| 80 | + // 调用aclnnMish第一段接口 | ||
| 81 | + ret = aclnnMishGetWorkspaceSize(self, out, &workspaceSize, &executor); | ||
| 82 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMishGetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 83 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 84 | + void* workspaceAddr = nullptr; | ||
| 85 | + if (workspaceSize > 0) { | ||
| 86 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 87 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret); | ||
| 88 | + } | ||
| 89 | + // 调用aclnnMish第二段接口 | ||
| 90 | + ret = aclnnMish(workspaceAddr, workspaceSize, executor, stream); | ||
| 91 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnMish failed. ERROR: %d\n", ret); return ret); | ||
| 92 | + // 4. (固定写法)同步等待任务执行结束 | ||
| 93 | + ret = aclrtSynchronizeStream(stream); | ||
| 94 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 95 | + | ||
| 96 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 97 | + auto size = GetShapeSize(outShape); | ||
| 98 | + std::vector<float> resultData(size, 0); | ||
| 99 | + ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, | ||
| 100 | + size * sizeof(resultData[0]), ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 101 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 102 | + for (int64_t i = 0; i < size; i++) { | ||
| 103 | + LOG_PRINT("aclnnMish result[%ld] is: %f\n", i, resultData[i]); | ||
| 104 | + } | ||
| 105 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 106 | + aclDestroyTensor(self); | ||
| 107 | + aclDestroyTensor(out); | ||
| 108 | + | ||
| 109 | + // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 110 | + aclrtFree(selfDeviceAddr); | ||
| 111 | + aclrtFree(outDeviceAddr); | ||
| 112 | + if (workspaceSize > 0) { | ||
| 113 | + aclrtFree(workspaceAddr); | ||
| 114 | + } | ||
| 115 | + aclrtDestroyStream(stream); | ||
| 116 | + aclrtResetDevice(deviceId); | ||
| 117 | + aclFinalize(); | ||
| 118 | + return 0; | ||
| 119 | +} | ||
| @@ -0,0 +1,10 @@ | |||
| 1 | +# This program is free software, you can redistribute it and/or modify it. | ||
| 2 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 3 | +# This file is a part of the CANN Open Software. | ||
| 4 | +# Licensed under 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 mish ACLNNTYPE aclnn_exclude) | ||
| @@ -0,0 +1,36 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +*/ | ||
| 9 | + | ||
| 10 | +/*! | ||
| 11 | + * \file mish_def.cpp | ||
| 12 | + * \brief | ||
| 13 | +*/ | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +namespace ops { | ||
| 17 | +class Mish : public OpDef { | ||
| 18 | +public: | ||
| 19 | + explicit Mish(const char* name) : OpDef(name) | ||
| 20 | + { | ||
| 21 | + this->Input("x") | ||
| 22 | + .ParamType(REQUIRED) | ||
| 23 | + .DataType({ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16}) | ||
| 24 | + .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 25 | + .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}); | ||
| 26 | + this->Output("y") | ||
| 27 | + .ParamType(REQUIRED) | ||
| 28 | + .DataType({ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16}) | ||
| 29 | + .Format({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 30 | + .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND}); | ||
| 31 | + | ||
| 32 | + this->AICore().AddConfig("ascend910b"); | ||
| 33 | + } | ||
| 34 | +}; | ||
| 35 | +OP_ADD(Mish); // 添加算子信息库 | ||
| 36 | +} // namespace ops | ||
| @@ -0,0 +1,41 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +*/ | ||
| 9 | + | ||
| 10 | +/*! | ||
| 11 | + * \file mish_infershape.cpp | ||
| 12 | + * \brief | ||
| 13 | +*/ | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +using namespace ge; | ||
| 18 | + | ||
| 19 | +namespace ops { | ||
| 20 | +static constexpr int64_t IDX_0 = 0; | ||
| 21 | + | ||
| 22 | +static ge::graphStatus InferShapeMish(gert::InferShapeContext* context) | ||
| 23 | +{ | ||
| 24 | + OP_CHECK_IF(context == nullptr, OP_LOGE(context, "context is nullptr"), return ge::GRAPH_FAILED); | ||
| 25 | + OP_LOGD(context->GetNodeName(), "Begin to do InferShapeMish"); | ||
| 26 | + | ||
| 27 | + // get input shapes | ||
| 28 | + const gert::Shape* xShape = context->GetInputShape(IDX_0); | ||
| 29 | + OP_CHECK_NULL_WITH_CONTEXT(context, xShape); | ||
| 30 | + | ||
| 31 | + // get output shapes | ||
| 32 | + gert::Shape* yShape = context->GetOutputShape(IDX_0); | ||
| 33 | + OP_CHECK_NULL_WITH_CONTEXT(context, yShape); | ||
| 34 | + | ||
| 35 | + *yShape = *xShape; | ||
| 36 | + OP_LOGD(context->GetNodeName(), "End to do InferShapeMish"); | ||
| 37 | + return GRAPH_SUCCESS; | ||
| 38 | +} | ||
| 39 | + | ||
| 40 | +IMPL_OP_INFERSHAPE(Mish).InferShape(InferShapeMish); | ||
| 41 | +} | ||
| @@ -0,0 +1,184 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +*/ | ||
| 9 | + | ||
| 10 | +/*! | ||
| 11 | + * \file mish_tiling.cpp | ||
| 12 | + * \brief | ||
| 13 | + */ | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +namespace optiling { | ||
| 25 | + | ||
| 26 | +using namespace Ops::NN::OpTiling; | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +constexpr uint32_t BUFFER_NUM = 2; | ||
| 34 | +constexpr uint32_t WS_SYS_SIZE = 0; | ||
| 35 | +struct MishCompileInfo {}; | ||
| 36 | + | ||
| 37 | +static ge::graphStatus TilingParseForMish([[maybe_unused]] gert::TilingParseContext* context) | ||
| 38 | +{ | ||
| 39 | + OP_CHECK_IF(context == nullptr, OP_LOGE(context, "context is nullptr"), return ge::GRAPH_FAILED); | ||
| 40 | + return ge::GRAPH_SUCCESS; | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +static ge::graphStatus GetPlatformInfo(gert::TilingContext* context, uint64_t& ubSize, int64_t& coreNum) | ||
| 44 | +{ | ||
| 45 | + OP_CHECK_IF(context == nullptr, OP_LOGE(context, "context is nullptr"), return ge::GRAPH_FAILED); | ||
| 46 | + // 获取ubsize coreNum | ||
| 47 | + OP_CHECK_IF(context->GetPlatformInfo() == nullptr, OP_LOGE(context, "context is nullptr"), return ge::GRAPH_FAILED); | ||
| 48 | + auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); | ||
context->GetPlatformInfo()需要判空 OP_CHECK_IF(context->GetPlatformInfo() == nullptr, OP_LOGE(context, "context is nullptr"), return ge::GRAPH_FAILED); ![]() ![]() | |||
| 49 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSize); | ||
| 50 | + coreNum = ascendcPlatform.GetCoreNum(); | ||
| 51 | + OP_CHECK_IF(coreNum <= 0, OP_LOGE(context, "coreNum is 0"), return ge::GRAPH_FAILED); | ||
| 52 | + OP_CHECK_IF(ubSize <= 0, OP_LOGE(context, "ubSize is 0"), return ge::GRAPH_FAILED); | ||
| 53 | + return ge::GRAPH_SUCCESS; | ||
| 54 | +} | ||
| 55 | +static ge::graphStatus GetWorkspaceSize(gert::TilingContext* context) | ||
| 56 | +{ | ||
| 57 | + OP_CHECK_IF(context == nullptr, OP_LOGE(context, "context is nullptr"), return ge::GRAPH_FAILED); | ||
| 58 | + size_t usrSize = 0; | ||
| 59 | + auto ascendcPlatform = platform_ascendc::PlatformAscendC(context->GetPlatformInfo()); | ||
| 60 | + uint32_t sysWorkspaceSize = ascendcPlatform.GetLibApiWorkSpaceSize(); | ||
| 61 | + size_t* currentWorkspace = context->GetWorkspaceSizes( | ||
| 62 | + 1); // 通过框架获取workspace的指针,GetWorkspaceSizes入参为所需workspace的块数。当前限制使用一块。 | ||
| 63 | + currentWorkspace[0] = usrSize + sysWorkspaceSize; | ||
| 64 | + return ge::GRAPH_SUCCESS; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +static ge::graphStatus GetShapeAttrsInfo( | ||
| 68 | + gert::TilingContext* context, uint64_t ubSize, uint64_t& inputNum, uint64_t& inputBytes, uint64_t& tileBlockNum, | ||
| 69 | + uint64_t& tileDataNum, uint64_t& inputLengthAlgin32) | ||
| 70 | +{ | ||
| 71 | + OP_CHECK_IF( | ||
| 72 | + context == nullptr || context->GetInputShape(0) == nullptr, OP_LOGE(context, "context is nullptr"), | ||
| 73 | + return ge::GRAPH_FAILED); | ||
| 74 | + inputNum = context->GetInputShape(0)->GetStorageShape().GetShapeSize(); | ||
| 75 | + uint32_t typeLength = 0; | ||
| 76 | + ge::TypeUtils::GetDataTypeLength(context->GetInputDesc(0)->GetDataType(), typeLength); | ||
| 77 | + uint64_t inputLength = inputNum * typeLength; | ||
| 78 | + if (inputNum == 0) { | ||
异常返回,添加打印 ![]() ![]() | |||
| 79 | + OP_LOGE(context, "inputNum is 0"); | ||
| 80 | + return ge::GRAPH_FAILED; | ||
| 81 | + } | ||
| 82 | + inputBytes = inputLength / inputNum; | ||
| 83 | + uint64_t ubDataNumber = | ||
| 84 | + (context->GetInputDesc(0)->GetDataType() == ge::DT_FLOAT) ? UB_DATA_NUM_FLOAT : UB_DATA_NUM_OTHER; | ||
| 85 | + tileBlockNum = (ubSize / BLOCK_SIZE) / ubDataNumber; | ||
| 86 | + if (inputBytes == 0) { | ||
异常返回,添加打印 ![]() ![]() | |||
| 87 | + OP_LOGE(context, "inputBytes is 0"); | ||
| 88 | + return ge::GRAPH_FAILED; | ||
| 89 | + } | ||
| 90 | + tileBlockNum = tileBlockNum <= BLOCK_ALIGN_NUM ? tileBlockNum : tileBlockNum / BLOCK_ALIGN_NUM * BLOCK_ALIGN_NUM; | ||
| 91 | + tileDataNum = (tileBlockNum * BLOCK_SIZE) / inputBytes; | ||
| 92 | + inputLengthAlgin32 = (((inputLength + BLOCK_SIZE - 1) / BLOCK_SIZE) * BLOCK_SIZE); | ||
| 93 | + return ge::GRAPH_SUCCESS; | ||
| 94 | +} | ||
| 95 | + | ||
| 96 | +static ge::graphStatus CalculateCoreBlockNums( | ||
| 97 | + gert::TilingContext* context, | ||
| 98 | + uint64_t inputLengthAlgin32, int64_t coreNum, uint64_t tileBlockNum, uint64_t inputBytes, uint64_t tileDataNum, | ||
| 99 | + uint64_t& smallCoreDataNum, uint64_t& bigCoreDataNum, uint64_t& smallTailDataNum, uint64_t& bigTailDataNum, | ||
| 100 | + uint64_t& finalSmallTileNum, uint64_t& finalBigTileNum, uint64_t& tailBlockNum) | ||
| 101 | +{ | ||
| 102 | + if (0 == BLOCK_SIZE || 0 == coreNum || 0 == tileBlockNum || 0 == inputBytes) { | ||
异常返回,添加打印 ![]() ![]() | |||
| 103 | + OP_LOGE(context, "BLOCK_SIZE is 0 or coreNum is 0 or tileBlockNum is 0 or inputBytes is 0"); | ||
| 104 | + return ge::GRAPH_FAILED; | ||
| 105 | + } | ||
| 106 | + uint64_t everyCoreInputBlockNum = inputLengthAlgin32 / BLOCK_SIZE / coreNum; | ||
| 107 | + tailBlockNum = (inputLengthAlgin32 / BLOCK_SIZE) % coreNum; | ||
| 108 | + smallCoreDataNum = everyCoreInputBlockNum * BLOCK_SIZE / inputBytes; | ||
| 109 | + uint64_t smallTileNum = everyCoreInputBlockNum / tileBlockNum; | ||
| 110 | + finalSmallTileNum = (everyCoreInputBlockNum % tileBlockNum) == 0 ? smallTileNum : smallTileNum + 1; | ||
| 111 | + smallTailDataNum = smallCoreDataNum - (tileDataNum * smallTileNum); | ||
| 112 | + smallTailDataNum = smallTailDataNum == 0 ? tileDataNum : smallTailDataNum; | ||
| 113 | + | ||
| 114 | + everyCoreInputBlockNum += 1; | ||
| 115 | + bigCoreDataNum = everyCoreInputBlockNum * BLOCK_SIZE / inputBytes; | ||
| 116 | + uint64_t bigTileNum = everyCoreInputBlockNum / tileBlockNum; | ||
| 117 | + finalBigTileNum = (everyCoreInputBlockNum % tileBlockNum) == 0 ? bigTileNum : bigTileNum + 1; | ||
| 118 | + bigTailDataNum = bigCoreDataNum - tileDataNum * bigTileNum; | ||
| 119 | + bigTailDataNum = bigTailDataNum == 0 ? tileDataNum : bigTailDataNum; | ||
| 120 | + | ||
| 121 | + return ge::GRAPH_SUCCESS; | ||
| 122 | +} | ||
| 123 | + | ||
| 124 | +static ge::graphStatus MishTilingFunc(gert::TilingContext* context) | ||
| 125 | +{ | ||
| 126 | + // MishTilingData tiling; | ||
| 127 | + MishTilingData* tiling = context->GetTilingData<MishTilingData>(); | ||
| 128 | + OP_CHECK_NULL_WITH_CONTEXT(context, tiling); | ||
| 129 | + OP_CHECK_IF( | ||
| 130 | + memset_s(tiling, sizeof(MishTilingData), 0, sizeof(MishTilingData)) != EOK, | ||
| 131 | + OP_LOGE(context, "set tiling data error"), return ge::GRAPH_FAILED); | ||
| 132 | + // 获取平台运行信息 | ||
| 133 | + uint64_t ubSize; | ||
| 134 | + int64_t coreNum; | ||
| 135 | + int64_t usedcoreNum; | ||
| 136 | + ge::graphStatus ret = GetPlatformInfo(context, ubSize, coreNum); | ||
| 137 | + OP_CHECK_IF(ret != ge::GRAPH_SUCCESS, OP_LOGE(context, "GetPlatformInfo error"), return ge::GRAPH_FAILED); | ||
| 138 | + // 获取输入数据信息 | ||
| 139 | + uint64_t inputNum, inputBytes, tileBlockNum, tileDataNum, inputLengthAlgin32; | ||
| 140 | + ret = GetShapeAttrsInfo(context, ubSize, inputNum, inputBytes, tileBlockNum, tileDataNum, inputLengthAlgin32); | ||
| 141 | + OP_CHECK_IF(ret != ge::GRAPH_SUCCESS, OP_LOGE(context, "GetShapeAttrsInfo error"), return ge::GRAPH_FAILED); | ||
| 142 | + | ||
| 143 | + // 计算coreNum | ||
| 144 | + if (OPT_CORE_SIZE >= inputNum) { | ||
| 145 | + usedcoreNum = 1; | ||
| 146 | + } else { | ||
| 147 | + usedcoreNum = inputNum / OPT_CORE_SIZE > coreNum ? coreNum : inputNum / OPT_CORE_SIZE; | ||
| 148 | + if(inputNum % OPT_CORE_SIZE > 0) { | ||
| 149 | + if(usedcoreNum < coreNum) { | ||
| 150 | + usedcoreNum += 1; | ||
| 151 | + } | ||
| 152 | + } | ||
| 153 | + } | ||
| 154 | + // 计算每个core处理的数据块数 | ||
| 155 | + uint64_t smallCoreDataNum, bigCoreDataNum, smallTailDataNum, bigTailDataNum; | ||
| 156 | + uint64_t finalSmallTileNum, finalBigTileNum, tailBlockNum; | ||
| 157 | + ret = CalculateCoreBlockNums( | ||
| 158 | + context, | ||
| 159 | + inputLengthAlgin32, usedcoreNum, tileBlockNum, inputBytes, tileDataNum, smallCoreDataNum, bigCoreDataNum, | ||
| 160 | + smallTailDataNum, bigTailDataNum, finalSmallTileNum, finalBigTileNum, tailBlockNum); | ||
| 161 | + OP_CHECK_IF(ret != ge::GRAPH_SUCCESS, OP_LOGE(context, "CalculateCoreBlockNums error"), return ge::GRAPH_FAILED); | ||
| 162 | + // 设置tiling数据 | ||
| 163 | + tiling->smallCoreDataNum = static_cast<uint64_t>(smallCoreDataNum); | ||
| 164 | + tiling->bigCoreDataNum = static_cast<uint64_t>(bigCoreDataNum); | ||
| 165 | + tiling->tileDataNum = static_cast<uint64_t>(tileDataNum); | ||
| 166 | + tiling->smallTailDataNum = static_cast<uint64_t>(smallTailDataNum); | ||
| 167 | + tiling->bigTailDataNum = static_cast<uint64_t>(bigTailDataNum); | ||
| 168 | + tiling->finalSmallTileNum = static_cast<uint64_t>(finalSmallTileNum); | ||
| 169 | + tiling->finalBigTileNum = static_cast<uint64_t>(finalBigTileNum); | ||
| 170 | + tiling->tailBlockNum = static_cast<uint64_t>(tailBlockNum); | ||
| 171 | + // 计算workspace大小 | ||
| 172 | + OP_CHECK_IF( | ||
| 173 | + GetWorkspaceSize(context) != ge::GRAPH_SUCCESS, OP_LOGE(context, "GetWorkspaceSize error"), | ||
| 174 | + return ge::GRAPH_FAILED); | ||
| 175 | + uint64_t tilingKey = 0; | ||
| 176 | + tilingKey = GET_TPL_TILING_KEY(0); | ||
| 177 | + context->SetTilingKey(tilingKey); | ||
| 178 | + context->SetBlockDim(usedcoreNum); | ||
| 179 | + return ge::GRAPH_SUCCESS; | ||
| 180 | +} | ||
| 181 | + | ||
| 182 | +// tiling注册入口. | ||
| 183 | +IMPL_OP_OPTILING(Mish).Tiling(MishTilingFunc).TilingParse<MishCompileInfo>(TilingParseForMish); | ||
| 184 | +} // namespace optiling | ||
| @@ -0,0 +1,123 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +*/ | ||
| 9 | + | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +using namespace op; | ||
| 25 | + | ||
| 26 | + | ||
| 27 | +extern "C" { | ||
| 28 | + | ||
| 29 | + | ||
| 30 | +static const std::initializer_list<DataType> ASCEND910_DTYPE_SUPPORT_LIST = { | ||
| 31 | + DataType::DT_FLOAT, DataType::DT_FLOAT16}; | ||
| 32 | + | ||
| 33 | +static const std::initializer_list<DataType> ASCEND910B_DTYPE_SUPPORT_LIST = { | ||
| 34 | + DataType::DT_FLOAT, DataType::DT_FLOAT16, DataType::DT_BF16}; | ||
| 35 | + | ||
| 36 | +static bool CheckDtypeValid(const aclTensor* self, const aclTensor* out) { | ||
| 37 | + // 检查self的数据类型是否在支持列表内 | ||
| 38 | + auto supportList = GetDtypeSupportListV2(ASCEND910B_DTYPE_SUPPORT_LIST, ASCEND910_DTYPE_SUPPORT_LIST); | ||
| 39 | + OP_CHECK_DTYPE_NOT_SUPPORT(self, supportList, return false); | ||
| 40 | + OP_CHECK_DTYPE_NOT_SUPPORT(out, supportList, return false); | ||
| 41 | + // 检查self和out的数据类型是否相等 | ||
| 42 | + OP_CHECK_DTYPE_NOT_SAME(self, out, return false); | ||
| 43 | + return true; | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +static bool CheckShape(const aclTensor* self, const aclTensor* out) { | ||
| 47 | + OP_CHECK_MAX_DIM(self, MAX_SUPPORT_DIMS_NUMS, return false); | ||
| 48 | + OP_CHECK_MAX_DIM(out, MAX_SUPPORT_DIMS_NUMS, return false); | ||
| 49 | + // 输入和输出的shape必须一致 | ||
| 50 | + OP_CHECK_SHAPE_NOT_EQUAL(out, self, return false); | ||
| 51 | + return true; | ||
| 52 | +} | ||
| 53 | + | ||
| 54 | +static aclnnStatus CheckParams(const aclTensor* self, const aclTensor* out) { | ||
| 55 | + // 1. 检查参数是否为空指针 | ||
| 56 | + CHECK_RET(CheckNotNull2Tensor(self, out), ACLNN_ERR_PARAM_NULLPTR); | ||
| 57 | + | ||
| 58 | + // 2. 检查输入的数据类型是否在API支持的数据类型范围内,需要根据api定义校验 | ||
| 59 | + CHECK_RET(CheckDtypeValid(self, out), ACLNN_ERR_PARAM_INVALID); | ||
| 60 | + | ||
| 61 | + // 3. 检查shape是否满足约束 | ||
| 62 | + CHECK_RET(CheckShape(self, out), ACLNN_ERR_PARAM_INVALID); | ||
| 63 | + | ||
| 64 | + return ACLNN_SUCCESS; | ||
| 65 | +} | ||
| 66 | + | ||
| 67 | +aclnnStatus aclnnMishGetWorkspaceSize(const aclTensor* self, aclTensor* out, uint64_t* workspaceSize, | ||
| 68 | + aclOpExecutor** executor) { | ||
| 69 | + L2_DFX_PHASE_1(aclnnMish, DFX_IN(self), DFX_OUT(out)); | ||
| 70 | + | ||
| 71 | + // 固定写法,创建OpExecutor | ||
| 72 | + auto uniqueExecutor = CREATE_EXECUTOR(); | ||
| 73 | + CHECK_RET(uniqueExecutor.get() != nullptr, ACLNN_ERR_INNER_CREATE_EXECUTOR); | ||
| 74 | + | ||
| 75 | + // 固定写法,参数检查 | ||
| 76 | + auto ret = CheckParams(self, out); | ||
| 77 | + CHECK_RET(ret == ACLNN_SUCCESS, ret); | ||
| 78 | + | ||
| 79 | + // 空Tensor处理 | ||
| 80 | + if (self->IsEmpty()) { | ||
| 81 | + *workspaceSize = 0; | ||
| 82 | + uniqueExecutor.ReleaseTo(executor); | ||
| 83 | + return ACLNN_SUCCESS; | ||
| 84 | + } | ||
| 85 | + | ||
| 86 | + // self如果非连续,需要转换 | ||
| 87 | + auto selfContiguous = l0op::Contiguous(self, uniqueExecutor.get()); | ||
| 88 | + CHECK_RET(selfContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 89 | + | ||
| 90 | + // 调用l0算子进行计算 | ||
| 91 | + auto mishResult = l0op::Mish(selfContiguous, uniqueExecutor.get()); | ||
| 92 | + CHECK_RET(mishResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 93 | + | ||
| 94 | + // 如果出参out是非连续Tensor,需要把计算完的连续Tensor转非连续 | ||
| 95 | + auto viewCopyResult = l0op::ViewCopy(mishResult, out, uniqueExecutor.get()); | ||
| 96 | + CHECK_RET(viewCopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR); | ||
| 97 | + | ||
| 98 | + // 固定写法,获取计算过程中需要使用的workspace大小 | ||
| 99 | + *workspaceSize = uniqueExecutor->GetWorkspaceSize(); | ||
| 100 | + uniqueExecutor.ReleaseTo(executor); | ||
| 101 | + return ACLNN_SUCCESS; | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +aclnnStatus aclnnMish(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream) { | ||
| 105 | + L2_DFX_PHASE_2(aclnnMish); | ||
| 106 | + | ||
| 107 | + return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); | ||
| 108 | +} | ||
| 109 | + | ||
| 110 | +aclnnStatus aclnnInplaceMishGetWorkspaceSize(aclTensor *selfRef, uint64_t *workspaceSize, aclOpExecutor **executor) { | ||
| 111 | + L2_DFX_PHASE_1(aclnnInplaceMish, DFX_IN(selfRef), DFX_OUT(selfRef)); | ||
| 112 | + return aclnnMishGetWorkspaceSize(selfRef, selfRef, workspaceSize, executor); | ||
| 113 | +} | ||
| 114 | + | ||
| 115 | +aclnnStatus aclnnInplaceMish(void *workspace, uint64_t workspaceSize, aclOpExecutor *executor, aclrtStream stream) { | ||
| 116 | + L2_DFX_PHASE_2(aclnnInplaceMish); | ||
| 117 | + // 调用框架能力,完成计算 | ||
| 118 | + return CommonOpExecutorRun(workspace, workspaceSize, executor, stream); | ||
| 119 | +} | ||
| 120 | + | ||
| 121 | + | ||
| 122 | +} | ||
| 123 | + | ||
| @@ -0,0 +1,81 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +*/ | ||
| 9 | + | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +extern "C" { | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * @brief aclnnMish的第一段接口,根据具体的计算流程,计算workspace大小。 | ||
| 21 | + * @domain aclnn_ops_infer | ||
| 22 | + * | ||
| 23 | + * 算子功能:一个自正则化的非单调神经网络激活函数。 | ||
| 24 | + * | ||
| 25 | + * @param [in] self: npu device侧的aclTensor,数据类型支持FLOAT16、BFLOAT16、FLOAT。支持非连续的Tensor,数据格式支持ND。 | ||
| 26 | + * @param [in] out: npu | ||
| 27 | + * device侧的aclTensor,数据类型支持FLOAT16、BFLOAT16、FLOAT。它的shape与self相同,且数据类型需要与self一致,数据格式支持ND。 | ||
| 28 | + * @param [out] workspaceSize: 返回用户需要在npu device侧申请的workspace大小。 | ||
| 29 | + * @param [out] executor: 返回op执行器,包含算子计算流程。 | ||
| 30 | + * @return aclnnStatus: 返回状态码。 | ||
| 31 | + */ | ||
| 32 | +ACLNN_API aclnnStatus aclnnMishGetWorkspaceSize(const aclTensor* self, aclTensor* out, uint64_t* workspaceSize, | ||
| 33 | + aclOpExecutor** executor); | ||
| 34 | + | ||
| 35 | +/** | ||
| 36 | + * @brief aclnnMish的第二段接口,用于执行计算。 | ||
| 37 | + * | ||
| 38 | + * 算子功能:一个自正则化的非单调神经网络激活函数。 | ||
| 39 | + * | ||
| 40 | + * @param [in] workspace: 在npu device侧申请的workspace内存起址。 | ||
| 41 | + * @param [in] workspaceSize: 在npu device侧申请的workspace大小,由第一段接口aclnnMishGetWorkspaceSize获取。 | ||
| 42 | + * @param [in] executor: op执行器,包含了算子计算流程。 | ||
| 43 | + * @param [in] stream: acl stream流。 | ||
| 44 | + * @return aclnnStatus: 返回状态码。 | ||
| 45 | + */ | ||
| 46 | +ACLNN_API aclnnStatus aclnnMish(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream); | ||
| 47 | + | ||
| 48 | +/** | ||
| 49 | + * @brief aclnnInplaceMish的第一段接口,根据具体的计算流程,计算workspace大小。 | ||
| 50 | + * @domain aclnn_ops_infer | ||
| 51 | + * | ||
| 52 | + * 算子功能:一个自正则化的非单调神经网络激活函数。 | ||
| 53 | + * | ||
| 54 | + * @param [in] selfRef: npu | ||
| 55 | + * device侧的aclTensor,数据类型支持FLOAT16、BFLOAT16、FLOAT。支持非连续的Tensor,数据格式支持ND。 | ||
| 56 | + * @param [out] workspaceSize: 返回用户需要在npu device侧申请的workspace大小。 | ||
| 57 | + * @param [out] executor: 返回op执行器,包含算子计算流程。 | ||
| 58 | + * @return aclnnStatus: 返回状态码。 | ||
| 59 | + */ | ||
| 60 | +ACLNN_API aclnnStatus aclnnInplaceMishGetWorkspaceSize(aclTensor* selfRef, uint64_t* workspaceSize, | ||
| 61 | + aclOpExecutor** executor); | ||
| 62 | + | ||
| 63 | +/** | ||
| 64 | + * @brief aclnnInplaceMish的第二段接口,用于执行计算。 | ||
| 65 | + * | ||
| 66 | + * 算子功能:一个自正则化的非单调神经网络激活函数。 | ||
| 67 | + * | ||
| 68 | + * @param [in] workspace: 在npu device侧申请的workspace内存起址。 | ||
| 69 | + * @param [in] workspaceSize: 在npu device侧申请的workspace大小,由第一段接口aclnnInplaceMishGetWorkspaceSize获取。 | ||
| 70 | + * @param [in] executor: op执行器,包含了算子计算流程。 | ||
| 71 | + * @param [in] stream: acl stream流。 | ||
| 72 | + * @return aclnnStatus: 返回状态码。 | ||
| 73 | + */ | ||
| 74 | +ACLNN_API aclnnStatus aclnnInplaceMish(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, | ||
| 75 | + aclrtStream stream); | ||
| 76 | + | ||
| 77 | + | ||
| 78 | +} | ||
| 79 | + | ||
| 80 | + | ||
| 81 | + | ||
| @@ -0,0 +1,38 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +*/ | ||
| 9 | + | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | +using namespace op; | ||
| 19 | + | ||
| 20 | +namespace l0op { | ||
| 21 | +OP_TYPE_REGISTER(Mish); | ||
| 22 | + | ||
| 23 | +// AICORE算子kernel | ||
| 24 | +static const aclTensor *MishAiCore(const aclTensor *self, aclTensor *out, aclOpExecutor *executor) { | ||
| 25 | + L0_DFX(MishAiCore, self, out); | ||
| 26 | + // 使用框架宏ADD_TO_LAUNCHER_LIST_AICORE,将Aicore Mish算子加入任务队列 | ||
| 27 | + // Mish是算子的OpType,self是算子的输入,out是算子的输出 | ||
| 28 | + auto retAicore = ADD_TO_LAUNCHER_LIST_AICORE(Mish, OP_INPUT(self), OP_OUTPUT(out)); | ||
| 29 | + OP_CHECK_ADD_TO_LAUNCHER_LIST_AICORE(retAicore != ACLNN_SUCCESS, return nullptr, | ||
| 30 | + "Mish ADD_TO_LAUNCHER_LIST_AICORE failed."); | ||
| 31 | + return out; | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +const aclTensor *Mish(const aclTensor *self, aclOpExecutor *executor) { | ||
| 35 | + auto mishOut = executor->AllocTensor(self->GetViewShape(), self->GetDataType()); | ||
| 36 | + return MishAiCore(self, mishOut, executor); | ||
| 37 | +} | ||
| 38 | +} // namespace l0op | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +*/ | ||
| 9 | + | ||
| 10 | + | ||
| 11 | + | ||
| 12 | + | ||
| 13 | + | ||
| 14 | +namespace l0op { | ||
| 15 | +const aclTensor* Mish(const aclTensor* self, aclOpExecutor* executor); | ||
| 16 | +} | ||
| 17 | + | ||
| 18 | + | ||
| @@ -0,0 +1,30 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +*/ | ||
| 9 | + | ||
| 10 | +/*! | ||
| 11 | + * \file mish.cpp | ||
| 12 | + * \brief | ||
| 13 | +*/ | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | +enum class MishTilingKey : uint32_t | ||
| 18 | +{ | ||
| 19 | + TILING_KEY_EXAMPLE_FLOAT = 0, | ||
| 20 | + TILING_KEY_EXAMPLE_OTHER = 1, | ||
| 21 | +}; | ||
| 22 | +template <uint32_t schMode> | ||
| 23 | +__global__ __aicore__ void mish(GM_ADDR x, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling) | ||
| 24 | +{ | ||
| 25 | + REGISTER_TILING_DEFAULT(MishTilingData); | ||
| 26 | + GET_TILING_DATA_WITH_STRUCT(MishTilingData, tilingData, tiling); | ||
| 27 | + MyMish::KernelMish<DTYPE_X,DTYPE_Y> op; | ||
| 28 | + op.Init(x, y, &tilingData); | ||
| 29 | + op.Process(); | ||
| 30 | +} | ||
| @@ -0,0 +1,333 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +*/ | ||
| 9 | + | ||
| 10 | +/*! | ||
| 11 | + * \file mish.h | ||
| 12 | + * \brief | ||
| 13 | + */ | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace MyMish { | ||
| 24 | + | ||
| 25 | +using namespace AscendC; | ||
| 26 | + | ||
| 27 | +constexpr int32_t BUFFER_NUM = 2; | ||
| 28 | +constexpr uint32_t COMPARE_ALIGN = 64; | ||
| 29 | + | ||
| 30 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 31 | +class KernelMish { | ||
| 32 | +public: | ||
| 33 | + __aicore__ inline KernelMish(){}; | ||
| 34 | + | ||
| 35 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, const MishTilingData* tilingData); | ||
| 36 | + __aicore__ inline void Process(); | ||
| 37 | + | ||
| 38 | +private: | ||
| 39 | + __aicore__ inline void CopyIn(int32_t progress); | ||
| 40 | + __aicore__ inline void CopyOut(int32_t progress); | ||
| 41 | + __aicore__ inline void Compute(int32_t progress); | ||
| 42 | + __aicore__ inline void ComputeSupPerfBf16(LocalTensor<TYPE_X> &xLocal, LocalTensor<TYPE_Y> &yLocal); | ||
| 43 | + __aicore__ inline void ComputeSupPerf(LocalTensor<TYPE_X> &xLocal, LocalTensor<TYPE_Y> &yLocal); | ||
| 44 | + __aicore__ inline void ComputeHighPerf16(LocalTensor<TYPE_X> &xLocal, LocalTensor<TYPE_Y> &yLocal); | ||
| 45 | + __aicore__ inline void ComputeHighPerf(LocalTensor<TYPE_X> &xLocal, LocalTensor<TYPE_Y> &yLocal); | ||
| 46 | + | ||
| 47 | +private: | ||
| 48 | + AscendC::TPipe pipe; | ||
| 49 | + AscendC::TQue<AscendC::QuePosition::VECIN, BUFFER_NUM> inQueueX; | ||
| 50 | + AscendC::TQue<AscendC::QuePosition::VECOUT, BUFFER_NUM> outQueueY; | ||
| 51 | + AscendC::TBuf<QuePosition::VECCALC> tmpBuffer1, tmpBuffer2, tmpBuffer3; | ||
| 52 | + AscendC::TBuf<QuePosition::VECCALC> QueueTmpX, QueueTmpY; | ||
| 53 | + AscendC::GlobalTensor<TYPE_X> xGm; | ||
| 54 | + AscendC::GlobalTensor<TYPE_Y> yGm; | ||
| 55 | + uint64_t coreDataNum; | ||
| 56 | + uint64_t tileNum; | ||
| 57 | + uint64_t tileDataNum; | ||
| 58 | + uint64_t tailDataNum; | ||
| 59 | + uint64_t processDataNum; | ||
| 60 | +}; | ||
| 61 | + | ||
| 62 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 63 | +__aicore__ inline void KernelMish<TYPE_X, TYPE_Y>::Init(GM_ADDR x, GM_ADDR y, const MishTilingData* tilingData) | ||
| 64 | +{ | ||
| 65 | + ASSERT(AscendC::GetBlockNum() != 0 && "block dim can not be zero!"); | ||
| 66 | + uint64_t coreId = AscendC::GetBlockIdx(); | ||
| 67 | + uint64_t globalBufferIndex = tilingData->bigCoreDataNum * coreId; | ||
| 68 | + this->tileDataNum = tilingData->tileDataNum; | ||
| 69 | + if (coreId < tilingData->tailBlockNum) { | ||
| 70 | + this->coreDataNum = tilingData->bigCoreDataNum; | ||
| 71 | + this->tileNum = tilingData->finalBigTileNum; | ||
| 72 | + this->tailDataNum = tilingData->bigTailDataNum; | ||
| 73 | + } else { | ||
| 74 | + this->coreDataNum = tilingData->smallCoreDataNum; | ||
| 75 | + this->tileNum = tilingData->finalSmallTileNum; | ||
| 76 | + this->tailDataNum = tilingData->smallTailDataNum; | ||
| 77 | + globalBufferIndex -= (tilingData->bigCoreDataNum - tilingData->smallCoreDataNum) * (coreId - tilingData->tailBlockNum); | ||
| 78 | + } | ||
| 79 | + xGm.SetGlobalBuffer((__gm__ TYPE_X*)x + globalBufferIndex, this->coreDataNum); | ||
| 80 | + yGm.SetGlobalBuffer((__gm__ TYPE_Y*)y + globalBufferIndex, this->coreDataNum); | ||
| 81 | + pipe.InitBuffer(inQueueX, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_X)); | ||
| 82 | + pipe.InitBuffer(outQueueY, BUFFER_NUM, this->tileDataNum * sizeof(TYPE_Y)); | ||
| 83 | + | ||
| 84 | + pipe.InitBuffer(tmpBuffer1, this->tileDataNum * sizeof(float)); | ||
| 85 | + pipe.InitBuffer(tmpBuffer2, this->tileDataNum * sizeof(float)); | ||
| 86 | + pipe.InitBuffer(tmpBuffer3, this->tileDataNum * sizeof(uint8_t)); | ||
| 87 | + pipe.InitBuffer(QueueTmpX, this->tileDataNum * sizeof(float)); | ||
| 88 | + pipe.InitBuffer(QueueTmpY, this->tileDataNum * sizeof(float)); | ||
| 89 | +} | ||
| 90 | + | ||
| 91 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 92 | +__aicore__ inline void KernelMish<TYPE_X, TYPE_Y>::CopyIn(int32_t progress) | ||
| 93 | +{ | ||
| 94 | + AscendC::LocalTensor<TYPE_X> xLocal = inQueueX.AllocTensor<TYPE_X>(); | ||
| 95 | + AscendC::DataCopy(xLocal, xGm[progress * this->tileDataNum], this->processDataNum); | ||
| 96 | + inQueueX.EnQue(xLocal); | ||
| 97 | +} | ||
| 98 | + | ||
| 99 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 100 | +__aicore__ inline void KernelMish<TYPE_X, TYPE_Y>::CopyOut(int32_t progress) | ||
| 101 | +{ | ||
| 102 | + AscendC::LocalTensor<TYPE_Y> yLocal = outQueueY.DeQue<TYPE_Y>(); | ||
| 103 | + AscendC::DataCopy(yGm[progress * this->tileDataNum], yLocal, this->processDataNum); | ||
| 104 | + outQueueY.FreeTensor(yLocal); | ||
| 105 | +} | ||
| 106 | + | ||
| 107 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 108 | +__aicore__ inline void KernelMish<TYPE_X, TYPE_Y>::ComputeSupPerfBf16(LocalTensor<TYPE_X> &xLocal, LocalTensor<TYPE_Y> &yLocal) | ||
| 109 | +{ | ||
| 110 | + AscendC::LocalTensor<float> tmp1Local = tmpBuffer1.Get<float>(); | ||
| 111 | + AscendC::LocalTensor<float> xLocalfp32 = QueueTmpX.Get<float>(); | ||
| 112 | + AscendC::LocalTensor<float> yLocalfp32 = QueueTmpY.Get<float>(); | ||
| 113 | + AscendC::Cast(xLocalfp32, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 114 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 115 | + | ||
| 116 | + AscendC::Muls(yLocalfp32, xLocalfp32, float(0.015625), this->processDataNum); | ||
| 117 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 118 | + AscendC::Adds(yLocalfp32, yLocalfp32, float(1), this->processDataNum); | ||
| 119 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 120 | + AscendC::Mul(yLocalfp32, yLocalfp32, yLocalfp32, this->processDataNum); | ||
| 121 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 122 | + AscendC::Mul(yLocalfp32, yLocalfp32, yLocalfp32, this->processDataNum); | ||
| 123 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 124 | + AscendC::Mul(yLocalfp32, yLocalfp32, yLocalfp32, this->processDataNum); | ||
| 125 | + AscendC::Mul(yLocalfp32, yLocalfp32, yLocalfp32, this->processDataNum); | ||
| 126 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 127 | + AscendC::Mul(yLocalfp32, yLocalfp32, yLocalfp32, this->processDataNum); | ||
| 128 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 129 | + AscendC::Mul(yLocalfp32, yLocalfp32, yLocalfp32, this->processDataNum); | ||
| 130 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 131 | + AscendC::Adds(yLocalfp32, yLocalfp32, float(1), this->processDataNum); | ||
| 132 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 133 | + AscendC::Mul(yLocalfp32, yLocalfp32, yLocalfp32, this->processDataNum); | ||
| 134 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 135 | + AscendC::Adds(yLocalfp32, yLocalfp32, float(1), this->processDataNum); | ||
| 136 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 137 | + AscendC::Duplicate(tmp1Local, float(1), this->processDataNum); | ||
| 138 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 139 | + AscendC::Div(yLocalfp32, tmp1Local, yLocalfp32, this->processDataNum); | ||
| 140 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 141 | + AscendC::Muls(yLocalfp32, yLocalfp32, float(-2), this->processDataNum); | ||
| 142 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 143 | + AscendC::Adds(yLocalfp32, yLocalfp32, float(1), this->processDataNum); | ||
| 144 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 145 | + AscendC::Mul(yLocalfp32, xLocalfp32, yLocalfp32, this->processDataNum); | ||
| 146 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 147 | + AscendC::Cast(yLocal, yLocalfp32, RoundMode::CAST_RINT, this->processDataNum); | ||
| 148 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 149 | +} | ||
| 150 | + | ||
| 151 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 152 | +__aicore__ inline void KernelMish<TYPE_X, TYPE_Y>::ComputeSupPerf(LocalTensor<TYPE_X> &xLocal, LocalTensor<TYPE_Y> &yLocal) | ||
| 153 | +{ | ||
| 154 | + AscendC::LocalTensor<TYPE_X> tmp1Local = tmpBuffer1.Get<TYPE_X>(); | ||
| 155 | + AscendC::Muls(yLocal, xLocal, TYPE_X(0.015625), this->processDataNum); | ||
| 156 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 157 | + AscendC::Adds(yLocal, yLocal, TYPE_X(1), this->processDataNum); | ||
| 158 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 159 | + AscendC::Mul(yLocal, yLocal, yLocal, this->processDataNum); | ||
| 160 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 161 | + AscendC::Mul(yLocal, yLocal, yLocal, this->processDataNum); | ||
| 162 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 163 | + AscendC::Mul(yLocal, yLocal, yLocal, this->processDataNum); | ||
| 164 | + AscendC::Mul(yLocal, yLocal, yLocal, this->processDataNum); | ||
| 165 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 166 | + AscendC::Mul(yLocal, yLocal, yLocal, this->processDataNum); | ||
| 167 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 168 | + AscendC::Mul(yLocal, yLocal, yLocal, this->processDataNum); | ||
| 169 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 170 | + AscendC::Adds(yLocal, yLocal, TYPE_X(1), this->processDataNum); | ||
| 171 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 172 | + AscendC::Mul(yLocal, yLocal, yLocal, this->processDataNum); | ||
| 173 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 174 | + AscendC::Adds(yLocal, yLocal, TYPE_X(1), this->processDataNum); | ||
| 175 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 176 | + AscendC::Duplicate(tmp1Local, TYPE_X(-2), this->processDataNum); | ||
| 177 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 178 | + AscendC::Div(yLocal, tmp1Local, yLocal, this->processDataNum); | ||
| 179 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 180 | + AscendC::Adds(yLocal, yLocal, TYPE_X(1), this->processDataNum); | ||
| 181 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 182 | + AscendC::Mul(yLocal, xLocal, yLocal, this->processDataNum); | ||
| 183 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 184 | +} | ||
| 185 | + | ||
| 186 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 187 | +__aicore__ inline void KernelMish<TYPE_X, TYPE_Y>::ComputeHighPerf16(LocalTensor<TYPE_X> &xLocal, LocalTensor<TYPE_Y> &yLocal) | ||
| 188 | +{ | ||
| 189 | + AscendC::LocalTensor<float> xLocalfp32 = QueueTmpX.Get<float>(); | ||
| 190 | + AscendC::LocalTensor<float> yLocalfp32 = QueueTmpY.Get<float>(); | ||
| 191 | + AscendC::LocalTensor<float> tmp1Local = tmpBuffer1.Get<float>(); | ||
| 192 | + AscendC::LocalTensor<float> tmp2Local = tmpBuffer2.Get<float>(); | ||
| 193 | + AscendC::LocalTensor<uint8_t> cmp1 = tmpBuffer3.Get<uint8_t>(); | ||
| 194 | + | ||
| 195 | + AscendC::Cast(xLocalfp32, xLocal, RoundMode::CAST_NONE, this->processDataNum); | ||
| 196 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 197 | + uint32_t comparelength = (this->processDataNum + COMPARE_ALIGN - 1) / COMPARE_ALIGN * COMPARE_ALIGN; | ||
| 198 | + AscendC::CompareScalar(cmp1, xLocalfp32, float(0), CMPMODE::GT, comparelength); | ||
| 199 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 200 | + | ||
| 201 | + AscendC::Muls(tmp1Local , xLocalfp32, float(-1), this->processDataNum); | ||
| 202 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 203 | + AscendC::Exp(tmp1Local, tmp1Local, this->processDataNum); | ||
| 204 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 205 | + AscendC::Muls(tmp1Local, tmp1Local, float(2), this->processDataNum); | ||
| 206 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 207 | + AscendC::Adds(tmp1Local, tmp1Local, float(1), this->processDataNum); | ||
| 208 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 209 | + AscendC::Muls(tmp2Local , xLocalfp32, float(-2), this->processDataNum); | ||
| 210 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 211 | + AscendC::Exp(tmp2Local, tmp2Local, this->processDataNum); | ||
| 212 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 213 | + AscendC::Muls(tmp2Local, tmp2Local, float(2), this->processDataNum); | ||
| 214 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 215 | + AscendC::Add(tmp2Local, tmp1Local, tmp2Local, this->processDataNum); | ||
| 216 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 217 | + AscendC::Div(tmp1Local, tmp1Local, tmp2Local, this->processDataNum); // res for x > 0 | ||
| 218 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 219 | + | ||
| 220 | + AscendC::Muls(tmp2Local , xLocalfp32, float(2), this->processDataNum); | ||
| 221 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 222 | + AscendC::Exp(tmp2Local, tmp2Local, this->processDataNum); | ||
| 223 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 224 | + AscendC::Exp(yLocalfp32, xLocalfp32, this->processDataNum); | ||
| 225 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 226 | + AscendC::Muls(yLocalfp32, yLocalfp32, float(2), this->processDataNum); | ||
| 227 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 228 | + AscendC::Add(yLocalfp32, yLocalfp32, tmp2Local, this->processDataNum); | ||
| 229 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 230 | + AscendC::Adds(tmp2Local, yLocalfp32, float(2), this->processDataNum); | ||
| 231 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 232 | + AscendC::Div(yLocalfp32, yLocalfp32, tmp2Local, this->processDataNum); //res for x <= 0 | ||
| 233 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 234 | + | ||
| 235 | + AscendC::Select(yLocalfp32, cmp1, tmp1Local, yLocalfp32, SELMODE::VSEL_TENSOR_TENSOR_MODE, this->processDataNum); | ||
| 236 | + AscendC::Mul(yLocalfp32, yLocalfp32, xLocalfp32, this->processDataNum); | ||
| 237 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 238 | + | ||
| 239 | + AscendC::Cast(yLocal, yLocalfp32, RoundMode::CAST_RINT, this->processDataNum); | ||
| 240 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 241 | +} | ||
| 242 | + | ||
| 243 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 244 | +__aicore__ inline void KernelMish<TYPE_X, TYPE_Y>::ComputeHighPerf(LocalTensor<TYPE_X> &xLocal, LocalTensor<TYPE_Y> &yLocal) | ||
| 245 | +{ | ||
| 246 | + AscendC::LocalTensor<TYPE_X> tmp1Local = tmpBuffer1.Get<TYPE_X>(); | ||
| 247 | + AscendC::LocalTensor<TYPE_X> tmp2Local = tmpBuffer2.Get<TYPE_X>(); | ||
| 248 | + AscendC::LocalTensor<uint8_t> cmp1 = tmpBuffer3.Get<uint8_t>(); | ||
| 249 | + | ||
| 250 | + uint32_t comparelength = (this->processDataNum + COMPARE_ALIGN - 1) / COMPARE_ALIGN * COMPARE_ALIGN; | ||
| 251 | + AscendC::CompareScalar(cmp1, xLocal, TYPE_X(0), CMPMODE::GT, comparelength); | ||
| 252 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 253 | + AscendC::Muls(tmp1Local , xLocal, TYPE_X(-1), this->processDataNum); | ||
| 254 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 255 | + AscendC::Exp(tmp1Local, tmp1Local, this->processDataNum); | ||
| 256 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 257 | + AscendC::Muls(tmp1Local, tmp1Local, TYPE_X(2), this->processDataNum); | ||
| 258 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 259 | + AscendC::Adds(tmp1Local, tmp1Local, TYPE_X(1), this->processDataNum); | ||
| 260 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 261 | + AscendC::Muls(tmp2Local , xLocal, TYPE_X(-2), this->processDataNum); | ||
| 262 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 263 | + AscendC::Exp(tmp2Local, tmp2Local, this->processDataNum); | ||
| 264 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 265 | + AscendC::Muls(tmp2Local, tmp2Local, TYPE_X(2), this->processDataNum); | ||
| 266 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 267 | + AscendC::Add(tmp2Local, tmp1Local, tmp2Local, this->processDataNum); | ||
| 268 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 269 | + AscendC::Div(tmp1Local, tmp1Local, tmp2Local, this->processDataNum); // res for x > 0 | ||
| 270 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 271 | + | ||
| 272 | + AscendC::Muls(tmp2Local , xLocal, TYPE_X(2), this->processDataNum); | ||
| 273 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 274 | + AscendC::Exp(tmp2Local, tmp2Local, this->processDataNum); | ||
| 275 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 276 | + AscendC::Exp(yLocal, xLocal, this->processDataNum); | ||
| 277 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 278 | + AscendC::Muls(yLocal, yLocal, TYPE_X(2), this->processDataNum); | ||
| 279 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 280 | + AscendC::Add(yLocal, yLocal, tmp2Local, this->processDataNum); | ||
| 281 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 282 | + AscendC::Adds(tmp2Local, yLocal, TYPE_X(2), this->processDataNum); | ||
| 283 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 284 | + AscendC::Div(yLocal, yLocal, tmp2Local, this->processDataNum); //res for x <= 0 | ||
| 285 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 286 | + | ||
| 287 | + AscendC::Select(yLocal, cmp1, tmp1Local, yLocal, SELMODE::VSEL_TENSOR_TENSOR_MODE, this->processDataNum); | ||
| 288 | + AscendC::Mul(yLocal, yLocal, xLocal, this->processDataNum); | ||
| 289 | + AscendC::PipeBarrier<PIPE_V>(); | ||
| 290 | +} | ||
| 291 | + | ||
| 292 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 293 | +__aicore__ inline void KernelMish<TYPE_X, TYPE_Y>::Compute(int32_t progress) | ||
| 294 | +{ | ||
| 295 | + AscendC::LocalTensor<TYPE_X> xLocal = inQueueX.DeQue<TYPE_X>(); | ||
| 296 | + AscendC::LocalTensor<TYPE_Y> yLocal = outQueueY.AllocTensor<TYPE_Y>(); | ||
| 297 | + | ||
| 298 | + | ||
| 299 | + if constexpr (std::is_same_v<TYPE_X, __bf16>) { | ||
| 300 | + ComputeSupPerfBf16(xLocal, yLocal); | ||
| 301 | + } else if constexpr (std::is_same_v<TYPE_X, float> || std::is_same_v<TYPE_X, half>){ | ||
| 302 | + ComputeSupPerf(xLocal, yLocal); | ||
| 303 | + } | ||
| 304 | + | ||
| 305 | + if constexpr (std::is_same_v<TYPE_X, __bf16> || std::is_same_v<TYPE_X, half>) { | ||
| 306 | + ComputeHighPerf16(xLocal, yLocal); | ||
| 307 | + } else if constexpr (std::is_same_v<TYPE_X, float>) { | ||
| 308 | + ComputeHighPerf(xLocal, yLocal); | ||
| 309 | + } | ||
| 310 | + | ||
| 311 | + | ||
| 312 | + outQueueY.EnQue<TYPE_Y>(yLocal); | ||
| 313 | + inQueueX.FreeTensor(xLocal); | ||
| 314 | +} | ||
| 315 | + | ||
| 316 | +template <typename TYPE_X, typename TYPE_Y> | ||
| 317 | +__aicore__ inline void KernelMish<TYPE_X, TYPE_Y>::Process() | ||
| 318 | +{ | ||
| 319 | + int32_t loopCount = this->tileNum; | ||
| 320 | + this->processDataNum = this->tileDataNum; | ||
| 321 | + for (int32_t i = 0; i < loopCount - 1; i++) { | ||
| 322 | + CopyIn(i); | ||
| 323 | + Compute(i); | ||
| 324 | + CopyOut(i); | ||
| 325 | + } | ||
| 326 | + this->processDataNum = this->tailDataNum; | ||
| 327 | + CopyIn(loopCount - 1); | ||
| 328 | + Compute(loopCount - 1); | ||
| 329 | + CopyOut(loopCount - 1); | ||
| 330 | +} | ||
| 331 | + | ||
| 332 | +} // namespace MyMish | ||
| 333 | + | ||
| @@ -0,0 +1,26 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +*/ | ||
| 9 | + | ||
| 10 | +/*! | ||
| 11 | + * \file mish_tiling_data.h | ||
| 12 | + * \brief tiling data struct | ||
| 13 | +*/ | ||
| 14 | + | ||
| 15 | + | ||
| 16 | +struct MishTilingData{ | ||
| 17 | + uint64_t smallCoreDataNum; | ||
| 18 | + uint64_t bigCoreDataNum; | ||
| 19 | + uint64_t finalBigTileNum; | ||
| 20 | + uint64_t finalSmallTileNum; | ||
| 21 | + uint64_t tileDataNum; | ||
| 22 | + uint64_t smallTailDataNum; | ||
| 23 | + uint64_t bigTailDataNum; | ||
| 24 | + uint64_t tailBlockNum; | ||
| 25 | +} ; | ||
| 26 | + | ||
| @@ -0,0 +1,27 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +*/ | ||
| 9 | + | ||
| 10 | +/*! | ||
| 11 | + * \file mish_tiling_key.h | ||
| 12 | + * \brief mish tiling key declare | ||
| 13 | +*/ | ||
| 14 | + | ||
| 15 | + | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | +ASCENDC_TPL_ARGS_DECL( | ||
| 20 | + Mish, | ||
| 21 | + ASCENDC_TPL_UINT_DECL(schMode, 1, ASCENDC_TPL_UI_LIST, ELEMENTWISE_TPL_SCH_MODE_0, ELEMENTWISE_TPL_SCH_MODE_1)); | ||
| 22 | + | ||
| 23 | +ASCENDC_TPL_SEL( | ||
| 24 | + ASCENDC_TPL_ARGS_SEL( | ||
| 25 | + ASCENDC_TPL_UINT_SEL(schMode, ASCENDC_TPL_UI_LIST,ELEMENTWISE_TPL_SCH_MODE_0,ELEMENTWISE_TPL_SCH_MODE_1) | ||
| 26 | + ), | ||
| 27 | +); | ||
| @@ -0,0 +1,17 @@ | |||
| 1 | +# ---------------------------------------------------------------------------- | ||
| 2 | +# This program is free software, you can redistribute it and/or modify it. | ||
| 3 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | +# This file is a part of the CANN Open Software. | ||
| 5 | +# Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING | ||
| 8 | +# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. See LICENSE in the root of | ||
| 9 | +# the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 13 | +foreach(SUB_DIR ${CURRENT_DIRS}) | ||
| 14 | + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | ||
| 15 | + add_subdirectory(${SUB_DIR}) | ||
| 16 | + endif() | ||
| 17 | +endforeach() | ||
| @@ -0,0 +1,17 @@ | |||
| 1 | +# ---------------------------------------------------------------------------- | ||
| 2 | +# This program is free software, you can redistribute it and/or modify it. | ||
| 3 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | +# This file is a part of the CANN Open Software. | ||
| 5 | +# Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING | ||
| 8 | +# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. See LICENSE in the root of | ||
| 9 | +# the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 13 | +foreach(SUB_DIR ${CURRENT_DIRS}) | ||
| 14 | + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | ||
| 15 | + add_subdirectory(${SUB_DIR}) | ||
| 16 | + endif() | ||
| 17 | +endforeach() | ||
| @@ -0,0 +1,18 @@ | |||
| 1 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 2 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 3 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 4 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 5 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 6 | +# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 7 | +# See LICENSE in the root of the software repository for the full text of the License. | ||
| 8 | +#/ | ||
| 9 | + | ||
| 10 | + | ||
| 11 | +file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 12 | +if(UT_TEST_ALL OR OP_HOST_UT) | ||
| 13 | + add_modules_ut_sources(HOSTNAME ${OP_TILING_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 14 | + add_modules_ut_sources(HOSTNAME ${OP_INFERSHAPE_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 15 | +endif() | ||
| 16 | +if(UT_TEST_ALL OR OP_API_UT) | ||
| 17 | + add_modules_ut_sources(HOSTNAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR}) | ||
| 18 | +endif() | ||
| @@ -0,0 +1,279 @@ | |||
| 1 | +/** | ||
| 2 | + * Copyright (c) 2025 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 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +using namespace ut_util; | ||
| 34 | +using namespace std; | ||
| 35 | +using namespace ge; | ||
| 36 | + | ||
| 37 | +class MishTilingTest : public testing::Test | ||
| 38 | +{ | ||
| 39 | +protected: | ||
| 40 | + static void SetUpTestCase() | ||
| 41 | + { | ||
| 42 | + std::cout << "MishTilingTest Setup" << std::endl; | ||
| 43 | + } | ||
| 44 | + static void TearDownTestCase() | ||
| 45 | + { | ||
| 46 | + std::cout << "MishTilingTest TearDown" << std::endl; | ||
| 47 | + } | ||
| 48 | +}; | ||
| 49 | + | ||
| 50 | +TEST_F(MishTilingTest, mish_001) | ||
| 51 | +{ | ||
| 52 | + gert::StorageShape x_shape = {{2,2}, {2,2}}; | ||
| 53 | + gert::StorageShape output_shapes = {{2,2}, {2,2}}; | ||
| 54 | + | ||
| 55 | + string compile_info_string = R"({ | ||
| 56 | + "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1", | ||
| 57 | + "Intrinsic_fix_pipe_l0c2out": false, "Intrinsic_data_move_l12ub": true, | ||
| 58 | + "Intrinsic_data_move_l0c2ub": true, "Intrinsic_data_move_out2l1_nd2nz": false, | ||
| 59 | + "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288, | ||
| 60 | + "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072, | ||
| 61 | + "CORE_NUM": 40} | ||
| 62 | + })"; | ||
| 63 | + map<string, string> soc_infos; | ||
| 64 | + map<string, string> aicore_spec; | ||
| 65 | + map<string, string> intrinsics; | ||
| 66 | + GetPlatFormInfos(compile_info_string.c_str(), soc_infos, aicore_spec, intrinsics); | ||
| 67 | + | ||
| 68 | + fe::PlatFormInfos platform_info; | ||
| 69 | + platform_info.Init(); | ||
| 70 | + | ||
| 71 | + struct MishCompileInfo { | ||
| 72 | + }; | ||
| 73 | + MishCompileInfo compile_info; | ||
| 74 | + | ||
| 75 | + std::string op_type("Mish"); | ||
| 76 | + ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr); | ||
| 77 | + auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling; | ||
| 78 | + auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse; | ||
| 79 | + | ||
| 80 | + // tilingParseFunc simulate | ||
| 81 | + auto kernel_holder = | ||
| 82 | + gert::KernelRunContextFaker() | ||
| 83 | + .KernelIONum(1, 1) | ||
| 84 | + .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)}) | ||
| 85 | + .Outputs({&compile_info}) | ||
| 86 | + .Build(); | ||
| 87 | + | ||
| 88 | + ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init()); | ||
| 89 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos); | ||
| 90 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec); | ||
| 91 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore"); | ||
| 92 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes( | ||
| 93 | + "AICoreintrinsicDtypeMap", intrinsics); | ||
| 94 | + ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS); | ||
| 95 | + | ||
| 96 | + // tilingFunc simulate | ||
| 97 | + | ||
| 98 | + auto param = gert::TilingData::CreateCap(4096); | ||
| 99 | + auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(4096); | ||
| 100 | + auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get()); | ||
| 101 | + ASSERT_NE(param, nullptr); | ||
| 102 | + | ||
| 103 | + auto holder = gert::TilingContextFaker() | ||
| 104 | + .NodeIoNum(1, 1) | ||
| 105 | + .IrInstanceNum({1}) | ||
| 106 | + .InputShapes({&x_shape}) | ||
| 107 | + .OutputShapes({&output_shapes}) | ||
| 108 | + .CompileInfo(&compile_info) | ||
| 109 | + .PlatformInfo(reinterpret_cast<char*>(&platform_info)) | ||
| 110 | + .NodeInputTd(0, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 111 | + .NodeOutputTd(0, ge::DT_FLOAT, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 112 | + .TilingData(param.get()) | ||
| 113 | + .Workspace(ws_size) | ||
| 114 | + .Build(); | ||
| 115 | + | ||
| 116 | + gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>(); | ||
| 117 | + ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr); | ||
| 118 | + | ||
| 119 | + tiling_context->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos); | ||
| 120 | + tiling_context->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec); | ||
| 121 | + tiling_context->GetPlatformInfo()->SetCoreNumByCoreType("AICore"); | ||
| 122 | + tiling_context->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics); | ||
| 123 | + | ||
| 124 | + EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS); | ||
| 125 | +} | ||
| 126 | + | ||
| 127 | +TEST_F(MishTilingTest, mish_002) | ||
| 128 | +{ | ||
| 129 | + gert::StorageShape x_shape = {{267,54}, {267,54}}; | ||
| 130 | + gert::StorageShape output_shapes = {{267,54}, {267,54}}; | ||
| 131 | + | ||
| 132 | + string compile_info_string = R"({ | ||
| 133 | + "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1", | ||
| 134 | + "Intrinsic_fix_pipe_l0c2out": false, "Intrinsic_data_move_l12ub": true, | ||
| 135 | + "Intrinsic_data_move_l0c2ub": true, "Intrinsic_data_move_out2l1_nd2nz": false, | ||
| 136 | + "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288, | ||
| 137 | + "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072, | ||
| 138 | + "CORE_NUM": 40} | ||
| 139 | + })"; | ||
| 140 | + map<string, string> soc_infos; | ||
| 141 | + map<string, string> aicore_spec; | ||
| 142 | + map<string, string> intrinsics; | ||
| 143 | + GetPlatFormInfos(compile_info_string.c_str(), soc_infos, aicore_spec, intrinsics); | ||
| 144 | + | ||
| 145 | + fe::PlatFormInfos platform_info; | ||
| 146 | + platform_info.Init(); | ||
| 147 | + | ||
| 148 | + struct MishCompileInfo { | ||
| 149 | + }; | ||
| 150 | + MishCompileInfo compile_info; | ||
| 151 | + | ||
| 152 | + std::string op_type("Mish"); | ||
| 153 | + ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr); | ||
| 154 | + auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling; | ||
| 155 | + auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse; | ||
| 156 | + | ||
| 157 | + // tilingParseFunc simulate | ||
| 158 | + auto kernel_holder = | ||
| 159 | + gert::KernelRunContextFaker() | ||
| 160 | + .KernelIONum(1, 1) | ||
| 161 | + .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)}) | ||
| 162 | + .Outputs({&compile_info}) | ||
| 163 | + .Build(); | ||
| 164 | + | ||
| 165 | + ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init()); | ||
| 166 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos); | ||
| 167 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec); | ||
| 168 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore"); | ||
| 169 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes( | ||
| 170 | + "AICoreintrinsicDtypeMap", intrinsics); | ||
| 171 | + ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS); | ||
| 172 | + | ||
| 173 | + // tilingFunc simulate | ||
| 174 | + | ||
| 175 | + auto param = gert::TilingData::CreateCap(4096); | ||
| 176 | + auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(4096); | ||
| 177 | + auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get()); | ||
| 178 | + ASSERT_NE(param, nullptr); | ||
| 179 | + | ||
| 180 | + auto holder = gert::TilingContextFaker() | ||
| 181 | + .NodeIoNum(1, 1) | ||
| 182 | + .IrInstanceNum({1}) | ||
| 183 | + .InputShapes({&x_shape}) | ||
| 184 | + .OutputShapes({&output_shapes}) | ||
| 185 | + .CompileInfo(&compile_info) | ||
| 186 | + .PlatformInfo(reinterpret_cast<char*>(&platform_info)) | ||
| 187 | + .NodeInputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 188 | + .NodeOutputTd(0, ge::DT_FLOAT16, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 189 | + .TilingData(param.get()) | ||
| 190 | + .Workspace(ws_size) | ||
| 191 | + .Build(); | ||
| 192 | + | ||
| 193 | + gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>(); | ||
| 194 | + ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr); | ||
| 195 | + | ||
| 196 | + tiling_context->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos); | ||
| 197 | + tiling_context->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec); | ||
| 198 | + tiling_context->GetPlatformInfo()->SetCoreNumByCoreType("AICore"); | ||
| 199 | + tiling_context->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics); | ||
| 200 | + | ||
| 201 | + EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS); | ||
| 202 | +} | ||
| 203 | + | ||
| 204 | +TEST_F(MishTilingTest, mish_003) | ||
| 205 | +{ | ||
| 206 | + gert::StorageShape x_shape = {{267,354}, {267,354}}; | ||
| 207 | + gert::StorageShape output_shapes = {{267,354}, {267,354}}; | ||
| 208 | + | ||
| 209 | + string compile_info_string = R"({ | ||
| 210 | + "hardware_info": {"BT_SIZE": 0, "load3d_constraints": "1", | ||
| 211 | + "Intrinsic_fix_pipe_l0c2out": false, "Intrinsic_data_move_l12ub": true, | ||
| 212 | + "Intrinsic_data_move_l0c2ub": true, "Intrinsic_data_move_out2l1_nd2nz": false, | ||
| 213 | + "UB_SIZE": 196608, "L2_SIZE": 33554432, "L1_SIZE": 524288, | ||
| 214 | + "L0A_SIZE": 65536, "L0B_SIZE": 65536, "L0C_SIZE": 131072, | ||
| 215 | + "CORE_NUM": 40} | ||
| 216 | + })"; | ||
| 217 | + map<string, string> soc_infos; | ||
| 218 | + map<string, string> aicore_spec; | ||
| 219 | + map<string, string> intrinsics; | ||
| 220 | + GetPlatFormInfos(compile_info_string.c_str(), soc_infos, aicore_spec, intrinsics); | ||
| 221 | + | ||
| 222 | + fe::PlatFormInfos platform_info; | ||
| 223 | + platform_info.Init(); | ||
| 224 | + | ||
| 225 | + struct MishCompileInfo { | ||
| 226 | + }; | ||
| 227 | + MishCompileInfo compile_info; | ||
| 228 | + | ||
| 229 | + std::string op_type("Mish"); | ||
| 230 | + ASSERT_NE(gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str()), nullptr); | ||
| 231 | + auto tiling_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling; | ||
| 232 | + auto tiling_parse_func = gert::OpImplRegistry::GetInstance().GetOpImpl(op_type.c_str())->tiling_parse; | ||
| 233 | + | ||
| 234 | + // tilingParseFunc simulate | ||
| 235 | + auto kernel_holder = | ||
| 236 | + gert::KernelRunContextFaker() | ||
| 237 | + .KernelIONum(1, 1) | ||
| 238 | + .Inputs({const_cast<char*>(compile_info_string.c_str()), reinterpret_cast<void*>(&platform_info)}) | ||
| 239 | + .Outputs({&compile_info}) | ||
| 240 | + .Build(); | ||
| 241 | + | ||
| 242 | + ASSERT_TRUE(kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->Init()); | ||
| 243 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos); | ||
| 244 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec); | ||
| 245 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetCoreNumByCoreType("AICore"); | ||
| 246 | + kernel_holder.GetContext<gert::TilingParseContext>()->GetPlatformInfo()->SetPlatformRes( | ||
| 247 | + "AICoreintrinsicDtypeMap", intrinsics); | ||
| 248 | + ASSERT_EQ(tiling_parse_func(kernel_holder.GetContext<gert::KernelContext>()), ge::GRAPH_SUCCESS); | ||
| 249 | + | ||
| 250 | + // tilingFunc simulate | ||
| 251 | + | ||
| 252 | + auto param = gert::TilingData::CreateCap(4096); | ||
| 253 | + auto workspace_size_holer = gert::ContinuousVector::Create<size_t>(4096); | ||
| 254 | + auto ws_size = reinterpret_cast<gert::ContinuousVector*>(workspace_size_holer.get()); | ||
| 255 | + ASSERT_NE(param, nullptr); | ||
| 256 | + | ||
| 257 | + auto holder = gert::TilingContextFaker() | ||
| 258 | + .NodeIoNum(1, 1) | ||
| 259 | + .IrInstanceNum({1}) | ||
| 260 | + .InputShapes({&x_shape}) | ||
| 261 | + .OutputShapes({&output_shapes}) | ||
| 262 | + .CompileInfo(&compile_info) | ||
| 263 | + .PlatformInfo(reinterpret_cast<char*>(&platform_info)) | ||
| 264 | + .NodeInputTd(0, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 265 | + .NodeOutputTd(0, ge::DT_BF16, ge::FORMAT_ND, ge::FORMAT_ND) | ||
| 266 | + .TilingData(param.get()) | ||
| 267 | + .Workspace(ws_size) | ||
| 268 | + .Build(); | ||
| 269 | + | ||
| 270 | + gert::TilingContext* tiling_context = holder.GetContext<gert::TilingContext>(); | ||
| 271 | + ASSERT_NE(tiling_context->GetPlatformInfo(), nullptr); | ||
| 272 | + | ||
| 273 | + tiling_context->GetPlatformInfo()->SetPlatformRes("SoCInfo", soc_infos); | ||
| 274 | + tiling_context->GetPlatformInfo()->SetPlatformRes("AICoreSpec", aicore_spec); | ||
| 275 | + tiling_context->GetPlatformInfo()->SetCoreNumByCoreType("AICore"); | ||
| 276 | + tiling_context->GetPlatformInfo()->SetPlatformRes("AICoreintrinsicDtypeMap", intrinsics); | ||
| 277 | + | ||
| 278 | + EXPECT_EQ(tiling_func(tiling_context), ge::GRAPH_SUCCESS); | ||
| 279 | +} | ||
| @@ -0,0 +1,29 @@ | |||
| 1 | +# ---------------------------------------------------------------------------- | ||
| 2 | +# This program is free software, you can redistribute it and/or modify it. | ||
| 3 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | +# This file is a part of the CANN Open Software. | ||
| 5 | +# Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING | ||
| 8 | +# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. See LICENSE in the root of | ||
| 9 | +# the software repository for the full text of the License. | ||
| 10 | +# ---------------------------------------------------------------------------- | ||
| 11 | + | ||
| 12 | +if (UT_TEST_ALL OR OP_KERNEL_UT) | ||
| 13 | + # 需要将Tiling依赖的文件添加到CMakeLists.txt中 | ||
| 14 | + # set(elewise_common_tiling_files | ||
| 15 | + # ${CANN_ROOT}/ops/built-in/op_tiling/runtime/elewise_tiling.cc | ||
| 16 | + # ) | ||
| 17 | + # 算子自己的tiling文件路径 | ||
| 18 | + set(mish_tiling_files | ||
| 19 | + ${CMAKE_CURRENT_SOURCE_DIR}/../../../op_host/mish_tiling.cpp | ||
| 20 | + ${CMAKE_CURRENT_SOURCE_DIR}/../../../op_host/mish_infershape.cpp | ||
| 21 | + # ${elewise_common_tiling_files} | ||
| 22 | + ) | ||
| 23 | + # 使用AddOpTestCase | ||
| 24 | + # param1:算子名称,以kernel方式命名 | ||
| 25 | + # param2:soc版本,多个以分号分隔,例如:"ascend910_9599;AscendB1" | ||
| 26 | + # param3:自定义编译选项,一般填写测试的一种典型数据类型组合,不需要则传入空字符串,例如:"-DDTYPE_X=float",多个使用空格分隔,例如:"-DDTYPE_X=float -DDTYPE_Y=float" | ||
| 27 | + # param4:该算子依赖的所有tiling源码文件 | ||
| 28 | + # # AddOpTestCase(mish "ascend910B1" "" "${mish_tiling_files}") | ||
把注释去掉 ![]() ![]() | |||
| 29 | +endif() | ||
| @@ -0,0 +1,57 @@ | |||
| 1 | +#!/usr/bin/env python3 | ||
| 2 | +# -*- coding: utf-8 -*- | ||
| 3 | +# ---------------------------------------------------------------------------- | ||
| 4 | +# This program is free software, you can redistribute it and/or modify it. | ||
| 5 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 6 | +# This file is a part of the CANN Open Software. | ||
| 7 | +# Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 8 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 9 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING | ||
| 10 | +# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. See LICENSE in the root of | ||
| 11 | +# the software repository for the full text of the License. | ||
| 12 | +# ---------------------------------------------------------------------------- | ||
| 13 | + | ||
| 14 | +import sys | ||
| 15 | +import numpy as np | ||
| 16 | +import glob | ||
| 17 | +import os | ||
| 18 | + | ||
| 19 | +curr_dir = os.path.dirname(os.path.realpath(__file__)) | ||
| 20 | + | ||
| 21 | +def compare_data(golden_file_lists, output_file_lists, d_type): | ||
| 22 | + if d_type == "float16": | ||
| 23 | + np_dtype = np.float16 | ||
| 24 | + elif d_type == "float32": | ||
| 25 | + np_dtype = np.float32 | ||
| 26 | + else: | ||
| 27 | + raise ValueError("d_type must be float16 or float32") | ||
| 28 | + | ||
| 29 | + data_same = True | ||
| 30 | + for gold, out in zip(golden_file_lists, output_file_lists): | ||
| 31 | + tmp_out = np.fromfile(out, np_dtype) | ||
| 32 | + tmp_gold = np.fromfile(gold, np_dtype) | ||
| 33 | + diff_res = np.isclose(tmp_out, tmp_gold, 0, 0, True) | ||
| 34 | + diff_idx = np.where(diff_res != True)[0] | ||
| 35 | + if len(diff_idx) == 0: | ||
| 36 | + print("PASSED!") | ||
| 37 | + else: | ||
| 38 | + print("FAILED!") | ||
| 39 | + for idx in diff_idx[:5]: | ||
| 40 | + print(f"index: {idx}, output: {tmp_out[idx]}, golden: {tmp_gold[idx]}") | ||
| 41 | + data_same = False | ||
| 42 | + return data_same | ||
| 43 | + | ||
| 44 | +def get_file_lists(dtype): | ||
| 45 | + golden_file_lists = sorted(glob.glob(curr_dir + "/*golden*.bin")) | ||
| 46 | + output_file_lists = sorted(glob.glob(curr_dir + "/*output*.bin")) | ||
| 47 | + return golden_file_lists, output_file_lists | ||
| 48 | + | ||
| 49 | +def process(d_type): | ||
| 50 | + golden_file_lists, output_file_lists = get_file_lists(d_type) | ||
| 51 | + result = compare_data(golden_file_lists, output_file_lists, d_type) | ||
| 52 | + print("compare result:", result) | ||
| 53 | + return result | ||
| 54 | + | ||
| 55 | +if __name__ == '__main__': | ||
| 56 | + ret = process(sys.argv[1]) | ||
| 57 | + exit(0 if ret else 1) | ||
| @@ -0,0 +1,55 @@ | |||
| 1 | +#!/usr/bin/env python3 | ||
| 2 | +# -*- coding: utf-8 -*- | ||
| 3 | +# ---------------------------------------------------------------------------- | ||
| 4 | +# This program is free software, you can redistribute it and/or modify it. | ||
| 5 | +# Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 6 | +# This file is a part of the CANN Open Software. | ||
| 7 | +# Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 8 | +# Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 9 | +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING | ||
| 10 | +# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. See LICENSE in the root of | ||
| 11 | +# the software repository for the full text of the License. | ||
| 12 | +# ---------------------------------------------------------------------------- | ||
| 13 | + | ||
| 14 | +import sys | ||
| 15 | +import os | ||
| 16 | +import numpy as np | ||
| 17 | +import re | ||
| 18 | +import tensorflow as tf | ||
| 19 | + | ||
| 20 | + | ||
| 21 | +def parse_str_to_shape_list(shape_str): | ||
| 22 | + shape_str = shape_str.strip('(').strip(')') | ||
| 23 | + shape_list = [int(x) for x in shape_str.split(",")] | ||
| 24 | + return np.array(shape_list) | ||
| 25 | + | ||
| 26 | +def mish(x): | ||
| 27 | + return x * tf.tanh(tf.math.softplus(x)) | ||
| 28 | + | ||
| 29 | +def gen_data_and_golden(shape_str, d_type="float32"): | ||
| 30 | + d_type_dict = { | ||
| 31 | + "float32": np.float32, | ||
| 32 | + "float16": np.float16, | ||
| 33 | + "bfloat16": tf.bfloat16.as_numpy_dtype | ||
| 34 | + } | ||
| 35 | + np_type = d_type_dict[d_type] | ||
| 36 | + shape = parse_str_to_shape_list(shape_str) | ||
| 37 | + size = np.prod(shape) | ||
| 38 | + tmp_input = np.random.choice([0, 0.5, 1, 65504, np.nan, np.inf], size=size) | ||
| 39 | + tmp_input = tmp_input.reshape(shape).astype(np_type) | ||
| 40 | + tmp_golden = mish(tmp_input) | ||
| 41 | + | ||
| 42 | + tmp_input.astype(np_type).tofile(f"{d_type}_input_t_mish.bin") | ||
| 43 | + tmp_golden.astype(np_type).tofile(f"{d_type}_golden_t_mish.bin") | ||
| 44 | + | ||
| 45 | + | ||
| 46 | +if __name__ == "__main__": | ||
| 47 | + if len(sys.argv) != 3: | ||
| 48 | + print("Param num must be 3.") | ||
| 49 | + exit(1) | ||
| 50 | + # 清理bin文件 | ||
| 51 | + os.system("rm -rf *.bin") | ||
| 52 | + gen_data_and_golden(sys.argv[1], sys.argv[2]) | ||
| 53 | + | ||
| 54 | + | ||
| 55 | + | ||
| @@ -0,0 +1,146 @@ | |||
| 1 | +/** | ||
| 2 | + * This program is free software, you can redistribute it and/or modify it. | ||
| 3 | + * Copyright (c) 2025 Huawei Technologies Co., Ltd. | ||
| 4 | + * This file is a part of the CANN Open Software. | ||
| 5 | + * Licensed under CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 6 | + * Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 7 | + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING | ||
| 8 | + * BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 9 | + * See LICENSE in the root of the software repository for the full text of the License. | ||
| 10 | + */ | ||
| 11 | + | ||
| 12 | +/*! | ||
| 13 | + * \file test_mish.cpp | ||
| 14 | + * \brief | ||
| 15 | + */ | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | +using namespace std; | ||
| 29 | + | ||
| 30 | +extern "C" __global__ __aicore__ void mish(GM_ADDR x, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling); | ||
| 31 | + | ||
| 32 | +class MishTest : public testing::Test { | ||
| 33 | +protected: | ||
| 34 | + static void SetUpTestCase() | ||
| 35 | + { | ||
| 36 | + std::cout << "mish_test SetUp" << std::endl; | ||
| 37 | + const string cmd = "cp -rf " + dataPath + " ./"; | ||
| 38 | + system(cmd.c_str()); | ||
| 39 | + system("chmod -R 755 ./mish_data/"); | ||
| 40 | + } | ||
| 41 | + static void TearDownTestCase() | ||
| 42 | + { | ||
| 43 | + std::cout << "mish_test TearDown" << std::endl; | ||
| 44 | + } | ||
| 45 | + | ||
| 46 | +private: | ||
| 47 | + const static std::string rootPath; | ||
| 48 | + const static std::string dataPath; | ||
| 49 | +}; | ||
| 50 | + | ||
| 51 | +const std::string MishTest::rootPath = "../../../../"; | ||
| 52 | +const std::string MishTest::dataPath = rootPath + "math/mish/tests/ut/op_kernel/mish_data"; | ||
| 53 | + | ||
| 54 | +template <typename T1, typename T2> | ||
| 55 | +inline T1 CeilAlign(T1 a, T2 b) | ||
| 56 | +{ | ||
| 57 | + return (a + b - 1) / b * b; | ||
| 58 | +} | ||
| 59 | + | ||
| 60 | +TEST_F(MishTest, test_case_float16_1) | ||
| 61 | +{ | ||
| 62 | + optiling::MishCompileInfo compileInfo = {64, 262144, false}; | ||
| 63 | + gert::TilingContextPara tilingContextPara( | ||
| 64 | + "Mish", | ||
| 65 | + { | ||
| 66 | + {{{128, 64}, {128, 64}}, ge::DT_FLOAT16, ge::FORMAT_ND}, | ||
| 67 | + }, | ||
| 68 | + { | ||
| 69 | + {{{128, 64}, {128, 64}}, ge::DT_FLOAT16, ge::FORMAT_ND}, | ||
| 70 | + }, | ||
| 71 | + &compileInfo); | ||
| 72 | + TilingInfo tilingInfo; | ||
| 73 | + auto tilingRet = ExecuteTiling(tilingContextPara, tilingInfo); | ||
| 74 | + EXPECT_EQ(tilingRet, true); | ||
| 75 | + | ||
| 76 | + system("cd ./mish_data/ && python3 gen_data.py '(128, 64)' 'float16'"); | ||
| 77 | + uint32_t dataCount = 128 * 64; | ||
| 78 | + size_t inputByteSize = dataCount * sizeof(half); | ||
| 79 | + std::string fileName = "./mish_data/float16_input_t_mish.bin"; | ||
| 80 | + ; | ||
| 81 | + uint8_t* x = (uint8_t*)AscendC::GmAlloc(CeilAlign(inputByteSize, 32)); | ||
| 82 | + ReadFile(fileName, inputByteSize, x, inputByteSize); | ||
| 83 | + size_t outputByteSize = dataCount * sizeof(half); | ||
| 84 | + uint8_t* y = (uint8_t*)AscendC::GmAlloc(CeilAlign(outputByteSize, 32)); | ||
| 85 | + | ||
| 86 | + uint8_t* workspace = (uint8_t*)AscendC::GmAlloc(tilingInfo.workspaceSizes[0]); | ||
| 87 | + uint8_t* tiling = (uint8_t*)AscendC::GmAlloc(tilingInfo.tilingDataSize); | ||
| 88 | + std::memcpy(tiling, tilingInfo.tilingData.get(), tilingInfo.tilingDataSize); | ||
| 89 | + ICPU_SET_TILING_KEY(tilingInfo.tilingKey); | ||
| 90 | + AscendC::SetKernelMode(KernelMode::AIV_MODE); | ||
| 91 | + ICPU_RUN_KF(mish, tilingInfo.blockNum, x, y, workspace, tiling); | ||
| 92 | + | ||
| 93 | + fileName = "./mish_data/float16_output_t_mish.bin"; | ||
| 94 | + WriteFile(fileName, y, outputByteSize); | ||
| 95 | + | ||
| 96 | + AscendC::GmFree((void*)(x)); | ||
| 97 | + AscendC::GmFree((void*)(y)); | ||
| 98 | + AscendC::GmFree((void*)workspace); | ||
| 99 | + AscendC::GmFree((void*)tiling); | ||
| 100 | + | ||
| 101 | + system("cd ./mish_data/ && python3 compare_data.py 'float16'"); | ||
| 102 | +} | ||
| 103 | + | ||
| 104 | +TEST_F(MishTest, test_case_float32_1) | ||
| 105 | +{ | ||
| 106 | + optiling::MishCompileInfo compileInfo = {64, 262144, false}; | ||
| 107 | + gert::TilingContextPara tilingContextPara( | ||
| 108 | + "Mish", | ||
| 109 | + { | ||
| 110 | + {{{256, 33}, {256, 33}}, ge::DT_FLOAT, ge::FORMAT_ND}, | ||
| 111 | + }, | ||
| 112 | + { | ||
| 113 | + {{{256, 33}, {256, 33}}, ge::DT_FLOAT, ge::FORMAT_ND}, | ||
| 114 | + }, | ||
| 115 | + &compileInfo); | ||
| 116 | + TilingInfo tilingInfo; | ||
| 117 | + auto tilingRet = ExecuteTiling(tilingContextPara, tilingInfo); | ||
| 118 | + EXPECT_EQ(tilingRet, true); | ||
| 119 | + | ||
| 120 | + system("cd ./mish_data/ && python3 gen_data.py '(256, 33)' 'float32'"); | ||
| 121 | + uint32_t dataCount = 256 * 33; | ||
| 122 | + size_t inputByteSize = dataCount * sizeof(float); | ||
| 123 | + std::string fileName = "./mish_data/float32_input_t_mish.bin"; | ||
| 124 | + ; | ||
| 125 | + uint8_t* x = (uint8_t*)AscendC::GmAlloc(CeilAlign(inputByteSize, 32)); | ||
| 126 | + ReadFile(fileName, inputByteSize, x, inputByteSize); | ||
| 127 | + size_t outputByteSize = dataCount * sizeof(float); | ||
| 128 | + uint8_t* y = (uint8_t*)AscendC::GmAlloc(CeilAlign(outputByteSize, 32)); | ||
| 129 | + | ||
| 130 | + uint8_t* workspace = (uint8_t*)AscendC::GmAlloc(tilingInfo.workspaceSizes[0]); | ||
| 131 | + uint8_t* tiling = (uint8_t*)AscendC::GmAlloc(tilingInfo.tilingDataSize); | ||
| 132 | + std::memcpy(tiling, tilingInfo.tilingData.get(), tilingInfo.tilingDataSize); | ||
| 133 | + ICPU_SET_TILING_KEY(tilingInfo.tilingKey); | ||
| 134 | + AscendC::SetKernelMode(KernelMode::AIV_MODE); | ||
| 135 | + ICPU_RUN_KF(mish, tilingInfo.blockNum, x, y, workspace, tiling); | ||
| 136 | + | ||
| 137 | + fileName = "./mish_data/float32_output_t_mish.bin"; | ||
| 138 | + WriteFile(fileName, y, outputByteSize); | ||
| 139 | + | ||
| 140 | + AscendC::GmFree((void*)(x)); | ||
| 141 | + AscendC::GmFree((void*)(y)); | ||
| 142 | + AscendC::GmFree((void*)workspace); | ||
| 143 | + AscendC::GmFree((void*)tiling); | ||
| 144 | + | ||
| 145 | + system("cd ./mish_data/ && python3 compare_data.py 'float32'"); | ||
| 146 | +} | ||


加一个贡献说明 参考:
贡献说明