已合并
[CANNBot]TanV3、SinhV2算子支持A2 AscendC实现 #1969
Hana77创建于 3月28日
[CANNBot]TanV3、SinhV2算子支持A2 AscendC实现 #1969
已合并
共 22 个文件变更+1527-0
| @@ -0,0 +1,24 @@ | |||
| 1 | +# ---------------------------------------------------------------------------------------------------------- | ||
| 2 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + | ||
| 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, | ||
| 8 | +# INCLUDING 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 | +# NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +# technically reviewed for functional accuracy and security | ||
| 15 | + | ||
| 16 | +file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 17 | +if(NOT ENABLE_TEST) | ||
| 18 | + list(REMOVE_ITEM CURRENT_DIRS tests) | ||
| 19 | +endif() | ||
| 20 | +foreach(SUB_DIR ${CURRENT_DIRS}) | ||
| 21 | + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | ||
| 22 | + add_subdirectory(${SUB_DIR}) | ||
| 23 | + endif() | ||
| 24 | +endforeach() | ||
| @@ -0,0 +1,143 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + do { \ | ||
| 24 | + if (!(cond)) { \ | ||
| 25 | + return_expr; \ | ||
| 26 | + } \ | ||
| 27 | +} while (0) | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + do { \ | ||
| 31 | + printf(message, ##__VA_ARGS__); \ | ||
| 32 | +} while (0) | ||
| 33 | + | ||
| 34 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 35 | + int64_t shape_size = 1; | ||
| 36 | + for (auto i : shape) { | ||
| 37 | + shape_size *= i; | ||
| 38 | + } | ||
| 39 | + return shape_size; | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 43 | + // 固定写法,资源初始化 | ||
| 44 | + auto ret = aclInit(nullptr); | ||
| 45 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 46 | + ret = aclrtSetDevice(deviceId); | ||
| 47 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 48 | + ret = aclrtCreateStream(stream); | ||
| 49 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 50 | + return 0; | ||
| 51 | +} | ||
| 52 | + | ||
| 53 | +template <typename T> | ||
| 54 | +int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 55 | + aclDataType dataType, aclTensor** tensor) { | ||
| 56 | + auto size = GetShapeSize(shape) * sizeof(T); | ||
| 57 | + // 调用aclrtMalloc申请Device侧内存 | ||
| 58 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 59 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 60 | + // 调用aclrtMemcpy将Host侧数据拷贝到Device侧内存上 | ||
| 61 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 62 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 63 | + // 计算连续tensor的strides | ||
| 64 | + std::vector<int64_t> strides(shape.size(), 1); | ||
| 65 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 66 | + strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 67 | + } | ||
| 68 | + // 调用aclCreateTensor接口创建aclTensor | ||
| 69 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 70 | + shape.data(), shape.size(), *deviceAddr); | ||
| 71 | + return 0; | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +int main() { | ||
| 75 | + // 1. (固定写法)device/stream初始化, 参考acl对外接口列表 | ||
| 76 | + // 根据自己的实际device填写deviceId | ||
| 77 | + int32_t deviceId = 0; | ||
| 78 | + aclrtStream stream; | ||
| 79 | + auto ret = Init(deviceId, &stream); | ||
| 80 | + // check根据自己的需要处理 | ||
| 81 | + CHECK_RET(ret == 0, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 82 | + | ||
| 83 | + // 2. 构造输入与输出,需要根据API的接口自定义构造 | ||
| 84 | + std::vector<int64_t> xShape = {4, 2}; | ||
| 85 | + std::vector<int64_t> outShape = {4, 2}; | ||
| 86 | + void* xDeviceAddr = nullptr; | ||
| 87 | + void* outDeviceAddr = nullptr; | ||
| 88 | + aclTensor* x = nullptr; | ||
| 89 | + aclTensor* out = nullptr; | ||
| 90 | + std::vector<float> xHostData = {1, 2, 3, 4, 5, 6, 7, 8}; | ||
| 91 | + std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 92 | + // 创建x aclTensor | ||
| 93 | + ret = CreateAclTensor(xHostData, xShape, &xDeviceAddr, aclDataType::ACL_FLOAT, &x); | ||
| 94 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 95 | + // 创建out aclTensor | ||
| 96 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 97 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 98 | + | ||
| 99 | + // 3. 调用CANN算子库API | ||
| 100 | + uint64_t workspaceSize = 0; | ||
| 101 | + aclOpExecutor* executor; | ||
| 102 | + // 调用aclnnSinhV2第一段接口 | ||
| 103 | + ret = aclnnSinhV2GetWorkspaceSize(x, out, &workspaceSize, &executor); | ||
| 104 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSinhV2GetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 105 | + // 根据第一段接口计算出的workspaceSize申请device内存 | ||
| 106 | + void* workspaceAddr = nullptr; | ||
| 107 | + if (workspaceSize > 0) { | ||
| 108 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 109 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret;); | ||
| 110 | + } | ||
| 111 | + // 调用aclnnSinhV2第二段接口 | ||
| 112 | + ret = aclnnSinhV2(workspaceAddr, workspaceSize, executor, stream); | ||
| 113 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnSinhV2 failed. ERROR: %d\n", ret); return ret); | ||
| 114 | + | ||
| 115 | + // 4. (固定写法)同步等待任务执行结束 | ||
| 116 | + ret = aclrtSynchronizeStream(stream); | ||
| 117 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 118 | + | ||
| 119 | + // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改 | ||
| 120 | + auto size = GetShapeSize(outShape); | ||
| 121 | + std::vector<float> resultData(size, 0); | ||
| 122 | + ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, size * sizeof(float), | ||
| 123 | + ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 124 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 125 | + for (int64_t i = 0; i < size; i++) { | ||
| 126 | + LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 127 | + } | ||
| 128 | + | ||
| 129 | + // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改 | ||
| 130 | + aclDestroyTensor(x); | ||
| 131 | + aclDestroyTensor(out); | ||
| 132 | + | ||
| 133 | + // 7. 释放device资源,需要根据具体API的接口定义修改 | ||
| 134 | + aclrtFree(xDeviceAddr); | ||
| 135 | + aclrtFree(outDeviceAddr); | ||
| 136 | + if (workspaceSize > 0) { | ||
| 137 | + aclrtFree(workspaceAddr); | ||
| 138 | + } | ||
| 139 | + aclrtDestroyStream(stream); | ||
| 140 | + aclrtResetDevice(deviceId); | ||
| 141 | + aclFinalize(); | ||
| 142 | + return 0; | ||
| 143 | +} | ||
| @@ -0,0 +1,16 @@ | |||
| 1 | +# ---------------------------------------------------------------------------------------------------------- | ||
| 2 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + | ||
| 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, | ||
| 8 | +# INCLUDING 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 | +# NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +# technically reviewed for functional accuracy and security | ||
| 15 | + | ||
| 16 | +add_modules_sources(OPTYPE sinh_v2 ACLNNTYPE aclnn) | ||
| @@ -0,0 +1,53 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file sinh_v2_def.cpp | ||
| 19 | + * \brief SinhV2 operator definition - declares inputs, outputs, and chip configuration | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace ops { | ||
| 24 | +class SinhV2 : public OpDef { | ||
| 25 | +public: | ||
| 26 | + explicit SinhV2(const char* name) : OpDef(name) | ||
| 27 | + { | ||
| 28 | + this->Input("x") | ||
| 29 | + .ParamType(REQUIRED) | ||
| 30 | + .DataType({ge::DT_FLOAT, ge::DT_FLOAT16}) | ||
| 31 | + .Format({ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 32 | + .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 33 | + .AutoContiguous(); | ||
| 34 | + this->Output("y") | ||
| 35 | + .ParamType(REQUIRED) | ||
| 36 | + .DataType({ge::DT_FLOAT, ge::DT_FLOAT16}) | ||
| 37 | + .Format({ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 38 | + .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 39 | + .AutoContiguous(); | ||
| 40 | + | ||
| 41 | + OpAICoreConfig aicoreConfig910B; | ||
| 42 | + aicoreConfig910B.DynamicCompileStaticFlag(true) | ||
| 43 | + .DynamicFormatFlag(false) | ||
| 44 | + .DynamicRankSupportFlag(true) | ||
| 45 | + .DynamicShapeSupportFlag(true) | ||
| 46 | + .NeedCheckSupportFlag(false) | ||
| 47 | + .PrecisionReduceFlag(true) | ||
| 48 | + .ExtendCfgInfo("opFile.value", "sinh_v2"); | ||
| 49 | + this->AICore().AddConfig("ascend910b", aicoreConfig910B); | ||
| 50 | + } | ||
| 51 | +}; | ||
| 52 | +OP_ADD(SinhV2); | ||
| 53 | +} // namespace ops | ||
| @@ -0,0 +1,48 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file sinh_v2_infershape.cpp | ||
| 19 | + * \brief SinhV2 shape inference - output shape equals input shape | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +using namespace ge; | ||
| 26 | + | ||
| 27 | +namespace ops { | ||
| 28 | + | ||
| 29 | +static ge::graphStatus InferShape4SinhV2(gert::InferShapeContext* context) | ||
| 30 | +{ | ||
| 31 | + const gert::Shape* input_shape = context->GetInputShape(0); | ||
| 32 | + if (input_shape == nullptr) { | ||
| 33 | + return ge::GRAPH_FAILED; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + gert::Shape* output_shape = context->GetOutputShape(0); | ||
| 37 | + if (output_shape == nullptr) { | ||
| 38 | + return ge::GRAPH_FAILED; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + *output_shape = *input_shape; | ||
| 42 | + | ||
| 43 | + return ge::GRAPH_SUCCESS; | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +IMPL_OP_INFERSHAPE(SinhV2).InferShape(InferShape4SinhV2); | ||
| 47 | + | ||
| 48 | +} // namespace ops | ||
| @@ -0,0 +1,158 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file sinh_v2_tiling.cpp | ||
| 19 | + * \brief SinhV2 Tiling implementation (arch32 - Ascend910B) | ||
| 20 | + * | ||
| 21 | + * Computes tiling parameters for SinhV2 operator: | ||
| 22 | + * - Multi-core splitting: totalNum divided evenly across AI Cores | ||
| 23 | + * - UB splitting: each core processes data in chunks of ubFactor elements | ||
| 24 | + * - TilingKey selection: based on input dtype (float32 vs float16) | ||
| 25 | + */ | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | +namespace optiling { | ||
| 35 | + | ||
| 36 | +using Ops::Base::CeilDiv; | ||
| 37 | +using Ops::Base::FloorDiv; | ||
| 38 | +using Ops::Base::FloorAlign; | ||
| 39 | +using Ops::Base::GetUbBlockSize; | ||
| 40 | + | ||
| 41 | +constexpr uint32_t WS_SYS_SIZE = 0U; | ||
| 42 | +// float32: inputQueue(x2) + outputQueue(x2) + tmpBuf1(x1) + tmpBuf2(x1) = 6 float-sized buffers | ||
| 43 | +// Total bytes = ubFactor * 6 * sizeof(float) | ||
| 44 | +constexpr int64_t BUFFER_NUM_FP32 = 6; | ||
| 45 | +// float16: inputQueue(x2,half) + outputQueue(x2,half) + tmpBuf1(x1,float) + tmpBuf2(x1,float) | ||
| 46 | +// Total bytes = ubFactor * (2*2 + 2*2 + 4 + 4) = ubFactor * 16 = ubFactor * sizeof(float) * 4 | ||
| 47 | +constexpr int64_t BUFFER_NUM_FP16 = 4; | ||
| 48 | + | ||
| 49 | +static const gert::Shape g_vec_1_shape = {1}; | ||
| 50 | + | ||
| 51 | +static inline const gert::Shape EnsureNotScalar(const gert::Shape& in_shape) | ||
| 52 | +{ | ||
| 53 | + if (in_shape.GetDimNum() == 0) { | ||
| 54 | + return g_vec_1_shape; | ||
| 55 | + } | ||
| 56 | + return in_shape; | ||
| 57 | +} | ||
| 58 | + | ||
| 59 | +static ge::graphStatus GetPlatformInfo(gert::TilingContext* context, uint64_t& ubSize, int64_t& coreNum) | ||
| 60 | +{ | ||
| 61 | + fe::PlatFormInfos* platformInfoPtr = context->GetPlatformInfo(); | ||
| 62 | + OP_CHECK_NULL_WITH_CONTEXT(context, platformInfoPtr); | ||
| 63 | + auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfoPtr); | ||
| 64 | + coreNum = ascendcPlatform.GetCoreNumAiv(); | ||
| 65 | + OP_CHECK_IF(coreNum == 0, OP_LOGE(context, "coreNum is 0"), return ge::GRAPH_FAILED); | ||
| 66 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSize); | ||
| 67 | + OP_CHECK_IF(ubSize == 0, OP_LOGE(context, "ubSize is 0"), return ge::GRAPH_FAILED); | ||
| 68 | + return ge::GRAPH_SUCCESS; | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +static ge::graphStatus GetWorkspaceSize(gert::TilingContext* context) | ||
| 72 | +{ | ||
| 73 | + size_t* currentWorkspace = context->GetWorkspaceSizes(1); | ||
| 74 | + OP_CHECK_NULL_WITH_CONTEXT(context, currentWorkspace); | ||
| 75 | + currentWorkspace[0] = WS_SYS_SIZE; | ||
| 76 | + return ge::GRAPH_SUCCESS; | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +static ge::graphStatus SinhV2TilingFunc(gert::TilingContext* context) | ||
| 80 | +{ | ||
| 81 | + // 1. Get platform info | ||
| 82 | + uint64_t ubSize; | ||
| 83 | + int64_t coreNum; | ||
| 84 | + OP_CHECK_IF( | ||
| 85 | + GetPlatformInfo(context, ubSize, coreNum) != ge::GRAPH_SUCCESS, | ||
| 86 | + OP_LOGE(context, "GetPlatformInfo error"), | ||
| 87 | + return ge::GRAPH_FAILED); | ||
| 88 | + | ||
| 89 | + // 2. Get input shape and dtype | ||
| 90 | + auto inputShape = context->GetInputShape(0); | ||
| 91 | + OP_CHECK_NULL_WITH_CONTEXT(context, inputShape); | ||
| 92 | + auto storageShape = EnsureNotScalar(inputShape->GetStorageShape()); | ||
| 93 | + int64_t totalNum = storageShape.GetShapeSize(); | ||
| 94 | + | ||
| 95 | + auto inputDesc = context->GetInputDesc(0); | ||
| 96 | + OP_CHECK_NULL_WITH_CONTEXT(context, inputDesc); | ||
| 97 | + ge::DataType dtype = inputDesc->GetDataType(); | ||
| 98 | + | ||
| 99 | + // 3. Get workspace size | ||
| 100 | + OP_CHECK_IF( | ||
| 101 | + GetWorkspaceSize(context) != ge::GRAPH_SUCCESS, | ||
| 102 | + OP_LOGE(context, "GetWorkspaceSize error"), | ||
| 103 | + return ge::GRAPH_FAILED); | ||
| 104 | + | ||
| 105 | + // 4. Set TilingData | ||
| 106 | + SinhV2TilingData* tiling = context->GetTilingData<SinhV2TilingData>(); | ||
| 107 | + OP_CHECK_NULL_WITH_CONTEXT(context, tiling); | ||
| 108 | + OP_CHECK_IF( | ||
| 109 | + memset_s(tiling, sizeof(SinhV2TilingData), 0, sizeof(SinhV2TilingData)) != EOK, | ||
| 110 | + OP_LOGE(context, "set tiling data error"), | ||
| 111 | + return ge::GRAPH_FAILED); | ||
| 112 | + | ||
| 113 | + // Handle empty tensor | ||
| 114 | + if (totalNum == 0) { | ||
| 115 | + tiling->totalNum = 0; | ||
| 116 | + tiling->blockFactor = 0; | ||
| 117 | + tiling->ubFactor = 0; | ||
| 118 | + context->SetBlockDim(1); | ||
| 119 | + context->SetTilingKey(GET_TPL_TILING_KEY(SINHV2_TPL_SCH_MODE_0)); | ||
| 120 | + return ge::GRAPH_SUCCESS; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + // 5. Multi-core splitting | ||
| 124 | + tiling->totalNum = totalNum; | ||
| 125 | + tiling->blockFactor = CeilDiv(totalNum, coreNum); | ||
| 126 | + int64_t usedCoreNum = CeilDiv(totalNum, tiling->blockFactor); | ||
| 127 | + | ||
| 128 | + // 6. UB splitting and TilingKey selection | ||
| 129 | + int64_t ubCanUse = static_cast<int64_t>(ubSize); | ||
| 130 | + int64_t ubBlockSize = GetUbBlockSize(context); | ||
| 131 | + // Both paths compute internally in float32, so typeSize = 4 | ||
| 132 | + constexpr int64_t typeSize = 4; | ||
| 133 | + | ||
| 134 | + if (dtype == ge::DT_FLOAT) { | ||
| 135 | + tiling->ubFactor = FloorAlign(FloorDiv((ubCanUse / typeSize), BUFFER_NUM_FP32), ubBlockSize); | ||
| 136 | + context->SetTilingKey(GET_TPL_TILING_KEY(SINHV2_TPL_SCH_MODE_0)); | ||
| 137 | + } else if (dtype == ge::DT_FLOAT16) { | ||
| 138 | + tiling->ubFactor = FloorAlign(FloorDiv((ubCanUse / typeSize), BUFFER_NUM_FP16), ubBlockSize); | ||
| 139 | + context->SetTilingKey(GET_TPL_TILING_KEY(SINHV2_TPL_SCH_MODE_1)); | ||
| 140 | + } else { | ||
| 141 | + OP_LOGE(context, "SinhV2: unsupported dtype"); | ||
| 142 | + return ge::GRAPH_FAILED; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + context->SetBlockDim(usedCoreNum); | ||
| 146 | + return ge::GRAPH_SUCCESS; | ||
| 147 | +} | ||
| 148 | + | ||
| 149 | +static ge::graphStatus TilingParseForSinhV2([[maybe_unused]] gert::TilingParseContext* context) | ||
| 150 | +{ | ||
| 151 | + return ge::GRAPH_SUCCESS; | ||
| 152 | +} | ||
| 153 | + | ||
| 154 | +struct SinhV2CompileInfo {}; | ||
| 155 | + | ||
| 156 | +IMPL_OP_OPTILING(SinhV2).Tiling(SinhV2TilingFunc).TilingParse<SinhV2CompileInfo>(TilingParseForSinhV2); | ||
| 157 | + | ||
| 158 | +} // namespace optiling | ||
| @@ -0,0 +1,45 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file sinh_v2_arch32.cpp | ||
| 19 | + * \brief SinhV2 kernel entry point (arch32 architecture - Ascend910B) | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +enum class SinhV2TilingKey : uint32_t | ||
| 25 | +{ | ||
| 26 | + TILING_KEY_FLOAT32 = 0, | ||
| 27 | + TILING_KEY_FLOAT16 = 1, | ||
| 28 | +}; | ||
| 29 | + | ||
| 30 | +template <uint32_t schMode> | ||
| 31 | +__global__ __aicore__ void sinh_v2(GM_ADDR x, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling) | ||
| 32 | +{ | ||
| 33 | + REGISTER_TILING_DEFAULT(SinhV2TilingData); | ||
| 34 | + GET_TILING_DATA_WITH_STRUCT(SinhV2TilingData, tilingData, tiling); | ||
| 35 | + if constexpr (schMode == static_cast<uint32_t>(SinhV2TilingKey::TILING_KEY_FLOAT32)) { | ||
| 36 | + NsSinhV2::SinhV2<float> op; | ||
| 37 | + op.Init(x, y, &tilingData); | ||
| 38 | + op.Process(); | ||
| 39 | + } | ||
| 40 | + if constexpr (schMode == static_cast<uint32_t>(SinhV2TilingKey::TILING_KEY_FLOAT16)) { | ||
| 41 | + NsSinhV2::SinhV2<half> op; | ||
| 42 | + op.Init(x, y, &tilingData); | ||
| 43 | + op.Process(); | ||
| 44 | + } | ||
| 45 | +} | ||
| @@ -0,0 +1,213 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file sinh_v2.h | ||
| 19 | + * \brief SinhV2 kernel class definition (arch32 - Ascend910B) | ||
| 20 | + * | ||
| 21 | + * Computes sinh(x) = (exp(x) - exp(-x)) / 2 for each element. | ||
| 22 | + * - float32 path: direct computation | ||
| 23 | + * - float16 path: cast to float32 for computation, then cast back | ||
| 24 | + * | ||
| 25 | + * Uses double buffering (BUFFER_NUM=2) for pipeline parallelism: | ||
| 26 | + * - CopyIn: GM -> UB (input data transfer) | ||
| 27 | + * - Compute: UB vector computation (sinh formula) | ||
| 28 | + * - CopyOut: UB -> GM (output data transfer) | ||
| 29 | + */ | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + | ||
| 38 | +namespace NsSinhV2 { | ||
| 39 | + | ||
| 40 | +using namespace AscendC; | ||
| 41 | + | ||
| 42 | +constexpr int32_t BUFFER_NUM = 2; | ||
| 43 | + | ||
| 44 | +template <typename T> | ||
| 45 | +class SinhV2 { | ||
| 46 | +public: | ||
| 47 | + __aicore__ inline SinhV2() {}; | ||
| 48 | + | ||
| 49 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, const SinhV2TilingData* tilingData); | ||
| 50 | + __aicore__ inline void Process(); | ||
| 51 | + | ||
| 52 | +private: | ||
| 53 | + __aicore__ inline void CopyIn(int64_t progress, int64_t currentNum); | ||
| 54 | + __aicore__ inline void CopyOut(int64_t progress, int64_t currentNum); | ||
| 55 | + __aicore__ inline void Compute(int64_t currentNum); | ||
| 56 | + | ||
| 57 | +private: | ||
| 58 | + TPipe pipe; | ||
| 59 | + TQue<QuePosition::VECIN, BUFFER_NUM> inputQueue; | ||
| 60 | + TQue<QuePosition::VECOUT, BUFFER_NUM> outputQueue; | ||
| 61 | + TBuf<QuePosition::VECCALC> tmpBuf1; | ||
| 62 | + TBuf<QuePosition::VECCALC> tmpBuf2; | ||
| 63 | + | ||
| 64 | + GlobalTensor<T> inputGM; | ||
| 65 | + GlobalTensor<T> outputGM; | ||
| 66 | + | ||
| 67 | + int64_t blockLength_ = 0; | ||
| 68 | + int64_t ubLength_ = 0; | ||
| 69 | +}; | ||
| 70 | + | ||
| 71 | +// ============================================================================ | ||
| 72 | +// Init - Initialize GM pointers and allocate UB buffers | ||
| 73 | +// ============================================================================ | ||
| 74 | +template <typename T> | ||
| 75 | +__aicore__ inline void SinhV2<T>::Init(GM_ADDR x, GM_ADDR y, const SinhV2TilingData* tilingData) | ||
| 76 | +{ | ||
| 77 | + int64_t remainderLength = tilingData->totalNum - tilingData->blockFactor * AscendC::GetBlockIdx(); | ||
| 78 | + blockLength_ = (remainderLength > tilingData->blockFactor) ? tilingData->blockFactor : remainderLength; | ||
| 79 | + // Clamp to 0 for idle cores (when totalNum < coreNum, some cores have no work) | ||
| 80 | + if (blockLength_ < 0) { | ||
| 81 | + blockLength_ = 0; | ||
| 82 | + } | ||
| 83 | + ubLength_ = tilingData->ubFactor; | ||
| 84 | + | ||
| 85 | + // Guard: empty tensor or idle core - skip buffer allocation | ||
| 86 | + if (blockLength_ <= 0 || ubLength_ <= 0) { | ||
| 87 | + return; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + inputGM.SetGlobalBuffer((__gm__ T*)x + tilingData->blockFactor * AscendC::GetBlockIdx(), blockLength_); | ||
| 91 | + outputGM.SetGlobalBuffer((__gm__ T*)y + tilingData->blockFactor * AscendC::GetBlockIdx(), blockLength_); | ||
| 92 | + | ||
| 93 | + pipe.InitBuffer(inputQueue, BUFFER_NUM, ubLength_ * sizeof(T)); | ||
| 94 | + pipe.InitBuffer(outputQueue, BUFFER_NUM, ubLength_ * sizeof(T)); | ||
| 95 | + // Temporary buffers for intermediate computation (exp results) | ||
| 96 | + // For float32: used as float buffers directly | ||
| 97 | + // For float16: used as float32 buffers for precision-promoted computation | ||
| 98 | + pipe.InitBuffer(tmpBuf1, ubLength_ * sizeof(float)); | ||
| 99 | + pipe.InitBuffer(tmpBuf2, ubLength_ * sizeof(float)); | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +// ============================================================================ | ||
| 103 | +// CopyIn - Transfer data from GM to UB | ||
| 104 | +// ============================================================================ | ||
| 105 | +template <typename T> | ||
| 106 | +__aicore__ inline void SinhV2<T>::CopyIn(int64_t progress, int64_t currentNum) | ||
| 107 | +{ | ||
| 108 | + AscendC::LocalTensor<T> xLocal = inputQueue.AllocTensor<T>(); | ||
| 109 | + AscendC::DataCopyParams copyParams; | ||
| 110 | + copyParams.blockCount = 1; | ||
| 111 | + copyParams.blockLen = currentNum * sizeof(T); | ||
| 112 | + copyParams.srcStride = 0; | ||
| 113 | + copyParams.dstStride = 0; | ||
| 114 | + AscendC::DataCopyPad(xLocal, inputGM[progress * ubLength_], copyParams, {false, 0, 0, 0}); | ||
| 115 | + inputQueue.EnQue(xLocal); | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +// ============================================================================ | ||
| 119 | +// CopyOut - Transfer data from UB to GM | ||
| 120 | +// ============================================================================ | ||
| 121 | +template <typename T> | ||
| 122 | +__aicore__ inline void SinhV2<T>::CopyOut(int64_t progress, int64_t currentNum) | ||
| 123 | +{ | ||
| 124 | + AscendC::LocalTensor<T> yLocal = outputQueue.DeQue<T>(); | ||
| 125 | + AscendC::DataCopyParams copyParams; | ||
| 126 | + copyParams.blockCount = 1; | ||
| 127 | + copyParams.blockLen = currentNum * sizeof(T); | ||
| 128 | + copyParams.srcStride = 0; | ||
| 129 | + copyParams.dstStride = 0; | ||
| 130 | + AscendC::DataCopyPad(outputGM[progress * ubLength_], yLocal, copyParams); | ||
| 131 | + outputQueue.FreeTensor(yLocal); | ||
| 132 | +} | ||
| 133 | + | ||
| 134 | +// ============================================================================ | ||
| 135 | +// Compute - float32 specialization: direct sinh computation | ||
| 136 | +// sinh(x) = (exp(x) - exp(-x)) / 2 | ||
| 137 | +// ============================================================================ | ||
| 138 | +template <> | ||
| 139 | +__aicore__ inline void SinhV2<float>::Compute(int64_t currentNum) | ||
| 140 | +{ | ||
| 141 | + AscendC::LocalTensor<float> xLocal = inputQueue.DeQue<float>(); | ||
| 142 | + AscendC::LocalTensor<float> yLocal = outputQueue.AllocTensor<float>(); | ||
| 143 | + AscendC::LocalTensor<float> expPos = tmpBuf1.Get<float>(); | ||
| 144 | + AscendC::LocalTensor<float> expNeg = tmpBuf2.Get<float>(); | ||
| 145 | + | ||
| 146 | + // Step 1: exp(x) | ||
| 147 | + AscendC::Exp(expPos, xLocal, currentNum); | ||
| 148 | + // Step 2: -x | ||
| 149 | + AscendC::Muls(xLocal, xLocal, static_cast<float>(-1.0f), currentNum); | ||
| 150 | + // Step 3: exp(-x) | ||
| 151 | + AscendC::Exp(expNeg, xLocal, currentNum); | ||
| 152 | + // Step 4: exp(x) - exp(-x) | ||
| 153 | + AscendC::Sub(expPos, expPos, expNeg, currentNum); | ||
| 154 | + // Step 5: (exp(x) - exp(-x)) * 0.5 | ||
| 155 | + AscendC::Muls(yLocal, expPos, static_cast<float>(0.5f), currentNum); | ||
| 156 | + | ||
| 157 | + outputQueue.EnQue<float>(yLocal); | ||
| 158 | + inputQueue.FreeTensor(xLocal); | ||
| 159 | +} | ||
| 160 | + | ||
| 161 | +// ============================================================================ | ||
| 162 | +// Compute - float16 specialization: cast to float32, compute, cast back | ||
| 163 | +// ============================================================================ | ||
| 164 | +template <> | ||
| 165 | +__aicore__ inline void SinhV2<half>::Compute(int64_t currentNum) | ||
| 166 | +{ | ||
| 167 | + AscendC::LocalTensor<half> xLocal = inputQueue.DeQue<half>(); | ||
| 168 | + AscendC::LocalTensor<half> yLocal = outputQueue.AllocTensor<half>(); | ||
| 169 | + AscendC::LocalTensor<float> xFloat = tmpBuf1.Get<float>(); | ||
| 170 | + AscendC::LocalTensor<float> expNeg = tmpBuf2.Get<float>(); | ||
| 171 | + | ||
| 172 | + // Step 1: Cast half -> float for precision | ||
| 173 | + AscendC::Cast(xFloat, xLocal, AscendC::RoundMode::CAST_NONE, currentNum); | ||
| 174 | + // Step 2: exp(x) - store in xLocal's position (we reuse xFloat after saving exp result) | ||
| 175 | + // We need expPos, so let's compute exp(x) into expNeg first as temp, then swap | ||
| 176 | + // Actually: compute exp(x) into expNeg (as temp for expPos), then compute -x, then exp(-x) | ||
| 177 | + AscendC::Exp(expNeg, xFloat, currentNum); // expNeg temporarily holds exp(x) | ||
| 178 | + // Step 3: -x | ||
| 179 | + AscendC::Muls(xFloat, xFloat, static_cast<float>(-1.0f), currentNum); | ||
| 180 | + // Step 4: exp(-x) - store back into xFloat (reuse) | ||
| 181 | + AscendC::Exp(xFloat, xFloat, currentNum); // xFloat now holds exp(-x) | ||
| 182 | + // Step 5: exp(x) - exp(-x) : expNeg has exp(x), xFloat has exp(-x) | ||
| 183 | + AscendC::Sub(expNeg, expNeg, xFloat, currentNum); | ||
| 184 | + // Step 6: * 0.5 | ||
| 185 | + AscendC::Muls(xFloat, expNeg, static_cast<float>(0.5f), currentNum); | ||
| 186 | + // Step 7: Cast float -> half | ||
| 187 | + AscendC::Cast(yLocal, xFloat, AscendC::RoundMode::CAST_ROUND, currentNum); | ||
| 188 | + | ||
| 189 | + outputQueue.EnQue<half>(yLocal); | ||
| 190 | + inputQueue.FreeTensor(xLocal); | ||
| 191 | +} | ||
| 192 | + | ||
| 193 | +// ============================================================================ | ||
| 194 | +// Process - Main loop: iterate over tiles | ||
| 195 | +// ============================================================================ | ||
| 196 | +template <typename T> | ||
| 197 | +__aicore__ inline void SinhV2<T>::Process() | ||
| 198 | +{ | ||
| 199 | + // Guard: empty tensor or idle core - nothing to process | ||
| 200 | + if (blockLength_ <= 0 || ubLength_ <= 0) { | ||
| 201 | + return; | ||
| 202 | + } | ||
| 203 | + int64_t loopCount = (blockLength_ + ubLength_ - 1) / ubLength_; | ||
| 204 | + for (int64_t i = 0; i < loopCount; i++) { | ||
| 205 | + int64_t currentNum = (i == (loopCount - 1)) ? (blockLength_ - ubLength_ * i) : ubLength_; | ||
| 206 | + CopyIn(i, currentNum); | ||
| 207 | + Compute(currentNum); | ||
| 208 | + CopyOut(i, currentNum); | ||
| 209 | + } | ||
| 210 | +} | ||
| 211 | + | ||
| 212 | +} // namespace NsSinhV2 | ||
| 213 | + | ||
| @@ -0,0 +1,31 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file sinh_v2_tiling_data.h | ||
| 19 | + * \brief SinhV2 TilingData structure definition | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +struct SinhV2TilingData { | ||
| 26 | + int64_t totalNum = 0; // Total number of elements | ||
| 27 | + int64_t blockFactor = 0; // Number of elements per AI Core | ||
| 28 | + int64_t ubFactor = 0; // Number of elements per UB loop iteration | ||
| 29 | +}; | ||
| 30 | + | ||
| 31 | + | ||
| @@ -0,0 +1,43 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file sinh_v2_tiling_key.h | ||
| 19 | + * \brief SinhV2 TilingKey definition | ||
| 20 | + * | ||
| 21 | + * TilingKey mapping: | ||
| 22 | + * - SINHV2_TPL_SCH_MODE_0 (0): FLOAT32 type | ||
| 23 | + * - SINHV2_TPL_SCH_MODE_1 (1): FLOAT16 type | ||
| 24 | + */ | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | +ASCENDC_TPL_ARGS_DECL( | ||
| 35 | + SinhV2, | ||
| 36 | + ASCENDC_TPL_UINT_DECL(schMode, 1, ASCENDC_TPL_UI_LIST, | ||
| 37 | + SINHV2_TPL_SCH_MODE_0, SINHV2_TPL_SCH_MODE_1)); | ||
| 38 | + | ||
| 39 | +ASCENDC_TPL_SEL(ASCENDC_TPL_ARGS_SEL( | ||
| 40 | + ASCENDC_TPL_UINT_SEL(schMode, ASCENDC_TPL_UI_LIST, | ||
| 41 | + SINHV2_TPL_SCH_MODE_0, SINHV2_TPL_SCH_MODE_1))); | ||
| 42 | + | ||
| 43 | + | ||
| @@ -0,0 +1,24 @@ | |||
| 1 | +# ---------------------------------------------------------------------------------------------------------- | ||
| 2 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + | ||
| 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, | ||
| 8 | +# INCLUDING 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 | +# NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +# technically reviewed for functional accuracy and security | ||
| 15 | + | ||
| 16 | +file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*) | ||
| 17 | +if(NOT ENABLE_TEST) | ||
| 18 | + list(REMOVE_ITEM CURRENT_DIRS tests) | ||
| 19 | +endif() | ||
| 20 | +foreach(SUB_DIR ${CURRENT_DIRS}) | ||
| 21 | + if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt") | ||
| 22 | + add_subdirectory(${SUB_DIR}) | ||
| 23 | + endif() | ||
| 24 | +endforeach() | ||
| @@ -0,0 +1,130 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | + | ||
| 18 | + | ||
| 19 | + | ||
| 20 | + | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + do { \ | ||
| 24 | + if (!(cond)) { \ | ||
| 25 | + return_expr; \ | ||
| 26 | + } \ | ||
| 27 | + } while (0) | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + do { \ | ||
| 31 | + printf(message, ##__VA_ARGS__); \ | ||
| 32 | + } while (0) | ||
| 33 | + | ||
| 34 | +int64_t GetShapeSize(const std::vector<int64_t>& shape) { | ||
| 35 | + int64_t shape_size = 1; | ||
| 36 | + for (auto i : shape) { | ||
| 37 | + shape_size *= i; | ||
| 38 | + } | ||
| 39 | + return shape_size; | ||
| 40 | +} | ||
| 41 | + | ||
| 42 | +int Init(int32_t deviceId, aclrtStream* stream) { | ||
| 43 | + auto ret = aclInit(nullptr); | ||
| 44 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret); | ||
| 45 | + ret = aclrtSetDevice(deviceId); | ||
| 46 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret); | ||
| 47 | + ret = aclrtCreateStream(stream); | ||
| 48 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret); | ||
| 49 | + return 0; | ||
| 50 | +} | ||
| 51 | + | ||
| 52 | +template <typename T> | ||
| 53 | +int CreateAclTensor(const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, | ||
| 54 | + aclDataType dataType, aclTensor** tensor) { | ||
| 55 | + auto size = GetShapeSize(shape) * sizeof(T); | ||
| 56 | + auto ret = aclrtMalloc(deviceAddr, size, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 57 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMalloc failed. ERROR: %d\n", ret); return ret); | ||
| 58 | + ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE); | ||
| 59 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret); | ||
| 60 | + | ||
| 61 | + std::vector<int64_t> strides(shape.size(), 1); | ||
| 62 | + for (int64_t i = shape.size() - 2; i >= 0; i--) { | ||
| 63 | + strides[i] = shape[i + 1] * strides[i + 1]; | ||
| 64 | + } | ||
| 65 | + | ||
| 66 | + *tensor = aclCreateTensor(shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, | ||
| 67 | + shape.data(), shape.size(), *deviceAddr); | ||
| 68 | + return 0; | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +int main() { | ||
| 72 | + int32_t deviceId = 0; | ||
| 73 | + aclrtStream stream; | ||
| 74 | + auto ret = Init(deviceId, &stream); | ||
| 75 | + CHECK_RET(ret == 0, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret); | ||
| 76 | + | ||
| 77 | + std::vector<int64_t> xShape = {4, 2}; | ||
| 78 | + std::vector<int64_t> outShape = {4, 2}; | ||
| 79 | + void* xDeviceAddr = nullptr; | ||
| 80 | + void* outDeviceAddr = nullptr; | ||
| 81 | + aclTensor* x = nullptr; | ||
| 82 | + aclTensor* out = nullptr; | ||
| 83 | + std::vector<float> xHostData = {1, 2, 3, 4, 5, 6, 7, 8}; | ||
| 84 | + std::vector<float> outHostData = {0, 0, 0, 0, 0, 0, 0, 0}; | ||
| 85 | + | ||
| 86 | + ret = CreateAclTensor(xHostData, xShape, &xDeviceAddr, aclDataType::ACL_FLOAT, &x); | ||
| 87 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 88 | + ret = CreateAclTensor(outHostData, outShape, &outDeviceAddr, aclDataType::ACL_FLOAT, &out); | ||
| 89 | + CHECK_RET(ret == ACL_SUCCESS, return ret); | ||
| 90 | + | ||
| 91 | + uint64_t workspaceSize = 0; | ||
| 92 | + aclOpExecutor* executor = nullptr; | ||
| 93 | + ret = aclnnTanV3GetWorkspaceSize(x, out, &workspaceSize, &executor); | ||
| 94 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnTanV3GetWorkspaceSize failed. ERROR: %d\n", ret); return ret); | ||
| 95 | + | ||
| 96 | + void* workspaceAddr = nullptr; | ||
| 97 | + if (workspaceSize > 0) { | ||
| 98 | + ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST); | ||
| 99 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret;); | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + ret = aclnnTanV3(workspaceAddr, workspaceSize, executor, stream); | ||
| 103 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnTanV3 failed. ERROR: %d\n", ret); return ret); | ||
| 104 | + | ||
| 105 | + ret = aclrtSynchronizeStream(stream); | ||
| 106 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret); | ||
| 107 | + | ||
| 108 | + auto size = GetShapeSize(outShape); | ||
| 109 | + std::vector<float> resultData(size, 0); | ||
| 110 | + ret = aclrtMemcpy(resultData.data(), resultData.size() * sizeof(resultData[0]), outDeviceAddr, size * sizeof(float), | ||
| 111 | + ACL_MEMCPY_DEVICE_TO_HOST); | ||
| 112 | + CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret); | ||
| 113 | + | ||
| 114 | + for (int64_t i = 0; i < size; i++) { | ||
| 115 | + LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]); | ||
| 116 | + } | ||
| 117 | + | ||
| 118 | + aclDestroyTensor(x); | ||
| 119 | + aclDestroyTensor(out); | ||
| 120 | + | ||
| 121 | + aclrtFree(xDeviceAddr); | ||
| 122 | + aclrtFree(outDeviceAddr); | ||
| 123 | + if (workspaceSize > 0) { | ||
| 124 | + aclrtFree(workspaceAddr); | ||
| 125 | + } | ||
| 126 | + aclrtDestroyStream(stream); | ||
| 127 | + aclrtResetDevice(deviceId); | ||
| 128 | + aclFinalize(); | ||
| 129 | + return 0; | ||
| 130 | +} | ||
| @@ -0,0 +1,16 @@ | |||
| 1 | +# ---------------------------------------------------------------------------------------------------------- | ||
| 2 | +# Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +# This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +# CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | + | ||
| 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, | ||
| 8 | +# INCLUDING 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 | +# NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +# technically reviewed for functional accuracy and security | ||
| 15 | + | ||
| 16 | +add_modules_sources(OPTYPE tan_v3 ACLNNTYPE aclnn) | ||
| @@ -0,0 +1,53 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file tan_v3_def.cpp | ||
| 19 | + * \brief TanV3 operator definition - declares inputs, outputs, and chip configuration | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | + | ||
| 23 | +namespace ops { | ||
| 24 | +class TanV3 : public OpDef { | ||
| 25 | +public: | ||
| 26 | + explicit TanV3(const char* name) : OpDef(name) | ||
| 27 | + { | ||
| 28 | + this->Input("x") | ||
| 29 | + .ParamType(REQUIRED) | ||
| 30 | + .DataType({ge::DT_FLOAT, ge::DT_FLOAT16}) | ||
| 31 | + .Format({ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 32 | + .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 33 | + .AutoContiguous(); | ||
| 34 | + this->Output("y") | ||
| 35 | + .ParamType(REQUIRED) | ||
| 36 | + .DataType({ge::DT_FLOAT, ge::DT_FLOAT16}) | ||
| 37 | + .Format({ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 38 | + .UnknownShapeFormat({ge::FORMAT_ND, ge::FORMAT_ND}) | ||
| 39 | + .AutoContiguous(); | ||
| 40 | + | ||
| 41 | + OpAICoreConfig aicoreConfig910B; | ||
| 42 | + aicoreConfig910B.DynamicCompileStaticFlag(true) | ||
| 43 | + .DynamicFormatFlag(false) | ||
| 44 | + .DynamicRankSupportFlag(true) | ||
| 45 | + .DynamicShapeSupportFlag(true) | ||
| 46 | + .NeedCheckSupportFlag(false) | ||
| 47 | + .PrecisionReduceFlag(true) | ||
| 48 | + .ExtendCfgInfo("opFile.value", "tan_v3"); | ||
| 49 | + this->AICore().AddConfig("ascend910b", aicoreConfig910B); | ||
| 50 | + } | ||
| 51 | +}; | ||
| 52 | +OP_ADD(TanV3); | ||
| 53 | +} // namespace ops | ||
| @@ -0,0 +1,48 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file tan_v3_infershape.cpp | ||
| 19 | + * \brief TanV3 shape inference - output shape equals input shape | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +using namespace ge; | ||
| 26 | + | ||
| 27 | +namespace ops { | ||
| 28 | + | ||
| 29 | +static ge::graphStatus InferShape4TanV3(gert::InferShapeContext* context) | ||
| 30 | +{ | ||
| 31 | + const gert::Shape* input_shape = context->GetInputShape(0); | ||
| 32 | + if (input_shape == nullptr) { | ||
| 33 | + return ge::GRAPH_FAILED; | ||
| 34 | + } | ||
| 35 | + | ||
| 36 | + gert::Shape* output_shape = context->GetOutputShape(0); | ||
| 37 | + if (output_shape == nullptr) { | ||
| 38 | + return ge::GRAPH_FAILED; | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + *output_shape = *input_shape; | ||
| 42 | + | ||
| 43 | + return ge::GRAPH_SUCCESS; | ||
| 44 | +} | ||
| 45 | + | ||
| 46 | +IMPL_OP_INFERSHAPE(TanV3).InferShape(InferShape4TanV3); | ||
| 47 | + | ||
| 48 | +} // namespace ops | ||
| @@ -0,0 +1,158 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file tan_v3_tiling.cpp | ||
| 19 | + * \brief Tanv3 Tiling implementation (arch32 - Ascend910B) | ||
| 20 | + * | ||
| 21 | + * Computes tiling parameters for Tanv3 operator: | ||
| 22 | + * - Multi-core splitting: totalNum divided evenly across AI Cores | ||
| 23 | + * - UB splitting: each core processes data in chunks of ubFactor elements | ||
| 24 | + * - TilingKey selection: based on input dtype (float32 vs float16) | ||
| 25 | + */ | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | +namespace optiling { | ||
| 35 | + | ||
| 36 | +using Ops::Base::CeilDiv; | ||
| 37 | +using Ops::Base::FloorDiv; | ||
| 38 | +using Ops::Base::FloorAlign; | ||
| 39 | +using Ops::Base::GetUbBlockSize; | ||
| 40 | + | ||
| 41 | +constexpr uint32_t WS_SYS_SIZE = 0U; | ||
| 42 | +// float32: inputQueue(x2) + outputQueue(x2) + tmpBuf1(x1) + tmpBuf2(x1) = 6 float-sized buffers | ||
| 43 | +// Total bytes = ubFactor * 6 * sizeof(float) | ||
| 44 | +constexpr int64_t BUFFER_NUM_FP32 = 6; | ||
| 45 | +// float16: inputQueue(x2,half) + outputQueue(x2,half) + tmpBuf1(x1,float) + tmpBuf2(x1,float) | ||
| 46 | +// Total bytes = ubFactor * (2*2 + 2*2 + 4 + 4) = ubFactor * 16 = ubFactor * sizeof(float) * 4 | ||
| 47 | +constexpr int64_t BUFFER_NUM_FP16 = 4; | ||
| 48 | + | ||
| 49 | +static const gert::Shape g_vec_1_shape = {1}; | ||
| 50 | + | ||
| 51 | +static inline const gert::Shape EnsureNotScalar(const gert::Shape& in_shape) | ||
| 52 | +{ | ||
| 53 | + if (in_shape.GetDimNum() == 0) { | ||
| 54 | + return g_vec_1_shape; | ||
| 55 | + } | ||
| 56 | + return in_shape; | ||
| 57 | +} | ||
| 58 | + | ||
| 59 | +static ge::graphStatus GetPlatformInfo(gert::TilingContext* context, uint64_t& ubSize, int64_t& coreNum) | ||
| 60 | +{ | ||
| 61 | + fe::PlatFormInfos* platformInfoPtr = context->GetPlatformInfo(); | ||
| 62 | + OP_CHECK_NULL_WITH_CONTEXT(context, platformInfoPtr); | ||
| 63 | + auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfoPtr); | ||
| 64 | + coreNum = ascendcPlatform.GetCoreNumAiv(); | ||
| 65 | + OP_CHECK_IF(coreNum == 0, OP_LOGE(context, "coreNum is 0"), return ge::GRAPH_FAILED); | ||
| 66 | + ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSize); | ||
| 67 | + OP_CHECK_IF(ubSize == 0, OP_LOGE(context, "ubSize is 0"), return ge::GRAPH_FAILED); | ||
| 68 | + return ge::GRAPH_SUCCESS; | ||
| 69 | +} | ||
| 70 | + | ||
| 71 | +static ge::graphStatus GetWorkspaceSize(gert::TilingContext* context) | ||
| 72 | +{ | ||
| 73 | + size_t* currentWorkspace = context->GetWorkspaceSizes(1); | ||
| 74 | + OP_CHECK_NULL_WITH_CONTEXT(context, currentWorkspace); | ||
| 75 | + currentWorkspace[0] = WS_SYS_SIZE; | ||
| 76 | + return ge::GRAPH_SUCCESS; | ||
| 77 | +} | ||
| 78 | + | ||
| 79 | +static ge::graphStatus TanV3TilingFunc(gert::TilingContext* context) | ||
| 80 | +{ | ||
| 81 | + // 1. Get platform info | ||
| 82 | + uint64_t ubSize; | ||
| 83 | + int64_t coreNum; | ||
| 84 | + OP_CHECK_IF( | ||
| 85 | + GetPlatformInfo(context, ubSize, coreNum) != ge::GRAPH_SUCCESS, | ||
| 86 | + OP_LOGE(context, "GetPlatformInfo error"), | ||
| 87 | + return ge::GRAPH_FAILED); | ||
| 88 | + | ||
| 89 | + // 2. Get input shape and dtype | ||
| 90 | + auto inputShape = context->GetInputShape(0); | ||
| 91 | + OP_CHECK_NULL_WITH_CONTEXT(context, inputShape); | ||
| 92 | + auto storageShape = EnsureNotScalar(inputShape->GetStorageShape()); | ||
| 93 | + int64_t totalNum = storageShape.GetShapeSize(); | ||
| 94 | + | ||
| 95 | + auto inputDesc = context->GetInputDesc(0); | ||
| 96 | + OP_CHECK_NULL_WITH_CONTEXT(context, inputDesc); | ||
| 97 | + ge::DataType dtype = inputDesc->GetDataType(); | ||
| 98 | + | ||
| 99 | + // 3. Get workspace size | ||
| 100 | + OP_CHECK_IF( | ||
| 101 | + GetWorkspaceSize(context) != ge::GRAPH_SUCCESS, | ||
| 102 | + OP_LOGE(context, "GetWorkspaceSize error"), | ||
| 103 | + return ge::GRAPH_FAILED); | ||
| 104 | + | ||
| 105 | + // 4. Set TilingData | ||
| 106 | + TanV3TilingData* tiling = context->GetTilingData<TanV3TilingData>(); | ||
| 107 | + OP_CHECK_NULL_WITH_CONTEXT(context, tiling); | ||
| 108 | + OP_CHECK_IF( | ||
| 109 | + memset_s(tiling, sizeof(TanV3TilingData), 0, sizeof(TanV3TilingData)) != EOK, | ||
| 110 | + OP_LOGE(context, "set tiling data error"), | ||
| 111 | + return ge::GRAPH_FAILED); | ||
| 112 | + | ||
| 113 | + // Handle empty tensor | ||
| 114 | + if (totalNum == 0) { | ||
| 115 | + tiling->totalNum = 0; | ||
| 116 | + tiling->blockFactor = 0; | ||
| 117 | + tiling->ubFactor = 0; | ||
| 118 | + context->SetBlockDim(1); | ||
| 119 | + context->SetTilingKey(GET_TPL_TILING_KEY(TANV3_TPL_SCH_MODE_0)); | ||
| 120 | + return ge::GRAPH_SUCCESS; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + // 5. Multi-core splitting | ||
| 124 | + tiling->totalNum = totalNum; | ||
| 125 | + tiling->blockFactor = CeilDiv(totalNum, coreNum); | ||
| 126 | + int64_t usedCoreNum = CeilDiv(totalNum, tiling->blockFactor); | ||
| 127 | + | ||
| 128 | + // 6. UB splitting and TilingKey selection | ||
| 129 | + int64_t ubCanUse = static_cast<int64_t>(ubSize); | ||
| 130 | + int64_t ubBlockSize = GetUbBlockSize(context); | ||
| 131 | + // Both paths compute internally in float32, so typeSize = 4 | ||
| 132 | + constexpr int64_t typeSize = 4; | ||
| 133 | + | ||
| 134 | + if (dtype == ge::DT_FLOAT) { | ||
| 135 | + tiling->ubFactor = FloorAlign(FloorDiv((ubCanUse / typeSize), BUFFER_NUM_FP32), ubBlockSize); | ||
| 136 | + context->SetTilingKey(GET_TPL_TILING_KEY(TANV3_TPL_SCH_MODE_0)); | ||
| 137 | + } else if (dtype == ge::DT_FLOAT16) { | ||
| 138 | + tiling->ubFactor = FloorAlign(FloorDiv((ubCanUse / typeSize), BUFFER_NUM_FP16), ubBlockSize); | ||
| 139 | + context->SetTilingKey(GET_TPL_TILING_KEY(TANV3_TPL_SCH_MODE_1)); | ||
| 140 | + } else { | ||
| 141 | + OP_LOGE(context, "TanV3: unsupported dtype"); | ||
| 142 | + return ge::GRAPH_FAILED; | ||
| 143 | + } | ||
| 144 | + | ||
| 145 | + context->SetBlockDim(usedCoreNum); | ||
| 146 | + return ge::GRAPH_SUCCESS; | ||
| 147 | +} | ||
| 148 | + | ||
| 149 | +static ge::graphStatus TilingParseForTanV3([[maybe_unused]] gert::TilingParseContext* context) | ||
| 150 | +{ | ||
| 151 | + return ge::GRAPH_SUCCESS; | ||
| 152 | +} | ||
| 153 | + | ||
| 154 | +struct TanV3CompileInfo {}; | ||
| 155 | + | ||
| 156 | +IMPL_OP_OPTILING(TanV3).Tiling(TanV3TilingFunc).TilingParse<TanV3CompileInfo>(TilingParseForTanV3); | ||
| 157 | + | ||
| 158 | +} // namespace optiling | ||
| @@ -0,0 +1,45 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file tan_v3_arch32.cpp | ||
| 19 | + * \brief TanV3 kernel entry point (arch32 architecture - Ascend910B) | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | +enum class TanV3TilingKey : uint32_t | ||
| 25 | +{ | ||
| 26 | + TILING_KEY_FLOAT32 = 0, | ||
| 27 | + TILING_KEY_FLOAT16 = 1, | ||
| 28 | +}; | ||
| 29 | + | ||
| 30 | +template <uint32_t schMode> | ||
| 31 | +__global__ __aicore__ void tan_v3(GM_ADDR x, GM_ADDR y, GM_ADDR workspace, GM_ADDR tiling) | ||
| 32 | +{ | ||
| 33 | + REGISTER_TILING_DEFAULT(TanV3TilingData); | ||
| 34 | + GET_TILING_DATA_WITH_STRUCT(TanV3TilingData, tilingData, tiling); | ||
| 35 | + if constexpr (schMode == static_cast<uint32_t>(TanV3TilingKey::TILING_KEY_FLOAT32)) { | ||
| 36 | + NsTanV3::TanV3<float> op; | ||
| 37 | + op.Init(x, y, &tilingData); | ||
| 38 | + op.Process(); | ||
| 39 | + } | ||
| 40 | + if constexpr (schMode == static_cast<uint32_t>(TanV3TilingKey::TILING_KEY_FLOAT16)) { | ||
| 41 | + NsTanV3::TanV3<half> op; | ||
| 42 | + op.Init(x, y, &tilingData); | ||
| 43 | + op.Process(); | ||
| 44 | + } | ||
| 45 | +} | ||
| @@ -0,0 +1,205 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file tan_v3.h | ||
| 19 | + * \brief TanV3 kernel class definition (arch32 - Ascend910B) | ||
| 20 | + * | ||
| 21 | + * Computes tan(x) = sin(x) / cos(x) for each element. | ||
| 22 | + * - float32 path: direct computation using Sin, Cos, Div | ||
| 23 | + * - float16 path: cast to float32 for computation, then cast back | ||
| 24 | + * | ||
| 25 | + * Uses double buffering (BUFFER_NUM=2) for pipeline parallelism: | ||
| 26 | + * - CopyIn: GM -> UB (input data transfer) | ||
| 27 | + * - Compute: UB vector computation (tan formula) | ||
| 28 | + * - CopyOut: UB -> GM (output data transfer) | ||
| 29 | + */ | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + | ||
| 38 | +namespace NsTanV3 { | ||
| 39 | + | ||
| 40 | +using namespace AscendC; | ||
| 41 | + | ||
| 42 | +constexpr int32_t BUFFER_NUM = 2; | ||
| 43 | + | ||
| 44 | +template <typename T> | ||
| 45 | +class TanV3 { | ||
| 46 | +public: | ||
| 47 | + __aicore__ inline TanV3() {}; | ||
| 48 | + | ||
| 49 | + __aicore__ inline void Init(GM_ADDR x, GM_ADDR y, const TanV3TilingData* tilingData); | ||
| 50 | + __aicore__ inline void Process(); | ||
| 51 | + | ||
| 52 | +private: | ||
| 53 | + __aicore__ inline void CopyIn(int64_t progress, int64_t currentNum); | ||
| 54 | + __aicore__ inline void CopyOut(int64_t progress, int64_t currentNum); | ||
| 55 | + __aicore__ inline void Compute(int64_t currentNum); | ||
| 56 | + | ||
| 57 | +private: | ||
| 58 | + TPipe pipe; | ||
| 59 | + TQue<QuePosition::VECIN, BUFFER_NUM> inputQueue; | ||
| 60 | + TQue<QuePosition::VECOUT, BUFFER_NUM> outputQueue; | ||
| 61 | + TBuf<QuePosition::VECCALC> tmpBuf1; // stores sin(x) intermediate result | ||
| 62 | + TBuf<QuePosition::VECCALC> tmpBuf2; // stores cos(x) intermediate result | ||
| 63 | + | ||
| 64 | + GlobalTensor<T> inputGM; | ||
| 65 | + GlobalTensor<T> outputGM; | ||
| 66 | + | ||
| 67 | + int64_t blockLength_ = 0; | ||
| 68 | + int64_t ubLength_ = 0; | ||
| 69 | +}; | ||
| 70 | + | ||
| 71 | +// ============================================================================ | ||
| 72 | +// Init - Initialize GM pointers and allocate UB buffers | ||
| 73 | +// ============================================================================ | ||
| 74 | +template <typename T> | ||
| 75 | +__aicore__ inline void TanV3<T>::Init(GM_ADDR x, GM_ADDR y, const TanV3TilingData* tilingData) | ||
| 76 | +{ | ||
| 77 | + int64_t remainderLength = tilingData->totalNum - tilingData->blockFactor * AscendC::GetBlockIdx(); | ||
| 78 | + blockLength_ = (remainderLength > tilingData->blockFactor) ? tilingData->blockFactor : remainderLength; | ||
| 79 | + // Clamp to 0 for idle cores (when totalNum < coreNum, some cores have no work) | ||
| 80 | + if (blockLength_ < 0) { | ||
| 81 | + blockLength_ = 0; | ||
| 82 | + } | ||
| 83 | + ubLength_ = tilingData->ubFactor; | ||
| 84 | + | ||
| 85 | + // Guard: empty tensor or idle core - skip buffer allocation | ||
| 86 | + if (blockLength_ <= 0 || ubLength_ <= 0) { | ||
| 87 | + return; | ||
| 88 | + } | ||
| 89 | + | ||
| 90 | + inputGM.SetGlobalBuffer((__gm__ T*)x + tilingData->blockFactor * AscendC::GetBlockIdx(), blockLength_); | ||
| 91 | + outputGM.SetGlobalBuffer((__gm__ T*)y + tilingData->blockFactor * AscendC::GetBlockIdx(), blockLength_); | ||
| 92 | + | ||
| 93 | + pipe.InitBuffer(inputQueue, BUFFER_NUM, ubLength_ * sizeof(T)); | ||
| 94 | + pipe.InitBuffer(outputQueue, BUFFER_NUM, ubLength_ * sizeof(T)); | ||
| 95 | + // Temporary buffers for sin and cos intermediate results | ||
| 96 | + // For float32: used as float buffers directly | ||
| 97 | + // For float16: used as float32 buffers for precision-promoted computation | ||
| 98 | + pipe.InitBuffer(tmpBuf1, ubLength_ * sizeof(float)); | ||
| 99 | + pipe.InitBuffer(tmpBuf2, ubLength_ * sizeof(float)); | ||
| 100 | +} | ||
| 101 | + | ||
| 102 | +// ============================================================================ | ||
| 103 | +// CopyIn - Transfer data from GM to UB | ||
| 104 | +// ============================================================================ | ||
| 105 | +template <typename T> | ||
| 106 | +__aicore__ inline void TanV3<T>::CopyIn(int64_t progress, int64_t currentNum) | ||
| 107 | +{ | ||
| 108 | + AscendC::LocalTensor<T> xLocal = inputQueue.AllocTensor<T>(); | ||
| 109 | + AscendC::DataCopyParams copyParams; | ||
| 110 | + copyParams.blockCount = 1; | ||
| 111 | + copyParams.blockLen = currentNum * sizeof(T); | ||
| 112 | + copyParams.srcStride = 0; | ||
| 113 | + copyParams.dstStride = 0; | ||
| 114 | + AscendC::DataCopyPad(xLocal, inputGM[progress * ubLength_], copyParams, {false, 0, 0, 0}); | ||
| 115 | + inputQueue.EnQue(xLocal); | ||
| 116 | +} | ||
| 117 | + | ||
| 118 | +// ============================================================================ | ||
| 119 | +// CopyOut - Transfer data from UB to GM | ||
| 120 | +// ============================================================================ | ||
| 121 | +template <typename T> | ||
| 122 | +__aicore__ inline void TanV3<T>::CopyOut(int64_t progress, int64_t currentNum) | ||
| 123 | +{ | ||
| 124 | + AscendC::LocalTensor<T> yLocal = outputQueue.DeQue<T>(); | ||
| 125 | + AscendC::DataCopyParams copyParams; | ||
| 126 | + copyParams.blockCount = 1; | ||
| 127 | + copyParams.blockLen = currentNum * sizeof(T); | ||
| 128 | + copyParams.srcStride = 0; | ||
| 129 | + copyParams.dstStride = 0; | ||
| 130 | + AscendC::DataCopyPad(outputGM[progress * ubLength_], yLocal, copyParams); | ||
| 131 | + outputQueue.FreeTensor(yLocal); | ||
| 132 | +} | ||
| 133 | + | ||
| 134 | +// ============================================================================ | ||
| 135 | +// Compute - float32 specialization: direct tan computation | ||
| 136 | +// tan(x) = sin(x) / cos(x) | ||
| 137 | +// ============================================================================ | ||
| 138 | +template <> | ||
| 139 | +__aicore__ inline void TanV3<float>::Compute(int64_t currentNum) | ||
| 140 | +{ | ||
| 141 | + AscendC::LocalTensor<float> xLocal = inputQueue.DeQue<float>(); | ||
| 142 | + AscendC::LocalTensor<float> yLocal = outputQueue.AllocTensor<float>(); | ||
| 143 | + AscendC::LocalTensor<float> sinVal = tmpBuf1.Get<float>(); | ||
| 144 | + AscendC::LocalTensor<float> cosVal = tmpBuf2.Get<float>(); | ||
| 145 | + | ||
| 146 | + // Step 1: sin(x) -> sinVal (tmpBuf1) | ||
| 147 | + AscendC::Sin(sinVal, xLocal, currentNum); | ||
| 148 | + // Step 2: cos(x) -> cosVal (tmpBuf2) | ||
| 149 | + AscendC::Cos(cosVal, xLocal, currentNum); | ||
| 150 | + // Step 3: sin(x) / cos(x) -> yLocal | ||
| 151 | + AscendC::Div(yLocal, sinVal, cosVal, currentNum); | ||
| 152 | + | ||
| 153 | + outputQueue.EnQue<float>(yLocal); | ||
| 154 | + inputQueue.FreeTensor(xLocal); | ||
| 155 | +} | ||
| 156 | + | ||
| 157 | +// ============================================================================ | ||
| 158 | +// Compute - float16 specialization: cast to float32, compute, cast back | ||
| 159 | +// Flow: Cast(half->float) -> Cos -> Sin -> Div -> Cast(float->half) | ||
| 160 | +// Key constraint: Cos must be computed before Sin to avoid overwriting input | ||
| 161 | +// ============================================================================ | ||
| 162 | +template <> | ||
| 163 | +__aicore__ inline void TanV3<half>::Compute(int64_t currentNum) | ||
| 164 | +{ | ||
| 165 | + AscendC::LocalTensor<half> xLocal = inputQueue.DeQue<half>(); | ||
| 166 | + AscendC::LocalTensor<half> yLocal = outputQueue.AllocTensor<half>(); | ||
| 167 | + AscendC::LocalTensor<float> sinVal = tmpBuf1.Get<float>(); | ||
| 168 | + AscendC::LocalTensor<float> cosVal = tmpBuf2.Get<float>(); | ||
| 169 | + | ||
| 170 | + // Step 1: Cast half -> float (store in sinVal as temp for x_float) | ||
| 171 | + AscendC::Cast(sinVal, xLocal, AscendC::RoundMode::CAST_NONE, currentNum); | ||
| 172 | + // Step 2: cos(x) - must compute before sin overwrites sinVal | ||
| 173 | + AscendC::Cos(cosVal, sinVal, currentNum); | ||
| 174 | + // Step 3: sin(x) - overwrites sinVal (cosVal already saved) | ||
| 175 | + AscendC::Sin(sinVal, sinVal, currentNum); | ||
| 176 | + // Step 4: sin(x) / cos(x) -> sinVal (reuse) | ||
| 177 | + AscendC::Div(sinVal, sinVal, cosVal, currentNum); | ||
| 178 | + // Step 5: Cast float -> half | ||
| 179 | + AscendC::Cast(yLocal, sinVal, AscendC::RoundMode::CAST_ROUND, currentNum); | ||
| 180 | + | ||
| 181 | + outputQueue.EnQue<half>(yLocal); | ||
| 182 | + inputQueue.FreeTensor(xLocal); | ||
| 183 | +} | ||
| 184 | + | ||
| 185 | +// ============================================================================ | ||
| 186 | +// Process - Main loop: iterate over tiles | ||
| 187 | +// ============================================================================ | ||
| 188 | +template <typename T> | ||
| 189 | +__aicore__ inline void TanV3<T>::Process() | ||
| 190 | +{ | ||
| 191 | + // Guard: empty tensor or idle core - nothing to process | ||
| 192 | + if (blockLength_ <= 0 || ubLength_ <= 0) { | ||
| 193 | + return; | ||
| 194 | + } | ||
| 195 | + int64_t loopCount = (blockLength_ + ubLength_ - 1) / ubLength_; | ||
| 196 | + for (int64_t i = 0; i < loopCount; i++) { | ||
| 197 | + int64_t currentNum = (i == (loopCount - 1)) ? (blockLength_ - ubLength_ * i) : ubLength_; | ||
| 198 | + CopyIn(i, currentNum); | ||
| 199 | + Compute(currentNum); | ||
| 200 | + CopyOut(i, currentNum); | ||
| 201 | + } | ||
| 202 | +} | ||
| 203 | + | ||
| 204 | +} // namespace NsTanV3 | ||
| 205 | + | ||
| @@ -0,0 +1,31 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file tan_v3_tiling_data.h | ||
| 19 | + * \brief TanV3 TilingData structure definition | ||
| 20 | + */ | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +struct TanV3TilingData { | ||
| 26 | + int64_t totalNum = 0; // Total number of elements | ||
| 27 | + int64_t blockFactor = 0; // Number of elements per AI Core | ||
| 28 | + int64_t ubFactor = 0; // Number of elements per UB loop iteration | ||
| 29 | +}; | ||
| 30 | + | ||
| 31 | + | ||
| @@ -0,0 +1,43 @@ | |||
| 1 | +/** | ||
| 2 | +* Copyright (c) 2026 Huawei Technologies Co., Ltd. | ||
| 3 | +* This program is free software, you can redistribute it and/or modify it under the terms and conditions of | ||
| 4 | +* CANN Open Software License Agreement Version 2.0 (the "License"). | ||
| 5 | +* Please refer to the License for details. You may not use this file except in compliance with the License. | ||
| 6 | +* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED, | ||
| 7 | +* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. | ||
| 8 | +* See LICENSE in the root of the software repository for the full text of the License. | ||
| 9 | +*/ | ||
| 10 | + | ||
| 11 | +/** | ||
| 12 | +* | ||
| 13 | +* NOTE: Portions of this code were AI-generated and have been | ||
| 14 | +* technically reviewed for functional accuracy and security | ||
| 15 | +*/ | ||
| 16 | + | ||
| 17 | +/** | ||
| 18 | + * \file tan_v3_tiling_key.h | ||
| 19 | + * \brief TanV3 TilingKey definition | ||
| 20 | + * | ||
| 21 | + * TilingKey mapping: | ||
| 22 | + * - TANV3_TPL_SCH_MODE_0 (0): FLOAT32 type | ||
| 23 | + * - TANV3_TPL_SCH_MODE_1 (1): FLOAT16 type | ||
| 24 | + */ | ||
| 25 | + | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + | ||
| 33 | + | ||
| 34 | +ASCENDC_TPL_ARGS_DECL( | ||
| 35 | + TanV3, | ||
| 36 | + ASCENDC_TPL_UINT_DECL(schMode, 1, ASCENDC_TPL_UI_LIST, | ||
| 37 | + TANV3_TPL_SCH_MODE_0, TANV3_TPL_SCH_MODE_1)); | ||
| 38 | + | ||
| 39 | +ASCENDC_TPL_SEL(ASCENDC_TPL_ARGS_SEL( | ||
| 40 | + ASCENDC_TPL_UINT_SEL(schMode, ASCENDC_TPL_UI_LIST, | ||
| 41 | + TANV3_TPL_SCH_MODE_0, TANV3_TPL_SCH_MODE_1))); | ||
| 42 | + | ||
| 43 | + | ||
experimental/math/tan_v3/op_host/tan_v3_def.cpp.DataType({ge::DT_FLOAT, ge::DT_FLOAT16}) .Format({ge::FORMAT_ND, ge::FORMAT_ND})此评论由代码审查工具自动生成