已合并
下一代math支持tanh_grad #589
Sun创建于 2025年12月30日
下一代math支持tanh_grad #589
已合并
Sun创建于 2025年12月30日
47 个文件变更+4937-393
Mdocs/zh/op_list.md+5-5
@@ -1557,12 +1557,12 @@
1557 <tr>1557 <tr>
1558 <td>math</td>1558 <td>math</td>
1559 <td><a href="../../math/tanh_grad">tanh_grad</a></td>1559 <td><a href="../../math/tanh_grad">tanh_grad</a></td>
1560- <td>×</td>1560+ <td></td>
1561- <td>×</td>1561+ <td></td>
1562- <td>×</td>1562+ <td></td>
1563- <td>×</td>1563+ <td></td>
1564 <td>AI Core</td>1564 <td>AI Core</td>
1565- <td>子暂无Ascend C代码实现,欢迎开发者补充贡献,贡献方式参考<a href="../../CONTRIBUTING.md">贡献指南</a>。</td>1565+ <td>Tanh的反向计算。</td>
1566 </tr>1566 </tr>
1567 <tr>1567 <tr>
1568 <td>math</td>1568 <td>math</td>
Mmath/tanh_grad/CMakeLists.txt+9-14
@@ -1,20 +1,15 @@
1# ----------------------------------------------------------------------------1# ----------------------------------------------------------------------------
2-# This program is free software, you can redistribute it and/or modify it.
3# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
4-# This file is a part of the CANN Open Software.3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
5-# Licensed under CANN Open Software License Agreement Version 2.0 (the "License").4+# 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.5# 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, INCLUDING6+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
8-# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7+# 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.8# See LICENSE in the root of the software repository for the full text of the License.
10# ----------------------------------------------------------------------------9# ----------------------------------------------------------------------------
11 10 
12-file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)11+# 设置算子定义时支持的芯片类型
13-if(NOT ENABLE_TEST AND NOT BENCHMARK)12+set(SUPPORT_COMPUTE_UNIT "ascend910_95")
14- list(REMOVE_ITEM CURRENT_DIRS tests)13+# 设置每种芯片类型对应的tiling文件目录,即采用op_host目录下哪个文件夹下的tiling文件编译
15-endif()14+set(SUPPORT_TILING_DIR "arch35")
16-foreach(SUB_DIR ${CURRENT_DIRS})15+add_all_modules_sources(OPTYPE tanh_grad ACLNNTYPE aclnn_exclude COMPUTE_UNIT ${SUPPORT_COMPUTE_UNIT} TILING_DIR ${SUPPORT_TILING_DIR} DISABLE_IN_OPP TRUE)
17- if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
18- add_subdirectory(${SUB_DIR})
19- endif()
20-endforeach()
Mmath/tanh_grad/README.md+71-1
@@ -1,3 +1,73 @@
1# TanhGrad1# TanhGrad
2 2 
3-本目录仅包含TanhGrad算子对应的aclnn接口;如您想要贡献该算子的AscendC实现,请参考[贡献流程](../../CONTRIBUTING.md)。3+## 产品支持情况
4+ 
5+| 产品 | 是否支持 |
6+| ---- | :----:|
7+|Ascend 950PR/Ascend 950DT|√|
8+|Atlas A3 训练系列产品/Atlas A3 推理系列产品|√|
9+|Atlas A2 训练系列产品/Atlas 800I A2 推理产品/A200I A2 Box 异构组件|√|
10+ 
11+## 功能说明
12+ 
13+- 算子功能:Tanh的反向实现。
14+ 
15+- 计算公式:
16+ 
17+$$
18+d = tanh(x)= (\frac{e^{x} - {e^{-x}}}{e^{x} + {e^{-x}}}) \tag{1}
19+$$
20+$$
21+dy = 1 -tanh(x)^2 \tag{2}
22+$$
23+ 
24+## 参数说明
25+ 
26+<table style="undefined;table-layout: fixed; width: 980px"><colgroup>
27+ <col style="width: 100px">
28+ <col style="width: 150px">
29+ <col style="width: 280px">
30+ <col style="width: 330px">
31+ <col style="width: 120px">
32+ </colgroup>
33+ <thead>
34+ <tr>
35+ <th>参数名</th>
36+ <th>输入/输出/属性</th>
37+ <th>描述</th>
38+ <th>数据类型</th>
39+ <th>数据格式</th>
40+ </tr></thead>
41+ <tbody>
42+ <tr>
43+ <td>y</td>
44+ <td>输入</td>
45+ <td>正向的输出。</td>
46+ <td>FLOAT16、FLOAT、BFLOAT16</td>
47+ <td>ND</td>
48+ </tr>
49+ <tr>
50+ <td>dy</td>
51+ <td>输入</td>
52+ <td>反向上一个算子的梯度。</td>
53+ <td>FLOAT16、FLOAT、BFLOAT16</td>
54+ <td>ND</td>
55+ </tr>
56+ <tr>
57+ <td>z</td>
58+ <td>输出</td>
59+ <td>反向的输出。</td>
60+ <td>FLOAT16、FLOAT、BFLOAT16</td>
61+ <td>ND</td>
62+ </tr>
63+ </tbody></table>
64+ 
65+## 约束说明
66+ 
67+
68+ 
69+## 调用说明
70+ 
71+| 调用方式 | 调用样例 | 说明 |
72+|--------------|------------------------------------------------------------------------|--------------------------------------------------------------|
73+| aclnn调用 | [test_aclnn_tanh_backward](./examples/test_aclnn_tanh_grad.cpp) | 通过[aclnnTanhBackward](./docs/aclnnTanhBackward.md)接口方式调用tanh_grad算子。 |
Mmath/tanh_grad/docs/aclnnTanhBackward.md+1-0
@@ -3,6 +3,7 @@
3## 产品支持情况3## 产品支持情况
4| 产品 | 是否支持 |4| 产品 | 是否支持 |
5| :----------------------------------------------------------- | :------: |5| :----------------------------------------------------------- | :------: |
6+|Ascend 950PR/Ascend 950DT|√|
6| <term>Atlas A3 训练系列产品/Atlas A3 推理系列产品</term> | √ |7| <term>Atlas A3 训练系列产品/Atlas A3 推理系列产品</term> | √ |
7| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | √ |8| <term>Atlas A2 训练系列产品/Atlas A2 推理系列产品</term> | √ |
8 9 
Amath/tanh_grad/examples/test_aclnn_tanh_backward.cpp+154-0
@@ -0,0 +1,154 @@
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+#include <iostream>
12+#include <vector>
13+#include "acl/acl.h"
14+#include "aclnnop/aclnn_tanh_backward.h"
15+ 
16+#define CHECK_RET(cond, return_expr) \
17+ do { \
18+ if (!(cond)) { \
19+ return_expr; \
20+ } \
21+ } while (0)
22+ 
23+#define LOG_PRINT(message, ...) \
24+ do { \
25+ printf(message, ##__VA_ARGS__); \
26+ } while (0)
27+ 
28+int64_t GetShapeSize(const std::vector<int64_t>& shape)
29+{
30+ int64_t shape_size = 1;
31+ for (auto i : shape) {
32+ shape_size *= i;
33+ }
34+ return shape_size;
35+}
36+ 
37+int Init(int32_t deviceId, aclrtStream* stream)
38+{
39+ // 固定写法,资源初始化
40+ auto ret = aclInit(nullptr);
41+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclInit failed. ERROR: %d\n", ret); return ret);
42+ ret = aclrtSetDevice(deviceId);
43+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSetDevice failed. ERROR: %d\n", ret); return ret);
44+ ret = aclrtCreateStream(stream);
45+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtCreateStream failed. ERROR: %d\n", ret); return ret);
46+ return 0;
47+}
48+ 
49+template <typename T>
50+int CreateAclTensor(
51+ const std::vector<T>& hostData, const std::vector<int64_t>& shape, void** deviceAddr, aclDataType dataType,
52+ aclTensor** tensor)
53+{
54+ auto size = GetShapeSize(shape) * sizeof(T);
55+ // 调用aclrtMalloc申请device侧内存
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+ 
59+ // 调用aclrtMemcpy将host侧数据拷贝到device侧内存上
60+ ret = aclrtMemcpy(*deviceAddr, size, hostData.data(), size, ACL_MEMCPY_HOST_TO_DEVICE);
61+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtMemcpy failed. ERROR: %d\n", ret); return ret);
62+ 
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+ 
69+ // 调用aclCreateTensor接口创建aclTensor
70+ *tensor = aclCreateTensor(
71+ shape.data(), shape.size(), dataType, strides.data(), 0, aclFormat::ACL_FORMAT_ND, shape.data(), shape.size(),
72+ *deviceAddr);
73+ return 0;
74+}
75+ 
76+int main()
77+{
78+ // 1. (固定写法)device/stream初始化, 参考acl API手册
79+ // 根据自己的实际device填写deviceId
80+ int32_t deviceId = 0;
81+ aclrtStream stream;
82+ auto ret = Init(deviceId, &stream);
83+ // check根据自己的需要处理
84+ CHECK_RET(ret == 0, LOG_PRINT("Init acl failed. ERROR: %d\n", ret); return ret);
85+ // 2. 构造输入与输出,需要根据API的接口自定义构造
86+ std::vector<int64_t> gradOutputShape = {4, 2};
87+ std::vector<int64_t> outputShape = {4, 2};
88+ std::vector<int64_t> gradInputShape = {4, 2};
89+ void* gradOutputDeviceAddr = nullptr;
90+ void* outputDeviceAddr = nullptr;
91+ void* gradInputDeviceAddr = nullptr;
92+ aclTensor* gradOutput = nullptr;
93+ aclTensor* output = nullptr;
94+ aclTensor* gradInput = nullptr;
95+ std::vector<float> gradOutputHostData = {0, 1, 2, 3, 4, 5, 6, 7.0};
96+ std::vector<float> outputHostData = {1, 1, 1, 2, 2, 2, 3, 3.0};
97+ std::vector<float> gradInputHostData = {0, 0, 0, 0, 0, 0, 0, 0.0};
98+ // 创建gradOutput aclTensor
99+ ret = CreateAclTensor(
100+ gradOutputHostData, gradOutputShape, &gradOutputDeviceAddr, aclDataType::ACL_FLOAT, &gradOutput);
101+ CHECK_RET(ret == ACL_SUCCESS, return ret);
102+ // 创建output aclTensor
103+ ret = CreateAclTensor(outputHostData, outputShape, &outputDeviceAddr, aclDataType::ACL_FLOAT, &output);
104+ CHECK_RET(ret == ACL_SUCCESS, return ret);
105+ // 创建gradInput aclTensor
106+ ret = CreateAclTensor(gradInputHostData, gradInputShape, &gradInputDeviceAddr, aclDataType::ACL_FLOAT, &gradInput);
107+ CHECK_RET(ret == ACL_SUCCESS, return ret);
108+ 
109+ // 3. 调用CANN算子库API,需要修改为具体的API
110+ uint64_t workspaceSize = 0;
111+ aclOpExecutor* executor;
112+ // 调用aclnnTanhBackward第一段接口
113+ ret = aclnnTanhBackwardGetWorkspaceSize(gradOutput, output, gradInput, &workspaceSize, &executor);
114+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnTanhBackwardGetWorkspaceSize failed. ERROR: %d\n", ret); return ret);
115+ // 根据第一段接口计算出的workspaceSize申请device内存
116+ void* workspaceAddr = nullptr;
117+ if (workspaceSize > 0) {
118+ ret = aclrtMalloc(&workspaceAddr, workspaceSize, ACL_MEM_MALLOC_HUGE_FIRST);
119+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("allocate workspace failed. ERROR: %d\n", ret); return ret;);
120+ }
121+ // 调用aclnnTanhBackward第二段接口
122+ ret = aclnnTanhBackward(workspaceAddr, workspaceSize, executor, stream);
123+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclnnTanhBackward failed. ERROR: %d\n", ret); return ret);
124+ // 4. (固定写法)同步等待任务执行结束
125+ ret = aclrtSynchronizeStream(stream);
126+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("aclrtSynchronizeStream failed. ERROR: %d\n", ret); return ret);
127+ // 5. 获取输出的值,将device侧内存上的结果拷贝至host侧,需要根据具体API的接口定义修改
128+ auto size = GetShapeSize(gradInputShape);
129+ std::vector<float> resultData(size, 0);
130+ ret = aclrtMemcpy(
131+ resultData.data(), resultData.size() * sizeof(resultData[0]), gradInputDeviceAddr, size * sizeof(float),
132+ ACL_MEMCPY_DEVICE_TO_HOST);
133+ CHECK_RET(ret == ACL_SUCCESS, LOG_PRINT("copy result from device to host failed. ERROR: %d\n", ret); return ret);
134+ for (int64_t i = 0; i < size; i++) {
135+ LOG_PRINT("result[%ld] is: %f\n", i, resultData[i]);
136+ }
137+ 
138+ // 6. 释放aclTensor和aclScalar,需要根据具体API的接口定义修改
139+ aclDestroyTensor(gradOutput);
140+ aclDestroyTensor(output);
141+ aclDestroyTensor(gradInput);
142+ 
143+ // 7. 释放device资源,需要根据具体API的接口定义修改
144+ aclrtFree(gradOutputDeviceAddr);
145+ aclrtFree(outputDeviceAddr);
146+ aclrtFree(gradInputDeviceAddr);
147+ if (workspaceSize > 0) {
148+ aclrtFree(workspaceAddr);
149+ }
150+ aclrtDestroyStream(stream);
151+ aclrtResetDevice(deviceId);
152+ aclFinalize();
153+ return 0;
154+}
Rmath/tanh_grad/op_host/op_api/aclnn_tanh_backward.cppmath/tanh_grad/op_api/aclnn_tanh_backward.cpp+8-8
@@ -1,12 +1,12 @@
1/**1/**
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.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 of3+ * 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").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.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,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.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.8+ * See LICENSE in the root of the software repository for the full text of the License.
9- */9+ */
10 10 
11#include "tanh_grad.h"11#include "tanh_grad.h"
12#include "aclnn_kernels/contiguous.h"12#include "aclnn_kernels/contiguous.h"
Rmath/tanh_grad/op_host/op_api/aclnn_tanh_backward.hmath/tanh_grad/op_api/aclnn_tanh_backward.h+8-8
@@ -1,12 +1,12 @@
1/**1/**
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.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 of3+ * 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").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.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,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.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.8+ * See LICENSE in the root of the software repository for the full text of the License.
9- */9+ */
10 10 
11#ifndef OP_API_INC_TANH_BACKWARD_H_11#ifndef OP_API_INC_TANH_BACKWARD_H_
12#define OP_API_INC_TANH_BACKWARD_H_12#define OP_API_INC_TANH_BACKWARD_H_
Rmath/tanh_grad/op_host/op_api/tanh_grad.cppmath/tanh_grad/op_api/tanh_grad.cpp+8-8
@@ -1,12 +1,12 @@
1/**1/**
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.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 of3+ * 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").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.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,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.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.8+ * See LICENSE in the root of the software repository for the full text of the License.
9- */9+ */
10#include "tanh_grad.h"10#include "tanh_grad.h"
11#include "opdev/aicpu/aicpu_task.h"11#include "opdev/aicpu/aicpu_task.h"
12#include "opdev/op_log.h"12#include "opdev/op_log.h"
Rmath/tanh_grad/op_host/op_api/tanh_grad.hmath/tanh_grad/op_api/tanh_grad.h+8-8
@@ -1,12 +1,12 @@
1/**1/**
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.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 of3+ * 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").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.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,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.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.8+ * See LICENSE in the root of the software repository for the full text of the License.
9- */9+ */
10 10 
11#ifndef OP_API_INC_LEVEL0_TANH_GRAD_H_11#ifndef OP_API_INC_LEVEL0_TANH_GRAD_H_
12#define OP_API_INC_LEVEL0_TANH_GRAD_H_12#define OP_API_INC_LEVEL0_TANH_GRAD_H_
Rmath/tanh_grad/graph_plugin/tanh_grad_proto.hmath/tanh_grad/op_graph/tanh_grad_proto.h+8-9
@@ -1,12 +1,12 @@
1/**1/**
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.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 of3+ * 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").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.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,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.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.8+ * See LICENSE in the root of the software repository for the full text of the License.
9- */9+ */
10 10 
11/*!11/*!
12 * \file tanh_grad_proto.h12 * \file tanh_grad_proto.h
@@ -47,4 +47,3 @@ REG_OP(TanhGrad)
47} // namespace ge47} // namespace ge
48 48 
49#endif // OPS_OP_PROTO_INC_TANH_GRAD_H_49#endif // OPS_OP_PROTO_INC_TANH_GRAD_H_
50- 
Dmath/tanh_grad/op_host/CMakeLists.txt+0-12
@@ -1,12 +0,0 @@
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-add_modules_sources(OPTYPE tanh_grad ACLNNTYPE aclnn_exclude)
Amath/tanh_grad/op_host/arch35/tanh_grad_tiling_arch35.cpp+292-0
@@ -0,0 +1,292 @@
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+ * \file tanh_grad_tiling_arch35.cpp
13+ * \brief
14+ */
15+ 
16+#include "tanh_grad_tiling_arch35.h"
17+#include "log/log.h"
18+#include "util/math_util.h"
19+#include "platform/platform_info.h"
20+ 
21+using namespace AscendC;
22+using namespace ge;
23+ 
24+namespace optiling {
25+ 
26+static constexpr uint64_t OP_KEY_INVALID = 0;
27+static constexpr uint64_t OP_KEY_1 = 1;
28+static constexpr uint64_t OP_KEY_2 = 2;
29+static constexpr uint64_t OP_KEY_3 = 3;
30+static constexpr uint64_t OP_KEY_4 = 4;
31+static constexpr uint64_t OP_KEY_5 = 5;
32+static constexpr uint64_t OP_KEY_6 = 6;
33+static constexpr uint64_t OP_KEY_7 = 7;
34+static constexpr uint64_t OP_KEY_8 = 8;
35+static constexpr uint64_t OP_KEY_9 = 9;
36+static constexpr uint64_t INDEX_0 = 0;
37+static constexpr uint64_t INDEX_1 = 1;
38+static constexpr uint64_t INDEX_2 = 2;
39+static constexpr uint64_t WORKSPACE_SIZE = 32;
40+ 
41+ge::graphStatus TanhGradTiling::GetPlatformInfo()
42+{
43+ auto platformInfo = context_->GetPlatformInfo();
44+ auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfo);
45+ coreNum = ascendcPlatform.GetCoreNumAiv();
46+ uint64_t ubSizePlatForm;
47+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSizePlatForm);
48+ ubSize = ubSizePlatForm;
49+ 
50+ return ge::GRAPH_SUCCESS;
51+}
52+ 
53+uint64_t TanhGradTiling::GetOpKey(ge::DataType yDtype, ge::DataType dyDtype, ge::DataType zDtype)
54+{
55+ bool opKey1Flag = yDtype == DT_FLOAT16 && dyDtype == DT_FLOAT16 && zDtype == DT_FLOAT16;
CANN-robot
CANN-robotCANN-robot2025年12月30日

代码结构与可维护性: GetOpKey函数使用了大量重复的模式化代码来判断数据类型组合,代码冗长且难以维护。当需要新增数据类型组合时,需要添加新的条件判断,容易出错。

问题类型: 代码结构与可维护性 文件路径: math/tanh_grad/op_host/arch35/tanh_grad_tiling_arch35.cpp 行号: 55 问题代码:

    bool opKey1Flag = yDtype == DT_FLOAT16 && dyDtype == DT_FLOAT16 && zDtype == DT_FLOAT16;
    if (opKey1Flag) {
        return OP_KEY_1;
    }

修改建议:

1. 考虑使用查找表(lookup table)或映射表来简化逻辑。例如,可以创建一个std::map<std::tuple<DataType, DataType, DataType>, uint64_t>来映射数据类型组合到opKey。2. 或者使用switch-case结合位运算来编码数据类型,减少重复代码。3. 至少将数据类型组合的判断提取为内联函数或宏,提高可读性。

此评论由代码审查工具自动生成

likedislike
56+ if (opKey1Flag) {
57+ return OP_KEY_1;
58+ }
59+ bool opKey2Flag = yDtype == DT_FLOAT && dyDtype == DT_FLOAT && zDtype == DT_FLOAT;
60+ if (opKey2Flag) {
61+ return OP_KEY_2;
62+ }
63+ bool opKey3Flag = yDtype == DT_BF16 && dyDtype == DT_BF16 && zDtype == DT_BF16;
64+ if (opKey3Flag) {
65+ return OP_KEY_3;
66+ }
67+ bool opKey4Flag = yDtype == DT_FLOAT16 && dyDtype == DT_FLOAT && zDtype == DT_FLOAT;
68+ if (opKey4Flag) {
69+ return OP_KEY_4;
70+ }
71+ bool opKey5Flag = yDtype == DT_FLOAT16 && dyDtype == DT_BF16 && zDtype == DT_FLOAT;
72+ if (opKey5Flag) {
73+ return OP_KEY_5;
74+ }
75+ bool opKey6Flag = yDtype == DT_FLOAT && dyDtype == DT_FLOAT16 && zDtype == DT_FLOAT;
76+ if (opKey6Flag) {
77+ return OP_KEY_6;
78+ }
79+ bool opKey7Flag = yDtype == DT_FLOAT && dyDtype == DT_BF16 && zDtype == DT_FLOAT;
80+ if (opKey7Flag) {
81+ return OP_KEY_7;
82+ }
83+ bool opKey8Flag = yDtype == DT_BF16 && dyDtype == DT_FLOAT16 && zDtype == DT_FLOAT;
84+ if (opKey8Flag) {
85+ return OP_KEY_8;
86+ }
87+ bool opKey9Flag = yDtype == DT_BF16 && dyDtype == DT_FLOAT && zDtype == DT_FLOAT;
88+ if (opKey9Flag) {
89+ return OP_KEY_9;
90+ }
91+ 
92+ return OP_KEY_INVALID;
93+}
94+ 
95+uint64_t TanhGradTiling::GenerateTilingKey(uint64_t innerKey)
96+{
97+ return opKey * Ops::Base::BROADCAST_OP_KEY_OFFSET + innerKey;
98+}
99+ 
100+std::map<uint64_t, Ops::Base::BroadcastComputeParams> TanhGradTiling::GetComputeMap(uint64_t opKeyInput)
101+{
102+ Ops::Base::BroadcastComputeParams computeParams0;
103+ switch (opKeyInput) {
104+ case OP_KEY_1:
CANN-robot
CANN-robotCANN-robot2025年12月30日

代码结构与可维护性: GetComputeMap函数中的switch-case结构存在大量重复代码,每个case都设置computeParams0的相同字段(maxDtypeBits、minDtypeBits、extraSize、bufferDivisor),只是值不同。这种重复增加了维护成本,且容易在修改时遗漏某些case。

问题类型: 代码结构与可维护性 文件路径: math/tanh_grad/op_host/arch35/tanh_grad_tiling_arch35.cpp 行号: 104 问题代码:

        case OP_KEY_1:
            computeParams0.maxDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS32_SIZE);
            computeParams0.minDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS16_SIZE);
            computeParams0.extraSize = {0, 0};
            computeParams0.bufferDivisor = {96, 96};
            return {{1, computeParams0}};

修改建议:

1. 将每个opKey对应的参数值定义为常量数组或映射表,在函数中根据opKey查找对应的参数值。2. 使用静态const std::map<uint64_t, BroadcastComputeParams>预先初始化所有配置,函数中直接返回查找结果。3. 如果逻辑允许,将参数计算提取为单独的函数,根据数据类型动态计算这些值,而不是硬编码。

此评论由代码审查工具自动生成

