Open
[feat][ops] norm_multiply_dropout反向算子op_kernel实现 #232
[feat][ops] norm_multiply_dropout反向算子op_kernel实现 #232
Open
penghuiyangAdd on 5 days ago
Total: 3 files changed+601-0
@@ -0,0 +1,24 @@
1+# ============================================================================
2+# norm_multiply_dropout_backward/op_kernel:AscendC kernel 编译
3+# ----------------------------------------------------------------------------
4+# 使用 CANN 的 npu_op_kernel_* 函数编译 kernel。
5+# npu_op_package 已在上层 CMakeLists.txt 调用。
6+# OPS_REC_SOC_CXX_DEFS 由根 CMakeLists.txt 统一设置(SUPPORT_950 / SUPPORT_A2 / SUPPORT_A3)
7+set(_KERNEL_TARGET "${VENDOR_NAME}_kernels")
8+ 
9+npu_op_kernel_options(${_KERNEL_TARGET} ALL
10+ OPTIONS "--cce-long-call=true" ${OPS_REC_SOC_CXX_DEFS}
11+)
12+ 
13+npu_op_kernel_sources(${_KERNEL_TARGET}
14+ KERNEL_DIR ./
15+)
16+ 
17+npu_op_kernel_library(${_KERNEL_TARGET}
18+ SRC_BASE ${CMAKE_CURRENT_SOURCE_DIR}/
19+ TILING_LIBRARY cust_optiling
20+)
21+ 
22+npu_op_package_add(${VENDOR_NAME}
23+ LIBRARY ${_KERNEL_TARGET}
24+)
@@ -0,0 +1,553 @@
1+/* Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
2+ 
3+Licensed under the Apache License, Version 2.0 (the "License");
4+you may not use this file except in compliance with the License.
5+You may obtain a copy of the License at
6+ 
7+ http://www.apache.org/licenses/LICENSE-2.0
8+ 
9+Unless required by applicable law or agreed to in writing, software
10+distributed under the License is distributed on an "AS IS" BASIS,
11+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+See the License for the specific language governing permissions and
13+ limitations under the License.
14+==============================================================================*/
15+#include "kernel_operator.h"
16+ 
17+#include "norm_multiply_dropout_backward_tilingKey.h"
18+ 
19+using namespace AscendC;
20+ 
21+namespace kernels {
22+constexpr uint32_t VEC_BLOCK_BYTES = 32;
23+constexpr int32_t BUFFER_NUM = 1;
24+constexpr int32_t NO_DOUBLE = 1;
25+constexpr int32_t REDUCE_CALC_BYTE = 256;
26+constexpr int32_t MASK_ELEMENTS_BITS = 8;
27+constexpr float NEGATIVE_ONE_F = -1.0;
28+constexpr float POSITIVE_ONE_F = 1.0;
29+constexpr int32_t DROP_TEMP_BUF = 2048;
30+ 
31+template <typename T, bool isNeedDrop>
32+class NormMultiplyDropoutBackward {
33+public:
34+ __aicore__ NormMultiplyDropoutBackward() {};
35+ 
36+ __aicore__ inline void init(GM_ADDR dOut, GM_ADDR x, GM_ADDR u, GM_ADDR weight, GM_ADDR bias, GM_ADDR mean,
37+ GM_ADDR var, GM_ADDR mask, GM_ADDR dX, GM_ADDR dU, GM_ADDR dWeight, GM_ADDR dBias,
38+ GM_ADDR workspace, const NormMultiplyDropoutBackwardTilingData& tiling)
39+ {
40+ ASSERT(GetBlockNum() != 0 && "useful core num can not be zero!!!");
41+ this->tiling = tiling;
42+ int32_t coreId = GetBlockIdx();
43+ 
44+ bigCoreNum = tiling.bigCoreNum;
45+ avgCoreCalcRows = tiling.avgCoreCalcRows;
46+ xRowCount = tiling.xRowCount;
47+ xColCount = tiling.xColCount;
48+ singleBlockRows = tiling.singleBlockRows;
49+ eps = tiling.eps;
50+ dropoutRatio = tiling.dropoutRatio;
51+ 
52+ if (bigCoreNum == 0) {
53+ coreOffset = coreId * avgCoreCalcRows;
54+ coreCalcRows = avgCoreCalcRows;
55+ } else if (coreId < bigCoreNum) {
56+ coreOffset = coreId * (avgCoreCalcRows + 1);
57+ coreCalcRows = avgCoreCalcRows + 1;
58+ } else {
59+ coreOffset = bigCoreNum * (avgCoreCalcRows + 1) + (coreId - bigCoreNum) * avgCoreCalcRows;
60+ coreCalcRows = avgCoreCalcRows;
61+ }
atomgit-bot
atomgit-botatomgit-bot5 days ago

🟡 Medium Priority

变更行:第 44-63 行读取 useCoreNum = tiling.useCoreNum;(第 50 行)后从未使用,littleCoreNum(第 45 行)同样只赋值不参与任何判断;核间行切分完全按 coreId 与 bigCoreNum 计算:

失败模式:一旦实际启动的 block 数(GetBlockNum()/SetBlockDim)大于 tiling 规划的 useCoreNum,coreId ∈ [useCoreNum, blockNum) 的核不会得到"本核 0 行"的结论,而是继续按 avg 行做计算,coreOffset + coreCalcRows 越过 xRowCount,导致:1) 对 dOut/x/u/weight/mean/var/mask 的 GM 越界读;2) 对 dX/dU 的 GM 越界写(内存踩踏);3) 即使不越界,同一批行被两个核重复计算,SetAtomicAdd 会把 dWeight/dBias 重复累加两遍,结果放大。