likedislike
105+ computeParams0.maxDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS32_SIZE);
106+ computeParams0.minDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS16_SIZE);
107+ computeParams0.extraSize = {0, 0};
108+ computeParams0.bufferDivisor = {96, 96};
109+ return {{1, computeParams0}};
110+ case OP_KEY_2:
111+ computeParams0.maxDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS32_SIZE);
112+ computeParams0.minDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS32_SIZE);
113+ computeParams0.extraSize = {0, 0};
114+ computeParams0.bufferDivisor = {192, 192};
115+ return {{1, computeParams0}};
116+ case OP_KEY_3:
117+ computeParams0.maxDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS32_SIZE);
118+ computeParams0.minDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS16_SIZE);
119+ computeParams0.extraSize = {0, 0};
120+ computeParams0.bufferDivisor = {96, 96};
121+ return {{1, computeParams0}};
122+ case OP_KEY_4:
123+ computeParams0.maxDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS32_SIZE);
124+ computeParams0.minDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS16_SIZE);
125+ computeParams0.extraSize = {0, 0};
126+ computeParams0.bufferDivisor = {160, 160};
127+ return {{1, computeParams0}};
128+ case OP_KEY_5:
129+ computeParams0.maxDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS32_SIZE);
130+ computeParams0.minDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS16_SIZE);
131+ computeParams0.extraSize = {0, 0};
132+ computeParams0.bufferDivisor = {128, 128};
133+ return {{1, computeParams0}};
134+ case OP_KEY_6:
135+ computeParams0.maxDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS32_SIZE);
136+ computeParams0.minDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS16_SIZE);
137+ computeParams0.extraSize = {0, 0};
138+ computeParams0.bufferDivisor = {160, 160};
139+ return {{1, computeParams0}};
140+ case OP_KEY_7:
141+ computeParams0.maxDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS32_SIZE);
142+ computeParams0.minDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS16_SIZE);
143+ computeParams0.extraSize = {0, 0};
144+ computeParams0.bufferDivisor = {160, 160};
145+ return {{1, computeParams0}};
146+ case OP_KEY_8:
147+ computeParams0.maxDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS32_SIZE);
148+ computeParams0.minDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS16_SIZE);
149+ computeParams0.extraSize = {0, 0};
150+ computeParams0.bufferDivisor = {128, 128};
151+ return {{1, computeParams0}};
152+ case OP_KEY_9:
153+ computeParams0.maxDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS32_SIZE);
154+ computeParams0.minDtypeBits = static_cast<int64_t>(Ops::Base::BROADCAST_BITS_SIZE::BITS16_SIZE);
155+ computeParams0.extraSize = {0, 0};
156+ computeParams0.bufferDivisor = {160, 160};
157+ return {{1, computeParams0}};
158+ default:
159+ return {};
160+ }
161+}
162+ 
163+ge::graphStatus TanhGradTiling::GetShapeAttrsInfo()
164+{
165+ auto y = context_->GetInputDesc(INDEX_0);
166+ OP_CHECK_NULL_WITH_CONTEXT(context_, y);
167+ auto yDtype = y->GetDataType();
168+ auto dy = context_->GetInputDesc(INDEX_1);
169+ OP_CHECK_NULL_WITH_CONTEXT(context_, dy);
170+ auto dyDtype = dy->GetDataType();
171+ auto z = context_->GetOutputDesc(INDEX_0);
172+ OP_CHECK_NULL_WITH_CONTEXT(context_, z);
173+ auto zDtype = z->GetDataType();
174+ 
175+ opKey = GetOpKey(yDtype, dyDtype, zDtype);
176+ OP_CHECK_IF(
177+ (opKey == OP_KEY_INVALID), OP_LOGE(context_->GetNodeName(), "can not get opKey"), return ge::GRAPH_FAILED);
178+ return ge::GRAPH_SUCCESS;
179+}
180+ 
181+bool TanhGradTiling::IsCapable()
182+{
183+ return true;
184+}
185+ 
186+ge::graphStatus TanhGradTiling::DoOpTiling()
187+{
188+ Ops::Base::BroadcastTilingParams broadcastTilingParams;
189+ for (uint64_t i = 0; i < context_->GetComputeNodeInputNum(); i++) {
190+ auto shape = context_->GetInputShape(i);
191+ OP_CHECK_NULL_WITH_CONTEXT(context_, shape);
192+ broadcastTilingParams.inShape.push_back(Ops::Base::EnsureNotScalar(shape->GetStorageShape()));
193+ }
194+ auto outputShape = context_->GetOutputShape(0);
195+ OP_CHECK_NULL_WITH_CONTEXT(context_, outputShape);
196+ broadcastTilingParams.outShape = Ops::Base::EnsureNotScalar(outputShape->GetStorageShape());
197+ broadcastTilingParams.computeMap = GetComputeMap(opKey);
198+ broadcastTilingParams.coreNum = coreNum;
199+ broadcastTilingParams.ubSize = ubSize;
200+ 
201+ Ops::Base::BroadcastTilingData broadcastTilingData;
202+ ge::graphStatus status = BroadcastTiling(broadcastTilingParams, broadcastTilingData);
203+ if (status != ge::GRAPH_SUCCESS) {
204+ OP_LOGE(context_->GetNodeName(), "broadcast tiling failed.");
205+ return ge::GRAPH_FAILED;
206+ }
207+ 
208+ tilingKey_ = GenerateTilingKey(broadcastTilingData.innerKey);
209+ blockNum = broadcastTilingData.blockNum;
210+ tilingData.set_blockFormer(broadcastTilingData.blockFormer);
211+ tilingData.set_ubFormer(broadcastTilingData.ubFormer);
212+ tilingData.set_ubOuter(broadcastTilingData.ubOuter);
213+ tilingData.set_ubTail(broadcastTilingData.ubTail);
214+ tilingData.set_blockTail(broadcastTilingData.blockTail);
215+ tilingData.set_shapeLen(broadcastTilingData.shapeLen);
216+ tilingData.set_ubSplitAxis(broadcastTilingData.ubSplitAxis);
217+ tilingData.set_dimProductBeforeUbInner(broadcastTilingData.dimProductBeforeUbInner);
218+ tilingData.set_elemNum(broadcastTilingData.elemNum);
219+ 
220+ std::copy(broadcastTilingData.dims[INDEX_0].begin(), broadcastTilingData.dims[INDEX_0].end(), input0Dims);
221+ tilingData.set_input0Dims(input0Dims);
222+ std::copy(broadcastTilingData.dims[INDEX_1].begin(), broadcastTilingData.dims[INDEX_1].end(), input1Dims);
223+ tilingData.set_input1Dims(input1Dims);
224+ std::copy(broadcastTilingData.dims[INDEX_2].begin(), broadcastTilingData.dims[INDEX_2].end(), outputDims);
225+ tilingData.set_outputDims(outputDims);
226+ std::copy(broadcastTilingData.strides[INDEX_0].begin(), broadcastTilingData.strides[INDEX_0].end(), input0Strides);
227+ tilingData.set_input0Strides(input0Strides);
228+ std::copy(broadcastTilingData.strides[INDEX_1].begin(), broadcastTilingData.strides[INDEX_1].end(), input1Strides);
229+ tilingData.set_input1Strides(input1Strides);
230+ std::copy(broadcastTilingData.strides[INDEX_2].begin(), broadcastTilingData.strides[INDEX_2].end(), outputStrides);
231+ tilingData.set_outputStrides(outputStrides);
232+ 
233+ return ge::GRAPH_SUCCESS;
234+}
235+ 
236+std::string TanhGradTiling::ToString(TanhGradTilingData& tilingDataInput)
237+{
238+ std::string str;
239+ str += " blockFormer:" + std::to_string(tilingDataInput.get_blockFormer());
240+ str += " ubFormer:" + std::to_string(tilingDataInput.get_ubFormer());
241+ str += " ubOuter:" + std::to_string(tilingDataInput.get_ubOuter());
242+ str += " ubTail:" + std::to_string(tilingDataInput.get_ubTail());
243+ str += " blockTail:" + std::to_string(tilingDataInput.get_blockTail());
244+ str += " shapeLen:" + std::to_string(tilingDataInput.get_shapeLen());
245+ str += " ubSplitAxis:" + std::to_string(tilingDataInput.get_ubSplitAxis());
246+ str += " dimProductBeforeUbInner:" + std::to_string(tilingDataInput.get_dimProductBeforeUbInner());
247+ str += " elemNum:" + std::to_string(tilingDataInput.get_elemNum());
248+ return str;
249+}
250+ 
251+ge::graphStatus TanhGradTiling::DoLibApiTiling()
252+{
253+ return ge::GRAPH_SUCCESS;
254+}
255+ 
256+uint64_t TanhGradTiling::GetTilingKey() const
257+{
258+ return tilingKey_;
259+}
260+ 
261+ge::graphStatus TanhGradTiling::GetWorkspaceSize()
262+{
263+ workspaceSize_ = WORKSPACE_SIZE;
264+ return ge::GRAPH_SUCCESS;
265+}
266+ 
267+ge::graphStatus TanhGradTiling::PostTiling()
268+{
269+ context_->SetTilingKey(GetTilingKey());
270+ context_->SetBlockDim(blockNum);
271+ size_t* workspaces = context_->GetWorkspaceSizes(1);
272+ workspaces[0] = workspaceSize_;
273+ tilingData.SaveToBuffer(context_->GetRawTilingData()->GetData(), context_->GetRawTilingData()->GetCapacity());
274+ context_->GetRawTilingData()->SetDataSize(tilingData.GetDataSize());
275+ OP_LOGI(context_, "TilingInfo: %s.", ToString(tilingData).c_str());
276+ return ge::GRAPH_SUCCESS;
277+}
278+ 
279+ge::graphStatus TilingForTanhGrad([[maybe_unused]] gert::TilingContext* context)
280+{
281+ TanhGradTiling tiling(context);
282+ return tiling.DoTiling();
283+}
284+ 
285+ge::graphStatus TilingPrepareForTanhGrad([[maybe_unused]] gert::TilingParseContext* context)
286+{
287+ return ge::GRAPH_SUCCESS;
288+}
289+ 
290+IMPL_OP_OPTILING(TanhGrad).Tiling(TilingForTanhGrad).TilingParse<TanhGradCompileInfo>(TilingPrepareForTanhGrad);
291+ 
292+} // namespace optiling
Amath/tanh_grad/op_host/arch35/tanh_grad_tiling_arch35.h+90-0
@@ -0,0 +1,90 @@
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+ * \file tanh_grad_tiling_arch35.h
13+ * \brief
14+ */
15+ 
16+#ifndef AIR_CXX_RUNTIME_V2_OP_IMPL_TANH_GRAD_H_
CANN-robot
CANN-robotCANN-robot2025年12月30日

头文件卫士命名冲突风险: 头文件卫士定义为 AIR_CXX_RUNTIME_V2_OP_IMPL_TANH_GRAD_H_,但文件名是 tanh_grad_tiling_arch35.h。这种命名不一致可能导致与其他 tanh_grad 相关头文件的卫士冲突,特别是如果存在多个架构版本的文件。

问题类型: 头文件卫士命名冲突风险 文件路径: math/tanh_grad/op_host/arch35/tanh_grad_tiling_arch35.h 行号: 16 问题代码:

#ifndef AIR_CXX_RUNTIME_V2_OP_IMPL_TANH_GRAD_H_
#define AIR_CXX_RUNTIME_V2_OP_IMPL_TANH_GRAD_H_

修改建议:

将头文件卫士改为与文件名更相关的唯一标识,例如:AIR_CXX_RUNTIME_V2_OP_IMPL_TANH_GRAD_TILING_ARCH35_H_

此评论由代码审查工具自动生成

likedislike
17+#define AIR_CXX_RUNTIME_V2_OP_IMPL_TANH_GRAD_H_
18+ 
19+#include "register/op_def_registry.h"
20+#include "register/tilingdata_base.h"
21+#include "tiling_base/tiling_base.h"
22+#include "util/shape_util.h"
23+#include "atvoss/broadcast/broadcast_tiling.h"
24+ 
25+namespace optiling {
26+ 
27+constexpr int64_t TANH_GRAD_MAX_DIM_SIZE = 8;
28+ 
29+BEGIN_TILING_DATA_DEF(TanhGradTilingData)
30+TILING_DATA_FIELD_DEF(int64_t, blockFormer);
31+TILING_DATA_FIELD_DEF(int64_t, ubFormer);
32+TILING_DATA_FIELD_DEF(int64_t, ubOuter);
33+TILING_DATA_FIELD_DEF(int64_t, ubTail);
34+TILING_DATA_FIELD_DEF(int64_t, blockTail);
35+TILING_DATA_FIELD_DEF(int64_t, shapeLen);
36+TILING_DATA_FIELD_DEF(int64_t, ubSplitAxis);
37+TILING_DATA_FIELD_DEF(int64_t, dimProductBeforeUbInner);
38+TILING_DATA_FIELD_DEF(int64_t, elemNum);
39+TILING_DATA_FIELD_DEF_ARR(int64_t, TANH_GRAD_MAX_DIM_SIZE, input0Dims);
40+TILING_DATA_FIELD_DEF_ARR(int64_t, TANH_GRAD_MAX_DIM_SIZE, input1Dims);
41+TILING_DATA_FIELD_DEF_ARR(int64_t, TANH_GRAD_MAX_DIM_SIZE, outputDims);
42+TILING_DATA_FIELD_DEF_ARR(int64_t, TANH_GRAD_MAX_DIM_SIZE, input0Strides);
43+TILING_DATA_FIELD_DEF_ARR(int64_t, TANH_GRAD_MAX_DIM_SIZE, input1Strides);
44+TILING_DATA_FIELD_DEF_ARR(int64_t, TANH_GRAD_MAX_DIM_SIZE, outputStrides);
45+END_TILING_DATA_DEF;
46+ 
47+REGISTER_TILING_DATA_CLASS(TanhGrad, TanhGradTilingData);
48+ 
49+struct TanhGradCompileInfo {
50+ uint64_t coreNum;
51+ uint64_t ubSize;
52+};
53+ 
54+class TanhGradTiling : public Ops::Math::OpTiling::TilingBaseClass {
55+public:
56+ explicit TanhGradTiling(gert::TilingContext* context) : TilingBaseClass(context)
57+ {}
58+ 
59+protected:
60+ bool IsCapable() override;
61+ ge::graphStatus GetPlatformInfo() override;
62+ ge::graphStatus GetShapeAttrsInfo() override;
63+ ge::graphStatus DoOpTiling() override;
64+ ge::graphStatus DoLibApiTiling() override;
65+ uint64_t GetTilingKey() const override;
66+ ge::graphStatus GetWorkspaceSize() override;
67+ ge::graphStatus PostTiling() override;
68+ std::string ToString(TanhGradTilingData& tilingDataInput);
69+ 
70+private:
71+ uint64_t GetOpKey(ge::DataType yDtype, ge::DataType dyDtype, ge::DataType zDtype);
72+ uint64_t GenerateTilingKey(uint64_t innerKey);
73+ std::map<uint64_t, Ops::Base::BroadcastComputeParams> GetComputeMap(uint64_t opKeyInput);
74+ 
75+ TanhGradTilingData tilingData;
76+ uint64_t opKey;
77+ int64_t coreNum;
CANN-robot
CANN-robotCANN-robot2025年12月30日

错误处理与异常安全: 成员变量coreNum和ubSize在TanhGradCompileInfo结构体中定义为uint64_t类型,但在TanhGradTiling类中定义为int64_t类型。同一概念在不同地方使用不同的类型可能导致类型转换问题或混淆。

问题类型: 错误处理与异常安全 文件路径: math/tanh_grad/op_host/arch35/tanh_grad_tiling_arch35.h 行号: 77 问题代码:

    int64_t coreNum;
    int64_t ubSize;

修改建议:

统一使用相同的类型,考虑到这些值应为非负,建议使用uint64_t以保持一致性。同时确保与基类或相关接口的类型匹配。

此评论由代码审查工具自动生成

likedislike
78+ int64_t ubSize;
79+ uint64_t blockNum;
80+ int64_t input0Dims[TANH_GRAD_MAX_DIM_SIZE] = {0};
81+ int64_t input1Dims[TANH_GRAD_MAX_DIM_SIZE] = {0};
82+ int64_t outputDims[TANH_GRAD_MAX_DIM_SIZE] = {0};
83+ int64_t input0Strides[TANH_GRAD_MAX_DIM_SIZE] = {0};
84+ int64_t input1Strides[TANH_GRAD_MAX_DIM_SIZE] = {0};
85+ int64_t outputStrides[TANH_GRAD_MAX_DIM_SIZE] = {0};
86+};
87+ 
88+} // namespace optiling
89+ 
90+#endif // AIR_CXX_RUNTIME_V2_OP_IMPL_TANH_GRAD_H_
Amath/tanh_grad/op_host/config/ascend910_95/tanh_grad_binary.json+338-0
@@ -0,0 +1,338 @@
1+{
2+ "op_type": "TanhGrad",
3+ "op_list": [
4+ {
5+ "bin_filename": "TanhGrad_FP16_FP16",
6+ "inputs": [
7+ {
8+ "name": "y",
9+ "index": 0,
10+ "dtype": "float16",
11+ "format": "ND",
12+ "paramType": "required",
13+ "shape": [
14+ -2
15+ ]
16+ },
17+ {
18+ "name": "dy",
19+ "index": 1,
20+ "dtype": "float16",
21+ "format": "ND",
22+ "paramType": "required",
23+ "shape": [
24+ -2
25+ ]
26+ }
27+ ],
28+ "outputs": [
29+ {
30+ "name": "z",
31+ "index": 0,
32+ "dtype": "float16",
33+ "format": "ND",
34+ "paramType": "required",
35+ "shape": [
36+ -2
37+ ]
38+ }
39+ ]
40+ },
41+ {
42+ "bin_filename": "TanhGrad_FP32_FP32",
43+ "inputs": [
44+ {
45+ "name": "y",
46+ "index": 0,
47+ "dtype": "float32",
48+ "format": "ND",
49+ "paramType": "required",
50+ "shape": [
51+ -2
52+ ]
53+ },
54+ {
55+ "name": "dy",
56+ "index": 1,
57+ "dtype": "float32",
58+ "format": "ND",
59+ "paramType": "required",
60+ "shape": [
61+ -2
62+ ]
63+ }
64+ ],
65+ "outputs": [
66+ {
67+ "name": "z",
68+ "index": 0,
69+ "dtype": "float32",
70+ "format": "ND",
71+ "paramType": "required",
72+ "shape": [
73+ -2
74+ ]
75+ }
76+ ]
77+ },
78+ {
79+ "bin_filename": "TanhGrad_BF16_BF16",
80+ "inputs": [
81+ {
82+ "name": "y",
83+ "index": 0,
84+ "dtype": "bfloat16",
85+ "format": "ND",
86+ "paramType": "required",
87+ "shape": [
88+ -2
89+ ]
90+ },
91+ {
92+ "name": "dy",
93+ "index": 1,
94+ "dtype": "bfloat16",
95+ "format": "ND",
96+ "paramType": "required",
97+ "shape": [
98+ -2
99+ ]
100+ }
101+ ],
102+ "outputs": [
103+ {
104+ "name": "z",
105+ "index": 0,
106+ "dtype": "bfloat16",
107+ "format": "ND",
108+ "paramType": "required",
109+ "shape": [
110+ -2
111+ ]
112+ }
113+ ]
114+ },
115+ {
116+ "bin_filename": "TanhGrad_FP16_FP32",
117+ "inputs": [
118+ {
119+ "name": "y",
120+ "index": 0,
121+ "dtype": "float16",
122+ "format": "ND",
123+ "paramType": "required",
124+ "shape": [
125+ -2
126+ ]
127+ },
128+ {
129+ "name": "dy",
130+ "index": 1,
131+ "dtype": "float32",
132+ "format": "ND",
133+ "paramType": "required",
134+ "shape": [
135+ -2
136+ ]
137+ }
138+ ],
139+ "outputs": [
140+ {
141+ "name": "z",
142+ "index": 0,
143+ "dtype": "float32",
144+ "format": "ND",
145+ "paramType": "required",
146+ "shape": [
147+ -2
148+ ]
149+ }
150+ ]
151+ },
152+ {
153+ "bin_filename": "TanhGrad_FP16_BF16",
154+ "inputs": [
155+ {
156+ "name": "y",
157+ "index": 0,
158+ "dtype": "float16",
159+ "format": "ND",
160+ "paramType": "required",
161+ "shape": [
162+ -2
163+ ]
164+ },
165+ {
166+ "name": "dy",
167+ "index": 1,
168+ "dtype": "bfloat16",
169+ "format": "ND",
170+ "paramType": "required",
171+ "shape": [
172+ -2
173+ ]
174+ }
175+ ],
176+ "outputs": [
177+ {
178+ "name": "z",
179+ "index": 0,
180+ "dtype": "float32",
181+ "format": "ND",
182+ "paramType": "required",
183+ "shape": [
184+ -2
185+ ]
186+ }
187+ ]
188+ },
189+ {
190+ "bin_filename": "TanhGrad_FP32_FP16",
191+ "inputs": [
192+ {
193+ "name": "y",
194+ "index": 0,
195+ "dtype": "float32",
196+ "format": "ND",
197+ "paramType": "required",
198+ "shape": [
199+ -2
200+ ]
201+ },
202+ {
203+ "name": "dy",
204+ "index": 1,
205+ "dtype": "float16",
206+ "format": "ND",
207+ "paramType": "required",
208+ "shape": [
209+ -2
210+ ]
211+ }
212+ ],
213+ "outputs": [
214+ {
215+ "name": "z",
216+ "index": 0,
217+ "dtype": "float32",
218+ "format": "ND",
219+ "paramType": "required",
220+ "shape": [
221+ -2
222+ ]
223+ }
224+ ]
225+ },
226+ {
227+ "bin_filename": "TanhGrad_FP32_BF16",
228+ "inputs": [
229+ {
230+ "name": "y",
231+ "index": 0,
232+ "dtype": "float32",
233+ "format": "ND",
234+ "paramType": "required",
235+ "shape": [
236+ -2
237+ ]
238+ },
239+ {
240+ "name": "dy",
241+ "index": 1,
242+ "dtype": "bfloat16",
243+ "format": "ND",
244+ "paramType": "required",
245+ "shape": [
246+ -2
247+ ]
248+ }
249+ ],
250+ "outputs": [
251+ {
252+ "name": "z",
253+ "index": 0,
254+ "dtype": "float32",
255+ "format": "ND",
256+ "paramType": "required",
257+ "shape": [
258+ -2
259+ ]
260+ }
261+ ]
262+ },
263+ {
264+ "bin_filename": "TanhGrad_BF16_FP32",
265+ "inputs": [
266+ {
267+ "name": "y",
268+ "index": 0,
269+ "dtype": "bfloat16",
270+ "format": "ND",
271+ "paramType": "required",
272+ "shape": [
273+ -2
274+ ]
275+ },
276+ {
277+ "name": "dy",
278+ "index": 1,
279+ "dtype": "float32",
280+ "format": "ND",
281+ "paramType": "required",
282+ "shape": [
283+ -2
284+ ]
285+ }
286+ ],
287+ "outputs": [
288+ {
289+ "name": "z",
290+ "index": 0,
291+ "dtype": "float32",
292+ "format": "ND",
293+ "paramType": "required",
294+ "shape": [
295+ -2
296+ ]
297+ }
298+ ]
299+ },
300+ {
301+ "bin_filename": "TanhGrad_BF16_FP16",
302+ "inputs": [
303+ {
304+ "name": "y",
305+ "index": 0,
306+ "dtype": "bfloat16",
307+ "format": "ND",
308+ "paramType": "required",
309+ "shape": [
310+ -2
311+ ]
312+ },
313+ {
314+ "name": "dy",
315+ "index": 1,
316+ "dtype": "float16",
317+ "format": "ND",
318+ "paramType": "required",
319+ "shape": [
320+ -2
321+ ]
322+ }
323+ ],
324+ "outputs": [
325+ {
326+ "name": "z",
327+ "index": 0,
328+ "dtype": "float32",
329+ "format": "ND",
330+ "paramType": "required",
331+ "shape": [
332+ -2
333+ ]
334+ }
335+ ]
336+ }
337+ ]
338+ }
Amath/tanh_grad/op_host/config/ascend910_95/tanh_grad_simplified_key.ini+13-0
@@ -0,0 +1,13 @@
1+; 该文件主要影响 opc 工具 编译二进制kernel时, --simplified_key_mode 选项中填写的值,格式如下所示:
2+; [某算子]
3+; default=xx
4+; ascendxx=xx
5+; 其中,default为默认mode,ascnedxx为可选mode,如果不同芯片有差异化要求时,需要配置;
6+; 1)如果没有配置:非ascendC算子继续按空处理,即opc编译命令中不添加 --simplified_key_mode 选项,AscendC算子按照 simplified_key_mode=0 处理
7+; 2)如果仅有default配置:各个版本按default配置
8+; 3)如果仅有某些平台的配置,没有default配置:对应平台的按照配置的值传递,非对应平台的:非AscendC算子继续按空处理,AscendC算子按照 simplified_key_mode=0 处理
9+; 4)如果default配置和平台配置都有:对应平台的使用平台的配置,非对应的平台的以default值配置。
10+; 5)对于自定义simplified key的情况,需要在binary_simplified_key_mode.ini 文件中显式配置为None,不传入 --simplified_key_mode 选项,由opc工具和FE框架自行判断使用何种模式
11+; 6)是否是AscendC算子,由 ops/build-in/tbe/op_info_cfg/parser/ascendc_config.json 中配置的算子名字和对于的平台决定
12+[TanhGrad]
13+default=0
Amath/tanh_grad/op_host/tanh_grad_def.cpp+68-0
@@ -0,0 +1,68 @@
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+ * \file tanh_grad.cpp
13+ * \brief
14+ */
15+#include "register/op_def_registry.h"
16+ 
17+namespace ops {
18+class TanhGrad : public OpDef {
19+public:
20+ explicit TanhGrad(const char* name) : OpDef(name)
21+ {
22+ this->Input("y")
23+ .ParamType(REQUIRED)
24+ .DataType(
CANN-robot
CANN-robotCANN-robot2025年12月30日

代码结构与可维护性: 数据类型列表存在重复项且顺序混乱。第24-26行中,ge::DT_FLOAT16重复出现了3次,ge::DT_FLOAT重复出现了2次,ge::DT_BF16重复出现了2次。这种重复不仅增加了代码冗余,还可能导致维护时的混淆。同样的问题也出现在第35-37行和第46-48行的数据类型列表中。

问题类型: 代码结构与可维护性 文件路径: math/tanh_grad/op_host/tanh_grad_def.cpp 行号: 24 问题代码:

            .DataType(
                {ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_FLOAT,
                 ge::DT_BF16, ge::DT_BF16})

修改建议:

建议移除重复的数据类型,只保留每个类型的唯一实例。如果业务上确实需要支持多种精度组合,应使用常量定义或配置文件来管理这些类型列表,避免硬编码。例如:
const std::vector<ge::DataType> kSupportedInputYTypes = {ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16};
然后使用.DataType(kSupportedInputYTypes)。

此评论由代码审查工具自动生成

likedislike
25+ {ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_FLOAT16, ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_FLOAT,
26+ ge::DT_BF16, ge::DT_BF16})
27+ .Format(
CANN-robot
CANN-robotCANN-robot2025年12月30日

代码结构与可维护性: Format和UnknownShapeFormat列表使用了硬编码的重复值,所有9个元素都是ge::FORMAT_ND。这种重复代码增加了维护成本,且当需要修改格式时需要在多个地方同步更新。

问题类型: 代码结构与可维护性 文件路径: math/tanh_grad/op_host/tanh_grad_def.cpp 行号: 27 问题代码:

            .Format(
                {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
                 ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})

修改建议:

建议使用循环或常量数组来初始化这些重复值。例如:
std::vector<ge::Format> formats(9, ge::FORMAT_ND);
然后使用.Format(formats)和.UnknownShapeFormat(formats)。或者如果所有数据类型都使用相同的格式,可以考虑使用更简洁的API(如果框架支持)。

此评论由代码审查工具自动生成

likedislike
28+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
29+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
30+ .UnknownShapeFormat(
31+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
32+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND});
33+ this->Input("dy")
34+ .ParamType(REQUIRED)
35+ .DataType(
36+ {ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_FLOAT16, ge::DT_BF16,
37+ ge::DT_FLOAT16, ge::DT_FLOAT})
38+ .Format(
39+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
40+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
41+ .UnknownShapeFormat(
42+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
43+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND});
44+ this->Output("z")
45+ .ParamType(REQUIRED)
46+ .DataType(
47+ {ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT, ge::DT_FLOAT,
48+ ge::DT_FLOAT, ge::DT_FLOAT})
49+ .Format(
50+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
51+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
52+ .UnknownShapeFormat(
53+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
54+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND});
55+ OpAICoreConfig aicoreConfig;
56+ aicoreConfig.DynamicCompileStaticFlag(true)
57+ .DynamicFormatFlag(false)
58+ .DynamicRankSupportFlag(true)
59+ .DynamicShapeSupportFlag(true)
60+ .NeedCheckSupportFlag(false)
61+ .PrecisionReduceFlag(true)
62+ .ExtendCfgInfo("opFile.value", "tanh_grad_apt");
63+ this->AICore().AddConfig("ascend910_95", aicoreConfig);
64+ }
65+};
66+ 
67+OP_ADD(TanhGrad);
68+} // namespace ops
Amath/tanh_grad/op_host/tanh_grad_infershape.cpp+24-0
@@ -0,0 +1,24 @@
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+#include "op_host/infershape_broadcast_util.h"
12+#include "register/op_impl_registry.h"
13+#include "log/log.h"
14+ 
15+using namespace ge;
16+namespace ops {
17+ 
18+static ge::graphStatus InferShape4GreaterEqual(gert::InferShapeContext* context)
19+{
20+ OP_LOGI("Begin InferShape4GreaterEqual");
21+ return Ops::Base::InferShape4Broadcast(context);
22+}
23+IMPL_OP_INFERSHAPE(TanhGrad).InferShape(InferShape4GreaterEqual);
24+} // namespace ops
Amath/tanh_grad/op_kernel/arch35/tanh_grad_bf16_nddma_with_loops.h+187-0
@@ -0,0 +1,187 @@
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+ * \file tanh_grad_bf16_nddma_with_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_BF16_NDDMA_WITH_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_BF16_NDDMA_WITH_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is bfloat16, dy is bfloat16, z is bfloat16, max dims in ub is 8 and nddma needs loops
31+class TanhGradBf16NddmaWithLoops {
32+public:
33+ __aicore__ inline TanhGradBf16NddmaWithLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ bfloat16_t*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ bfloat16_t*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ bfloat16_t*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(bfloat16_t);
44+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
45+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
47+ }
48+ 
49+ __aicore__ inline void Process()
50+ {
51+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
52+ tilingDataPtr_->blockFormer;
53+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
54+ Ops::Base::BroadcastGetAxesIndices(
55+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
56+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
57+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
58+ if (ubLoopIdx != 0) {
59+ Ops::Base::BroadcastUpdateAxesIndices(
60+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
61+ }
62+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
63+ tilingDataPtr_->ubTail :
64+ tilingDataPtr_->ubFormer;
65+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
66+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
67+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
68+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
69+ }
70+ }
71+ 
72+private:
73+ __aicore__ inline void CopyIn0(
74+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
75+ {
76+ bufferIn0_ = queIn0_.AllocTensor<bfloat16_t>();
77+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
78+ (ubLoopIdx <= 1 ||
79+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
80+ Ops::Base::BroadcastNddmaWithLoop(
81+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
82+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
83+ ubSplitSize, tilingDataPtr_->ubFormer);
84+ }
85+ queIn0_.EnQue<bfloat16_t>(bufferIn0_);
86+ }
87+ 
88+ __aicore__ inline void CopyIn1(
89+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
90+ {
91+ bufferIn1_ = queIn1_.AllocTensor<bfloat16_t>();
92+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
93+ (ubLoopIdx <= 1 ||
94+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
95+ Ops::Base::BroadcastNddmaWithLoop(
96+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
97+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
98+ ubSplitSize, tilingDataPtr_->ubFormer);
99+ }
100+ queIn1_.EnQue<bfloat16_t>(bufferIn1_);
101+ }
102+ 
103+ __aicore__ inline void Compute2(
104+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
105+ {
106+ bufferIn0_ = queIn0_.DeQue<bfloat16_t>();
107+ bufferIn1_ = queIn1_.DeQue<bfloat16_t>();
108+ bufferOut0_ = queOut0_.AllocTensor<bfloat16_t>();
109+ __VEC_SCOPE__
110+ {
111+ RegTensor<bfloat16_t> vreg0;
112+ RegTensor<float> vreg1;
113+ RegTensor<float> vreg2;
114+ RegTensor<float> vreg3;
115+ RegTensor<float> vreg4;
116+ RegTensor<bfloat16_t> vreg5;
117+ RegTensor<float> vreg6;
118+ RegTensor<float> vreg7;
119+ RegTensor<bfloat16_t> vreg8;
120+ MaskReg preg0;
121+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
122+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
123+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
124+ (AscendC::VECTOR_REG_WIDTH / 4);
125+ __local_mem__ bfloat16_t* bufferIn0Addr = (__local_mem__ bfloat16_t*)bufferIn0_.GetPhyAddr();
126+ __local_mem__ bfloat16_t* bufferIn1Addr = (__local_mem__ bfloat16_t*)bufferIn1_.GetPhyAddr();
127+ __local_mem__ bfloat16_t* bufferOut0Addr = (__local_mem__ bfloat16_t*)bufferOut0_.GetPhyAddr();
128+ for (uint16_t i = 0; i < vfLoopNum; i++) {
129+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
130+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
131+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
132+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg1, vreg0, preg0);
133+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
134+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
135+ vreg2, vreg1, static_cast<float>(-1), preg0);
136+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
137+ vreg4, vreg2, vreg1, preg0);
138+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
139+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
140+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg6, vreg5, preg0);
141+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg7, vreg4, vreg6, preg0);
142+ AscendC::MicroAPI::Cast<bfloat16_t, float, castTrait1>(vreg8, vreg7, preg0);
143+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::StoreDist::DIST_PACK_B32>(
144+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg8, preg0);
145+ }
146+ }
147+ queIn0_.FreeTensor(bufferIn0_);
148+ queIn1_.FreeTensor(bufferIn1_);
149+ queOut0_.EnQue<bfloat16_t>(bufferOut0_);
150+ }
151+ 
152+ __aicore__ inline void CopyOut3(
153+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
154+ {
155+ bufferOut0_ = queOut0_.DeQue<bfloat16_t>();
156+ AscendC::DataCopyExtParams dataCopyExtParams;
157+ dataCopyExtParams.blockCount = 1;
158+ dataCopyExtParams.blockLen =
159+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(bfloat16_t);
160+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
161+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
162+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
163+ queOut0_.FreeTensor(bufferOut0_);
164+ }
165+ 
166+private:
167+ TPipe* pipePtr_;
168+ const TanhGradTilingData* tilingDataPtr_;
169+ GlobalTensor<bfloat16_t> inputGmY_;
170+ GlobalTensor<bfloat16_t> inputGmDy_;
171+ GlobalTensor<bfloat16_t> outputGmZ_;
172+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
173+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
174+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
175+ LocalTensor<bfloat16_t> bufferIn0_;
176+ LocalTensor<bfloat16_t> bufferIn1_;
177+ LocalTensor<bfloat16_t> bufferOut0_;
178+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
179+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
180+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
181+ constexpr static AscendC::MicroAPI::CastTrait castTrait1 = {
182+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::NO_SAT,
183+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::CAST_RINT};
184+};
185+ 
186+} // namespace TanhGrad
187+#endif // ASCENDC_TANH_GRAD_BF16_NDDMA_WITH_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_bf16_nddma_without_loops.h+187-0
@@ -0,0 +1,187 @@
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+ * \file tanh_grad_bf16_nddma_without_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_BF16_NDDMA_WITHOUT_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_BF16_NDDMA_WITHOUT_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is bfloat16, dy is bfloat16, z is bfloat16, max dims in ub is 5 and nddma does not need loops
31+class TanhGradBf16NddmaWithoutLoops {
32+public:
33+ __aicore__ inline TanhGradBf16NddmaWithoutLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ bfloat16_t*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ bfloat16_t*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ bfloat16_t*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(bfloat16_t);
44+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
45+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
47+ }
48+ 
49+ __aicore__ inline void Process()
50+ {
51+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
52+ tilingDataPtr_->blockFormer;
53+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
54+ Ops::Base::BroadcastGetAxesIndices(
55+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
56+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
57+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
58+ if (ubLoopIdx != 0) {
59+ Ops::Base::BroadcastUpdateAxesIndices(
60+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
61+ }
62+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
63+ tilingDataPtr_->ubTail :
64+ tilingDataPtr_->ubFormer;
65+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
66+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
67+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
68+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
69+ }
70+ }
71+ 
72+private:
73+ __aicore__ inline void CopyIn0(
74+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
75+ {
76+ bufferIn0_ = queIn0_.AllocTensor<bfloat16_t>();
77+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
78+ (ubLoopIdx <= 1 ||
79+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
80+ Ops::Base::BroadcastNddmaWithoutLoop(
81+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
82+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
83+ ubSplitSize, tilingDataPtr_->ubFormer);
84+ }
85+ queIn0_.EnQue<bfloat16_t>(bufferIn0_);
86+ }
87+ 
88+ __aicore__ inline void CopyIn1(
89+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
90+ {
91+ bufferIn1_ = queIn1_.AllocTensor<bfloat16_t>();
92+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
93+ (ubLoopIdx <= 1 ||
94+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
95+ Ops::Base::BroadcastNddmaWithoutLoop(
96+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
97+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
98+ ubSplitSize, tilingDataPtr_->ubFormer);
99+ }
100+ queIn1_.EnQue<bfloat16_t>(bufferIn1_);
101+ }
102+ 
103+ __aicore__ inline void Compute2(
104+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
105+ {
106+ bufferIn0_ = queIn0_.DeQue<bfloat16_t>();
107+ bufferIn1_ = queIn1_.DeQue<bfloat16_t>();
108+ bufferOut0_ = queOut0_.AllocTensor<bfloat16_t>();
109+ __VEC_SCOPE__
110+ {
111+ RegTensor<bfloat16_t> vreg0;
112+ RegTensor<float> vreg1;
113+ RegTensor<float> vreg2;
114+ RegTensor<float> vreg3;
115+ RegTensor<float> vreg4;
116+ RegTensor<bfloat16_t> vreg5;
117+ RegTensor<float> vreg6;
118+ RegTensor<float> vreg7;
119+ RegTensor<bfloat16_t> vreg8;
120+ MaskReg preg0;
121+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
122+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
123+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
124+ (AscendC::VECTOR_REG_WIDTH / 4);
125+ __local_mem__ bfloat16_t* bufferIn0Addr = (__local_mem__ bfloat16_t*)bufferIn0_.GetPhyAddr();
126+ __local_mem__ bfloat16_t* bufferIn1Addr = (__local_mem__ bfloat16_t*)bufferIn1_.GetPhyAddr();
127+ __local_mem__ bfloat16_t* bufferOut0Addr = (__local_mem__ bfloat16_t*)bufferOut0_.GetPhyAddr();
128+ for (uint16_t i = 0; i < vfLoopNum; i++) {
129+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
130+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
131+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
132+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg1, vreg0, preg0);
133+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
134+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
135+ vreg2, vreg1, static_cast<float>(-1), preg0);
136+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
137+ vreg4, vreg2, vreg1, preg0);
138+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
139+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
140+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg6, vreg5, preg0);
141+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg7, vreg4, vreg6, preg0);
142+ AscendC::MicroAPI::Cast<bfloat16_t, float, castTrait1>(vreg8, vreg7, preg0);
143+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::StoreDist::DIST_PACK_B32>(
144+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg8, preg0);
145+ }
146+ }
147+ queIn0_.FreeTensor(bufferIn0_);
148+ queIn1_.FreeTensor(bufferIn1_);
149+ queOut0_.EnQue<bfloat16_t>(bufferOut0_);
150+ }
151+ 
152+ __aicore__ inline void CopyOut3(
153+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
154+ {
155+ bufferOut0_ = queOut0_.DeQue<bfloat16_t>();
156+ AscendC::DataCopyExtParams dataCopyExtParams;
157+ dataCopyExtParams.blockCount = 1;
158+ dataCopyExtParams.blockLen =
159+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(bfloat16_t);
160+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
161+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
162+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
163+ queOut0_.FreeTensor(bufferOut0_);
164+ }
165+ 
166+private:
167+ TPipe* pipePtr_;
168+ const TanhGradTilingData* tilingDataPtr_;
169+ GlobalTensor<bfloat16_t> inputGmY_;
170+ GlobalTensor<bfloat16_t> inputGmDy_;
171+ GlobalTensor<bfloat16_t> outputGmZ_;
172+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
173+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
174+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
175+ LocalTensor<bfloat16_t> bufferIn0_;
176+ LocalTensor<bfloat16_t> bufferIn1_;
177+ LocalTensor<bfloat16_t> bufferOut0_;
178+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
179+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
180+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
181+ constexpr static AscendC::MicroAPI::CastTrait castTrait1 = {
182+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::NO_SAT,
183+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::CAST_RINT};
184+};
185+ 
186+} // namespace TanhGrad
187+#endif // ASCENDC_TANH_GRAD_BF16_NDDMA_WITHOUT_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_0_nddma_with_loops.h+181-0
@@ -0,0 +1,181 @@
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+ * \file tanh_grad_dtype_comb_0_nddma_with_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_0_NDDMA_WITH_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_0_NDDMA_WITH_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float16, dy is float32, z is float32, max dims in ub is 8 and nddma needs loops
31+class TanhGradDtypeComb0NddmaWithLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb0NddmaWithLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ half*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ float*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(half);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(float);
45+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
47+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_1);
48+ }
49+ 
50+ __aicore__ inline void Process()
51+ {
52+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
53+ tilingDataPtr_->blockFormer;
54+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
55+ Ops::Base::BroadcastGetAxesIndices(
56+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
57+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
58+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
59+ if (ubLoopIdx != 0) {
60+ Ops::Base::BroadcastUpdateAxesIndices(
61+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
62+ }
63+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
64+ tilingDataPtr_->ubTail :
65+ tilingDataPtr_->ubFormer;
66+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
67+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
68+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
69+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
70+ }
71+ }
72+ 
73+private:
74+ __aicore__ inline void CopyIn0(
75+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
76+ {
77+ bufferIn0_ = queIn0_.AllocTensor<half>();
78+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
79+ (ubLoopIdx <= 1 ||
80+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
81+ Ops::Base::BroadcastNddmaWithLoop(
82+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
83+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
84+ ubSplitSize, tilingDataPtr_->ubFormer);
85+ }
86+ queIn0_.EnQue<half>(bufferIn0_);
87+ }
88+ 
89+ __aicore__ inline void CopyIn1(
90+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
91+ {
92+ bufferIn1_ = queIn1_.AllocTensor<float>();
93+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
94+ (ubLoopIdx <= 1 ||
95+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
96+ Ops::Base::BroadcastNddmaWithLoop(
97+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
98+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
99+ ubSplitSize, tilingDataPtr_->ubFormer);
100+ }
101+ queIn1_.EnQue<float>(bufferIn1_);
102+ }
103+ 
104+ __aicore__ inline void Compute2(
105+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
106+ {
107+ bufferIn0_ = queIn0_.DeQue<half>();
108+ bufferIn1_ = queIn1_.DeQue<float>();
109+ bufferOut0_ = queOut0_.AllocTensor<float>();
110+ __VEC_SCOPE__
111+ {
112+ RegTensor<half> vreg0;
113+ RegTensor<float> vreg1;
114+ RegTensor<float> vreg2;
115+ RegTensor<float> vreg3;
116+ RegTensor<float> vreg4;
117+ RegTensor<float> vreg5;
118+ RegTensor<float> vreg6;
119+ MaskReg preg0;
120+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
121+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
122+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
123+ (AscendC::VECTOR_REG_WIDTH / 4);
124+ __local_mem__ float* bufferIn1Addr = (__local_mem__ float*)bufferIn1_.GetPhyAddr();
125+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
126+ __local_mem__ half* bufferIn0Addr = (__local_mem__ half*)bufferIn0_.GetPhyAddr();
127+ for (uint16_t i = 0; i < vfLoopNum; i++) {
128+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
129+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
130+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
131+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg1, vreg0, preg0);
132+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
133+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
134+ vreg2, vreg1, static_cast<float>(-1), preg0);
135+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
136+ vreg4, vreg2, vreg1, preg0);
137+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
138+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
139+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg6, vreg4, vreg5, preg0);
140+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
141+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg6, preg0);
142+ }
143+ }
144+ queIn0_.FreeTensor(bufferIn0_);
145+ queIn1_.FreeTensor(bufferIn1_);
146+ queOut0_.EnQue<float>(bufferOut0_);
147+ }
148+ 
149+ __aicore__ inline void CopyOut3(
150+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
151+ {
152+ bufferOut0_ = queOut0_.DeQue<float>();
153+ AscendC::DataCopyExtParams dataCopyExtParams;
154+ dataCopyExtParams.blockCount = 1;
155+ dataCopyExtParams.blockLen =
156+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
157+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
158+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
159+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
160+ queOut0_.FreeTensor(bufferOut0_);
161+ }
162+ 
163+private:
164+ TPipe* pipePtr_;
165+ const TanhGradTilingData* tilingDataPtr_;
166+ GlobalTensor<half> inputGmY_;
167+ GlobalTensor<float> inputGmDy_;
168+ GlobalTensor<float> outputGmZ_;
169+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
170+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
171+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
172+ LocalTensor<half> bufferIn0_;
173+ LocalTensor<float> bufferIn1_;
174+ LocalTensor<float> bufferOut0_;
175+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
176+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
177+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
178+};
179+ 
180+} // namespace TanhGrad
181+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_0_NDDMA_WITH_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_0_nddma_without_loops.h+181-0
@@ -0,0 +1,181 @@
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+ * \file tanh_grad_dtype_comb_0_nddma_without_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_0_NDDMA_WITHOUT_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_0_NDDMA_WITHOUT_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float16, dy is float32, z is float32, max dims in ub is 5 and nddma does not need loops
31+class TanhGradDtypeComb0NddmaWithoutLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb0NddmaWithoutLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ half*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ float*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(half);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(float);
45+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
47+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_1);
48+ }
49+ 
50+ __aicore__ inline void Process()
51+ {
52+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
53+ tilingDataPtr_->blockFormer;
54+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
55+ Ops::Base::BroadcastGetAxesIndices(
56+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
57+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
58+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
59+ if (ubLoopIdx != 0) {
60+ Ops::Base::BroadcastUpdateAxesIndices(
61+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
62+ }
63+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
64+ tilingDataPtr_->ubTail :
65+ tilingDataPtr_->ubFormer;
66+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
67+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
68+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
69+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
70+ }
71+ }
72+ 
73+private:
74+ __aicore__ inline void CopyIn0(
75+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
76+ {
77+ bufferIn0_ = queIn0_.AllocTensor<half>();
78+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
79+ (ubLoopIdx <= 1 ||
80+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
81+ Ops::Base::BroadcastNddmaWithoutLoop(
82+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
83+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
84+ ubSplitSize, tilingDataPtr_->ubFormer);
85+ }
86+ queIn0_.EnQue<half>(bufferIn0_);
87+ }
88+ 
89+ __aicore__ inline void CopyIn1(
90+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
91+ {
92+ bufferIn1_ = queIn1_.AllocTensor<float>();
93+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
94+ (ubLoopIdx <= 1 ||
95+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
96+ Ops::Base::BroadcastNddmaWithoutLoop(
97+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
98+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
99+ ubSplitSize, tilingDataPtr_->ubFormer);
100+ }
101+ queIn1_.EnQue<float>(bufferIn1_);
102+ }
103+ 
104+ __aicore__ inline void Compute2(
105+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
106+ {
107+ bufferIn0_ = queIn0_.DeQue<half>();
108+ bufferIn1_ = queIn1_.DeQue<float>();
109+ bufferOut0_ = queOut0_.AllocTensor<float>();
110+ __VEC_SCOPE__
111+ {
112+ RegTensor<half> vreg0;
113+ RegTensor<float> vreg1;
114+ RegTensor<float> vreg2;
115+ RegTensor<float> vreg3;
116+ RegTensor<float> vreg4;
117+ RegTensor<float> vreg5;
118+ RegTensor<float> vreg6;
119+ MaskReg preg0;
120+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
121+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
122+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
123+ (AscendC::VECTOR_REG_WIDTH / 4);
124+ __local_mem__ float* bufferIn1Addr = (__local_mem__ float*)bufferIn1_.GetPhyAddr();
125+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
126+ __local_mem__ half* bufferIn0Addr = (__local_mem__ half*)bufferIn0_.GetPhyAddr();
127+ for (uint16_t i = 0; i < vfLoopNum; i++) {
128+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
129+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
130+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
131+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg1, vreg0, preg0);
132+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
133+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
134+ vreg2, vreg1, static_cast<float>(-1), preg0);
135+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
136+ vreg4, vreg2, vreg1, preg0);
137+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
138+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
139+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg6, vreg4, vreg5, preg0);
140+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
141+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg6, preg0);
142+ }
143+ }
144+ queIn0_.FreeTensor(bufferIn0_);
145+ queIn1_.FreeTensor(bufferIn1_);
146+ queOut0_.EnQue<float>(bufferOut0_);
147+ }
148+ 
149+ __aicore__ inline void CopyOut3(
150+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
151+ {
152+ bufferOut0_ = queOut0_.DeQue<float>();
153+ AscendC::DataCopyExtParams dataCopyExtParams;
154+ dataCopyExtParams.blockCount = 1;
155+ dataCopyExtParams.blockLen =
156+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
157+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
158+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
159+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
160+ queOut0_.FreeTensor(bufferOut0_);
161+ }
162+ 
163+private:
164+ TPipe* pipePtr_;
165+ const TanhGradTilingData* tilingDataPtr_;
166+ GlobalTensor<half> inputGmY_;
167+ GlobalTensor<float> inputGmDy_;
168+ GlobalTensor<float> outputGmZ_;
169+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
170+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
171+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
172+ LocalTensor<half> bufferIn0_;
173+ LocalTensor<float> bufferIn1_;
174+ LocalTensor<float> bufferOut0_;
175+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
176+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
177+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
178+};
179+ 
180+} // namespace TanhGrad
181+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_0_NDDMA_WITHOUT_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_1_nddma_with_loops.h+184-0
@@ -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,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file tanh_grad_dtype_comb_1_nddma_with_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_1_NDDMA_WITH_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_1_NDDMA_WITH_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float16, dy is bfloat16, z is float32, max dims in ub is 8 and nddma needs loops
31+class TanhGradDtypeComb1NddmaWithLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb1NddmaWithLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ half*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ bfloat16_t*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(half);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(bfloat16_t);
45+ int64_t BUFFER_SIZE_2 = tilingDataPtr_->elemNum * sizeof(float);
46+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
47+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
48+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_2);
49+ }
50+ 
51+ __aicore__ inline void Process()
52+ {
53+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
54+ tilingDataPtr_->blockFormer;
55+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
56+ Ops::Base::BroadcastGetAxesIndices(
57+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
58+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
59+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
60+ if (ubLoopIdx != 0) {
61+ Ops::Base::BroadcastUpdateAxesIndices(
62+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
63+ }
64+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
65+ tilingDataPtr_->ubTail :
66+ tilingDataPtr_->ubFormer;
67+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
68+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
69+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
70+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
71+ }
72+ }
73+ 
74+private:
75+ __aicore__ inline void CopyIn0(
76+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
77+ {
78+ bufferIn0_ = queIn0_.AllocTensor<half>();
79+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
80+ (ubLoopIdx <= 1 ||
81+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
82+ Ops::Base::BroadcastNddmaWithLoop(
83+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
84+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
85+ ubSplitSize, tilingDataPtr_->ubFormer);
86+ }
87+ queIn0_.EnQue<half>(bufferIn0_);
88+ }
89+ 
90+ __aicore__ inline void CopyIn1(
91+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
92+ {
93+ bufferIn1_ = queIn1_.AllocTensor<bfloat16_t>();
94+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
95+ (ubLoopIdx <= 1 ||
96+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
97+ Ops::Base::BroadcastNddmaWithLoop(
98+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
99+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
100+ ubSplitSize, tilingDataPtr_->ubFormer);
101+ }
102+ queIn1_.EnQue<bfloat16_t>(bufferIn1_);
103+ }
104+ 
105+ __aicore__ inline void Compute2(
106+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
107+ {
108+ bufferIn0_ = queIn0_.DeQue<half>();
109+ bufferIn1_ = queIn1_.DeQue<bfloat16_t>();
110+ bufferOut0_ = queOut0_.AllocTensor<float>();
111+ __VEC_SCOPE__
112+ {
113+ RegTensor<half> vreg0;
114+ RegTensor<float> vreg1;
115+ RegTensor<float> vreg2;
116+ RegTensor<float> vreg3;
117+ RegTensor<float> vreg4;
118+ RegTensor<bfloat16_t> vreg5;
119+ RegTensor<float> vreg6;
120+ RegTensor<float> vreg7;
121+ MaskReg preg0;
122+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
123+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
124+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
125+ (AscendC::VECTOR_REG_WIDTH / 4);
126+ __local_mem__ bfloat16_t* bufferIn1Addr = (__local_mem__ bfloat16_t*)bufferIn1_.GetPhyAddr();
127+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
128+ __local_mem__ half* bufferIn0Addr = (__local_mem__ half*)bufferIn0_.GetPhyAddr();
129+ for (uint16_t i = 0; i < vfLoopNum; i++) {
130+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
131+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
132+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
133+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg1, vreg0, preg0);
134+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
135+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
136+ vreg2, vreg1, static_cast<float>(-1), preg0);
137+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
138+ vreg4, vreg2, vreg1, preg0);
139+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
140+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
141+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg6, vreg5, preg0);
142+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg7, vreg4, vreg6, preg0);
143+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
144+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg7, preg0);
145+ }
146+ }
147+ queIn0_.FreeTensor(bufferIn0_);
148+ queIn1_.FreeTensor(bufferIn1_);
149+ queOut0_.EnQue<float>(bufferOut0_);
150+ }
151+ 
152+ __aicore__ inline void CopyOut3(
153+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
154+ {
155+ bufferOut0_ = queOut0_.DeQue<float>();
156+ AscendC::DataCopyExtParams dataCopyExtParams;
157+ dataCopyExtParams.blockCount = 1;
158+ dataCopyExtParams.blockLen =
159+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
160+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
161+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
162+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
163+ queOut0_.FreeTensor(bufferOut0_);
164+ }
165+ 
166+private:
167+ TPipe* pipePtr_;
168+ const TanhGradTilingData* tilingDataPtr_;
169+ GlobalTensor<half> inputGmY_;
170+ GlobalTensor<bfloat16_t> inputGmDy_;
171+ GlobalTensor<float> outputGmZ_;
172+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
173+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
174+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
175+ LocalTensor<half> bufferIn0_;
176+ LocalTensor<bfloat16_t> bufferIn1_;
177+ LocalTensor<float> bufferOut0_;
178+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
179+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
180+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
181+};
182+ 
183+} // namespace TanhGrad
184+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_1_NDDMA_WITH_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_1_nddma_without_loops.h+184-0
@@ -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,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file tanh_grad_dtype_comb_1_nddma_without_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_1_NDDMA_WITHOUT_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_1_NDDMA_WITHOUT_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float16, dy is bfloat16, z is float32, max dims in ub is 5 and nddma does not need loops
31+class TanhGradDtypeComb1NddmaWithoutLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb1NddmaWithoutLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ half*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ bfloat16_t*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(half);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(bfloat16_t);
45+ int64_t BUFFER_SIZE_2 = tilingDataPtr_->elemNum * sizeof(float);
46+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
47+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
48+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_2);
49+ }
50+ 
51+ __aicore__ inline void Process()
52+ {
53+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
54+ tilingDataPtr_->blockFormer;
55+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
56+ Ops::Base::BroadcastGetAxesIndices(
57+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
58+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
59+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
60+ if (ubLoopIdx != 0) {
61+ Ops::Base::BroadcastUpdateAxesIndices(
62+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
63+ }
64+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
65+ tilingDataPtr_->ubTail :
66+ tilingDataPtr_->ubFormer;
67+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
68+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
69+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
70+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
71+ }
72+ }
73+ 
74+private:
75+ __aicore__ inline void CopyIn0(
76+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
77+ {
78+ bufferIn0_ = queIn0_.AllocTensor<half>();
79+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
80+ (ubLoopIdx <= 1 ||
81+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
82+ Ops::Base::BroadcastNddmaWithoutLoop(
83+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
84+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
85+ ubSplitSize, tilingDataPtr_->ubFormer);
86+ }
87+ queIn0_.EnQue<half>(bufferIn0_);
88+ }
89+ 
90+ __aicore__ inline void CopyIn1(
91+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
92+ {
93+ bufferIn1_ = queIn1_.AllocTensor<bfloat16_t>();
94+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
95+ (ubLoopIdx <= 1 ||
96+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
97+ Ops::Base::BroadcastNddmaWithoutLoop(
98+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
99+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
100+ ubSplitSize, tilingDataPtr_->ubFormer);
101+ }
102+ queIn1_.EnQue<bfloat16_t>(bufferIn1_);
103+ }
104+ 
105+ __aicore__ inline void Compute2(
106+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
107+ {
108+ bufferIn0_ = queIn0_.DeQue<half>();
109+ bufferIn1_ = queIn1_.DeQue<bfloat16_t>();
110+ bufferOut0_ = queOut0_.AllocTensor<float>();
111+ __VEC_SCOPE__
112+ {
113+ RegTensor<half> vreg0;
114+ RegTensor<float> vreg1;
115+ RegTensor<float> vreg2;
116+ RegTensor<float> vreg3;
117+ RegTensor<float> vreg4;
118+ RegTensor<bfloat16_t> vreg5;
119+ RegTensor<float> vreg6;
120+ RegTensor<float> vreg7;
121+ MaskReg preg0;
122+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
123+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
124+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
125+ (AscendC::VECTOR_REG_WIDTH / 4);
126+ __local_mem__ bfloat16_t* bufferIn1Addr = (__local_mem__ bfloat16_t*)bufferIn1_.GetPhyAddr();
127+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
128+ __local_mem__ half* bufferIn0Addr = (__local_mem__ half*)bufferIn0_.GetPhyAddr();
129+ for (uint16_t i = 0; i < vfLoopNum; i++) {
130+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
131+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
132+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
133+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg1, vreg0, preg0);
134+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
135+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
136+ vreg2, vreg1, static_cast<float>(-1), preg0);
137+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
138+ vreg4, vreg2, vreg1, preg0);
139+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
140+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
141+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg6, vreg5, preg0);
142+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg7, vreg4, vreg6, preg0);
143+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
144+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg7, preg0);
145+ }
146+ }
147+ queIn0_.FreeTensor(bufferIn0_);
148+ queIn1_.FreeTensor(bufferIn1_);
149+ queOut0_.EnQue<float>(bufferOut0_);
150+ }
151+ 
152+ __aicore__ inline void CopyOut3(
153+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
154+ {
155+ bufferOut0_ = queOut0_.DeQue<float>();
156+ AscendC::DataCopyExtParams dataCopyExtParams;
157+ dataCopyExtParams.blockCount = 1;
158+ dataCopyExtParams.blockLen =
159+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
160+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
161+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
162+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
163+ queOut0_.FreeTensor(bufferOut0_);
164+ }
165+ 
166+private:
167+ TPipe* pipePtr_;
168+ const TanhGradTilingData* tilingDataPtr_;
169+ GlobalTensor<half> inputGmY_;
170+ GlobalTensor<bfloat16_t> inputGmDy_;
171+ GlobalTensor<float> outputGmZ_;
172+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
173+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
174+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
175+ LocalTensor<half> bufferIn0_;
176+ LocalTensor<bfloat16_t> bufferIn1_;
177+ LocalTensor<float> bufferOut0_;
178+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
179+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
180+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
181+};
182+ 
183+} // namespace TanhGrad
184+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_1_NDDMA_WITHOUT_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_2_nddma_with_loops.h+181-0
@@ -0,0 +1,181 @@
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+ * \file tanh_grad_dtype_comb_2_nddma_with_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_2_NDDMA_WITH_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_2_NDDMA_WITH_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float32, dy is float16, z is float32, max dims in ub is 8 and nddma needs loops
31+class TanhGradDtypeComb2NddmaWithLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb2NddmaWithLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ float*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ half*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(float);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(half);
45+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
47+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
48+ }
49+ 
50+ __aicore__ inline void Process()
51+ {
52+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
53+ tilingDataPtr_->blockFormer;
54+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
55+ Ops::Base::BroadcastGetAxesIndices(
56+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
57+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
58+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
59+ if (ubLoopIdx != 0) {
60+ Ops::Base::BroadcastUpdateAxesIndices(
61+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
62+ }
63+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
64+ tilingDataPtr_->ubTail :
65+ tilingDataPtr_->ubFormer;
66+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
67+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
68+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
69+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
70+ }
71+ }
72+ 
73+private:
74+ __aicore__ inline void CopyIn0(
75+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
76+ {
77+ bufferIn0_ = queIn0_.AllocTensor<float>();
78+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
79+ (ubLoopIdx <= 1 ||
80+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
81+ Ops::Base::BroadcastNddmaWithLoop(
82+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
83+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
84+ ubSplitSize, tilingDataPtr_->ubFormer);
85+ }
86+ queIn0_.EnQue<float>(bufferIn0_);
87+ }
88+ 
89+ __aicore__ inline void CopyIn1(
90+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
91+ {
92+ bufferIn1_ = queIn1_.AllocTensor<half>();
93+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
94+ (ubLoopIdx <= 1 ||
95+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
96+ Ops::Base::BroadcastNddmaWithLoop(
97+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
98+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
99+ ubSplitSize, tilingDataPtr_->ubFormer);
100+ }
101+ queIn1_.EnQue<half>(bufferIn1_);
102+ }
103+ 
104+ __aicore__ inline void Compute2(
105+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
106+ {
107+ bufferIn0_ = queIn0_.DeQue<float>();
108+ bufferIn1_ = queIn1_.DeQue<half>();
109+ bufferOut0_ = queOut0_.AllocTensor<float>();
110+ __VEC_SCOPE__
111+ {
112+ RegTensor<float> vreg0;
113+ RegTensor<float> vreg1;
114+ RegTensor<float> vreg2;
115+ RegTensor<float> vreg3;
116+ RegTensor<half> vreg4;
117+ RegTensor<float> vreg5;
118+ RegTensor<float> vreg6;
119+ MaskReg preg0;
120+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
121+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
122+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
123+ (AscendC::VECTOR_REG_WIDTH / 4);
124+ __local_mem__ float* bufferIn0Addr = (__local_mem__ float*)bufferIn0_.GetPhyAddr();
125+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
126+ __local_mem__ half* bufferIn1Addr = (__local_mem__ half*)bufferIn1_.GetPhyAddr();
127+ for (uint16_t i = 0; i < vfLoopNum; i++) {
128+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
129+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
130+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
131+ AscendC::MicroAPI::Duplicate<float, float>(vreg3, 1.0);
132+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
133+ vreg2, vreg0, static_cast<float>(-1), preg0);
134+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
135+ vreg3, vreg2, vreg0, preg0);
136+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
137+ vreg4, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
138+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg5, vreg4, preg0);
139+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg6, vreg3, vreg5, preg0);
140+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
141+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg6, preg0);
142+ }
143+ }
144+ queIn0_.FreeTensor(bufferIn0_);
145+ queIn1_.FreeTensor(bufferIn1_);
146+ queOut0_.EnQue<float>(bufferOut0_);
147+ }
148+ 
149+ __aicore__ inline void CopyOut3(
150+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
151+ {
152+ bufferOut0_ = queOut0_.DeQue<float>();
153+ AscendC::DataCopyExtParams dataCopyExtParams;
154+ dataCopyExtParams.blockCount = 1;
155+ dataCopyExtParams.blockLen =
156+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
157+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
158+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
159+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
160+ queOut0_.FreeTensor(bufferOut0_);
161+ }
162+ 
163+private:
164+ TPipe* pipePtr_;
165+ const TanhGradTilingData* tilingDataPtr_;
166+ GlobalTensor<float> inputGmY_;
167+ GlobalTensor<half> inputGmDy_;
168+ GlobalTensor<float> outputGmZ_;
169+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
170+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
171+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
172+ LocalTensor<float> bufferIn0_;
173+ LocalTensor<half> bufferIn1_;
174+ LocalTensor<float> bufferOut0_;
175+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
176+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
177+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
178+};
179+ 
180+} // namespace TanhGrad
181+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_2_NDDMA_WITH_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_2_nddma_without_loops.h+181-0
@@ -0,0 +1,181 @@
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+ * \file tanh_grad_dtype_comb_2_nddma_without_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_2_NDDMA_WITHOUT_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_2_NDDMA_WITHOUT_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float32, dy is float16, z is float32, max dims in ub is 5 and nddma does not need loops
31+class TanhGradDtypeComb2NddmaWithoutLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb2NddmaWithoutLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ float*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ half*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(float);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(half);
45+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
47+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
48+ }
49+ 
50+ __aicore__ inline void Process()
51+ {
52+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
53+ tilingDataPtr_->blockFormer;
54+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
55+ Ops::Base::BroadcastGetAxesIndices(
56+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
57+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
58+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
59+ if (ubLoopIdx != 0) {
60+ Ops::Base::BroadcastUpdateAxesIndices(
61+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
62+ }
63+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
64+ tilingDataPtr_->ubTail :
65+ tilingDataPtr_->ubFormer;
66+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
67+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
68+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
69+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
70+ }
71+ }
72+ 
73+private:
74+ __aicore__ inline void CopyIn0(
75+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
76+ {
77+ bufferIn0_ = queIn0_.AllocTensor<float>();
78+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
79+ (ubLoopIdx <= 1 ||
80+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
81+ Ops::Base::BroadcastNddmaWithoutLoop(
82+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
83+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
84+ ubSplitSize, tilingDataPtr_->ubFormer);
85+ }
86+ queIn0_.EnQue<float>(bufferIn0_);
87+ }
88+ 
89+ __aicore__ inline void CopyIn1(
90+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
91+ {
92+ bufferIn1_ = queIn1_.AllocTensor<half>();
93+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
94+ (ubLoopIdx <= 1 ||
95+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
96+ Ops::Base::BroadcastNddmaWithoutLoop(
97+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
98+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
99+ ubSplitSize, tilingDataPtr_->ubFormer);
100+ }
101+ queIn1_.EnQue<half>(bufferIn1_);
102+ }
103+ 
104+ __aicore__ inline void Compute2(
105+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
106+ {
107+ bufferIn0_ = queIn0_.DeQue<float>();
108+ bufferIn1_ = queIn1_.DeQue<half>();
109+ bufferOut0_ = queOut0_.AllocTensor<float>();
110+ __VEC_SCOPE__
111+ {
112+ RegTensor<float> vreg0;
113+ RegTensor<float> vreg1;
114+ RegTensor<float> vreg2;
115+ RegTensor<float> vreg3;
116+ RegTensor<half> vreg4;
117+ RegTensor<float> vreg5;
118+ RegTensor<float> vreg6;
119+ MaskReg preg0;
120+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
121+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
122+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
123+ (AscendC::VECTOR_REG_WIDTH / 4);
124+ __local_mem__ float* bufferIn0Addr = (__local_mem__ float*)bufferIn0_.GetPhyAddr();
125+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
126+ __local_mem__ half* bufferIn1Addr = (__local_mem__ half*)bufferIn1_.GetPhyAddr();
127+ for (uint16_t i = 0; i < vfLoopNum; i++) {
128+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
129+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
130+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
131+ AscendC::MicroAPI::Duplicate<float, float>(vreg3, 1.0);
132+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
133+ vreg2, vreg0, static_cast<float>(-1), preg0);
134+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
135+ vreg3, vreg2, vreg0, preg0);
136+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
137+ vreg4, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
138+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg5, vreg4, preg0);
139+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg6, vreg3, vreg5, preg0);
140+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
141+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg6, preg0);
142+ }
143+ }
144+ queIn0_.FreeTensor(bufferIn0_);
145+ queIn1_.FreeTensor(bufferIn1_);
146+ queOut0_.EnQue<float>(bufferOut0_);
147+ }
148+ 
149+ __aicore__ inline void CopyOut3(
150+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
151+ {
152+ bufferOut0_ = queOut0_.DeQue<float>();
153+ AscendC::DataCopyExtParams dataCopyExtParams;
154+ dataCopyExtParams.blockCount = 1;
155+ dataCopyExtParams.blockLen =
156+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
157+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
158+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
159+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
160+ queOut0_.FreeTensor(bufferOut0_);
161+ }
162+ 
163+private:
164+ TPipe* pipePtr_;
165+ const TanhGradTilingData* tilingDataPtr_;
166+ GlobalTensor<float> inputGmY_;
167+ GlobalTensor<half> inputGmDy_;
168+ GlobalTensor<float> outputGmZ_;
169+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
170+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
171+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
172+ LocalTensor<float> bufferIn0_;
173+ LocalTensor<half> bufferIn1_;
174+ LocalTensor<float> bufferOut0_;
175+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
176+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
177+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
178+};
179+ 
180+} // namespace TanhGrad
181+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_2_NDDMA_WITHOUT_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_3_nddma_with_loops.h+181-0
@@ -0,0 +1,181 @@
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+ * \file tanh_grad_dtype_comb_3_nddma_with_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_3_NDDMA_WITH_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_3_NDDMA_WITH_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float32, dy is bfloat16, z is float32, max dims in ub is 8 and nddma needs loops
31+class TanhGradDtypeComb3NddmaWithLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb3NddmaWithLoops(){};
CANN-robot
CANN-robotCANN-robot2025年12月30日