建议:在 init() 中用 useCoreNum 做上界保护:coreId >= useCoreNum 时把 coreCalcRows/loop/tail 置 0 并让 process() 直接返回(同时跳过 dWeight/dBias 的原子累加),避免多余核对 GM 的越界读写和重复累加。

likedislike
Incorrect?
penghuiyang
4 days ago Comments:
62+ 
63+ tail = coreCalcRows % singleBlockRows;
64+ loop = coreCalcRows / singleBlockRows;
65+ 
66+ dOutGM.SetGlobalBuffer((__gm__ T*)dOut);
67+ xGM.SetGlobalBuffer((__gm__ T*)x);
68+ uGM.SetGlobalBuffer((__gm__ T*)u);
69+ weightGM.SetGlobalBuffer((__gm__ T*)weight);
70+ biasGM.SetGlobalBuffer((__gm__ T*)bias);
71+ meanGM.SetGlobalBuffer((__gm__ float*)mean);
72+ varGM.SetGlobalBuffer((__gm__ float*)var);
73+ maskGM.SetGlobalBuffer((__gm__ uint8_t*)mask);
74+ dUGM.SetGlobalBuffer((__gm__ T*)dU);
75+ dXGM.SetGlobalBuffer((__gm__ T*)dX);
76+ dWeightGM.SetGlobalBuffer((__gm__ float*)dWeight);
77+ dBiasGM.SetGlobalBuffer((__gm__ float*)dBias);
78+ 
79+ pipe.InitBuffer(dOutQue, BUFFER_NUM, singleBlockRows * xColCount * sizeof(float)); // n * C * 4
80+ pipe.InitBuffer(xQue, BUFFER_NUM, singleBlockRows * xColCount * sizeof(float)); // n * C * 4
81+ pipe.InitBuffer(uQue, BUFFER_NUM, singleBlockRows * xColCount * sizeof(float)); // n * C * 4
82+ pipe.InitBuffer(weightQue, NO_DOUBLE, xColCount * sizeof(float)); // C * 4
83+ pipe.InitBuffer(biasQue, NO_DOUBLE, xColCount * sizeof(float)); // C * 4
84+ pipe.InitBuffer(meanQue, NO_DOUBLE, singleBlockRows * sizeof(float)); // n * 4
85+ pipe.InitBuffer(varQue, NO_DOUBLE, singleBlockRows * sizeof(float)); // n * 4
86+ if constexpr (isNeedDrop) {
87+ pipe.InitBuffer(maskQue, BUFFER_NUM,
88+ singleBlockRows * xColCount / MASK_ELEMENTS_BITS * sizeof(uint8_t)); // n * C * 2
89+ }
90+ pipe.InitBuffer(duQue, BUFFER_NUM, singleBlockRows * xColCount * sizeof(float)); // n * C * 4
91+ pipe.InitBuffer(dxQue, BUFFER_NUM, singleBlockRows * xColCount * sizeof(float)); // n * C * 4
92+ 
93+ if constexpr (!std::is_same<T, float>::value) {
94+ pipe.InitBuffer(dOutcastQue, BUFFER_NUM, singleBlockRows * xColCount * sizeof(T)); // n * C * 2
95+ pipe.InitBuffer(xCastQue, BUFFER_NUM, singleBlockRows * xColCount * sizeof(T)); // n * C * 2
96+ pipe.InitBuffer(uCastQue, BUFFER_NUM, singleBlockRows * xColCount * sizeof(T)); // n * C * 2
97+ pipe.InitBuffer(weightCastQue, NO_DOUBLE, xColCount * sizeof(T)); // C * 2
98+ pipe.InitBuffer(biasCastQue, NO_DOUBLE, xColCount * sizeof(T)); // C * 2
99+ pipe.InitBuffer(dxCastQue, BUFFER_NUM, singleBlockRows * xColCount * sizeof(T)); // n * C * 2
100+ pipe.InitBuffer(duCastQue, BUFFER_NUM, singleBlockRows * xColCount * sizeof(T)); // n * C * 2
@@ -0,0 +1,24 @@
1+/* Copyright (c) Huawei Technologies Co., Ltd. 2026. All rights reserved.
2+ 
3+Licensed under the Apache License, Version 2.0 (the "License");
4+you may not use this file except in compliance with the License.
5+You may obtain a copy of the License at
6+ 
7+ http://www.apache.org/licenses/LICENSE-2.0
8+ 
9+Unless required by applicable law or agreed to in writing, software
10+distributed under the License is distributed on an "AS IS" BASIS,
11+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+See the License for the specific language governing permissions and
13+ limitations under the License.
14+==============================================================================*/
15+#ifndef MXREC_NORM_MULTIPLY_DROPOUT_BACKWARD_TILINGKEY_H
16+#define MXREC_NORM_MULTIPLY_DROPOUT_BACKWARD_TILINGKEY_H
17+ 
18+#include "ascendc/host_api/tiling/template_argument.h"
19+ 
20+ASCENDC_TPL_ARGS_DECL(NormMultiplyDropoutBackward, ASCENDC_TPL_BOOL_DECL(isNeedDrop, 0, 1));
21+ 
22+ASCENDC_TPL_SEL(ASCENDC_TPL_ARGS_SEL(ASCENDC_TPL_BOOL_DECL(isNeedDrop, 0, 1)));
23+ 
24+#endif // MXREC_NORM_MULTIPLY_DROPOUT_BACKWARD_TILINGKEY_H