构造函数设计: 默认构造函数为空,但类中有指针成员 pipePtr_tilingDataPtr_。虽然这些指针在 Init 函数中初始化,但如果在调用 Init 之前使用了这些指针,会导致未定义行为。

问题类型: 构造函数设计 文件路径: math/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_3_nddma_with_loops.h 行号: 33 问题代码:

__aicore__ inline TanhGradDtypeComb3NddmaWithLoops(){};

修改建议:

建议:
1. 在构造函数中将指针初始化为 `nullptr`
2. 或者在 `Init` 函数中添加指针有效性检查
3. 考虑使用 RAII 模式,将资源初始化放在构造函数中

此评论由代码审查工具自动生成

likedislike
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ float*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ bfloat16_t*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(float);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(bfloat16_t);
45+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
47+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
48+ }
49+ 
50+ __aicore__ inline void Process()
51+ {
52+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
53+ tilingDataPtr_->blockFormer;
54+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
55+ Ops::Base::BroadcastGetAxesIndices(
56+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
57+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
58+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
59+ if (ubLoopIdx != 0) {
60+ Ops::Base::BroadcastUpdateAxesIndices(
61+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
62+ }
63+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
64+ tilingDataPtr_->ubTail :
65+ tilingDataPtr_->ubFormer;
66+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
67+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
68+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
69+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
70+ }
71+ }
72+ 
73+private:
74+ __aicore__ inline void CopyIn0(
75+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
76+ {
77+ bufferIn0_ = queIn0_.AllocTensor<float>();
78+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
79+ (ubLoopIdx <= 1 ||
80+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
81+ Ops::Base::BroadcastNddmaWithLoop(
82+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
83+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
84+ ubSplitSize, tilingDataPtr_->ubFormer);
85+ }
86+ queIn0_.EnQue<float>(bufferIn0_);
87+ }
88+ 
89+ __aicore__ inline void CopyIn1(
90+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
91+ {
92+ bufferIn1_ = queIn1_.AllocTensor<bfloat16_t>();
93+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
94+ (ubLoopIdx <= 1 ||
95+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
96+ Ops::Base::BroadcastNddmaWithLoop(
97+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
98+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
99+ ubSplitSize, tilingDataPtr_->ubFormer);
100+ }
101+ queIn1_.EnQue<bfloat16_t>(bufferIn1_);
102+ }
103+ 
104+ __aicore__ inline void Compute2(
105+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
106+ {
107+ bufferIn0_ = queIn0_.DeQue<float>();
108+ bufferIn1_ = queIn1_.DeQue<bfloat16_t>();
109+ bufferOut0_ = queOut0_.AllocTensor<float>();
110+ __VEC_SCOPE__
111+ {
112+ RegTensor<float> vreg0;
113+ RegTensor<float> vreg1;
114+ RegTensor<float> vreg2;
115+ RegTensor<float> vreg3;
116+ RegTensor<bfloat16_t> vreg4;
117+ RegTensor<float> vreg5;
118+ RegTensor<float> vreg6;
119+ MaskReg preg0;
120+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
121+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
122+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
123+ (AscendC::VECTOR_REG_WIDTH / 4);
124+ __local_mem__ bfloat16_t* bufferIn1Addr = (__local_mem__ bfloat16_t*)bufferIn1_.GetPhyAddr();
125+ __local_mem__ float* bufferIn0Addr = (__local_mem__ float*)bufferIn0_.GetPhyAddr();
126+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
127+ for (uint16_t i = 0; i < vfLoopNum; i++) {
128+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
129+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
130+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
131+ AscendC::MicroAPI::Duplicate<float, float>(vreg3, 1.0);
132+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
133+ vreg2, vreg0, static_cast<float>(-1), preg0);
134+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
135+ vreg3, vreg2, vreg0, preg0);
136+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
137+ vreg4, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
138+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg5, vreg4, preg0);
139+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg6, vreg3, vreg5, preg0);
140+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
141+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg6, preg0);
142+ }
143+ }
144+ queIn0_.FreeTensor(bufferIn0_);
145+ queIn1_.FreeTensor(bufferIn1_);
146+ queOut0_.EnQue<float>(bufferOut0_);
147+ }
148+ 
149+ __aicore__ inline void CopyOut3(
150+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
151+ {
152+ bufferOut0_ = queOut0_.DeQue<float>();
153+ AscendC::DataCopyExtParams dataCopyExtParams;
154+ dataCopyExtParams.blockCount = 1;
155+ dataCopyExtParams.blockLen =
156+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
157+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
158+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
159+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
160+ queOut0_.FreeTensor(bufferOut0_);
161+ }
162+ 
163+private:
164+ TPipe* pipePtr_;
165+ const TanhGradTilingData* tilingDataPtr_;
166+ GlobalTensor<float> inputGmY_;
167+ GlobalTensor<bfloat16_t> inputGmDy_;
168+ GlobalTensor<float> outputGmZ_;
169+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
170+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
171+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
172+ LocalTensor<float> bufferIn0_;
173+ LocalTensor<bfloat16_t> bufferIn1_;
174+ LocalTensor<float> bufferOut0_;
175+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
176+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
177+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
178+};
179+ 
180+} // namespace TanhGrad
181+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_3_NDDMA_WITH_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_3_nddma_without_loops.h+181-0
@@ -0,0 +1,181 @@
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+ * \file tanh_grad_dtype_comb_3_nddma_without_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_3_NDDMA_WITHOUT_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_3_NDDMA_WITHOUT_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float32, dy is bfloat16, z is float32, max dims in ub is 5 and nddma does not need loops
31+class TanhGradDtypeComb3NddmaWithoutLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb3NddmaWithoutLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ float*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ bfloat16_t*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(float);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(bfloat16_t);
45+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
47+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
48+ }
49+ 
50+ __aicore__ inline void Process()
51+ {
52+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
53+ tilingDataPtr_->blockFormer;
54+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
55+ Ops::Base::BroadcastGetAxesIndices(
56+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
57+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
58+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
59+ if (ubLoopIdx != 0) {
60+ Ops::Base::BroadcastUpdateAxesIndices(
61+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
62+ }
63+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
64+ tilingDataPtr_->ubTail :
65+ tilingDataPtr_->ubFormer;
66+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
67+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
68+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
69+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
70+ }
71+ }
72+ 
73+private:
74+ __aicore__ inline void CopyIn0(
75+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
76+ {
77+ bufferIn0_ = queIn0_.AllocTensor<float>();
78+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
79+ (ubLoopIdx <= 1 ||
80+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
81+ Ops::Base::BroadcastNddmaWithoutLoop(
82+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
83+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
84+ ubSplitSize, tilingDataPtr_->ubFormer);
85+ }
86+ queIn0_.EnQue<float>(bufferIn0_);
87+ }
88+ 
89+ __aicore__ inline void CopyIn1(
90+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
91+ {
92+ bufferIn1_ = queIn1_.AllocTensor<bfloat16_t>();
93+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
94+ (ubLoopIdx <= 1 ||
95+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
96+ Ops::Base::BroadcastNddmaWithoutLoop(
97+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
98+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
99+ ubSplitSize, tilingDataPtr_->ubFormer);
100+ }
101+ queIn1_.EnQue<bfloat16_t>(bufferIn1_);
102+ }
103+ 
104+ __aicore__ inline void Compute2(
105+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
106+ {
107+ bufferIn0_ = queIn0_.DeQue<float>();
108+ bufferIn1_ = queIn1_.DeQue<bfloat16_t>();
109+ bufferOut0_ = queOut0_.AllocTensor<float>();
110+ __VEC_SCOPE__
111+ {
112+ RegTensor<float> vreg0;
113+ RegTensor<float> vreg1;
114+ RegTensor<float> vreg2;
115+ RegTensor<float> vreg3;
116+ RegTensor<bfloat16_t> vreg4;
117+ RegTensor<float> vreg5;
118+ RegTensor<float> vreg6;
119+ MaskReg preg0;
120+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
121+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
122+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
123+ (AscendC::VECTOR_REG_WIDTH / 4);
124+ __local_mem__ bfloat16_t* bufferIn1Addr = (__local_mem__ bfloat16_t*)bufferIn1_.GetPhyAddr();
125+ __local_mem__ float* bufferIn0Addr = (__local_mem__ float*)bufferIn0_.GetPhyAddr();
126+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
127+ for (uint16_t i = 0; i < vfLoopNum; i++) {
128+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
129+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
130+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
131+ AscendC::MicroAPI::Duplicate<float, float>(vreg3, 1.0);
132+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
133+ vreg2, vreg0, static_cast<float>(-1), preg0);
134+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
135+ vreg3, vreg2, vreg0, preg0);
136+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
137+ vreg4, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
138+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg5, vreg4, preg0);
139+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg6, vreg3, vreg5, preg0);
140+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
141+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg6, preg0);
142+ }
143+ }
144+ queIn0_.FreeTensor(bufferIn0_);
145+ queIn1_.FreeTensor(bufferIn1_);
146+ queOut0_.EnQue<float>(bufferOut0_);
147+ }
148+ 
149+ __aicore__ inline void CopyOut3(
150+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
151+ {
152+ bufferOut0_ = queOut0_.DeQue<float>();
153+ AscendC::DataCopyExtParams dataCopyExtParams;
154+ dataCopyExtParams.blockCount = 1;
155+ dataCopyExtParams.blockLen =
156+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
157+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
158+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
159+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
160+ queOut0_.FreeTensor(bufferOut0_);
161+ }
162+ 
163+private:
164+ TPipe* pipePtr_;
165+ const TanhGradTilingData* tilingDataPtr_;
166+ GlobalTensor<float> inputGmY_;
167+ GlobalTensor<bfloat16_t> inputGmDy_;
168+ GlobalTensor<float> outputGmZ_;
169+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
170+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
171+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
172+ LocalTensor<float> bufferIn0_;
173+ LocalTensor<bfloat16_t> bufferIn1_;
174+ LocalTensor<float> bufferOut0_;
175+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
176+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
177+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
178+};
179+ 
180+} // namespace TanhGrad
181+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_3_NDDMA_WITHOUT_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_4_nddma_with_loops.h+184-0
@@ -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,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file tanh_grad_dtype_comb_4_nddma_with_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_4_NDDMA_WITH_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_4_NDDMA_WITH_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is bfloat16, dy is float16, z is float32, max dims in ub is 8 and nddma needs loops
31+class TanhGradDtypeComb4NddmaWithLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb4NddmaWithLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ bfloat16_t*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ half*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(bfloat16_t);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(half);
45+ int64_t BUFFER_SIZE_2 = tilingDataPtr_->elemNum * sizeof(float);
46+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
47+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
48+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_2);
49+ }
50+ 
51+ __aicore__ inline void Process()
52+ {
53+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
54+ tilingDataPtr_->blockFormer;
55+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
56+ Ops::Base::BroadcastGetAxesIndices(
57+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
58+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
59+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
60+ if (ubLoopIdx != 0) {
61+ Ops::Base::BroadcastUpdateAxesIndices(
62+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
63+ }
64+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
65+ tilingDataPtr_->ubTail :
66+ tilingDataPtr_->ubFormer;
67+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
68+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
69+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
70+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
71+ }
72+ }
73+ 
74+private:
75+ __aicore__ inline void CopyIn0(
76+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
77+ {
78+ bufferIn0_ = queIn0_.AllocTensor<bfloat16_t>();
79+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
80+ (ubLoopIdx <= 1 ||
81+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
82+ Ops::Base::BroadcastNddmaWithLoop(
83+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
84+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
85+ ubSplitSize, tilingDataPtr_->ubFormer);
86+ }
87+ queIn0_.EnQue<bfloat16_t>(bufferIn0_);
88+ }
89+ 
90+ __aicore__ inline void CopyIn1(
91+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
92+ {
93+ bufferIn1_ = queIn1_.AllocTensor<half>();
94+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
95+ (ubLoopIdx <= 1 ||
96+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
97+ Ops::Base::BroadcastNddmaWithLoop(
98+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
99+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
100+ ubSplitSize, tilingDataPtr_->ubFormer);
101+ }
102+ queIn1_.EnQue<half>(bufferIn1_);
103+ }
104+ 
105+ __aicore__ inline void Compute2(
106+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
107+ {
108+ bufferIn0_ = queIn0_.DeQue<bfloat16_t>();
109+ bufferIn1_ = queIn1_.DeQue<half>();
110+ bufferOut0_ = queOut0_.AllocTensor<float>();
111+ __VEC_SCOPE__
112+ {
113+ RegTensor<bfloat16_t> vreg0;
114+ RegTensor<float> vreg1;
115+ RegTensor<float> vreg2;
116+ RegTensor<float> vreg3;
117+ RegTensor<float> vreg4;
118+ RegTensor<half> vreg5;
119+ RegTensor<float> vreg6;
120+ RegTensor<float> vreg7;
121+ MaskReg preg0;
122+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
123+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
124+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
125+ (AscendC::VECTOR_REG_WIDTH / 4);
126+ __local_mem__ bfloat16_t* bufferIn0Addr = (__local_mem__ bfloat16_t*)bufferIn0_.GetPhyAddr();
127+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
128+ __local_mem__ half* bufferIn1Addr = (__local_mem__ half*)bufferIn1_.GetPhyAddr();
129+ for (uint16_t i = 0; i < vfLoopNum; i++) {
130+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
131+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
132+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
133+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg1, vreg0, preg0);
134+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
135+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
136+ vreg2, vreg1, static_cast<float>(-1), preg0);
137+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
138+ vreg4, vreg2, vreg1, preg0);
139+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
140+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
141+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg6, vreg5, preg0);
142+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg7, vreg4, vreg6, preg0);
143+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
144+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg7, preg0);
145+ }
146+ }
147+ queIn0_.FreeTensor(bufferIn0_);
148+ queIn1_.FreeTensor(bufferIn1_);
149+ queOut0_.EnQue<float>(bufferOut0_);
150+ }
151+ 
152+ __aicore__ inline void CopyOut3(
153+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
154+ {
155+ bufferOut0_ = queOut0_.DeQue<float>();
156+ AscendC::DataCopyExtParams dataCopyExtParams;
157+ dataCopyExtParams.blockCount = 1;
158+ dataCopyExtParams.blockLen =
159+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
160+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
161+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
162+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
163+ queOut0_.FreeTensor(bufferOut0_);
164+ }
165+ 
166+private:
167+ TPipe* pipePtr_;
168+ const TanhGradTilingData* tilingDataPtr_;
169+ GlobalTensor<bfloat16_t> inputGmY_;
170+ GlobalTensor<half> inputGmDy_;
171+ GlobalTensor<float> outputGmZ_;
172+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
173+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
174+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
175+ LocalTensor<bfloat16_t> bufferIn0_;
176+ LocalTensor<half> bufferIn1_;
177+ LocalTensor<float> bufferOut0_;
178+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
179+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
180+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
181+};
182+ 
183+} // namespace TanhGrad
184+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_4_NDDMA_WITH_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_4_nddma_without_loops.h+184-0
@@ -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,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file tanh_grad_dtype_comb_4_nddma_without_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_4_NDDMA_WITHOUT_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_4_NDDMA_WITHOUT_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is bfloat16, dy is float16, z is float32, max dims in ub is 5 and nddma does not need loops
31+class TanhGradDtypeComb4NddmaWithoutLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb4NddmaWithoutLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ bfloat16_t*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ half*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(bfloat16_t);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(half);
45+ int64_t BUFFER_SIZE_2 = tilingDataPtr_->elemNum * sizeof(float);
46+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
47+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
48+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_2);
49+ }
50+ 
51+ __aicore__ inline void Process()
52+ {
53+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
54+ tilingDataPtr_->blockFormer;
55+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
56+ Ops::Base::BroadcastGetAxesIndices(
57+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
58+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
59+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
60+ if (ubLoopIdx != 0) {
61+ Ops::Base::BroadcastUpdateAxesIndices(
62+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
63+ }
64+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
65+ tilingDataPtr_->ubTail :
66+ tilingDataPtr_->ubFormer;
67+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
68+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
69+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
70+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
71+ }
72+ }
73+ 
74+private:
75+ __aicore__ inline void CopyIn0(
76+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
77+ {
78+ bufferIn0_ = queIn0_.AllocTensor<bfloat16_t>();
79+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
80+ (ubLoopIdx <= 1 ||
81+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
82+ Ops::Base::BroadcastNddmaWithoutLoop(
83+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
84+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
85+ ubSplitSize, tilingDataPtr_->ubFormer);
86+ }
87+ queIn0_.EnQue<bfloat16_t>(bufferIn0_);
88+ }
89+ 
90+ __aicore__ inline void CopyIn1(
91+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
92+ {
93+ bufferIn1_ = queIn1_.AllocTensor<half>();
94+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
95+ (ubLoopIdx <= 1 ||
96+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
97+ Ops::Base::BroadcastNddmaWithoutLoop(
98+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
99+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
100+ ubSplitSize, tilingDataPtr_->ubFormer);
101+ }
102+ queIn1_.EnQue<half>(bufferIn1_);
103+ }
104+ 
105+ __aicore__ inline void Compute2(
106+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
107+ {
108+ bufferIn0_ = queIn0_.DeQue<bfloat16_t>();
109+ bufferIn1_ = queIn1_.DeQue<half>();
110+ bufferOut0_ = queOut0_.AllocTensor<float>();
111+ __VEC_SCOPE__
112+ {
113+ RegTensor<bfloat16_t> vreg0;
114+ RegTensor<float> vreg1;
115+ RegTensor<float> vreg2;
116+ RegTensor<float> vreg3;
117+ RegTensor<float> vreg4;
118+ RegTensor<half> vreg5;
119+ RegTensor<float> vreg6;
120+ RegTensor<float> vreg7;
121+ MaskReg preg0;
122+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
123+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
124+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
125+ (AscendC::VECTOR_REG_WIDTH / 4);
126+ __local_mem__ bfloat16_t* bufferIn0Addr = (__local_mem__ bfloat16_t*)bufferIn0_.GetPhyAddr();
127+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
128+ __local_mem__ half* bufferIn1Addr = (__local_mem__ half*)bufferIn1_.GetPhyAddr();
129+ for (uint16_t i = 0; i < vfLoopNum; i++) {
130+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
131+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
132+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
133+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg1, vreg0, preg0);
134+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
135+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
136+ vreg2, vreg1, static_cast<float>(-1), preg0);
137+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
138+ vreg4, vreg2, vreg1, preg0);
139+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
140+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
141+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg6, vreg5, preg0);
142+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg7, vreg4, vreg6, preg0);
143+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
144+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg7, preg0);
145+ }
146+ }
147+ queIn0_.FreeTensor(bufferIn0_);
148+ queIn1_.FreeTensor(bufferIn1_);
149+ queOut0_.EnQue<float>(bufferOut0_);
150+ }
151+ 
152+ __aicore__ inline void CopyOut3(
153+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
154+ {
155+ bufferOut0_ = queOut0_.DeQue<float>();
156+ AscendC::DataCopyExtParams dataCopyExtParams;
157+ dataCopyExtParams.blockCount = 1;
158+ dataCopyExtParams.blockLen =
159+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
160+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
161+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
162+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
163+ queOut0_.FreeTensor(bufferOut0_);
164+ }
165+ 
166+private:
167+ TPipe* pipePtr_;
168+ const TanhGradTilingData* tilingDataPtr_;
169+ GlobalTensor<bfloat16_t> inputGmY_;
170+ GlobalTensor<half> inputGmDy_;
171+ GlobalTensor<float> outputGmZ_;
172+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
173+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
174+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
175+ LocalTensor<bfloat16_t> bufferIn0_;
176+ LocalTensor<half> bufferIn1_;
177+ LocalTensor<float> bufferOut0_;
178+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
179+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
180+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
181+};
182+ 
183+} // namespace TanhGrad
184+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_4_NDDMA_WITHOUT_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_5_nddma_with_loops.h+181-0
@@ -0,0 +1,181 @@
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+ * \file tanh_grad_dtype_comb_5_nddma_with_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_5_NDDMA_WITH_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_5_NDDMA_WITH_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is bfloat16, dy is float32, z is float32, max dims in ub is 8 and nddma needs loops
31+class TanhGradDtypeComb5NddmaWithLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb5NddmaWithLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ bfloat16_t*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ float*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(bfloat16_t);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(float);
45+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
47+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_1);
48+ }
49+ 
50+ __aicore__ inline void Process()
51+ {
52+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
53+ tilingDataPtr_->blockFormer;
54+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
55+ Ops::Base::BroadcastGetAxesIndices(
56+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
57+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
58+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
59+ if (ubLoopIdx != 0) {
60+ Ops::Base::BroadcastUpdateAxesIndices(
61+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
62+ }
63+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
64+ tilingDataPtr_->ubTail :
65+ tilingDataPtr_->ubFormer;
66+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
67+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
68+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
69+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
70+ }
71+ }
72+ 
73+private:
74+ __aicore__ inline void CopyIn0(
75+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
76+ {
77+ bufferIn0_ = queIn0_.AllocTensor<bfloat16_t>();
78+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
79+ (ubLoopIdx <= 1 ||
80+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
81+ Ops::Base::BroadcastNddmaWithLoop(
82+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
83+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
84+ ubSplitSize, tilingDataPtr_->ubFormer);
85+ }
86+ queIn0_.EnQue<bfloat16_t>(bufferIn0_);
87+ }
88+ 
89+ __aicore__ inline void CopyIn1(
90+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
91+ {
92+ bufferIn1_ = queIn1_.AllocTensor<float>();
93+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
94+ (ubLoopIdx <= 1 ||
95+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
96+ Ops::Base::BroadcastNddmaWithLoop(
97+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
98+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
99+ ubSplitSize, tilingDataPtr_->ubFormer);
100+ }
101+ queIn1_.EnQue<float>(bufferIn1_);
102+ }
103+ 
104+ __aicore__ inline void Compute2(
105+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
106+ {
107+ bufferIn0_ = queIn0_.DeQue<bfloat16_t>();
108+ bufferIn1_ = queIn1_.DeQue<float>();
109+ bufferOut0_ = queOut0_.AllocTensor<float>();
110+ __VEC_SCOPE__
111+ {
112+ RegTensor<bfloat16_t> vreg0;
113+ RegTensor<float> vreg1;
114+ RegTensor<float> vreg2;
115+ RegTensor<float> vreg3;
CANN-robot
CANN-robotCANN-robot2025年12月30日

未使用的变量: 第112-118行声明了多个RegTensor变量,但vreg3在后续计算中从未使用。这可能是代码遗留问题或复制粘贴错误,增加了不必要的寄存器占用和代码混乱。

问题类型: 未使用的变量 文件路径: math/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_5_nddma_with_loops.h 行号: 115 问题代码:

RegTensor<float> vreg3;

修改建议:

移除未使用的vreg3声明,或者如果未来需要扩展功能,添加注释说明预留目的。

此评论由代码审查工具自动生成

likedislike
116+ RegTensor<float> vreg4;
117+ RegTensor<float> vreg5;
118+ RegTensor<float> vreg6;
119+ MaskReg preg0;
120+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
121+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
122+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
123+ (AscendC::VECTOR_REG_WIDTH / 4);
124+ __local_mem__ bfloat16_t* bufferIn0Addr = (__local_mem__ bfloat16_t*)bufferIn0_.GetPhyAddr();
125+ __local_mem__ float* bufferIn1Addr = (__local_mem__ float*)bufferIn1_.GetPhyAddr();
126+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
127+ for (uint16_t i = 0; i < vfLoopNum; i++) {
128+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
129+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
130+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
131+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg1, vreg0, preg0);
132+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
133+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
134+ vreg2, vreg1, static_cast<float>(-1), preg0);
135+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
136+ vreg4, vreg2, vreg1, preg0);
137+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
138+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
139+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg6, vreg4, vreg5, preg0);
140+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
141+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg6, preg0);
142+ }
143+ }
144+ queIn0_.FreeTensor(bufferIn0_);
145+ queIn1_.FreeTensor(bufferIn1_);
146+ queOut0_.EnQue<float>(bufferOut0_);
147+ }
148+ 
149+ __aicore__ inline void CopyOut3(
150+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
151+ {
152+ bufferOut0_ = queOut0_.DeQue<float>();
153+ AscendC::DataCopyExtParams dataCopyExtParams;
154+ dataCopyExtParams.blockCount = 1;
155+ dataCopyExtParams.blockLen =
156+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
157+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
158+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
159+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
160+ queOut0_.FreeTensor(bufferOut0_);
161+ }
162+ 
163+private:
164+ TPipe* pipePtr_;
165+ const TanhGradTilingData* tilingDataPtr_;
166+ GlobalTensor<bfloat16_t> inputGmY_;
167+ GlobalTensor<float> inputGmDy_;
168+ GlobalTensor<float> outputGmZ_;
169+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
170+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
171+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
172+ LocalTensor<bfloat16_t> bufferIn0_;
173+ LocalTensor<float> bufferIn1_;
174+ LocalTensor<float> bufferOut0_;
175+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
176+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
177+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
178+};
179+ 
180+} // namespace TanhGrad
181+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_5_NDDMA_WITH_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_dtype_comb_5_nddma_without_loops.h+181-0
@@ -0,0 +1,181 @@
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+ * \file tanh_grad_dtype_comb_5_nddma_without_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_DTYPE_COMB_5_NDDMA_WITHOUT_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_DTYPE_COMB_5_NDDMA_WITHOUT_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is bfloat16, dy is float32, z is float32, max dims in ub is 5 and nddma does not need loops
31+class TanhGradDtypeComb5NddmaWithoutLoops {
32+public:
33+ __aicore__ inline TanhGradDtypeComb5NddmaWithoutLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ bfloat16_t*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ float*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(bfloat16_t);
44+ int64_t BUFFER_SIZE_1 = tilingDataPtr_->elemNum * sizeof(float);
45+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_1);
47+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_1);
48+ }
49+ 
50+ __aicore__ inline void Process()
51+ {
52+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
53+ tilingDataPtr_->blockFormer;
54+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
55+ Ops::Base::BroadcastGetAxesIndices(
56+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
57+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
58+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
59+ if (ubLoopIdx != 0) {
60+ Ops::Base::BroadcastUpdateAxesIndices(
61+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
62+ }
63+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
64+ tilingDataPtr_->ubTail :
65+ tilingDataPtr_->ubFormer;
66+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
67+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
68+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
69+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
70+ }
71+ }
72+ 
73+private:
74+ __aicore__ inline void CopyIn0(
75+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
76+ {
77+ bufferIn0_ = queIn0_.AllocTensor<bfloat16_t>();
78+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
79+ (ubLoopIdx <= 1 ||
80+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
81+ Ops::Base::BroadcastNddmaWithoutLoop(
82+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
83+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
84+ ubSplitSize, tilingDataPtr_->ubFormer);
85+ }
86+ queIn0_.EnQue<bfloat16_t>(bufferIn0_);
87+ }
88+ 
89+ __aicore__ inline void CopyIn1(
90+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
91+ {
92+ bufferIn1_ = queIn1_.AllocTensor<float>();
93+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
94+ (ubLoopIdx <= 1 ||
95+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
96+ Ops::Base::BroadcastNddmaWithoutLoop(
97+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
98+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
99+ ubSplitSize, tilingDataPtr_->ubFormer);
100+ }
101+ queIn1_.EnQue<float>(bufferIn1_);
102+ }
103+ 
104+ __aicore__ inline void Compute2(
105+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
106+ {
107+ bufferIn0_ = queIn0_.DeQue<bfloat16_t>();
108+ bufferIn1_ = queIn1_.DeQue<float>();
109+ bufferOut0_ = queOut0_.AllocTensor<float>();
110+ __VEC_SCOPE__
111+ {
112+ RegTensor<bfloat16_t> vreg0;
113+ RegTensor<float> vreg1;
114+ RegTensor<float> vreg2;
115+ RegTensor<float> vreg3;
116+ RegTensor<float> vreg4;
117+ RegTensor<float> vreg5;
118+ RegTensor<float> vreg6;
119+ MaskReg preg0;
120+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
121+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
122+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
123+ (AscendC::VECTOR_REG_WIDTH / 4);
124+ __local_mem__ bfloat16_t* bufferIn0Addr = (__local_mem__ bfloat16_t*)bufferIn0_.GetPhyAddr();
125+ __local_mem__ float* bufferIn1Addr = (__local_mem__ float*)bufferIn1_.GetPhyAddr();
126+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
127+ for (uint16_t i = 0; i < vfLoopNum; i++) {
128+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
129+ AscendC::MicroAPI::DataCopy<bfloat16_t, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
130+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
131+ AscendC::MicroAPI::Cast<float, bfloat16_t, castTrait0>(vreg1, vreg0, preg0);
132+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
133+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
134+ vreg2, vreg1, static_cast<float>(-1), preg0);
135+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
136+ vreg4, vreg2, vreg1, preg0);
137+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
138+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
139+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg6, vreg4, vreg5, preg0);
140+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
141+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg6, preg0);
142+ }
143+ }
144+ queIn0_.FreeTensor(bufferIn0_);
145+ queIn1_.FreeTensor(bufferIn1_);
146+ queOut0_.EnQue<float>(bufferOut0_);
147+ }
148+ 
149+ __aicore__ inline void CopyOut3(
150+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
151+ {
152+ bufferOut0_ = queOut0_.DeQue<float>();
153+ AscendC::DataCopyExtParams dataCopyExtParams;
154+ dataCopyExtParams.blockCount = 1;
155+ dataCopyExtParams.blockLen =
156+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
157+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
158+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
159+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
160+ queOut0_.FreeTensor(bufferOut0_);
161+ }
162+ 
163+private:
164+ TPipe* pipePtr_;
165+ const TanhGradTilingData* tilingDataPtr_;
166+ GlobalTensor<bfloat16_t> inputGmY_;
167+ GlobalTensor<float> inputGmDy_;
168+ GlobalTensor<float> outputGmZ_;
169+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
170+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
171+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
172+ LocalTensor<bfloat16_t> bufferIn0_;
173+ LocalTensor<float> bufferIn1_;
174+ LocalTensor<float> bufferOut0_;
175+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
176+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
177+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
178+};
179+ 
180+} // namespace TanhGrad
181+#endif // ASCENDC_TANH_GRAD_DTYPE_COMB_5_NDDMA_WITHOUT_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_f16_nddma_with_loops.h+187-0
@@ -0,0 +1,187 @@
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+ * \file tanh_grad_f16_nddma_with_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_F16_NDDMA_WITH_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_F16_NDDMA_WITH_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float16, dy is float16, z is float16, max dims in ub is 8 and nddma needs loops
CANN-robot
CANN-robotCANN-robot2025年12月30日

代码结构与可维护性: 类注释过于简单,只说明了数据类型和维度限制,没有说明类的功能、使用方式、参数要求等。对于复杂的核函数实现,缺乏足够的文档说明会影响代码的可维护性。

问题类型: 代码结构与可维护性 文件路径: math/tanh_grad/op_kernel/arch35/tanh_grad_f16_nddma_with_loops.h 行号: 30 问题代码:

// y is float16, dy is float16, z is float16, max dims in ub is 8 and nddma needs loops

修改建议:

添加详细的类文档注释,包括:1. 类的功能(计算tanh梯度);2. 输入输出说明;3. 参数要求;4. 使用示例或调用顺序;5. 注意事项和限制条件。

此评论由代码审查工具自动生成

likedislike
31+class TanhGradF16NddmaWithLoops {
32+public:
33+ __aicore__ inline TanhGradF16NddmaWithLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ half*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ half*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ half*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(half);
44+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
45+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
47+ }
48+ 
49+ __aicore__ inline void Process()
50+ {
51+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
52+ tilingDataPtr_->blockFormer;
53+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
54+ Ops::Base::BroadcastGetAxesIndices(
55+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
56+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
57+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
58+ if (ubLoopIdx != 0) {
59+ Ops::Base::BroadcastUpdateAxesIndices(
60+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
61+ }
62+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
63+ tilingDataPtr_->ubTail :
64+ tilingDataPtr_->ubFormer;
65+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
66+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
67+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
68+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
69+ }
70+ }
71+ 
72+private:
73+ __aicore__ inline void CopyIn0(
74+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
75+ {
76+ bufferIn0_ = queIn0_.AllocTensor<half>();
77+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
78+ (ubLoopIdx <= 1 ||
79+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
80+ Ops::Base::BroadcastNddmaWithLoop(
81+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
82+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
83+ ubSplitSize, tilingDataPtr_->ubFormer);
84+ }
85+ queIn0_.EnQue<half>(bufferIn0_);
86+ }
87+ 
88+ __aicore__ inline void CopyIn1(
89+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
90+ {
91+ bufferIn1_ = queIn1_.AllocTensor<half>();
92+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
93+ (ubLoopIdx <= 1 ||
94+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
95+ Ops::Base::BroadcastNddmaWithLoop(
96+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
97+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
98+ ubSplitSize, tilingDataPtr_->ubFormer);
99+ }
100+ queIn1_.EnQue<half>(bufferIn1_);
101+ }
102+ 
103+ __aicore__ inline void Compute2(
104+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
105+ {
106+ bufferIn0_ = queIn0_.DeQue<half>();
107+ bufferIn1_ = queIn1_.DeQue<half>();
108+ bufferOut0_ = queOut0_.AllocTensor<half>();
109+ __VEC_SCOPE__
110+ {
111+ RegTensor<half> vreg0;
112+ RegTensor<float> vreg1;
113+ RegTensor<float> vreg2;
114+ RegTensor<float> vreg3;
115+ RegTensor<float> vreg4;
116+ RegTensor<half> vreg5;
117+ RegTensor<float> vreg6;
118+ RegTensor<float> vreg7;
119+ RegTensor<half> vreg8;
120+ MaskReg preg0;
121+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
122+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
123+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
124+ (AscendC::VECTOR_REG_WIDTH / 4);
125+ __local_mem__ half* bufferIn0Addr = (__local_mem__ half*)bufferIn0_.GetPhyAddr();
126+ __local_mem__ half* bufferIn1Addr = (__local_mem__ half*)bufferIn1_.GetPhyAddr();
127+ __local_mem__ half* bufferOut0Addr = (__local_mem__ half*)bufferOut0_.GetPhyAddr();
128+ for (uint16_t i = 0; i < vfLoopNum; i++) {
129+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
130+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
131+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
132+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg1, vreg0, preg0);
133+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
134+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
135+ vreg2, vreg1, static_cast<float>(-1), preg0);
136+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
137+ vreg4, vreg2, vreg1, preg0);
138+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
139+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
140+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg6, vreg5, preg0);
141+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg7, vreg4, vreg6, preg0);
142+ AscendC::MicroAPI::Cast<half, float, castTrait1>(vreg8, vreg7, preg0);
143+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::StoreDist::DIST_PACK_B32>(
144+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg8, preg0);
145+ }
146+ }
147+ queIn0_.FreeTensor(bufferIn0_);
148+ queIn1_.FreeTensor(bufferIn1_);
149+ queOut0_.EnQue<half>(bufferOut0_);
150+ }
151+ 
152+ __aicore__ inline void CopyOut3(
153+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
154+ {
155+ bufferOut0_ = queOut0_.DeQue<half>();
156+ AscendC::DataCopyExtParams dataCopyExtParams;
157+ dataCopyExtParams.blockCount = 1;
158+ dataCopyExtParams.blockLen =
159+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(half);
160+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
161+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
162+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
163+ queOut0_.FreeTensor(bufferOut0_);
164+ }
165+ 
166+private:
167+ TPipe* pipePtr_;
168+ const TanhGradTilingData* tilingDataPtr_;
169+ GlobalTensor<half> inputGmY_;
170+ GlobalTensor<half> inputGmDy_;
171+ GlobalTensor<half> outputGmZ_;
172+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
173+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
174+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
175+ LocalTensor<half> bufferIn0_;
176+ LocalTensor<half> bufferIn1_;
177+ LocalTensor<half> bufferOut0_;
178+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
179+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
180+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
181+ constexpr static AscendC::MicroAPI::CastTrait castTrait1 = {
182+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::NO_SAT,
183+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::CAST_RINT};
184+};
185+ 
186+} // namespace TanhGrad
187+#endif // ASCENDC_TANH_GRAD_F16_NDDMA_WITH_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_f16_nddma_without_loops.h+187-0
@@ -0,0 +1,187 @@
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+ * \file tanh_grad_f16_nddma_without_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_F16_NDDMA_WITHOUT_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_F16_NDDMA_WITHOUT_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float16, dy is float16, z is float16, max dims in ub is 5 and nddma does not need loops
31+class TanhGradF16NddmaWithoutLoops {
32+public:
33+ __aicore__ inline TanhGradF16NddmaWithoutLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ half*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ half*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ half*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(half);
44+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
45+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
47+ }
48+ 
49+ __aicore__ inline void Process()
50+ {
51+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
52+ tilingDataPtr_->blockFormer;
53+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
54+ Ops::Base::BroadcastGetAxesIndices(
55+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
56+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
57+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
58+ if (ubLoopIdx != 0) {
59+ Ops::Base::BroadcastUpdateAxesIndices(
60+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
61+ }
62+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
63+ tilingDataPtr_->ubTail :
64+ tilingDataPtr_->ubFormer;
65+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
66+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
67+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
68+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
69+ }
70+ }
71+ 
72+private:
73+ __aicore__ inline void CopyIn0(
74+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
75+ {
76+ bufferIn0_ = queIn0_.AllocTensor<half>();
77+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
78+ (ubLoopIdx <= 1 ||
79+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
80+ Ops::Base::BroadcastNddmaWithoutLoop(
81+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
82+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
83+ ubSplitSize, tilingDataPtr_->ubFormer);
84+ }
85+ queIn0_.EnQue<half>(bufferIn0_);
86+ }
87+ 
88+ __aicore__ inline void CopyIn1(
89+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
90+ {
91+ bufferIn1_ = queIn1_.AllocTensor<half>();
92+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
93+ (ubLoopIdx <= 1 ||
94+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
95+ Ops::Base::BroadcastNddmaWithoutLoop(
96+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
97+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
98+ ubSplitSize, tilingDataPtr_->ubFormer);
99+ }
100+ queIn1_.EnQue<half>(bufferIn1_);
101+ }
102+ 
103+ __aicore__ inline void Compute2(
104+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
105+ {
106+ bufferIn0_ = queIn0_.DeQue<half>();
107+ bufferIn1_ = queIn1_.DeQue<half>();
108+ bufferOut0_ = queOut0_.AllocTensor<half>();
109+ __VEC_SCOPE__
110+ {
111+ RegTensor<half> vreg0;
112+ RegTensor<float> vreg1;
113+ RegTensor<float> vreg2;
114+ RegTensor<float> vreg3;
115+ RegTensor<float> vreg4;
116+ RegTensor<half> vreg5;
117+ RegTensor<float> vreg6;
118+ RegTensor<float> vreg7;
119+ RegTensor<half> vreg8;
120+ MaskReg preg0;
121+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
122+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
123+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
124+ (AscendC::VECTOR_REG_WIDTH / 4);
125+ __local_mem__ half* bufferIn0Addr = (__local_mem__ half*)bufferIn0_.GetPhyAddr();
126+ __local_mem__ half* bufferIn1Addr = (__local_mem__ half*)bufferIn1_.GetPhyAddr();
127+ __local_mem__ half* bufferOut0Addr = (__local_mem__ half*)bufferOut0_.GetPhyAddr();
128+ for (uint16_t i = 0; i < vfLoopNum; i++) {
129+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
130+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
131+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
132+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg1, vreg0, preg0);
133+ AscendC::MicroAPI::Duplicate<float, float>(vreg4, 1.0);
134+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
135+ vreg2, vreg1, static_cast<float>(-1), preg0);
136+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
137+ vreg4, vreg2, vreg1, preg0);
138+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::LoadDist::DIST_UNPACK_B16>(
139+ vreg5, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
140+ AscendC::MicroAPI::Cast<float, half, castTrait0>(vreg6, vreg5, preg0);
141+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg7, vreg4, vreg6, preg0);
142+ AscendC::MicroAPI::Cast<half, float, castTrait1>(vreg8, vreg7, preg0);
143+ AscendC::MicroAPI::DataCopy<half, AscendC::MicroAPI::StoreDist::DIST_PACK_B32>(
144+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg8, preg0);
145+ }
146+ }
147+ queIn0_.FreeTensor(bufferIn0_);
148+ queIn1_.FreeTensor(bufferIn1_);
149+ queOut0_.EnQue<half>(bufferOut0_);
150+ }
151+ 
152+ __aicore__ inline void CopyOut3(
153+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
154+ {
155+ bufferOut0_ = queOut0_.DeQue<half>();
156+ AscendC::DataCopyExtParams dataCopyExtParams;
157+ dataCopyExtParams.blockCount = 1;
158+ dataCopyExtParams.blockLen =
159+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(half);
160+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
161+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
162+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
163+ queOut0_.FreeTensor(bufferOut0_);
164+ }
165+ 
166+private:
167+ TPipe* pipePtr_;
168+ const TanhGradTilingData* tilingDataPtr_;
169+ GlobalTensor<half> inputGmY_;
170+ GlobalTensor<half> inputGmDy_;
171+ GlobalTensor<half> outputGmZ_;
172+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
173+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
174+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
175+ LocalTensor<half> bufferIn0_;
176+ LocalTensor<half> bufferIn1_;
177+ LocalTensor<half> bufferOut0_;
178+ constexpr static AscendC::MicroAPI::CastTrait castTrait0 = {
179+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::UNKNOWN,
180+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::UNKNOWN};
181+ constexpr static AscendC::MicroAPI::CastTrait castTrait1 = {
182+ AscendC::MicroAPI::RegLayout::ZERO, AscendC::MicroAPI::SatMode::NO_SAT,
183+ AscendC::MicroAPI::MaskMergeMode::ZEROING, AscendC::RoundMode::CAST_RINT};
184+};
185+ 
186+} // namespace TanhGrad
187+#endif // ASCENDC_TANH_GRAD_F16_NDDMA_WITHOUT_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_f32_nddma_with_loops.h+175-0
@@ -0,0 +1,175 @@
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+ * \file tanh_grad_f32_nddma_with_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_F32_NDDMA_WITH_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_F32_NDDMA_WITH_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float32, dy is float32, z is float32, max dims in ub is 8 and nddma needs loops
31+class TanhGradF32NddmaWithLoops {
32+public:
33+ __aicore__ inline TanhGradF32NddmaWithLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ float*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ float*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(float);
44+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
45+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
47+ }
48+ 
49+ __aicore__ inline void Process()
50+ {
51+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
52+ tilingDataPtr_->blockFormer;
53+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
54+ Ops::Base::BroadcastGetAxesIndices(
55+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
56+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
57+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
58+ if (ubLoopIdx != 0) {
59+ Ops::Base::BroadcastUpdateAxesIndices(
60+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
61+ }
62+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
63+ tilingDataPtr_->ubTail :
64+ tilingDataPtr_->ubFormer;
65+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
66+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
67+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
68+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
69+ }
70+ }
71+ 
72+private:
73+ __aicore__ inline void CopyIn0(
74+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
75+ {
76+ bufferIn0_ = queIn0_.AllocTensor<float>();
77+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
78+ (ubLoopIdx <= 1 ||
79+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
80+ Ops::Base::BroadcastNddmaWithLoop(
81+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
82+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
83+ ubSplitSize, tilingDataPtr_->ubFormer);
84+ }
85+ queIn0_.EnQue<float>(bufferIn0_);
86+ }
87+ 
88+ __aicore__ inline void CopyIn1(
89+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
90+ {
91+ bufferIn1_ = queIn1_.AllocTensor<float>();
92+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
93+ (ubLoopIdx <= 1 ||
94+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
95+ Ops::Base::BroadcastNddmaWithLoop(
96+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
97+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
98+ ubSplitSize, tilingDataPtr_->ubFormer);
99+ }
100+ queIn1_.EnQue<float>(bufferIn1_);
101+ }
102+ 
103+ __aicore__ inline void Compute2(
104+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
105+ {
106+ bufferIn0_ = queIn0_.DeQue<float>();
107+ bufferIn1_ = queIn1_.DeQue<float>();
108+ bufferOut0_ = queOut0_.AllocTensor<float>();
109+ __VEC_SCOPE__
110+ {
111+ RegTensor<float> vreg0;
112+ RegTensor<float> vreg1;
113+ RegTensor<float> vreg2;
114+ RegTensor<float> vreg3;
115+ RegTensor<float> vreg4;
116+ RegTensor<float> vreg5;
117+ MaskReg preg0;
118+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
119+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
120+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
121+ (AscendC::VECTOR_REG_WIDTH / 4);
122+ __local_mem__ float* bufferIn0Addr = (__local_mem__ float*)bufferIn0_.GetPhyAddr();
123+ __local_mem__ float* bufferIn1Addr = (__local_mem__ float*)bufferIn1_.GetPhyAddr();
124+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
125+ for (uint16_t i = 0; i < vfLoopNum; i++) {
126+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
127+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
128+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
129+ AscendC::MicroAPI::Duplicate<float, float>(vreg3, 1.0);
130+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
131+ vreg2, vreg0, static_cast<float>(-1), preg0);
132+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
133+ vreg3, vreg2, vreg0, preg0);
134+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
135+ vreg4, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
136+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg5, vreg3, vreg4, preg0);
137+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
138+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg5, preg0);
139+ }
140+ }
141+ queIn0_.FreeTensor(bufferIn0_);
142+ queIn1_.FreeTensor(bufferIn1_);
143+ queOut0_.EnQue<float>(bufferOut0_);
144+ }
145+ 
146+ __aicore__ inline void CopyOut3(
147+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
148+ {
149+ bufferOut0_ = queOut0_.DeQue<float>();
150+ AscendC::DataCopyExtParams dataCopyExtParams;
151+ dataCopyExtParams.blockCount = 1;
152+ dataCopyExtParams.blockLen =
153+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
154+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
155+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
156+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
157+ queOut0_.FreeTensor(bufferOut0_);
158+ }
159+ 
160+private:
161+ TPipe* pipePtr_;
162+ const TanhGradTilingData* tilingDataPtr_;
163+ GlobalTensor<float> inputGmY_;
164+ GlobalTensor<float> inputGmDy_;
165+ GlobalTensor<float> outputGmZ_;
166+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
167+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
168+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
169+ LocalTensor<float> bufferIn0_;
170+ LocalTensor<float> bufferIn1_;
171+ LocalTensor<float> bufferOut0_;
172+};
173+ 
174+} // namespace TanhGrad
175+#endif // ASCENDC_TANH_GRAD_F32_NDDMA_WITH_LOOPS_H_
Amath/tanh_grad/op_kernel/arch35/tanh_grad_f32_nddma_without_loops.h+175-0
@@ -0,0 +1,175 @@
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+ * \file tanh_grad_f32_nddma_without_loops.h
13+ * \brief
14+ */
15+#ifndef ASCENDC_TANH_GRAD_F32_NDDMA_WITHOUT_LOOPS_H_
16+#define ASCENDC_TANH_GRAD_F32_NDDMA_WITHOUT_LOOPS_H_
17+ 
18+#include "kernel_operator.h"
19+#include "atvoss/util/broadcast_utils.h"
20+ 
21+namespace TanhGrad {
22+using AscendC::GlobalTensor;
23+using AscendC::LocalTensor;
24+using AscendC::TBuf;
25+using AscendC::TPipe;
26+using AscendC::TQue;
27+using AscendC::MicroAPI::MaskReg;
28+using AscendC::MicroAPI::RegTensor;
29+ 
30+// y is float32, dy is float32, z is float32, max dims in ub is 5 and nddma does not need loops
31+class TanhGradF32NddmaWithoutLoops {
32+public:
33+ __aicore__ inline TanhGradF32NddmaWithoutLoops(){};
34+ __aicore__ inline void Init(
35+ GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, const TanhGradTilingData* tilingDataPtr, TPipe* pipePtr)
36+ {
37+ pipePtr_ = pipePtr;
38+ tilingDataPtr_ = tilingDataPtr;
39+ inputGmY_.SetGlobalBuffer((__gm__ float*)y);
40+ inputGmDy_.SetGlobalBuffer((__gm__ float*)dy);
41+ outputGmZ_.SetGlobalBuffer((__gm__ float*)z);
42+ constexpr int64_t DOUBLE_BUFFER = 2;
43+ int64_t BUFFER_SIZE_0 = tilingDataPtr_->elemNum * sizeof(float);
44+ pipePtr_->InitBuffer(queIn0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
45+ pipePtr_->InitBuffer(queIn1_, DOUBLE_BUFFER, BUFFER_SIZE_0);
46+ pipePtr_->InitBuffer(queOut0_, DOUBLE_BUFFER, BUFFER_SIZE_0);
47+ }
48+ 
49+ __aicore__ inline void Process()
50+ {
51+ int64_t ubLoopNum = AscendC::GetBlockIdx() == AscendC::GetBlockNum() - 1 ? tilingDataPtr_->blockTail :
52+ tilingDataPtr_->blockFormer;
53+ int64_t axesIndices[Ops::Base::BROADCAST_MAX_DIMS] = {0};
54+ Ops::Base::BroadcastGetAxesIndices(
55+ axesIndices, tilingDataPtr_->blockFormer * AscendC::GetBlockIdx(), tilingDataPtr_->outputDims,
56+ tilingDataPtr_->ubSplitAxis, tilingDataPtr_->dimProductBeforeUbInner);
57+ for (int64_t ubLoopIdx = 0; ubLoopIdx < ubLoopNum; ubLoopIdx += 1) {
58+ if (ubLoopIdx != 0) {
59+ Ops::Base::BroadcastUpdateAxesIndices(
60+ axesIndices, tilingDataPtr_->outputDims, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubOuter);
61+ }
62+ int64_t ubSplitSize = axesIndices[tilingDataPtr_->ubSplitAxis] == tilingDataPtr_->ubOuter - 1 ?
63+ tilingDataPtr_->ubTail :
64+ tilingDataPtr_->ubFormer;
65+ CopyIn0(ubSplitSize, axesIndices, ubLoopIdx);
66+ CopyIn1(ubSplitSize, axesIndices, ubLoopIdx);
67+ Compute2(ubSplitSize, axesIndices, ubLoopIdx);
68+ CopyOut3(ubSplitSize, axesIndices, ubLoopIdx);
69+ }
70+ }
71+ 
72+private:
73+ __aicore__ inline void CopyIn0(
74+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
75+ {
76+ bufferIn0_ = queIn0_.AllocTensor<float>();
77+ if ((tilingDataPtr_->input0Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
78+ (ubLoopIdx <= 1 ||
79+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
80+ Ops::Base::BroadcastNddmaWithoutLoop(
81+ inputGmY_, bufferIn0_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
82+ tilingDataPtr_->input0Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
83+ ubSplitSize, tilingDataPtr_->ubFormer);
84+ }
85+ queIn0_.EnQue<float>(bufferIn0_);
86+ }
87+ 
88+ __aicore__ inline void CopyIn1(
89+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
90+ {
91+ bufferIn1_ = queIn1_.AllocTensor<float>();
92+ if ((tilingDataPtr_->input1Strides[tilingDataPtr_->ubSplitAxis] != 0) ||
93+ (ubLoopIdx <= 1 ||
94+ (AscendC::GetBlockIdx() * tilingDataPtr_->blockFormer + ubLoopIdx) % tilingDataPtr_->ubOuter <= 1)) {
95+ Ops::Base::BroadcastNddmaWithoutLoop(
96+ inputGmDy_, bufferIn1_, tilingDataPtr_->outputDims, tilingDataPtr_->outputStrides,
97+ tilingDataPtr_->input1Strides, axesIndices, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->shapeLen,
98+ ubSplitSize, tilingDataPtr_->ubFormer);
99+ }
100+ queIn1_.EnQue<float>(bufferIn1_);
101+ }
102+ 
103+ __aicore__ inline void Compute2(
104+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
105+ {
106+ bufferIn0_ = queIn0_.DeQue<float>();
107+ bufferIn1_ = queIn1_.DeQue<float>();
108+ bufferOut0_ = queOut0_.AllocTensor<float>();
109+ __VEC_SCOPE__
110+ {
111+ RegTensor<float> vreg0;
112+ RegTensor<float> vreg1;
113+ RegTensor<float> vreg2;
114+ RegTensor<float> vreg3;
115+ RegTensor<float> vreg4;
116+ RegTensor<float> vreg5;
117+ MaskReg preg0;
118+ uint32_t size = ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis];
119+ uint16_t vfLoopNum = (ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] +
120+ (AscendC::VECTOR_REG_WIDTH / 4) - 1) /
121+ (AscendC::VECTOR_REG_WIDTH / 4);
122+ __local_mem__ float* bufferIn0Addr = (__local_mem__ float*)bufferIn0_.GetPhyAddr();
123+ __local_mem__ float* bufferIn1Addr = (__local_mem__ float*)bufferIn1_.GetPhyAddr();
124+ __local_mem__ float* bufferOut0Addr = (__local_mem__ float*)bufferOut0_.GetPhyAddr();
125+ for (uint16_t i = 0; i < vfLoopNum; i++) {
126+ preg0 = AscendC::MicroAPI::UpdateMask<float>(size);
127+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
128+ vreg0, bufferIn0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
129+ AscendC::MicroAPI::Duplicate<float, float>(vreg3, 1.0);
130+ AscendC::MicroAPI::Muls<float, float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
131+ vreg2, vreg0, static_cast<float>(-1), preg0);
132+ AscendC::MicroAPI::MulAddDst<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(
133+ vreg3, vreg2, vreg0, preg0);
134+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::LoadDist::DIST_NORM>(
135+ vreg4, bufferIn1Addr + i * (AscendC::VECTOR_REG_WIDTH / 4));
136+ AscendC::MicroAPI::Mul<float, AscendC::MicroAPI::MaskMergeMode::ZEROING>(vreg5, vreg3, vreg4, preg0);
137+ AscendC::MicroAPI::DataCopy<float, AscendC::MicroAPI::StoreDist::DIST_NORM_B32>(
138+ bufferOut0Addr + i * (AscendC::VECTOR_REG_WIDTH / 4), vreg5, preg0);
139+ }
140+ }
141+ queIn0_.FreeTensor(bufferIn0_);
142+ queIn1_.FreeTensor(bufferIn1_);
143+ queOut0_.EnQue<float>(bufferOut0_);
144+ }
145+ 
146+ __aicore__ inline void CopyOut3(
147+ int64_t ubSplitSize, const int64_t (&axesIndices)[Ops::Base::BROADCAST_MAX_DIMS], int64_t ubLoopIdx)
148+ {
149+ bufferOut0_ = queOut0_.DeQue<float>();
150+ AscendC::DataCopyExtParams dataCopyExtParams;
151+ dataCopyExtParams.blockCount = 1;
152+ dataCopyExtParams.blockLen =
153+ ubSplitSize * tilingDataPtr_->outputStrides[tilingDataPtr_->ubSplitAxis] * sizeof(float);
154+ int64_t gmOffset = Ops::Base::BroadcastGetGmOffset(
155+ axesIndices, tilingDataPtr_->outputStrides, tilingDataPtr_->ubSplitAxis, tilingDataPtr_->ubFormer);
156+ AscendC::DataCopyPad(outputGmZ_[gmOffset], bufferOut0_[0], dataCopyExtParams);
157+ queOut0_.FreeTensor(bufferOut0_);
158+ }
159+ 
160+private:
161+ TPipe* pipePtr_;
162+ const TanhGradTilingData* tilingDataPtr_;
163+ GlobalTensor<float> inputGmY_;
164+ GlobalTensor<float> inputGmDy_;
165+ GlobalTensor<float> outputGmZ_;
166+ TQue<AscendC::QuePosition::VECIN, 1> queIn0_;
167+ TQue<AscendC::QuePosition::VECIN, 1> queIn1_;
168+ TQue<AscendC::QuePosition::VECOUT, 1> queOut0_;
169+ LocalTensor<float> bufferIn0_;
170+ LocalTensor<float> bufferIn1_;
171+ LocalTensor<float> bufferOut0_;
172+};
173+ 
174+} // namespace TanhGrad
175+#endif // ASCENDC_TANH_GRAD_F32_NDDMA_WITHOUT_LOOPS_H_
Amath/tanh_grad/op_kernel/tanh_grad_apt.cpp+173-0
@@ -0,0 +1,173 @@
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+ * \file tanh_grad_apt.cpp
13+ * \brief
14+ */
15+#include "arch35/tanh_grad_f16_nddma_without_loops.h"
16+#include "arch35/tanh_grad_f16_nddma_with_loops.h"
17+#include "arch35/tanh_grad_f32_nddma_without_loops.h"
18+#include "arch35/tanh_grad_f32_nddma_with_loops.h"
19+#include "arch35/tanh_grad_bf16_nddma_without_loops.h"
20+#include "arch35/tanh_grad_bf16_nddma_with_loops.h"
21+#include "arch35/tanh_grad_dtype_comb_0_nddma_without_loops.h"
22+#include "arch35/tanh_grad_dtype_comb_0_nddma_with_loops.h"
23+#include "arch35/tanh_grad_dtype_comb_1_nddma_without_loops.h"
24+#include "arch35/tanh_grad_dtype_comb_1_nddma_with_loops.h"
25+#include "arch35/tanh_grad_dtype_comb_2_nddma_without_loops.h"
26+#include "arch35/tanh_grad_dtype_comb_2_nddma_with_loops.h"
27+#include "arch35/tanh_grad_dtype_comb_3_nddma_without_loops.h"
28+#include "arch35/tanh_grad_dtype_comb_3_nddma_with_loops.h"
29+#include "arch35/tanh_grad_dtype_comb_4_nddma_without_loops.h"
30+#include "arch35/tanh_grad_dtype_comb_4_nddma_with_loops.h"
31+#include "arch35/tanh_grad_dtype_comb_5_nddma_without_loops.h"
32+#include "arch35/tanh_grad_dtype_comb_5_nddma_with_loops.h"
33+ 
34+using namespace TanhGrad;
35+ 
36+// y is float16, dy is float16, z is float16, max dims in ub is 5 and nddma does not need loops
37+#define TANH_GRAD_F16_NDDMA_WITHOUT_LOOPS_TILING_KEY 100000001000100
38+// y is float16, dy is float16, z is float16, max dims in ub is 8 and nddma needs loops
39+#define TANH_GRAD_F16_NDDMA_WITH_LOOPS_TILING_KEY 100000001001100
40+// y is float32, dy is float32, z is float32, max dims in ub is 5 and nddma does not need loops
41+#define TANH_GRAD_F32_NDDMA_WITHOUT_LOOPS_TILING_KEY 200000001000100
42+// y is float32, dy is float32, z is float32, max dims in ub is 8 and nddma needs loops
43+#define TANH_GRAD_F32_NDDMA_WITH_LOOPS_TILING_KEY 200000001001100
44+// y is bfloat16, dy is bfloat16, z is bfloat16, max dims in ub is 5 and nddma does not need loops
45+#define TANH_GRAD_BF16_NDDMA_WITHOUT_LOOPS_TILING_KEY 300000001000100
46+// y is bfloat16, dy is bfloat16, z is bfloat16, max dims in ub is 8 and nddma needs loops
47+#define TANH_GRAD_BF16_NDDMA_WITH_LOOPS_TILING_KEY 300000001001100
48+// y is float16, dy is float32, z is float32, max dims in ub is 5 and nddma does not need loops
49+#define TANH_GRAD_DTYPE_COMB_0_NDDMA_WITHOUT_LOOPS_TILING_KEY 400000001000100
50+// y is float16, dy is float32, z is float32, max dims in ub is 8 and nddma needs loops
51+#define TANH_GRAD_DTYPE_COMB_0_NDDMA_WITH_LOOPS_TILING_KEY 400000001001100
52+// y is float16, dy is bfloat16, z is float32, max dims in ub is 5 and nddma does not need loops
53+#define TANH_GRAD_DTYPE_COMB_1_NDDMA_WITHOUT_LOOPS_TILING_KEY 500000001000100
54+// y is float16, dy is bfloat16, z is float32, max dims in ub is 8 and nddma needs loops
55+#define TANH_GRAD_DTYPE_COMB_1_NDDMA_WITH_LOOPS_TILING_KEY 500000001001100
56+// y is float32, dy is float16, z is float32, max dims in ub is 5 and nddma does not need loops
57+#define TANH_GRAD_DTYPE_COMB_2_NDDMA_WITHOUT_LOOPS_TILING_KEY 600000001000100
58+// y is float32, dy is float16, z is float32, max dims in ub is 8 and nddma needs loops
59+#define TANH_GRAD_DTYPE_COMB_2_NDDMA_WITH_LOOPS_TILING_KEY 600000001001100
60+// y is float32, dy is bfloat16, z is float32, max dims in ub is 5 and nddma does not need loops
61+#define TANH_GRAD_DTYPE_COMB_3_NDDMA_WITHOUT_LOOPS_TILING_KEY 700000001000100
62+// y is float32, dy is bfloat16, z is float32, max dims in ub is 8 and nddma needs loops
63+#define TANH_GRAD_DTYPE_COMB_3_NDDMA_WITH_LOOPS_TILING_KEY 700000001001100
64+// y is bfloat16, dy is float16, z is float32, max dims in ub is 5 and nddma does not need loops
65+#define TANH_GRAD_DTYPE_COMB_4_NDDMA_WITHOUT_LOOPS_TILING_KEY 800000001000100
66+// y is bfloat16, dy is float16, z is float32, max dims in ub is 8 and nddma needs loops
67+#define TANH_GRAD_DTYPE_COMB_4_NDDMA_WITH_LOOPS_TILING_KEY 800000001001100
68+// y is bfloat16, dy is float32, z is float32, max dims in ub is 5 and nddma does not need loops
69+#define TANH_GRAD_DTYPE_COMB_5_NDDMA_WITHOUT_LOOPS_TILING_KEY 900000001000100
70+// y is bfloat16, dy is float32, z is float32, max dims in ub is 8 and nddma needs loops
71+#define TANH_GRAD_DTYPE_COMB_5_NDDMA_WITH_LOOPS_TILING_KEY 900000001001100
72+ 
73+extern "C" __global__ __aicore__ void tanh_grad(GM_ADDR y, GM_ADDR dy, GM_ADDR z, GM_ADDR workspace, GM_ADDR tiling)
74+{
75+ if (g_coreType == AscendC::AIC) {
76+ return;
77+ }
78+ KERNEL_TASK_TYPE_DEFAULT(KERNEL_TYPE_AIV_ONLY);
79+ GET_TILING_DATA(tilingData, tiling);
80+ TPipe tPipe;
81+ if (TILING_KEY_IS(TANH_GRAD_F16_NDDMA_WITHOUT_LOOPS_TILING_KEY)) {
82+ TanhGradF16NddmaWithoutLoops op;
83+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
84+ op.Process();
85+ return;
86+ } else if (TILING_KEY_IS(TANH_GRAD_F16_NDDMA_WITH_LOOPS_TILING_KEY)) {
87+ TanhGradF16NddmaWithLoops op;
88+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
89+ op.Process();
90+ return;
91+ } else if (TILING_KEY_IS(TANH_GRAD_F32_NDDMA_WITHOUT_LOOPS_TILING_KEY)) {
92+ TanhGradF32NddmaWithoutLoops op;
93+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
94+ op.Process();
95+ return;
96+ } else if (TILING_KEY_IS(TANH_GRAD_F32_NDDMA_WITH_LOOPS_TILING_KEY)) {
97+ TanhGradF32NddmaWithLoops op;
98+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
99+ op.Process();
100+ return;
101+ } else if (TILING_KEY_IS(TANH_GRAD_BF16_NDDMA_WITHOUT_LOOPS_TILING_KEY)) {
102+ TanhGradBf16NddmaWithoutLoops op;
103+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
104+ op.Process();
105+ return;
106+ } else if (TILING_KEY_IS(TANH_GRAD_BF16_NDDMA_WITH_LOOPS_TILING_KEY)) {
107+ TanhGradBf16NddmaWithLoops op;
108+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
109+ op.Process();
110+ return;
111+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_0_NDDMA_WITHOUT_LOOPS_TILING_KEY)) {
112+ TanhGradDtypeComb0NddmaWithoutLoops op;
113+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
114+ op.Process();
115+ return;
116+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_0_NDDMA_WITH_LOOPS_TILING_KEY)) {
117+ TanhGradDtypeComb0NddmaWithLoops op;
118+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
119+ op.Process();
120+ return;
121+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_1_NDDMA_WITHOUT_LOOPS_TILING_KEY)) {
122+ TanhGradDtypeComb1NddmaWithoutLoops op;
123+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
124+ op.Process();
125+ return;
126+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_1_NDDMA_WITH_LOOPS_TILING_KEY)) {
127+ TanhGradDtypeComb1NddmaWithLoops op;
128+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
129+ op.Process();
130+ return;
131+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_2_NDDMA_WITHOUT_LOOPS_TILING_KEY)) {
132+ TanhGradDtypeComb2NddmaWithoutLoops op;
133+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
134+ op.Process();
135+ return;
136+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_2_NDDMA_WITH_LOOPS_TILING_KEY)) {
137+ TanhGradDtypeComb2NddmaWithLoops op;
138+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
139+ op.Process();
140+ return;
141+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_3_NDDMA_WITHOUT_LOOPS_TILING_KEY)) {
142+ TanhGradDtypeComb3NddmaWithoutLoops op;
143+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
144+ op.Process();
145+ return;
146+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_3_NDDMA_WITH_LOOPS_TILING_KEY)) {
147+ TanhGradDtypeComb3NddmaWithLoops op;
148+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
149+ op.Process();
150+ return;
151+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_4_NDDMA_WITHOUT_LOOPS_TILING_KEY)) {
152+ TanhGradDtypeComb4NddmaWithoutLoops op;
153+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
154+ op.Process();
155+ return;
156+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_4_NDDMA_WITH_LOOPS_TILING_KEY)) {
157+ TanhGradDtypeComb4NddmaWithLoops op;
158+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
159+ op.Process();
160+ return;
161+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_5_NDDMA_WITHOUT_LOOPS_TILING_KEY)) {
162+ TanhGradDtypeComb5NddmaWithoutLoops op;
163+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
164+ op.Process();
165+ return;
166+ } else if (TILING_KEY_IS(TANH_GRAD_DTYPE_COMB_5_NDDMA_WITH_LOOPS_TILING_KEY)) {
167+ TanhGradDtypeComb5NddmaWithLoops op;
168+ op.Init(y, dy, z, workspace, &tilingData, &tPipe);
169+ op.Process();
170+ return;
171+ }
172+ return;
173+}
Mmath/tanh_grad/tests/CMakeLists.txt+5-5
@@ -1,13 +1,13 @@
1# ----------------------------------------------------------------------------1# ----------------------------------------------------------------------------
2-# This program is free software, you can redistribute it and/or modify it.
3# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
4-# This file is a part of the CANN Open Software.3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
5-# Licensed under CANN Open Software License Agreement Version 2.0 (the "License").4+# 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.5# 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, INCLUDING6+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
8-# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7+# 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.8# See LICENSE in the root of the software repository for the full text of the License.
10# ----------------------------------------------------------------------------9# ----------------------------------------------------------------------------
10+ 
11file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)11file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)
12foreach(SUB_DIR ${CURRENT_DIRS})12foreach(SUB_DIR ${CURRENT_DIRS})
13 if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")13 if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
Mmath/tanh_grad/tests/ut/CMakeLists.txt+4-5
@@ -1,11 +1,10 @@
1# ----------------------------------------------------------------------------1# ----------------------------------------------------------------------------
2-# This program is free software, you can redistribute it and/or modify it.
3# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
4-# This file is a part of the CANN Open Software.3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
5-# Licensed under CANN Open Software License Agreement Version 2.0 (the "License").4+# 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.5# 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, INCLUDING6+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
8-# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7+# 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.8# See LICENSE in the root of the software repository for the full text of the License.
10# ----------------------------------------------------------------------------9# ----------------------------------------------------------------------------
11 10 
Dmath/tanh_grad/tests/ut/graph_plugin/CMakeLists.txt+0-10
@@ -1,10 +0,0 @@
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-# ----------------------------------------------------------------------------
Dmath/tanh_grad/tests/ut/graph_plugin/fusion_pass/CMakeLists.txt+0-10
@@ -1,10 +0,0 @@
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-# ----------------------------------------------------------------------------
Mmath/tanh_grad/tests/ut/op_host/CMakeLists.txt+6-8
@@ -1,11 +1,10 @@
1# ----------------------------------------------------------------------------1# ----------------------------------------------------------------------------
2-# This program is free software, you can redistribute it and/or modify it.
3# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
4-# This file is a part of the CANN Open Software.3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
5-# Licensed under CANN Open Software License Agreement Version 2.0 (the "License").4+# 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.5# 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, INCLUDING6+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
8-# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7+# 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.8# See LICENSE in the root of the software repository for the full text of the License.
10# ----------------------------------------------------------------------------9# ----------------------------------------------------------------------------
11 10 
@@ -16,7 +15,6 @@ foreach(SUB_DIR ${CURRENT_DIRS})
16 endif()15 endif()
17endforeach()16endforeach()
18 17 
19-if(UT_TEST_ALL OR OP_HOST_UT)18+if(TILING_UT OR PROTO_UT OR OP_API_UT OR (UT_TEST_ALL AND NOT AICPU_ONLY))
20- # add_modules_ut_sources(UT_NAME ${OP_TILING_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR})19+ add_modules_llt_sources(HOSTNAME ${OPTEST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR})
21- # add_modules_ut_sources(UT_NAME ${OP_INFERSHAPE_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR})
22endif()20endif()
Amath/tanh_grad/tests/ut/op_host/arch35/test_tanh_grad_tiling_arch35.cpp+49-0
@@ -0,0 +1,49 @@
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+#include <iostream>
12+#include <gtest/gtest.h>
13+#include "tiling_context_faker.h"
14+#include "tiling_case_executor.h"
15+#include "../../../../op_host/arch35/tanh_grad_tiling_arch35.h"
16+ 
17+using namespace std;
18+using namespace ge;
19+using namespace optiling;
20+ 
21+class TanhGradTilingTest : public testing::Test {
22+protected:
23+ static void SetUpTestCase()
24+ {
25+ std::cout << "TanhGradTilingTest SetUp" << std::endl;
26+ }
27+ 
28+ static void TearDownTestCase()
29+ {
30+ std::cout << "TanhGradTilingTest TearDown" << std::endl;
31+ }
32+};
33+ 
34+TEST_F(TanhGradTilingTest, tanh_grad_tiling_test_001)
35+{
36+ gert::StorageShape shape = {{32, 32}, {32, 32}};
37+ 
38+ TanhGradCompileInfo compileInfo = {64, 253952};
39+ 
40+ gert::TilingContextPara tilingContextPara(
41+ "TanhGrad",
42+ {{shape, ge::DT_FLOAT16, ge::FORMAT_ND}, {shape, ge::DT_FLOAT16, ge::FORMAT_ND}},
43+ {{shape, ge::DT_FLOAT16, ge::FORMAT_ND},},
44+ &compileInfo);
45+ uint64_t expectTilingKey = 100000001000100;
46+ string expectTilingData = "1 21760 1 1024 1 1 0 1 21760 1024 0 0 0 0 0 0 0 1024 0 0 0 0 0 0 0 1024 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 ";
47+ std::vector<size_t> expectWorkspaces = {32};
48+ ExecuteTestCase(tilingContextPara, ge::GRAPH_SUCCESS, expectTilingKey, expectTilingData, expectWorkspaces);
49+}
Mmath/tanh_grad/tests/ut/op_host/op_api/CMakeLists.txt+5-6
@@ -1,14 +1,13 @@
1# ----------------------------------------------------------------------------1# ----------------------------------------------------------------------------
2-# This program is free software, you can redistribute it and/or modify it.
3# Copyright (c) 2025 Huawei Technologies Co., Ltd.2# Copyright (c) 2025 Huawei Technologies Co., Ltd.
4-# This file is a part of the CANN Open Software.3+# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
5-# Licensed under CANN Open Software License Agreement Version 2.0 (the "License").4+# 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.5# 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, INCLUDING6+# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
8-# BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.7+# 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.8# See LICENSE in the root of the software repository for the full text of the License.
10# ----------------------------------------------------------------------------9# ----------------------------------------------------------------------------
11 10 
12if(UT_TEST_ALL OR OP_API_UT)11if(UT_TEST_ALL OR OP_API_UT)
13- # add_modules_ut_sources(UT_NAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR})12+ add_modules_ut_sources(UT_NAME ${OP_API_MODULE_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR})
14endif()13endif()
Dmath/tanh_grad/tests/ut/op_host/op_api/test_aclnn_tanh_backward_l0.cpp+0-9
@@ -1,9 +0,0 @@
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- */
Mmath/tanh_grad/tests/ut/op_host/op_api/test_aclnn_tanh_backward_l2.cpp+269-250
@@ -1,399 +1,418 @@
1/**1/**
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.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 of3+ * 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").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.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,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.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.8+ * See LICENSE in the root of the software repository for the full text of the License.
9- */9+ */
10#include "gtest/gtest.h"10#include "gtest/gtest.h"
11-#include "aclnn_tanh_backward.h"11+#include "../../../op_api/aclnn_tanh_backward.h"
12#include "op_api_ut_common/tensor_desc.h"12#include "op_api_ut_common/tensor_desc.h"
13#include "op_api_ut_common/scalar_desc.h"13#include "op_api_ut_common/scalar_desc.h"
14#include "op_api_ut_common/op_api_ut.h"14#include "op_api_ut_common/op_api_ut.h"
15 15 
16class l2_tanh_backward_test : public testing::Test {16class l2_tanh_backward_test : public testing::Test {
17protected:17protected:
18- static void SetUpTestCase() {18+ static void SetUpTestCase()
19- std::cout << "l2_tanh_backward_test SetUp" << std::endl;19+ {
20- }20+ std::cout << "l2_tanh_backward_test SetUp" << std::endl;
21+ }
21 22 
22- static void TearDownTestCase() { std::cout << "l2_tanh_backward_test TearDown" << std::endl; }23+ static void TearDownTestCase()
24+ {
25+ std::cout << "l2_tanh_backward_test TearDown" << std::endl;
26+ }
23};27};
24 28 
25// 正常场景_float32_nd29// 正常场景_float32_nd
26-TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_nd) {30+TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_nd)
27- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);31+{
28- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);32+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
29- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001);33+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
34+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND).Precision(0.0001, 0.0001);
30 35 
31- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));36+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
32 37 
33- uint64_t workspaceSize = 0;38+ uint64_t workspaceSize = 0;
34- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);39+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
35- EXPECT_EQ(aclRet, ACL_SUCCESS);40+ EXPECT_EQ(aclRet, ACL_SUCCESS);
36}41}
37 42 
38// 正常场景_float16_nd43// 正常场景_float16_nd
39-TEST_F(l2_tanh_backward_test, normal_dtype_float16_format_nd) {44+TEST_F(l2_tanh_backward_test, normal_dtype_float16_format_nd)
40- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT16, ACL_FORMAT_ND);45+{
41- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT16, ACL_FORMAT_ND);46+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT16, ACL_FORMAT_ND);
42- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.0001, 0.0001);47+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT16, ACL_FORMAT_ND);
48+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT16, ACL_FORMAT_ND).Precision(0.0001, 0.0001);
43 49 
44- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));50+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
45 51 
46- uint64_t workspaceSize = 0;52+ uint64_t workspaceSize = 0;
47- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);53+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
48- EXPECT_EQ(aclRet, ACL_SUCCESS);54+ EXPECT_EQ(aclRet, ACL_SUCCESS);
49-}
50- 
51-// 正常场景_double_nd
52-TEST_F(l2_tanh_backward_test, normal_dtype_double_format_nd) {
53- auto gradOutputDesc = TensorDesc({2, 3}, ACL_DOUBLE, ACL_FORMAT_ND);
54- auto outputDesc = TensorDesc({2, 3}, ACL_DOUBLE, ACL_FORMAT_ND);
55- auto outDesc = TensorDesc({2, 3}, ACL_DOUBLE, ACL_FORMAT_ND).Precision(0.0001, 0.0001);
56- 
57- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
58- 
59- uint64_t workspaceSize = 0;
60- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
61- EXPECT_EQ(aclRet, ACL_SUCCESS);
62}55}
63 56 
64// 不支持场景_complex64_nd57// 不支持场景_complex64_nd
65-TEST_F(l2_tanh_backward_test, normal_dtype_complex64_format_nd) {58+TEST_F(l2_tanh_backward_test, normal_dtype_complex64_format_nd)
66- auto gradOutputDesc = TensorDesc({2, 3}, ACL_COMPLEX64, ACL_FORMAT_ND);59+{
67- auto outputDesc = TensorDesc({2, 3}, ACL_COMPLEX64, ACL_FORMAT_ND);60+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_COMPLEX64, ACL_FORMAT_ND);
68- auto outDesc = TensorDesc({2, 3}, ACL_COMPLEX64, ACL_FORMAT_ND);61+ auto outputDesc = TensorDesc({2, 3}, ACL_COMPLEX64, ACL_FORMAT_ND);
62+ auto outDesc = TensorDesc({2, 3}, ACL_COMPLEX64, ACL_FORMAT_ND);
69 63 
70- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));64+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
71 65 
72- uint64_t workspaceSize = 0;66+ uint64_t workspaceSize = 0;
73- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);67+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
74- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);68+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
75}69}
76 70 
77// 不支持场景_complex128_nd71// 不支持场景_complex128_nd
78-TEST_F(l2_tanh_backward_test, normal_dtype_complex128_format_nd) {72+TEST_F(l2_tanh_backward_test, normal_dtype_complex128_format_nd)
79- auto gradOutputDesc = TensorDesc({2, 3}, ACL_COMPLEX128, ACL_FORMAT_ND);73+{
80- auto outputDesc = TensorDesc({2, 3}, ACL_COMPLEX128, ACL_FORMAT_ND);74+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_COMPLEX128, ACL_FORMAT_ND);
81- auto outDesc = TensorDesc({2, 3}, ACL_COMPLEX128, ACL_FORMAT_ND);75+ auto outputDesc = TensorDesc({2, 3}, ACL_COMPLEX128, ACL_FORMAT_ND);
76+ auto outDesc = TensorDesc({2, 3}, ACL_COMPLEX128, ACL_FORMAT_ND);
82 77 
83- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));78+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
84 79 
85- uint64_t workspaceSize = 0;80+ uint64_t workspaceSize = 0;
86- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);81+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
87- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);82+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
88}83}
89 84 
90// 不支持场景_uint8_nd85// 不支持场景_uint8_nd
91-TEST_F(l2_tanh_backward_test, abnormal_dtype_uint8_format_nd) {86+TEST_F(l2_tanh_backward_test, abnormal_dtype_uint8_format_nd)
92- auto gradOutputDesc = TensorDesc({2, 3}, ACL_UINT8, ACL_FORMAT_ND);87+{
93- auto outputDesc = TensorDesc({2, 3}, ACL_UINT8, ACL_FORMAT_ND);88+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_UINT8, ACL_FORMAT_ND);
94- auto outDesc = TensorDesc({2, 3}, ACL_UINT8, ACL_FORMAT_ND);89+ auto outputDesc = TensorDesc({2, 3}, ACL_UINT8, ACL_FORMAT_ND);
90+ auto outDesc = TensorDesc({2, 3}, ACL_UINT8, ACL_FORMAT_ND);
95 91 
96- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));92+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
97 93 
98- uint64_t workspaceSize = 0;94+ uint64_t workspaceSize = 0;
99- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);95+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
100- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);96+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
101}97}
102 98 
103// 不支持场景_int8_nd99// 不支持场景_int8_nd
104-TEST_F(l2_tanh_backward_test, abnormal_dtype_int8_format_nd) {100+TEST_F(l2_tanh_backward_test, abnormal_dtype_int8_format_nd)
105- auto gradOutputDesc = TensorDesc({2, 3}, ACL_INT8, ACL_FORMAT_ND);101+{
106- auto outputDesc = TensorDesc({2, 3}, ACL_INT8, ACL_FORMAT_ND);102+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_INT8, ACL_FORMAT_ND);
107- auto outDesc = TensorDesc({2, 3}, ACL_INT8, ACL_FORMAT_ND);103+ auto outputDesc = TensorDesc({2, 3}, ACL_INT8, ACL_FORMAT_ND);
104+ auto outDesc = TensorDesc({2, 3}, ACL_INT8, ACL_FORMAT_ND);
108 105 
109- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));106+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
110 107 
111- uint64_t workspaceSize = 0;108+ uint64_t workspaceSize = 0;
112- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);109+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
113- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);110+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
114}111}
115 112 
116// 不支持场景_int16_nd113// 不支持场景_int16_nd
117-TEST_F(l2_tanh_backward_test, abnormal_dtype_int16_format_nd) {114+TEST_F(l2_tanh_backward_test, abnormal_dtype_int16_format_nd)
118- auto gradOutputDesc = TensorDesc({2, 3}, ACL_INT16, ACL_FORMAT_ND);115+{
119- auto outputDesc = TensorDesc({2, 3}, ACL_INT16, ACL_FORMAT_ND);116+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_INT16, ACL_FORMAT_ND);
120- auto outDesc = TensorDesc({2, 3}, ACL_INT16, ACL_FORMAT_ND);117+ auto outputDesc = TensorDesc({2, 3}, ACL_INT16, ACL_FORMAT_ND);
118+ auto outDesc = TensorDesc({2, 3}, ACL_INT16, ACL_FORMAT_ND);
121 119 
122- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));120+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
123 121 
124- uint64_t workspaceSize = 0;122+ uint64_t workspaceSize = 0;
125- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);123+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
126- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);124+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
127}125}
128 126 
129// 不支持场景_int32_nd127// 不支持场景_int32_nd
130-TEST_F(l2_tanh_backward_test, abnormal_dtype_int32_format_nd) {128+TEST_F(l2_tanh_backward_test, abnormal_dtype_int32_format_nd)
131- auto gradOutputDesc = TensorDesc({2, 3}, ACL_INT32, ACL_FORMAT_ND);129+{
132- auto outputDesc = TensorDesc({2, 3}, ACL_INT32, ACL_FORMAT_ND);130+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_INT32, ACL_FORMAT_ND);
133- auto outDesc = TensorDesc({2, 3}, ACL_INT32, ACL_FORMAT_ND);131+ auto outputDesc = TensorDesc({2, 3}, ACL_INT32, ACL_FORMAT_ND);
132+ auto outDesc = TensorDesc({2, 3}, ACL_INT32, ACL_FORMAT_ND);
134 133 
135- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));134+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
136 135 
137- uint64_t workspaceSize = 0;136+ uint64_t workspaceSize = 0;
138- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);137+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
139- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);138+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
140}139}
141 140 
142// 不支持场景_int64_nd141// 不支持场景_int64_nd
143-TEST_F(l2_tanh_backward_test, abnormal_dtype_int64_format_nd) {142+TEST_F(l2_tanh_backward_test, abnormal_dtype_int64_format_nd)
144- auto gradOutputDesc = TensorDesc({2, 3}, ACL_INT64, ACL_FORMAT_ND);143+{
145- auto outputDesc = TensorDesc({2, 3}, ACL_INT64, ACL_FORMAT_ND);144+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_INT64, ACL_FORMAT_ND);
146- auto outDesc = TensorDesc({2, 3}, ACL_INT64, ACL_FORMAT_ND);145+ auto outputDesc = TensorDesc({2, 3}, ACL_INT64, ACL_FORMAT_ND);
146+ auto outDesc = TensorDesc({2, 3}, ACL_INT64, ACL_FORMAT_ND);
147 147 
148- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));148+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
149 149 
150- uint64_t workspaceSize = 0;150+ uint64_t workspaceSize = 0;
151- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);151+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
152- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);152+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
153}153}
154 154 
155// 不支持场景_bool_nd155// 不支持场景_bool_nd
156-TEST_F(l2_tanh_backward_test, abnormal_dtype_bool_format_nd) {156+TEST_F(l2_tanh_backward_test, abnormal_dtype_bool_format_nd)
157- auto gradOutputDesc = TensorDesc({2, 3}, ACL_BOOL, ACL_FORMAT_ND);157+{
158- auto outputDesc = TensorDesc({2, 3}, ACL_BOOL, ACL_FORMAT_ND);158+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_BOOL, ACL_FORMAT_ND);
159- auto outDesc = TensorDesc({2, 3}, ACL_BOOL, ACL_FORMAT_ND);159+ auto outputDesc = TensorDesc({2, 3}, ACL_BOOL, ACL_FORMAT_ND);
160+ auto outDesc = TensorDesc({2, 3}, ACL_BOOL, ACL_FORMAT_ND);
160 161 
161- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));162+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
162 163 
163- uint64_t workspaceSize = 0;164+ uint64_t workspaceSize = 0;
164- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);165+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
165- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);166+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
166}167}
167 168 
168// 正常场景_bfloat16_nd169// 正常场景_bfloat16_nd
169-TEST_F(l2_tanh_backward_test, ascend910B2_normal_dtype_bfloat16_format_nd) {170+TEST_F(l2_tanh_backward_test, ascend910B2_normal_dtype_bfloat16_format_nd)
170- auto gradOutputDesc = TensorDesc({2, 3}, ACL_BF16, ACL_FORMAT_ND);171+{
171- auto outputDesc = TensorDesc({2, 3}, ACL_BF16, ACL_FORMAT_ND);172+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_BF16, ACL_FORMAT_ND);
172- auto outDesc = TensorDesc({2, 3}, ACL_BF16, ACL_FORMAT_ND);173+ auto outputDesc = TensorDesc({2, 3}, ACL_BF16, ACL_FORMAT_ND);
174+ auto outDesc = TensorDesc({2, 3}, ACL_BF16, ACL_FORMAT_ND);
173 175 
174- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));176+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
175 177 
176- uint64_t workspaceSize = 0;178+ uint64_t workspaceSize = 0;
177- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);179+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
178- EXPECT_EQ(aclRet, ACL_SUCCESS);180+ EXPECT_EQ(aclRet, ACL_SUCCESS);
179}181}
180 182 
181// 正常场景_float32_fractal_nz183// 正常场景_float32_fractal_nz
182-TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_fractal_nz) {184+TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_fractal_nz)
183- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_FRACTAL_NZ).ValueRange(-2, 2);185+{
184- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_FRACTAL_NZ).ValueRange(-2, 2);186+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_FRACTAL_NZ).ValueRange(-2, 2);
185- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_FRACTAL_NZ).Precision(0.0001, 0.0001);187+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_FRACTAL_NZ).ValueRange(-2, 2);
188+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_FRACTAL_NZ).Precision(0.0001, 0.0001);
186 189 
187- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));190+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
188 191 
189- uint64_t workspaceSize = 0;192+ uint64_t workspaceSize = 0;
190- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);193+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
191- EXPECT_EQ(aclRet, ACL_SUCCESS);194+ EXPECT_EQ(aclRet, ACL_SUCCESS);
192}195}
193 196 
194// 正常场景_float32_nc1hwc0197// 正常场景_float32_nc1hwc0
195-TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_nc1hwc0) {198+TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_nc1hwc0)
196- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NC1HWC0).ValueRange(-2, 2);199+{
197- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NC1HWC0).ValueRange(-2, 2);200+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NC1HWC0).ValueRange(-2, 2);
198- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NC1HWC0).Precision(0.0001, 0.0001);201+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NC1HWC0).ValueRange(-2, 2);
202+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NC1HWC0).Precision(0.0001, 0.0001);
199 203 
200- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));204+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
201 205 
202- uint64_t workspaceSize = 0;206+ uint64_t workspaceSize = 0;
203- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);207+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
204- EXPECT_EQ(aclRet, ACL_SUCCESS);208+ EXPECT_EQ(aclRet, ACL_SUCCESS);
205}209}
206 210 
207// 正常场景_float32_nhwc211// 正常场景_float32_nhwc
208-TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_nhwc) {212+TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_nhwc)
209- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NHWC).ValueRange(-2, 2);213+{
210- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NHWC).ValueRange(-2, 2);214+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NHWC).ValueRange(-2, 2);
211- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NHWC).Precision(0.0001, 0.0001);215+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NHWC).ValueRange(-2, 2);
216+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NHWC).Precision(0.0001, 0.0001);
212 217 
213- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));218+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
214 219 
215- uint64_t workspaceSize = 0;220+ uint64_t workspaceSize = 0;
216- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);221+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
217- EXPECT_EQ(aclRet, ACL_SUCCESS);222+ EXPECT_EQ(aclRet, ACL_SUCCESS);
218}223}
219 224 
220// 正常场景_float32_nchw225// 正常场景_float32_nchw
221-TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_nchw) {226+TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_nchw)
222- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCHW).ValueRange(-2, 2);227+{
223- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCHW).ValueRange(-2, 2);228+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCHW).ValueRange(-2, 2);
224- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCHW).Precision(0.0001, 0.0001);229+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCHW).ValueRange(-2, 2);
230+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCHW).Precision(0.0001, 0.0001);
225 231 
226- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));232+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
227 233 
228- uint64_t workspaceSize = 0;234+ uint64_t workspaceSize = 0;
229- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);235+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
230- EXPECT_EQ(aclRet, ACL_SUCCESS);236+ EXPECT_EQ(aclRet, ACL_SUCCESS);
231}237}
232 238 
233// 正常场景_float32_hwcn239// 正常场景_float32_hwcn
234-TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_hwcn) {240+TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_hwcn)
235- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_HWCN).ValueRange(-2, 2);241+{
236- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_HWCN).ValueRange(-2, 2);242+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_HWCN).ValueRange(-2, 2);
237- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_HWCN).Precision(0.0001, 0.0001);243+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_HWCN).ValueRange(-2, 2);
244+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_HWCN).Precision(0.0001, 0.0001);
238 245 
239- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));246+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
240 247 
241- uint64_t workspaceSize = 0;248+ uint64_t workspaceSize = 0;
242- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);249+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
243- EXPECT_EQ(aclRet, ACL_SUCCESS);250+ EXPECT_EQ(aclRet, ACL_SUCCESS);
244}251}
245 252 
246// 正常场景_float32_ncdhw253// 正常场景_float32_ncdhw
247-TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_ncdhw) {254+TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_ncdhw)
248- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCDHW).ValueRange(-2, 2);255+{
249- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCDHW).ValueRange(-2, 2);256+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCDHW).ValueRange(-2, 2);
250- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCDHW).Precision(0.0001, 0.0001);257+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCDHW).ValueRange(-2, 2);
258+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NCDHW).Precision(0.0001, 0.0001);
251 259 
252- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));260+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
253 261 
254- uint64_t workspaceSize = 0;262+ uint64_t workspaceSize = 0;
255- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);263+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
256- EXPECT_EQ(aclRet, ACL_SUCCESS);264+ EXPECT_EQ(aclRet, ACL_SUCCESS);
257}265}
258 266 
259// 正常场景_float32_ndhwc267// 正常场景_float32_ndhwc
260-TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_ndhwc) {268+TEST_F(l2_tanh_backward_test, normal_dtype_float32_format_ndhwc)
261- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).ValueRange(-2, 2);269+{
262- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).ValueRange(-2, 2);270+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).ValueRange(-2, 2);
263- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).Precision(0.0001, 0.0001);271+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).ValueRange(-2, 2);
272+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).Precision(0.0001, 0.0001);
264 273 
265- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));274+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
266 275 
267- uint64_t workspaceSize = 0;276+ uint64_t workspaceSize = 0;
268- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);277+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
269- EXPECT_EQ(aclRet, ACL_SUCCESS);278+ EXPECT_EQ(aclRet, ACL_SUCCESS);
270}279}
271 280 
272// 空tensor场景281// 空tensor场景
273-TEST_F(l2_tanh_backward_test, normal_empty_tensor) {282+TEST_F(l2_tanh_backward_test, normal_empty_tensor)
274- auto gradOutputDesc = TensorDesc({0, 3}, ACL_FLOAT, ACL_FORMAT_ND);283+{
275- auto outputDesc = TensorDesc({0, 3}, ACL_FLOAT, ACL_FORMAT_ND);284+ auto gradOutputDesc = TensorDesc({0, 3}, ACL_FLOAT, ACL_FORMAT_ND);
276- auto outDesc = TensorDesc({0, 3}, ACL_FLOAT, ACL_FORMAT_ND);285+ auto outputDesc = TensorDesc({0, 3}, ACL_FLOAT, ACL_FORMAT_ND);
286+ auto outDesc = TensorDesc({0, 3}, ACL_FLOAT, ACL_FORMAT_ND);
277 287 
278- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));288+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
279 289 
280- uint64_t workspaceSize = 0;290+ uint64_t workspaceSize = 0;
281- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);291+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
282- EXPECT_EQ(aclRet, ACL_SUCCESS);292+ EXPECT_EQ(aclRet, ACL_SUCCESS);
283}293}
284 294 
285// CheckNotNull_1295// CheckNotNull_1
286-TEST_F(l2_tanh_backward_test, abnormal_grad_output_nullptr) {296+TEST_F(l2_tanh_backward_test, abnormal_grad_output_nullptr)
287- auto gradOutputDesc = nullptr;297+{
288- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);298+ auto gradOutputDesc = nullptr;
289- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);299+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
300+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
290 301 
291- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));302+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
292 303 
293- uint64_t workspaceSize = 0;304+ uint64_t workspaceSize = 0;
294- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);305+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
295- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_NULLPTR);306+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_NULLPTR);
296}307}
297 308 
298// CheckNotNull_2309// CheckNotNull_2
299-TEST_F(l2_tanh_backward_test, abnormal_output_nullptr) {310+TEST_F(l2_tanh_backward_test, abnormal_output_nullptr)
300- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);311+{
301- auto outputDesc = nullptr;312+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
302- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);313+ auto outputDesc = nullptr;
314+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
303 315 
304- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));316+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
305 317 
306- uint64_t workspaceSize = 0;318+ uint64_t workspaceSize = 0;
307- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);319+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
308- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_NULLPTR);320+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_NULLPTR);
309}321}
310 322 
311// CheckNotNull_3323// CheckNotNull_3
312-TEST_F(l2_tanh_backward_test, abnormal_grad_input_nullptr) {324+TEST_F(l2_tanh_backward_test, abnormal_grad_input_nullptr)
313- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);325+{
314- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);326+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
315- auto outDesc = nullptr;327+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
328+ auto outDesc = nullptr;
316 329 
317- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));330+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
318 331 
319- uint64_t workspaceSize = 0;332+ uint64_t workspaceSize = 0;
320- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);333+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
321- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_NULLPTR);334+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_NULLPTR);
322}335}
323 336 
324// CheckDtypeValid_1337// CheckDtypeValid_1
325-TEST_F(l2_tanh_backward_test, abnormal_dtype_grad_output_int64) {338+TEST_F(l2_tanh_backward_test, abnormal_dtype_grad_output_int64)
326- auto gradOutputDesc = TensorDesc({2, 3}, ACL_INT64, ACL_FORMAT_ND);339+{
327- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);340+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_INT64, ACL_FORMAT_ND);
328- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);341+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
342+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
329 343 
330- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));344+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
331 345 
332- uint64_t workspaceSize = 0;346+ uint64_t workspaceSize = 0;
333- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);347+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
334- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);348+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
335}349}
336 350 
337// CheckDtypeValid_2351// CheckDtypeValid_2
338-TEST_F(l2_tanh_backward_test, abnormal_dtype_output_int64) {352+TEST_F(l2_tanh_backward_test, abnormal_dtype_output_int64)
339- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);353+{
340- auto outputDesc = TensorDesc({2, 3}, ACL_INT64, ACL_FORMAT_ND);354+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
341- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);355+ auto outputDesc = TensorDesc({2, 3}, ACL_INT64, ACL_FORMAT_ND);
356+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
342 357 
343- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));358+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
344 359 
345- uint64_t workspaceSize = 0;360+ uint64_t workspaceSize = 0;
346- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);361+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
347- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);362+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
348}363}
349 364 
350// CheckDtypeValid_3365// CheckDtypeValid_3
351-TEST_F(l2_tanh_backward_test, abnormal_dtype_grad_output_output_unequal) {366+TEST_F(l2_tanh_backward_test, abnormal_dtype_grad_output_output_unequal)
352- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);367+{
353- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT16, ACL_FORMAT_ND);368+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
354- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);369+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT16, ACL_FORMAT_ND);
370+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
355 371 
356- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));372+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
357 373 
358- uint64_t workspaceSize = 0;374+ uint64_t workspaceSize = 0;
359- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);375+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
360- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);376+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
361}377}
362 378 
363// CheckShape_1379// CheckShape_1
364-TEST_F(l2_tanh_backward_test, abnormal_shape_grad_output_output_unequal) {380+TEST_F(l2_tanh_backward_test, abnormal_shape_grad_output_output_unequal)
365- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);381+{
366- auto outputDesc = TensorDesc({1, 3}, ACL_FLOAT, ACL_FORMAT_ND);382+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
367- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);383+ auto outputDesc = TensorDesc({1, 3}, ACL_FLOAT, ACL_FORMAT_ND);
384+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_ND);
368 385 
369- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));386+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
370 387 
371- uint64_t workspaceSize = 0;388+ uint64_t workspaceSize = 0;
372- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);389+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
373- // EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);390+ // EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
374}391}
375 392 
376// CheckShape_2393// CheckShape_2
377-TEST_F(l2_tanh_backward_test, abnormal_shape_dim_greater_than_threshold) {394+TEST_F(l2_tanh_backward_test, abnormal_shape_dim_greater_than_threshold)
378- auto gradOutputDesc = TensorDesc({7, 9, 11, 3, 4, 6, 9, 2, 2}, ACL_FLOAT, ACL_FORMAT_ND);395+{
379- auto outputDesc = TensorDesc({7, 9, 11, 3, 4, 6, 9, 2, 2}, ACL_FLOAT, ACL_FORMAT_ND);396+ auto gradOutputDesc = TensorDesc({7, 9, 11, 3, 4, 6, 9, 2, 2}, ACL_FLOAT, ACL_FORMAT_ND);
380- auto outDesc = TensorDesc({7, 9, 11, 3, 4, 6, 9, 2, 2}, ACL_FLOAT, ACL_FORMAT_ND);397+ auto outputDesc = TensorDesc({7, 9, 11, 3, 4, 6, 9, 2, 2}, ACL_FLOAT, ACL_FORMAT_ND);
398+ auto outDesc = TensorDesc({7, 9, 11, 3, 4, 6, 9, 2, 2}, ACL_FLOAT, ACL_FORMAT_ND);
381 399 
382- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));400+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
383 401 
384- uint64_t workspaceSize = 0;402+ uint64_t workspaceSize = 0;
385- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);403+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
386- EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);404+ EXPECT_EQ(aclRet, ACLNN_ERR_PARAM_INVALID);
387}405}
388 406 
389-TEST_F(l2_tanh_backward_test, Ascend910_9589_normal_dtype_float32_format_ndhwc) {407+TEST_F(l2_tanh_backward_test, Ascend910_9589_normal_dtype_float32_format_ndhwc)
390- auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).ValueRange(-2, 2);408+{
391- auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).ValueRange(-2, 2);409+ auto gradOutputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).ValueRange(-2, 2);
392- auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).Precision(0.0001, 0.0001);410+ auto outputDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).ValueRange(-2, 2);
411+ auto outDesc = TensorDesc({2, 3}, ACL_FLOAT, ACL_FORMAT_NDHWC).Precision(0.0001, 0.0001);
393 412 
394- auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));413+ auto ut = OP_API_UT(aclnnTanhBackward, INPUT(gradOutputDesc, outputDesc), OUTPUT(outDesc));
395 414 
396- uint64_t workspaceSize = 0;415+ uint64_t workspaceSize = 0;
397- aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);416+ aclnnStatus aclRet = ut.TestGetWorkspaceSize(&workspaceSize);
398- EXPECT_EQ(aclRet, ACL_SUCCESS);417+ EXPECT_EQ(aclRet, ACL_SUCCESS);
399}418}
Amath/tanh_grad/tests/ut/op_host/test_tanh_grad_infershape.cpp+39-0
@@ -0,0 +1,39 @@
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+#include <gtest/gtest.h>
12+#include <iostream>
13+#include "infershape_context_faker.h"
14+#include "infershape_case_executor.h"
15+#include "base/registry/op_impl_space_registry_v2.h"
16+ 
17+class TanhGradInfershapeTest : public testing::Test {
18+ protected:
19+ static void SetUpTestCase() {
20+ std::cout << "TanhGradInfershapeTest SetUp" << std::endl;
21+ }
22+ 
23+ static void TearDownTestCase() {
24+ std::cout << "TanhGradInfershapeTest TearDown" << std::endl;
25+ }
26+};
27+ 
28+TEST_F(TanhGradInfershapeTest, tanh_grad_infershape_test_01)
29+{
30+ gert::StorageShape shape = {{32, 32}, {32, 32}};
31+ 
32+ gert::InfershapeContextPara infershapeContextPara(
33+ "TanhGrad",
34+ {{shape, ge::DT_FLOAT, ge::FORMAT_ND}, {shape, ge::DT_FLOAT, ge::FORMAT_ND}},
35+ {{{{-2}, {-2}}, ge::DT_FLOAT, ge::FORMAT_ND}});
36+ 
37+ std::vector<std::vector<int64_t>> expectOutputShape = {{32, 32}};
38+ ExecuteTestCase(infershapeContextPara, ge::GRAPH_SUCCESS, expectOutputShape);
39+}
Dmath/tanh_grad/tests/ut/op_kernel/CMakeLists.txt+0-17
@@ -1,17 +0,0 @@
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-file(GLOB CURRENT_SOURCE_DIRS LIST_DIRECTORIES true ${CMAKE_CURRENT_SOURCE_DIR}/*)
13-foreach(SUB_DIR ${CURRENT_SOURCE_DIRS})
14- if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
15- add_subdirectory(${SUB_DIR})
16- endif()
17-endforeach()