已合并
scatter_nd_update support uncontigous for dim0 #5510
scatter_nd_update support uncontigous for dim0 #5510
已合并
zhangqijia1创建于 6月1日
共 28 个文件变更+3917-53
MOAT.xml+1-1
@@ -14,7 +14,7 @@
14 <policylist>14 <policylist>
15 <policy name="projectPolicy" desc="">15 <policy name="projectPolicy" desc="">
16 <!--policyitem type="compatibility" name="GPL-2.0+" path="abc/.*" desc="Process that runs independently, invoked by the X process."/-->16 <!--policyitem type="compatibility" name="GPL-2.0+" path="abc/.*" desc="Process that runs independently, invoked by the X process."/-->
17- <policyitem type="license" name="cann License" path=".*" desc=""/>17+ <policyitem type="license" name="CANN-2.0" path=".*" desc=""/>
18 <policyitem type="copyright" name="Huawei Technologies Co., Ltd." path=".*" rule="may" group="defaultGroup" filefilter="copyrightPolicyFilter" desc=""/>18 <policyitem type="copyright" name="Huawei Technologies Co., Ltd." path=".*" rule="may" group="defaultGroup" filefilter="copyrightPolicyFilter" desc=""/>
19 </policy>19 </policy>
20 </policylist>20 </policylist>
@@ -1,19 +1,15 @@
1-#1+# ----------------------------------------------------------------------------
2-# Copyright (c) 2025 Huawei Technologies Co., Ltd.2+# Copyright (c) 2026 Huawei Technologies Co., Ltd.
3# This program is free software, you can redistribute it and/or modify it under the terms and conditions of 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").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-file(GLOB CURRENT_DIRS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/*)11+# 设置算子定义时支持的芯片类型
12-if(NOT ENABLE_TEST AND NOT BENCHMARK)12+set(SUPPORT_COMPUTE_UNIT "ascend910b" "ascend910_93")
13- list(REMOVE_ITEM CURRENT_DIRS tests)13+# 设置每种芯片类型对应的tiling文件目录,即采用op_host目录下哪个文件夹下的tiling文件编译
14-endif()14+set(SUPPORT_TILING_DIR "arch32" "arch32")
15-foreach(SUB_DIR ${CURRENT_DIRS})15+add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE scatter_nd_update ACLNNTYPE aclnn_exclude COMPUTE_UNIT ${SUPPORT_COMPUTE_UNIT} TILING_DIR ${SUPPORT_TILING_DIR} DISABLE_IN_OPP TRUE DEPENDENCIES scatter_nd_add)
16- if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${SUB_DIR}/CMakeLists.txt")
17- add_subdirectory(${SUB_DIR})
18- endif()
19-endforeach()
Rindex/scatter_nd_update/op_host/op_api/aclnn_put.cpp→index/scatter_nd_update/op_api/aclnn_put.cpp+0-0
文件重命名但无更改。
Rindex/scatter_nd_update/op_host/op_api/aclnn_put.h→index/scatter_nd_update/op_api/aclnn_put.h+0-0
文件重命名但无更改。
Rindex/scatter_nd_update/op_host/op_api/aclnn_scatter_nd.cpp→index/scatter_nd_update/op_api/aclnn_scatter_nd.cpp+0-0
文件重命名但无更改。
Rindex/scatter_nd_update/op_host/op_api/aclnn_scatter_nd.h→index/scatter_nd_update/op_api/aclnn_scatter_nd.h+0-0
文件重命名但无更改。
Rindex/scatter_nd_update/op_host/op_api/aclnn_scatter_nd_update.cpp→index/scatter_nd_update/op_api/aclnn_scatter_nd_update.cpp+142-24
@@ -1,5 +1,5 @@
1/**1/**
2- * Copyright (c) 2025 Huawei Technologies Co., Ltd.2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3 * This program is free software, you can redistribute it and/or modify it under the terms and conditions 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.
@@ -91,6 +91,129 @@ static aclnnStatus CheckParams(aclTensor *varRef, const aclTensor *indices, cons
91 return ACLNN_SUCCESS;91 return ACLNN_SUCCESS;
92}92}
93 93 
94+// 判断指定轴范围是否连续
95+// startAxis: 起始轴(包含),endAxis: 结束轴(不包含)
96+// 当 startAxis == endAxis 时区间为空,视为平凡连续返回 true(专门给 arch32 的 1D 场景放行非连续优化路径)。
97+static bool IsAxesContiguous(const aclTensor *tensor, int64_t startAxis, int64_t endAxis) {
98+ if (tensor == nullptr || startAxis < 0 || endAxis < 0 || startAxis > endAxis) {
99+ return false;
100+ }
101+ if (startAxis == endAxis) {
102+ return true;
103+ }
104+ 
105+ auto viewShape = tensor->GetViewShape();
106+ auto viewStrides = tensor->GetViewStrides();
107+ int64_t dimNum = viewShape.GetDimNum();
108+ 
109+ if (endAxis > dimNum) {
110+ return false;
111+ }
112+ 
113+ int64_t validStride = 1;
114+ for (int64_t i = endAxis - 1; i >= startAxis; i--) {
115+ if (viewShape.GetDim(i) == 1) {
116+ continue;
117+ }
118+ if (viewStrides[i] != validStride) {
119+ return false;
120+ }
121+ validStride *= viewShape.GetDim(i);
122+ }
123+ return true;
124+}
125+ 
126+// arch32 (910b/910_93) 仅支持 var.stride[0] 非连续、其余 stride 全部连续的窄子集。
127+// 校验:dim>=1 全连续,dim 0 stride 大于 contiguous 期望值。
128+static bool IsSupportNonContiguousArch32(const aclTensor *varRef, int64_t indexAxisNum) {
129+ if (varRef == nullptr || indexAxisNum < 1) {
130+ return false;
131+ }
132+ auto viewShape = varRef->GetViewShape();
133+ auto viewStrides = varRef->GetViewStrides();
134+ int64_t varRefDimNum = viewShape.GetDimNum();
135+ if (indexAxisNum > varRefDimNum) {
136+ return false;
137+ }
138+ // dim>=1 必须全部连续
139+ if (!IsAxesContiguous(varRef, 1, varRefDimNum)) {
140+ return false;
141+ }
142+ // dim 0 的 stride 必须 >= contiguous 期望值(>= 而非 ==,等于的退回连续路径)
143+ int64_t expectedStride0 = 1;
144+ for (int64_t i = 1; i < varRefDimNum; ++i) {
145+ expectedStride0 *= viewShape.GetDim(i);
146+ }
147+ return viewStrides[0] > expectedStride0;
148+}
149+ 
150+// 执行 ScatterNdUpdate 算子计算(公共实现)
151+static aclnnStatus ExecuteScatterNdUpdate(const aclTensor *varRef, const aclTensor *indices, const aclTensor *updates,
152+ bool needViewCopy, uint64_t* workspaceSize, aclOpExecutor** executor,
153+ auto& uniqueExecutor) {
154+ // 将 indices 转换成连续的 tensor
155+ auto indicesContiguous = l0op::Contiguous(indices, uniqueExecutor.get());
156+ CHECK_RET(indicesContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
157+
158+ // 将 updates 转换成连续的 tensor
159+ auto updatesContiguous = l0op::Contiguous(updates, uniqueExecutor.get());
160+ CHECK_RET(updatesContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
161+
162+ // 执行 L0 算子
163+ auto scatterUpdateRes = l0op::ScatterNdUpdate(varRef, indicesContiguous, updatesContiguous, false, uniqueExecutor.get());
164+ CHECK_RET(scatterUpdateRes != nullptr, ACLNN_ERR_INNER_NULLPTR);
165+
166+ // 如果需要,将计算结果拷贝到输出 data 上
167+ if (needViewCopy) {
168+ auto viewCopyResult = l0op::ViewCopy(scatterUpdateRes, varRef, uniqueExecutor.get());
169+ CHECK_RET(viewCopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
170+ }
171+
172+ // 获取计算过程中需要使用的 workspace 大小
173+ *workspaceSize = uniqueExecutor->GetWorkspaceSize();
174+ uniqueExecutor.ReleaseTo(executor);
175+ return ACLNN_SUCCESS;
176+}
177+ 
178+// 非连续优化路径:indices 与 updates 转连续,varRef 使用 CreateView 设置 stride
179+static aclnnStatus ProcessNonContiguousCase(aclTensor *varRef, const aclTensor *indices, const aclTensor *updates,
180+ uint64_t* workspaceSize, aclOpExecutor** executor, auto& uniqueExecutor) {
181+ // 将 indices 转换成连续的 tensor
182+ auto indicesContiguous = l0op::Contiguous(indices, uniqueExecutor.get());
183+ CHECK_RET(indicesContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
184+
185+ // 将 updates 转换成连续的 tensor
186+ auto updatesContiguous = l0op::Contiguous(updates, uniqueExecutor.get());
187+ CHECK_RET(updatesContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
188+
189+ // 使用 CreateView 为 varRef 创建视图,保持原始 stride
190+ auto varRefView = uniqueExecutor->CreateView(varRef,
191+ varRef->GetViewShape(),
192+ varRef->GetStorageShape(),
193+ varRef->GetViewStrides(),
194+ varRef->GetViewOffset());
195+ CHECK_RET(varRefView != nullptr, ACLNN_ERR_INNER_NULLPTR);
196+
197+ auto scatterUpdateRes = l0op::ScatterNdUpdate(varRefView, indicesContiguous, updatesContiguous, false, uniqueExecutor.get());
198+ CHECK_RET(scatterUpdateRes != nullptr, ACLNN_ERR_INNER_NULLPTR);
199+
200+ *workspaceSize = uniqueExecutor->GetWorkspaceSize();
201+ uniqueExecutor.ReleaseTo(executor);
202+ return ACLNN_SUCCESS;
203+}
204+ 
205+// 常规路径:将所有输入转换成连续的 tensor
206+static aclnnStatus ProcessContiguousCase(aclTensor *varRef, const aclTensor *indices, const aclTensor *updates,
207+ uint64_t* workspaceSize, aclOpExecutor** executor, auto& uniqueExecutor) {
208+ // 将输入 varRef 转换成连续的 tensor
209+ auto varRefContiguous = l0op::Contiguous(varRef, uniqueExecutor.get());
210+ CHECK_RET(varRefContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
211+
212+ bool needViewCopy = !IsContiguous(varRef);
213+ return ExecuteScatterNdUpdate(varRefContiguous, indices, updates, needViewCopy,
214+ workspaceSize, executor, uniqueExecutor);
215+}
216+ 
94aclnnStatus aclnnScatterNdUpdateGetWorkspaceSize(aclTensor *varRef, const aclTensor *indices, const aclTensor *updates,217aclnnStatus aclnnScatterNdUpdateGetWorkspaceSize(aclTensor *varRef, const aclTensor *indices, const aclTensor *updates,
95 uint64_t* workspaceSize, aclOpExecutor** executor) {218 uint64_t* workspaceSize, aclOpExecutor** executor) {
96 L2_DFX_PHASE_1(aclnnScatterNdUpdate, DFX_IN(varRef, indices, updates), DFX_OUT(varRef));219 L2_DFX_PHASE_1(aclnnScatterNdUpdate, DFX_IN(varRef, indices, updates), DFX_OUT(varRef));
@@ -120,32 +243,27 @@ aclnnStatus aclnnScatterNdUpdateGetWorkspaceSize(aclTensor *varRef, const aclTen
120 return ACLNN_SUCCESS;243 return ACLNN_SUCCESS;
121 }244 }
122 245 
123- // 将输入varRef转换成连续的tensor246+ // 判断 varRef 索引轴部分是否非连续,非索引轴部分是否连续
124- auto varRefContiguous = l0op::Contiguous(varRef, uniqueExecutor.get());247+ auto indicesShape = indices->GetViewShape();
125- CHECK_RET(varRefContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);248+ constexpr int64_t MAX_INDICES_RANK = 4;
249+ // 索引轴的数量是 indices 的最后一个维度
250+ int64_t indexAxisNum = indicesShape.GetDim(indicesShape.GetDimNum() - 1);
251+ // 检查芯片架构,仅 arch32 支持非连续场景
252+ auto& platformInfo = op::GetCurrentPlatformInfo();
253+ auto socVersion = platformInfo.GetCurNpuArch();
254+
255+ // 检查是否满足准入条件
256+ bool dimCheck = (indicesDimNum > 0 && indexAxisNum <= MAX_INDICES_RANK);
126 257 
127- // 将输入indices转换成连续的tensor258+ if (dimCheck) {
128- auto indicesContiguous = l0op::Contiguous(indices, uniqueExecutor.get());259+ if (socVersion == NpuArch::DAV_2201 && IsSupportNonContiguousArch32(varRef, indexAxisNum)) {
129- CHECK_RET(indicesContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);260+ // arch32:仅支持 var.stride[0] 非连续、其余 stride 连续 → 透传给 arch32 tiling/kernel
130- 261+ return ProcessNonContiguousCase(varRef, indices, updates, workspaceSize, executor, uniqueExecutor);
131- // 将输入updates转换成连续的tensor262+ }
132- auto updatesContiguous = l0op::Contiguous(updates, uniqueExecutor.get());
133- CHECK_RET(updatesContiguous != nullptr, ACLNN_ERR_INNER_NULLPTR);
134- 
135- // 执行L0算子
136- auto scatterUpdateRes = l0op::ScatterNdUpdate(varRefContiguous, indicesContiguous, updatesContiguous, false, uniqueExecutor.get());
137- CHECK_RET(scatterUpdateRes != nullptr, ACLNN_ERR_INNER_NULLPTR);
138- 
139- // 将计算结果拷贝到输出data上
140- if (!IsContiguous(varRef)) {
141- auto viewCopyResult = l0op::ViewCopy(scatterUpdateRes, varRef, uniqueExecutor.get());
142- CHECK_RET(viewCopyResult != nullptr, ACLNN_ERR_INNER_NULLPTR);
143 }263 }
144 264 
145- // 获取计算过程中需要使用的workspace大小265+ // 常规路径:将所有输入转换成连续的 tensor
146- *workspaceSize = uniqueExecutor->GetWorkspaceSize();266+ return ProcessContiguousCase(varRef, indices, updates, workspaceSize, executor, uniqueExecutor);
147- uniqueExecutor.ReleaseTo(executor);
148- return ACLNN_SUCCESS;
149}267}
150 268 
151aclnnStatus aclnnScatterNdUpdate(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream) {269aclnnStatus aclnnScatterNdUpdate(void* workspace, uint64_t workspaceSize, aclOpExecutor* executor, aclrtStream stream) {
Rindex/scatter_nd_update/op_host/op_api/aclnn_scatter_nd_update.h→index/scatter_nd_update/op_api/aclnn_scatter_nd_update.h+0-0
文件重命名但无更改。
Rindex/scatter_nd_update/op_host/op_api/scatter_nd_update.cpp→index/scatter_nd_update/op_api/scatter_nd_update.cpp+0-0
文件重命名但无更改。
Rindex/scatter_nd_update/op_host/op_api/scatter_nd_update.h→index/scatter_nd_update/op_api/scatter_nd_update.h+0-0
文件重命名但无更改。
@@ -1,12 +0,0 @@
1-# Copyright (c) 2025 Huawei Technologies Co., Ltd.
2-# This program is free software, you can redistribute it and/or modify it under the terms and conditions of
3-# CANN Open Software License Agreement Version 2.0 (the "License").
4-# Please refer to the License for details. You may not use this file except in compliance with the License.
5-# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
6-# INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
7-# See LICENSE in the root of the software repository for the full text of the License.
8-#/
9- 
10-#optiling and opapi
11-message(STATUS "=== Debug: start ops.index.scatter_nd_update.CMakeLists.txt ")
12-add_modules_sources(HOSTNAME ${OPHOST_NAME} MODE PRIVATE DIR ${CMAKE_CURRENT_SOURCE_DIR} OPTYPE scatter_nd_update ACLNNTYPE aclnn_exclude)
@@ -0,0 +1,504 @@
1+/**
2+ * Copyright (c) 2025-2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file scatter_nd_update_tiling.cpp
13+ * \brief scatter_nd_update arch32 tiling implementation
14+ */
15+ 
16+#include "log/log.h"
17+#include "platform/platform_info.h"
18+#include "tiling/tiling_api.h"
19+#include "register/op_impl_registry.h"
20+#include "scatter_nd_update_tiling.h"
21+ 
22+namespace optiling {
23+constexpr uint64_t MAX_DIM_NUM = 8;
24+constexpr uint64_t MAX_LENGTH_INT32 = (1LL << 31) - 1;
25+constexpr uint64_t MAX_FLOAT_EXPRESS_INT32 = (1LL << 24) - 1;
26+constexpr uint64_t SORT_USE_GM_NUM = 2;
27+constexpr uint64_t SORT_BLOCK_LENGTH = 4096;
28+constexpr uint64_t GATHER_USE_NUM = 2;
29+constexpr uint64_t ALIGNED_NUM = 8;
30+constexpr uint64_t ALIGNED_SIZE = 32;
31+constexpr uint64_t HP_INDEX_TILE_MAX = 4096;
32+constexpr uint64_t HP_INDEX_TILE_ALIGN = 32;
33+constexpr uint64_t HP_UPDATE_UB_RATIO = 2;
34+constexpr uint64_t HP_DOUBLE_BUFFER = 2;
35+constexpr uint64_t HP_ROWS_PER_BATCH_MAX = 256;
36+ 
37+inline void ScatterNdUpdateArch32Tiling::SetTilingKeyMode()
38+{
39+ // tilingKey: indexType * 10 + sortFlag (indexType: 1=int32, 2=int64(cast), 3=int64(large))
40+ uint64_t indexType;
41+ if (!isInt64Indices_) {
42+ indexType = 1;
43+ } else if (needLargeIndexKernel_) {
44+ indexType = 3;
45+ } else {
46+ indexType = 2;
47+ }
48+ uint64_t sortFlag = (indexType == 3) ? 0 : (isSort_ ? 1 : 0);
49+ tilingKey_ = indexType * 10 + sortFlag;
50+ 
51+ tilingContext_->SetTilingKey(tilingKey_);
52+}
53+ 
54+inline bool ScatterNdUpdateArch32Tiling::IsLinearIndex(uint64_t totalLength) { return totalLength <= MAX_LENGTH_INT32; }
55+ 
56+inline bool ScatterNdUpdateArch32Tiling::IsSort(uint64_t totalLength) { return totalLength <= MAX_FLOAT_EXPRESS_INT32; }
57+ 
58+inline void ScatterNdUpdateArch32Tiling::Tiling4LinearIndex(uint64_t indexRow, uint64_t indexDim)
59+{
60+ auto varRefShape = tilingContext_->GetInputShape(0)->GetOriginShape();
61+ uint64_t strides = 1;
62+ for (int64_t i = indexDim - 1; i >= 0; --i) {
63+ indicesMask_[i] = strides;
64+ strides *= varRefShape.GetDim(i);
65+ }
66+ uint64_t coeff = isInt64Indices_ ? (2 * indexDim + 3) : (indexDim + 3);
67+ uint64_t maxBlockLength = ubSize_ / coeff / sizeof(int);
68+ blockLength_ = (maxBlockLength / ALIGNED_SIZE) * ALIGNED_SIZE;
69+ blockLength_ = std::min(blockLength_, (uint64_t)SORT_BLOCK_LENGTH);
70+ if (blockLength_ == 0) {
71+ blockLength_ = ALIGNED_SIZE;
72+ }
73+ blockNum_ = indexRow / blockLength_;
74+ blockRemainLength_ = indexRow % blockLength_;
75+ 
76+ if (blockNum_ == 0) {
77+ tailBlockNum_ = 0;
78+ frontBlockNum_ = 0;
79+ frontCoreNum_ = 1;
80+ tailCoreNum_ = 0;
81+ } else {
82+ tailBlockNum_ = blockNum_ / coreNum_;
83+ frontBlockNum_ = tailBlockNum_ + 1;
84+ frontCoreNum_ = blockNum_ % coreNum_;
85+ tailCoreNum_ = tailBlockNum_ == 0 ? 0 : coreNum_ - frontCoreNum_;
86+ }
87+}
88+ 
89+inline void ScatterNdUpdateArch32Tiling::Tiling4Scatter(uint64_t totalLength)
90+{
91+ uint64_t scatterAlignNum = ALIGNED_SIZE / dataTypeSize_;
92+ tailRow_ = totalLength / coreNum_;
93+ frontRow_ = tailRow_ + 1;
94+ frontNum_ = totalLength % coreNum_;
95+ tailNum_ = tailRow_ == 0 ? 0 : coreNum_ - frontNum_;
96+ ubLengthForUpdates_ =
97+ ((ubSize_ - SORT_BLOCK_LENGTH * SORT_USE_GM_NUM * sizeof(int)) / ALIGNED_SIZE * ALIGNED_SIZE) / dataTypeSize_;
98+ scatterAlignLength_ = (scatterLength_ + scatterAlignNum - 1) & ~(scatterAlignNum - 1);
99+ formDim_ = scatterAlignLength_ / ubLengthForUpdates_;
100+ 
101+ scatterTileLength_ = std::min(scatterLength_, ubLengthForUpdates_);
102+ if (scatterTileLength_ == 0) {
103+ scatterTileLength_ = 1;
104+ }
105+ scatterTileNum_ = (scatterLength_ + scatterTileLength_ - 1) / scatterTileLength_;
106+ scatterTileTail_ = scatterLength_ - (scatterTileNum_ - 1) * scatterTileLength_;
107+ scatterTileAlignLength_ = (scatterTileLength_ + scatterAlignNum - 1) & ~(scatterAlignNum - 1);
108+ 
109+ if (scatterTileNum_ > 1) {
110+ copyRow_ = 1;
111+ } else {
112+ copyRow_ = formDim_ == 0 ? ubLengthForUpdates_ / scatterAlignLength_ : 1;
113+ }
114+}
115+ 
116+inline uint64_t ScatterNdUpdateArch32Tiling::Tiling4HpScatterShape()
117+{
118+ uint64_t kMaxUpdateUbBytes = ubSize_ / HP_UPDATE_UB_RATIO;
119+ uint64_t fullRowBytes = scatterLength_ * dataTypeSize_;
120+ uint64_t updateUbBytes = 0;
121+ if (dataTypeSize_ == 0) {
122+ hpScatterTileLength_ = 1;
123+ hpRowBytesAligned_ = ALIGNED_SIZE;
124+ hpRowsPerBatch_ = 1;
125+ updateUbBytes = ALIGNED_SIZE;
126+ } else if (HP_DOUBLE_BUFFER * fullRowBytes <= kMaxUpdateUbBytes) {
127+ hpScatterTileLength_ = scatterLength_ == 0 ? 1 : scatterLength_;
128+ uint64_t rowBytes = hpScatterTileLength_ * dataTypeSize_;
129+ hpRowBytesAligned_ = (rowBytes + ALIGNED_SIZE - 1) & ~(ALIGNED_SIZE - 1);
130+ if (hpRowBytesAligned_ == 0)
131+ hpRowBytesAligned_ = ALIGNED_SIZE;
132+ uint64_t perBufBytes = kMaxUpdateUbBytes / HP_DOUBLE_BUFFER;
133+ hpRowsPerBatch_ = perBufBytes / hpRowBytesAligned_;
134+ if (hpRowsPerBatch_ > HP_ROWS_PER_BATCH_MAX)
135+ hpRowsPerBatch_ = HP_ROWS_PER_BATCH_MAX;
136+ if (hpRowsPerBatch_ == 0)
137+ hpRowsPerBatch_ = 1;
138+ updateUbBytes = HP_DOUBLE_BUFFER * hpRowsPerBatch_ * hpRowBytesAligned_;
139+ } else {
140+ updateUbBytes = (kMaxUpdateUbBytes / ALIGNED_SIZE) * ALIGNED_SIZE;
141+ uint64_t bufBytes = updateUbBytes / HP_DOUBLE_BUFFER;
142+ hpScatterTileLength_ = (bufBytes / dataTypeSize_ / ALIGNED_NUM) * ALIGNED_NUM;
143+ if (hpScatterTileLength_ == 0) {
144+ hpScatterTileLength_ = ALIGNED_NUM;
145+ }
146+ uint64_t sliceBytes = hpScatterTileLength_ * dataTypeSize_;
147+ hpRowBytesAligned_ = (sliceBytes + ALIGNED_SIZE - 1) & ~(ALIGNED_SIZE - 1);
148+ if (hpRowBytesAligned_ == 0)
149+ hpRowBytesAligned_ = ALIGNED_SIZE;
150+ hpRowsPerBatch_ = 1;
151+ }
152+ if (scatterLength_ == 0) {
153+ hpScatterTileNum_ = 1;
154+ hpScatterTileTail_ = 0;
155+ } else {
156+ hpScatterTileNum_ = (scatterLength_ + hpScatterTileLength_ - 1) / hpScatterTileLength_;
157+ hpScatterTileTail_ = scatterLength_ - (hpScatterTileNum_ - 1) * hpScatterTileLength_;
158+ }
159+ if (hpScatterTileNum_ > 1) {
160+ hpRowsPerBatch_ = 1;
161+ }
162+ return updateUbBytes;
163+}
164+ 
165+inline void ScatterNdUpdateArch32Tiling::Tiling4HpIndexTile(uint64_t updateUbBytes)
166+{
167+ uint64_t ubForIndex = (ubSize_ > updateUbBytes) ? (ubSize_ - updateUbBytes) : 0;
168+ uint64_t coeff = isInt64Indices_ ? (2 * indexDim_ + 3) : (indexDim_ + 3);
169+ if (coeff == 0) {
170+ coeff = 1;
171+ }
172+ uint64_t maxIndexTile = ubForIndex / coeff / sizeof(int);
173+ hpIndexTileLength_ = (maxIndexTile / HP_INDEX_TILE_ALIGN) * HP_INDEX_TILE_ALIGN;
174+ if (hpIndexTileLength_ > HP_INDEX_TILE_MAX) {
175+ hpIndexTileLength_ = HP_INDEX_TILE_MAX;
176+ }
177+ if (hpIndexTileLength_ == 0) {
178+ hpIndexTileLength_ = HP_INDEX_TILE_ALIGN;
179+ }
180+}
181+ 
182+inline void ScatterNdUpdateArch32Tiling::Tiling4HpCorePartition(uint64_t indexRow)
183+{
184+ hpCoreNum_ = std::min(coreNum_, indexRow);
185+ if (hpCoreNum_ == 0) {
186+ hpCoreNum_ = 1;
187+ }
188+ hpTailIndexNum_ = indexRow / hpCoreNum_;
189+ hpFrontIndexNum_ = hpTailIndexNum_ + 1;
190+ hpFrontCoreNum_ = indexRow % hpCoreNum_;
191+ hpTailCoreNum_ = (hpTailIndexNum_ == 0) ? 0 : (hpCoreNum_ - hpFrontCoreNum_);
192+}
193+ 
194+inline void ScatterNdUpdateArch32Tiling::Tiling4Hp(uint64_t indexRow)
195+{
196+ uint64_t updateUbBytes = Tiling4HpScatterShape();
197+ Tiling4HpIndexTile(updateUbBytes);
198+ Tiling4HpCorePartition(indexRow);
199+}
200+ 
201+inline ge::graphStatus ScatterNdUpdateArch32Tiling::HandleViewStride()
202+{
203+ firstDimStrideRows_ = (indexDim_ > 1) ? indicesMask_[0] : 1;
204+ uint64_t stride0Expected = scatterLength_ * firstDimStrideRows_;
205+ 
206+ if (!tilingContext_->InputIsView(0)) {
207+ isViewStride0_ = 0;
208+ varStride0Elements_ = stride0Expected;
209+ return ge::GRAPH_SUCCESS;
210+ }
211+ auto stride = tilingContext_->GetInputStride(0);
212+ if (stride == nullptr || stride->GetDimNum() == 0) {
213+ isViewStride0_ = 0;
214+ varStride0Elements_ = stride0Expected;
215+ return ge::GRAPH_SUCCESS;
216+ }
217+ auto varShape = tilingContext_->GetInputShape(0)->GetOriginShape();
218+ uint64_t varDimNum = varShape.GetDimNum();
219+ 
220+ uint64_t expectedStride = 1;
221+ for (int64_t dim = static_cast<int64_t>(varDimNum) - 1; dim >= 1; --dim) {
222+ int64_t dimSize = varShape.GetDim(dim);
223+ int64_t actualStride = stride->GetStride(dim);
224+ if (dimSize > 1 && actualStride != static_cast<int64_t>(expectedStride)) {
225+ OP_LOGE(
226+ tilingContext_,
227+ "arch32 view path requires dim>=1 strides to be contiguous, dim %ld stride %ld expected %lu", dim,
228+ actualStride, expectedStride);
229+ return ge::GRAPH_FAILED;
230+ }
231+ expectedStride *= static_cast<uint64_t>(dimSize);
232+ }
233+ 
234+ int64_t stride0 = stride->GetStride(0);
235+ if (static_cast<uint64_t>(stride0) > stride0Expected) {
236+ isViewStride0_ = 1;
237+ varStride0Elements_ = static_cast<uint64_t>(stride0);
238+ } else {
239+ isViewStride0_ = 0;
240+ varStride0Elements_ = stride0Expected;
241+ }
242+ return ge::GRAPH_SUCCESS;
243+}
244+ 
245+inline void ScatterNdUpdateArch32Tiling::GetDtypeSize()
246+{
247+ uint64_t varDtype = tilingContext_->GetInputDesc(0)->GetDataType();
248+ switch (varDtype) {
249+ case ge::DT_FLOAT:
250+ dataTypeSize_ = 4;
251+ break;
252+ case ge::DT_BF16:
253+ dataTypeSize_ = 2;
254+ break;
255+ case ge::DT_FLOAT16:
256+ dataTypeSize_ = 2;
257+ break;
258+ case ge::DT_BOOL:
259+ dataTypeSize_ = 1;
260+ break;
261+ case ge::DT_INT64:
262+ dataTypeSize_ = 8;
263+ break;
264+ case ge::DT_INT32:
265+ dataTypeSize_ = 4;
266+ break;
267+ case ge::DT_INT16:
268+ dataTypeSize_ = 2;
269+ break;
270+ case ge::DT_INT8:
271+ dataTypeSize_ = 1;
272+ break;
273+ default:
274+ break;
275+ }
276+}
277+ 
278+ge::graphStatus ScatterNdUpdateArch32Tiling::SetKernelTiling()
279+{
280+ tilingContext_->SetBlockDim(coreNum_);
281+ tilingData_.linearIndexTiling.set_indexDim(indexDim_);
282+ tilingData_.linearIndexTiling.set_ubSize(ubSize_);
283+ tilingData_.linearIndexTiling.set_indicesMask(indicesMask_);
284+ tilingData_.linearIndexTiling.set_coreNum(coreNum_);
285+ tilingData_.linearIndexTiling.set_blockLength(blockLength_);
286+ tilingData_.linearIndexTiling.set_blockNum(blockNum_);
287+ tilingData_.linearIndexTiling.set_blockRemainLength(blockRemainLength_);
288+ tilingData_.linearIndexTiling.set_tailBlockNum(tailBlockNum_);
289+ tilingData_.linearIndexTiling.set_frontBlockNum(frontBlockNum_);
290+ tilingData_.linearIndexTiling.set_frontCoreNum(frontCoreNum_);
291+ tilingData_.linearIndexTiling.set_tailCoreNum(tailCoreNum_);
292+ tilingData_.linearIndexTiling.set_sortWorkspace(sortWorkspace_);
293+ tilingData_.linearIndexTiling.set_isInt64Indices(isInt64Indices_);
294+ tilingData_.linearIndexTiling.set_needLargeIndexKernel(needLargeIndexKernel_);
295+ tilingData_.viewTiling.set_isViewStride0(isViewStride0_);
296+ tilingData_.viewTiling.set_varStride0Elements(varStride0Elements_);
297+ tilingData_.viewTiling.set_firstDimStrideRows(firstDimStrideRows_);
298+ tilingData_.scatterTiling.set_scatterLength(scatterLength_);
299+ tilingData_.scatterTiling.set_tailRow(tailRow_);
300+ tilingData_.scatterTiling.set_frontRow(frontRow_);
301+ tilingData_.scatterTiling.set_frontNum(frontNum_);
302+ tilingData_.scatterTiling.set_tailNum(tailNum_);
303+ tilingData_.scatterTiling.set_ubLengthForUpdates(ubLengthForUpdates_);
304+ tilingData_.scatterTiling.set_scatterAlignLength(scatterAlignLength_);
305+ tilingData_.scatterTiling.set_formDim(formDim_);
306+ tilingData_.scatterTiling.set_copyRow(copyRow_);
307+ tilingData_.scatterTiling.set_scatterTileNum(scatterTileNum_);
308+ tilingData_.scatterTiling.set_scatterTileLength(scatterTileLength_);
309+ tilingData_.scatterTiling.set_scatterTileTail(scatterTileTail_);
310+ tilingData_.scatterTiling.set_scatterTileAlignLength(scatterTileAlignLength_);
311+ tilingData_.hpTiling.set_hpCoreNum(hpCoreNum_);
312+ tilingData_.hpTiling.set_hpFrontIndexNum(hpFrontIndexNum_);
313+ tilingData_.hpTiling.set_hpTailIndexNum(hpTailIndexNum_);
314+ tilingData_.hpTiling.set_hpFrontCoreNum(hpFrontCoreNum_);
315+ tilingData_.hpTiling.set_hpTailCoreNum(hpTailCoreNum_);
316+ tilingData_.hpTiling.set_hpIndexTileLength(hpIndexTileLength_);
317+ tilingData_.hpTiling.set_hpScatterTileLength(hpScatterTileLength_);
318+ tilingData_.hpTiling.set_hpScatterTileNum(hpScatterTileNum_);
319+ tilingData_.hpTiling.set_hpScatterTileTail(hpScatterTileTail_);
320+ tilingData_.hpTiling.set_hpRowBytesAligned(hpRowBytesAligned_);
321+ tilingData_.hpTiling.set_hpRowsPerBatch(hpRowsPerBatch_);
322+ tilingData_.SaveToBuffer(
323+ tilingContext_->GetRawTilingData()->GetData(), tilingContext_->GetRawTilingData()->GetCapacity());
324+ tilingContext_->GetRawTilingData()->SetDataSize(tilingData_.GetDataSize());
325+ TilingDataPrint();
326+ return ge::GRAPH_SUCCESS;
327+}
328+ 
329+inline size_t ScatterNdUpdateArch32Tiling::CalcWorkSpaceSize(uint64_t indexRow)
330+{
331+ auto ascendcPlatform = platform_ascendc::PlatformAscendC(tilingContext_->GetPlatformInfo());
332+ size_t sysWorkspaceSize = ascendcPlatform.GetLibApiWorkSpaceSize();
333+ size_t indexRowAligned = (indexRow + ALIGNED_NUM - 1) & ~(ALIGNED_NUM - 1);
334+ sortWorkspace_ = indexRowAligned;
335+ size_t totalWorkspace = sysWorkspaceSize;
336+ if (isLinearIndex_) {
337+ totalWorkspace += sortWorkspace_ * sizeof(int);
338+ }
339+ if (isSort_) {
340+ totalWorkspace += sortWorkspace_ * sizeof(int);
341+ }
342+ return totalWorkspace;
343+}
344+ 
345+static ge::graphStatus TilingParseForScatterNdUpdateArch32(gert::TilingParseContext* context)
346+{
347+ auto compileInfo = context->GetCompiledInfo<ScatterNdUpdateArch32CompileInfo>();
348+ OP_CHECK_NULL_WITH_CONTEXT(context, compileInfo);
349+ auto platformInfo = context->GetPlatformInfo();
350+ OP_CHECK_NULL_WITH_CONTEXT(context, platformInfo);
351+ auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfo);
352+ compileInfo->vectorCoreNum = ascendcPlatform.GetCoreNumAiv();
353+ OP_CHECK_IF(
354+ (compileInfo->vectorCoreNum <= 0), OP_LOGE(context->GetNodeName(), "Failed to get core num."),
355+ return ge::GRAPH_FAILED);
356+ uint64_t ubSize = 0;
357+ ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSize);
358+ compileInfo->ubSize = ubSize;
359+ OP_CHECK_IF(
360+ (compileInfo->ubSize <= 0), OP_LOGE(context->GetNodeName(), "Failed to get ub size."), return ge::GRAPH_FAILED);
361+ return ge::GRAPH_SUCCESS;
362+}
363+ 
364+void ScatterNdUpdateArch32Tiling::TilingDataPrint() const
365+{
366+ OP_LOGD(tilingContext_, "coreNum: %lu", coreNum_);
367+ OP_LOGD(tilingContext_, "ubSize: %lu", ubSize_);
368+ OP_LOGD(tilingContext_, "tilingKey: %lu", tilingKey_);
369+ OP_LOGD(tilingContext_, "isInt64Indices: %lu", isInt64Indices_);
370+ OP_LOGD(tilingContext_, "needLargeIndexKernel: %lu", needLargeIndexKernel_);
371+ OP_LOGD(tilingContext_, "isLinearIndex: %lu", isLinearIndex_);
372+ OP_LOGD(tilingContext_, "isSort: %lu", isSort_);
373+ 
374+ OP_LOGD(tilingContext_, "isViewStride0: %lu", isViewStride0_);
375+ OP_LOGD(tilingContext_, "varStride0Elements: %lu", varStride0Elements_);
376+ OP_LOGD(tilingContext_, "firstDimStrideRows: %lu", firstDimStrideRows_);
377+ 
378+ OP_LOGD(tilingContext_, "indexDim: %lu", indexDim_);
379+ OP_LOGD(tilingContext_, "blockLength: %lu", blockLength_);
380+ OP_LOGD(tilingContext_, "blockNum: %lu", blockNum_);
381+ OP_LOGD(tilingContext_, "blockRemainLength: %lu", blockRemainLength_);
382+ OP_LOGD(tilingContext_, "frontBlockNum: %lu", frontBlockNum_);
383+ OP_LOGD(tilingContext_, "tailBlockNum: %lu", tailBlockNum_);
384+ OP_LOGD(tilingContext_, "frontCoreNum: %lu", frontCoreNum_);
385+ OP_LOGD(tilingContext_, "tailCoreNum: %lu", tailCoreNum_);
386+ OP_LOGD(tilingContext_, "sortWorkspace: %lu", sortWorkspace_);
387+ for (size_t i = 0; i < indexDim_; i++) {
388+ OP_LOGD(tilingContext_, "indicesMask[%zu]: %lu", i, indicesMask_[i]);
389+ }
390+ 
391+ OP_LOGD(tilingContext_, "scatterLength: %lu", scatterLength_);
392+ OP_LOGD(tilingContext_, "frontRow: %lu", frontRow_);
393+ OP_LOGD(tilingContext_, "tailRow: %lu", tailRow_);
394+ OP_LOGD(tilingContext_, "frontNum: %lu", frontNum_);
395+ OP_LOGD(tilingContext_, "tailNum: %lu", tailNum_);
396+ OP_LOGD(tilingContext_, "ubLengthForUpdates: %lu", ubLengthForUpdates_);
397+ OP_LOGD(tilingContext_, "scatterAlignLength: %lu", scatterAlignLength_);
398+ OP_LOGD(tilingContext_, "formDim: %lu", formDim_);
399+ OP_LOGD(tilingContext_, "copyRow: %lu", copyRow_);
400+ OP_LOGD(tilingContext_, "scatterTileNum: %lu", scatterTileNum_);
401+ OP_LOGD(tilingContext_, "scatterTileLength: %lu", scatterTileLength_);
402+ OP_LOGD(tilingContext_, "scatterTileTail: %lu", scatterTileTail_);
403+ OP_LOGD(tilingContext_, "scatterTileAlignLength: %lu", scatterTileAlignLength_);
404+ 
405+ OP_LOGD(tilingContext_, "hpCoreNum: %lu", hpCoreNum_);
406+ OP_LOGD(tilingContext_, "hpFrontIndexNum: %lu", hpFrontIndexNum_);
407+ OP_LOGD(tilingContext_, "hpTailIndexNum: %lu", hpTailIndexNum_);
408+ OP_LOGD(tilingContext_, "hpFrontCoreNum: %lu", hpFrontCoreNum_);
409+ OP_LOGD(tilingContext_, "hpTailCoreNum: %lu", hpTailCoreNum_);
410+ OP_LOGD(tilingContext_, "hpIndexTileLength: %lu", hpIndexTileLength_);
411+ OP_LOGD(tilingContext_, "hpScatterTileLength: %lu", hpScatterTileLength_);
412+ OP_LOGD(tilingContext_, "hpScatterTileNum: %lu", hpScatterTileNum_);
413+ OP_LOGD(tilingContext_, "hpScatterTileTail: %lu", hpScatterTileTail_);
414+ OP_LOGD(tilingContext_, "hpRowBytesAligned: %lu", hpRowBytesAligned_);
415+ OP_LOGD(tilingContext_, "hpRowsPerBatch: %lu", hpRowsPerBatch_);
416+}
417+ 
418+namespace {
419+struct ScatterInitInfo {
420+ uint64_t totalLength;
421+ uint64_t indexRow;
422+ uint64_t indexDim;
423+ uint64_t isInt64Indices;
424+ uint64_t scatterLength;
425+};
426+} // namespace
427+ 
428+static ScatterInitInfo ParseScatterShapes(gert::TilingContext* ctx, uint64_t scatterLengthInit)
429+{
430+ ScatterInitInfo info{};
431+ info.scatterLength = scatterLengthInit;
432+ auto varRefShape = ctx->GetInputShape(0)->GetOriginShape();
433+ auto indicesShape = ctx->GetInputShape(1)->GetOriginShape();
434+ uint64_t varDimNum = varRefShape.GetDimNum();
435+ info.indexDim = indicesShape.GetDim(indicesShape.GetDimNum() - 1);
436+ auto indicesDtype = ctx->GetInputDesc(1)->GetDataType();
437+ info.isInt64Indices = (indicesDtype == ge::DT_INT64);
438+ info.totalLength = 1;
439+ for (uint64_t i = 0; i < info.indexDim; ++i) {
440+ info.totalLength *= varRefShape.GetDim(i);
441+ }
442+ if (varDimNum > info.indexDim) {
443+ for (uint64_t i = info.indexDim; i < varDimNum; i++) {
444+ info.scatterLength *= varRefShape.GetDim(i);
445+ }
446+ }
447+ info.indexRow = 1;
448+ for (uint64_t i = 0; i < indicesShape.GetDimNum() - 1; i++) {
449+ info.indexRow *= indicesShape.GetDim(i);
450+ }
451+ return info;
452+}
453+ 
454+ge::graphStatus ScatterNdUpdateArch32Tiling::Init()
455+{
456+ auto info = ParseScatterShapes(tilingContext_, scatterLength_);
457+ indexDim_ = info.indexDim;
458+ isInt64Indices_ = info.isInt64Indices;
459+ scatterLength_ = info.scatterLength;
460+ if (isInt64Indices_) {
461+ needLargeIndexKernel_ = !IsLinearIndex(info.totalLength);
462+ }
463+ if (needLargeIndexKernel_) {
464+ isSort_ = false;
465+ isLinearIndex_ = false;
466+ } else {
467+ isSort_ = IsSort(info.totalLength);
468+ isLinearIndex_ = IsLinearIndex(info.totalLength);
469+ }
470+ auto compileInfo = tilingContext_->GetCompileInfo<ScatterNdUpdateArch32CompileInfo>();
471+ OP_CHECK_NULL_WITH_CONTEXT(tilingContext_, compileInfo);
472+ coreNum_ = std::min(static_cast<uint64_t>(compileInfo->vectorCoreNum), std::min(info.totalLength, info.indexRow));
473+ coreNum_ = coreNum_ == 0 ? 1 : coreNum_;
474+ ubSize_ = compileInfo->ubSize;
475+ GetDtypeSize();
476+ SetTilingKeyMode();
477+ tilingContext_->SetScheduleMode(1);
478+ Tiling4LinearIndex(info.indexRow, indexDim_);
479+ Tiling4Scatter(info.totalLength);
480+ Tiling4Hp(info.indexRow);
481+ if (HandleViewStride() != ge::GRAPH_SUCCESS) {
482+ return ge::GRAPH_FAILED;
483+ }
484+ size_t* currentWorkSpace = tilingContext_->GetWorkspaceSizes(1);
485+ currentWorkSpace[0] = CalcWorkSpaceSize(info.indexRow);
486+ return ge::GRAPH_SUCCESS;
487+}
488+ 
489+// tiling dispatch entry
490+static ge::graphStatus ScatterNdUpdateArch32TilingFunc(gert::TilingContext* context)
491+{
492+ ScatterNdUpdateArch32Tiling tilingOp(context);
493+ if (tilingOp.Init() != ge::GRAPH_SUCCESS) {
494+ OP_LOGE(context->GetNodeName(), "Tiling init fail");
495+ return ge::GRAPH_FAILED;
496+ }
497+ return tilingOp.SetKernelTiling();
498+}
499+ 
500+IMPL_OP_OPTILING(ScatterNdUpdate)
501+ .Tiling(ScatterNdUpdateArch32TilingFunc)
502+ .TilingParse<ScatterNdUpdateArch32CompileInfo>(TilingParseForScatterNdUpdateArch32);
503+ 
504+} // namespace optiling
@@ -0,0 +1,180 @@
1+/**
2+ * Copyright (c) 2025-2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file scatter_nd_update_tiling.h
13+ * \brief scatter_nd_update arch32 tiling data definition
14+ */
15+ 
16+#ifndef SCATTER_ND_UPDATE_ARCH32_TILING_H
17+#define SCATTER_ND_UPDATE_ARCH32_TILING_H
18+ 
19+#include "register/tilingdata_base.h"
20+#include "tiling/tiling_api.h"
21+ 
22+constexpr uint64_t MAX_DIM_NUM = 8;
23+ 
24+namespace optiling {
25+ 
26+BEGIN_TILING_DATA_DEF(ScatterNdUpdateScatterTiling)
27+TILING_DATA_FIELD_DEF(uint64_t, scatterLength)
28+TILING_DATA_FIELD_DEF(uint64_t, tailRow)
29+TILING_DATA_FIELD_DEF(uint64_t, frontRow)
30+TILING_DATA_FIELD_DEF(uint64_t, frontNum)
31+TILING_DATA_FIELD_DEF(uint64_t, tailNum)
32+TILING_DATA_FIELD_DEF(uint64_t, ubLengthForUpdates)
33+TILING_DATA_FIELD_DEF(uint64_t, scatterAlignLength)
34+TILING_DATA_FIELD_DEF(uint64_t, formDim)
35+TILING_DATA_FIELD_DEF(uint64_t, copyRow)
36+TILING_DATA_FIELD_DEF(uint64_t, scatterTileNum)
37+TILING_DATA_FIELD_DEF(uint64_t, scatterTileLength)
38+TILING_DATA_FIELD_DEF(uint64_t, scatterTileTail)
39+TILING_DATA_FIELD_DEF(uint64_t, scatterTileAlignLength)
40+END_TILING_DATA_DEF
41+ 
42+REGISTER_TILING_DATA_CLASS(ScatterNdUpdateScatterTilingOp, ScatterNdUpdateScatterTiling)
43+ 
44+BEGIN_TILING_DATA_DEF(ScatterNdUpdateLinearIndexTiling)
45+TILING_DATA_FIELD_DEF(uint64_t, coreNum)
46+TILING_DATA_FIELD_DEF(uint64_t, ubSize)
47+TILING_DATA_FIELD_DEF(uint64_t, indexDim)
48+TILING_DATA_FIELD_DEF(uint64_t, blockLength)
49+TILING_DATA_FIELD_DEF(uint64_t, blockNum)
50+TILING_DATA_FIELD_DEF(uint64_t, blockRemainLength)
51+TILING_DATA_FIELD_DEF(uint64_t, tailBlockNum)
52+TILING_DATA_FIELD_DEF(uint64_t, frontBlockNum)
53+TILING_DATA_FIELD_DEF(uint64_t, frontCoreNum)
54+TILING_DATA_FIELD_DEF(uint64_t, tailCoreNum)
55+TILING_DATA_FIELD_DEF(uint64_t, sortWorkspace)
56+TILING_DATA_FIELD_DEF_ARR(uint64_t, MAX_DIM_NUM, indicesMask)
57+TILING_DATA_FIELD_DEF(uint64_t, isInt64Indices)
58+TILING_DATA_FIELD_DEF(uint64_t, needLargeIndexKernel)
59+END_TILING_DATA_DEF
60+ 
61+REGISTER_TILING_DATA_CLASS(ScatterNdUpdateLinearIndexTilingOp, ScatterNdUpdateLinearIndexTiling)
62+ 
63+BEGIN_TILING_DATA_DEF(ScatterNdUpdateViewTiling)
64+TILING_DATA_FIELD_DEF(uint64_t, isViewStride0)
65+TILING_DATA_FIELD_DEF(uint64_t, varStride0Elements)
66+TILING_DATA_FIELD_DEF(uint64_t, firstDimStrideRows)
67+END_TILING_DATA_DEF
68+ 
69+REGISTER_TILING_DATA_CLASS(ScatterNdUpdateViewTilingOp, ScatterNdUpdateViewTiling)
70+ 
71+BEGIN_TILING_DATA_DEF(ScatterNdUpdateHpTiling)
72+TILING_DATA_FIELD_DEF(uint64_t, hpCoreNum)
73+TILING_DATA_FIELD_DEF(uint64_t, hpFrontIndexNum)
74+TILING_DATA_FIELD_DEF(uint64_t, hpTailIndexNum)
75+TILING_DATA_FIELD_DEF(uint64_t, hpFrontCoreNum)
76+TILING_DATA_FIELD_DEF(uint64_t, hpTailCoreNum)
77+TILING_DATA_FIELD_DEF(uint64_t, hpIndexTileLength)
78+TILING_DATA_FIELD_DEF(uint64_t, hpScatterTileLength)
79+TILING_DATA_FIELD_DEF(uint64_t, hpScatterTileNum)
80+TILING_DATA_FIELD_DEF(uint64_t, hpScatterTileTail)
81+TILING_DATA_FIELD_DEF(uint64_t, hpRowBytesAligned)
82+TILING_DATA_FIELD_DEF(uint64_t, hpRowsPerBatch)
83+END_TILING_DATA_DEF
84+ 
85+REGISTER_TILING_DATA_CLASS(ScatterNdUpdateHpTilingOp, ScatterNdUpdateHpTiling)
86+ 
87+BEGIN_TILING_DATA_DEF(ScatterNdUpdateArch32TilingData)
88+TILING_DATA_FIELD_DEF_STRUCT(ScatterNdUpdateScatterTiling, scatterTiling)
89+TILING_DATA_FIELD_DEF_STRUCT(ScatterNdUpdateLinearIndexTiling, linearIndexTiling)
90+TILING_DATA_FIELD_DEF_STRUCT(ScatterNdUpdateHpTiling, hpTiling)
91+TILING_DATA_FIELD_DEF_STRUCT(ScatterNdUpdateViewTiling, viewTiling)
92+END_TILING_DATA_DEF
93+ 
94+REGISTER_TILING_DATA_CLASS(ScatterNdUpdate, ScatterNdUpdateArch32TilingData)
95+REGISTER_TILING_DATA_CLASS(ScatterNdUpdateTilingDataOp, ScatterNdUpdateArch32TilingData)
96+ 
97+struct ScatterNdUpdateArch32CompileInfo {
98+ uint32_t vectorCoreNum = 0;
99+ uint64_t ubSize = 0;
100+};
101+ 
102+class ScatterNdUpdateArch32Tiling {
103+public:
104+ explicit ScatterNdUpdateArch32Tiling(gert::TilingContext* context) : tilingContext_(context) {}
105+ ge::graphStatus Init();
106+ ge::graphStatus SetKernelTiling();
107+ void TilingDataPrint() const;
108+ 
109+private:
110+ inline bool IsSort(uint64_t totalLength);
111+ inline bool IsLinearIndex(uint64_t totalLength);
112+ inline size_t CalcWorkSpaceSize(uint64_t indexRow);
113+ inline void SetTilingKeyMode();
114+ inline void GetDtypeSize();
115+ inline void Tiling4Scatter(uint64_t totalLength);
116+ inline void Tiling4LinearIndex(uint64_t indexRow, uint64_t indexDim);
117+ inline void Tiling4Hp(uint64_t indexRow);
118+ inline uint64_t Tiling4HpScatterShape();
119+ inline void Tiling4HpIndexTile(uint64_t updateUbBytes);
120+ inline void Tiling4HpCorePartition(uint64_t indexRow);
121+ inline ge::graphStatus HandleViewStride();
122+ 
123+ ScatterNdUpdateArch32TilingData tilingData_;
124+ gert::TilingContext* tilingContext_ = nullptr;
125+ 
126+ uint64_t coreNum_ = 0;
127+ uint64_t tilingKey_ = 0;
128+ uint64_t ubSize_ = 0;
129+ uint64_t isLinearIndex_ = false;
130+ uint64_t isSort_ = false;
131+ uint64_t sortWorkspace_ = 0;
132+ uint64_t dataTypeSize_ = 0;
133+ uint64_t isInt64Indices_ = false;
134+ uint64_t needLargeIndexKernel_ = false;
135+ uint64_t isViewStride0_ = 0;
136+ uint64_t varStride0Elements_ = 0;
137+ uint64_t firstDimStrideRows_ = 1;
138+ 
139+private:
140+ // LinearIndex
141+ uint64_t indexDim_ = 0;
142+ uint64_t blockLength_ = 0;
143+ uint64_t blockNum_ = 0;
144+ uint64_t blockRemainLength_ = 0;
145+ uint64_t tailBlockNum_ = 0;
146+ uint64_t frontBlockNum_ = 0;
147+ uint64_t frontCoreNum_ = 0;
148+ uint64_t tailCoreNum_ = 0;
149+ uint64_t indicesMask_[MAX_DIM_NUM] = {0};
150+ 
151+ // Scatter
152+ uint64_t scatterLength_ = 1;
153+ uint64_t tailRow_ = 0;
154+ uint64_t frontRow_ = 0;
155+ uint64_t frontNum_ = 0;
156+ uint64_t tailNum_ = 0;
157+ uint64_t ubLengthForUpdates_ = 0;
158+ uint64_t scatterAlignLength_ = 0;
159+ uint64_t formDim_ = 0;
160+ uint64_t copyRow_ = 0;
161+ uint64_t scatterTileNum_ = 1;
162+ uint64_t scatterTileLength_ = 0;
163+ uint64_t scatterTileTail_ = 0;
164+ uint64_t scatterTileAlignLength_ = 0;
165+ 
166+ // HighPerformance
167+ uint64_t hpCoreNum_ = 0;
168+ uint64_t hpFrontIndexNum_ = 0;
169+ uint64_t hpTailIndexNum_ = 0;
170+ uint64_t hpFrontCoreNum_ = 0;
171+ uint64_t hpTailCoreNum_ = 0;
172+ uint64_t hpIndexTileLength_ = 0;
173+ uint64_t hpScatterTileLength_ = 0;
174+ uint64_t hpScatterTileNum_ = 1;
175+ uint64_t hpScatterTileTail_ = 0;
176+ uint64_t hpRowBytesAligned_ = 0;
177+ uint64_t hpRowsPerBatch_ = 1;
178+};
179+} // namespace optiling
180+#endif // SCATTER_ND_UPDATE_ARCH32_TILING_H
@@ -0,0 +1,741 @@
1+{
2+ "op_type": "ScatterNdUpdate",
3+ "op_list": [
4+ {
5+ "bin_filename": "ScatterNdUpdate_float16_int32",
6+ "inputs": [
7+ {
8+ "name": "var",
9+ "index": 0,
10+ "dtype": "float16",
11+ "format": "ND",
12+ "paramType": "required",
13+ "shape": [-2]
14+ },
15+ {
16+ "name": "indices",
17+ "index": 1,
18+ "dtype": "int32",
19+ "format": "ND",
20+ "paramType": "required",
21+ "shape": [-2]
22+ },
23+ {
24+ "name": "updates",
25+ "index": 2,
26+ "dtype": "float16",
27+ "format": "ND",
28+ "paramType": "required",
29+ "shape": [-2]
30+ }
31+ ],
32+ "outputs": [
33+ {
34+ "name": "var",
35+ "index": 0,
36+ "dtype": "float16",
37+ "format": "ND",
38+ "paramType": "required",
39+ "shape": [-2]
40+ }
41+ ],
42+ "attrs": [
43+ {
44+ "name": "use_locking",
45+ "dtype": "bool",
46+ "value": null
47+ }
48+ ]
49+ },
50+ {
51+ "bin_filename": "ScatterNdUpdate_float16_int64",
52+ "inputs": [
53+ {
54+ "name": "var",
55+ "index": 0,
56+ "dtype": "float16",
57+ "format": "ND",
58+ "paramType": "required",
59+ "shape": [-2]
60+ },
61+ {
62+ "name": "indices",
63+ "index": 1,
64+ "dtype": "int64",
65+ "format": "ND",
66+ "paramType": "required",
67+ "shape": [-2]
68+ },
69+ {
70+ "name": "updates",
71+ "index": 2,
72+ "dtype": "float16",
73+ "format": "ND",
74+ "paramType": "required",
75+ "shape": [-2]
76+ }
77+ ],
78+ "outputs": [
79+ {
80+ "name": "var",
81+ "index": 0,
82+ "dtype": "float16",
83+ "format": "ND",
84+ "paramType": "required",
85+ "shape": [-2]
86+ }
87+ ],
88+ "attrs": [
89+ {
90+ "name": "use_locking",
91+ "dtype": "bool",
92+ "value": null
93+ }
94+ ]
95+ },
96+ {
97+ "bin_filename": "ScatterNdUpdate_float32_int32",
98+ "inputs": [
99+ {
100+ "name": "var",
101+ "index": 0,
102+ "dtype": "float32",
103+ "format": "ND",
104+ "paramType": "required",
105+ "shape": [-2]
106+ },
107+ {
108+ "name": "indices",
109+ "index": 1,
110+ "dtype": "int32",
111+ "format": "ND",
112+ "paramType": "required",
113+ "shape": [-2]
114+ },
115+ {
116+ "name": "updates",
117+ "index": 2,
118+ "dtype": "float32",
119+ "format": "ND",
120+ "paramType": "required",
121+ "shape": [-2]
122+ }
123+ ],
124+ "outputs": [
125+ {
126+ "name": "var",
127+ "index": 0,
128+ "dtype": "float32",
129+ "format": "ND",
130+ "paramType": "required",
131+ "shape": [-2]
132+ }
133+ ],
134+ "attrs": [
135+ {
136+ "name": "use_locking",
137+ "dtype": "bool",
138+ "value": null
139+ }
140+ ]
141+ },
142+ {
143+ "bin_filename": "ScatterNdUpdate_float32_int64",
144+ "inputs": [
145+ {
146+ "name": "var",
147+ "index": 0,
148+ "dtype": "float32",
149+ "format": "ND",
150+ "paramType": "required",
151+ "shape": [-2]
152+ },
153+ {
154+ "name": "indices",
155+ "index": 1,
156+ "dtype": "int64",
157+ "format": "ND",
158+ "paramType": "required",
159+ "shape": [-2]
160+ },
161+ {
162+ "name": "updates",
163+ "index": 2,
164+ "dtype": "float32",
165+ "format": "ND",
166+ "paramType": "required",
167+ "shape": [-2]
168+ }
169+ ],
170+ "outputs": [
171+ {
172+ "name": "var",
173+ "index": 0,
174+ "dtype": "float32",
175+ "format": "ND",
176+ "paramType": "required",
177+ "shape": [-2]
178+ }
179+ ],
180+ "attrs": [
181+ {
182+ "name": "use_locking",
183+ "dtype": "bool",
184+ "value": null
185+ }
186+ ]
187+ },
188+ {
189+ "bin_filename": "ScatterNdUpdate_bfloat16_int32",
190+ "inputs": [
191+ {
192+ "name": "var",
193+ "index": 0,
194+ "dtype": "bfloat16",
195+ "format": "ND",
196+ "paramType": "required",
197+ "shape": [-2]
198+ },
199+ {
200+ "name": "indices",
201+ "index": 1,
202+ "dtype": "int32",
203+ "format": "ND",
204+ "paramType": "required",
205+ "shape": [-2]
206+ },
207+ {
208+ "name": "updates",
209+ "index": 2,
210+ "dtype": "bfloat16",
211+ "format": "ND",
212+ "paramType": "required",
213+ "shape": [-2]
214+ }
215+ ],
216+ "outputs": [
217+ {
218+ "name": "var",
219+ "index": 0,
220+ "dtype": "bfloat16",
221+ "format": "ND",
222+ "paramType": "required",
223+ "shape": [-2]
224+ }
225+ ],
226+ "attrs": [
227+ {
228+ "name": "use_locking",
229+ "dtype": "bool",
230+ "value": null
231+ }
232+ ]
233+ },
234+ {
235+ "bin_filename": "ScatterNdUpdate_bfloat16_int64",
236+ "inputs": [
237+ {
238+ "name": "var",
239+ "index": 0,
240+ "dtype": "bfloat16",
241+ "format": "ND",
242+ "paramType": "required",
243+ "shape": [-2]
244+ },
245+ {
246+ "name": "indices",
247+ "index": 1,
248+ "dtype": "int64",
249+ "format": "ND",
250+ "paramType": "required",
251+ "shape": [-2]
252+ },
253+ {
254+ "name": "updates",
255+ "index": 2,
256+ "dtype": "bfloat16",
257+ "format": "ND",
258+ "paramType": "required",
259+ "shape": [-2]
260+ }
261+ ],
262+ "outputs": [
263+ {
264+ "name": "var",
265+ "index": 0,
266+ "dtype": "bfloat16",
267+ "format": "ND",
268+ "paramType": "required",
269+ "shape": [-2]
270+ }
271+ ],
272+ "attrs": [
273+ {
274+ "name": "use_locking",
275+ "dtype": "bool",
276+ "value": null
277+ }
278+ ]
279+ },
280+ {
281+ "bin_filename": "ScatterNdUpdate_int8_int32",
282+ "inputs": [
283+ {
284+ "name": "var",
285+ "index": 0,
286+ "dtype": "int8",
287+ "format": "ND",
288+ "paramType": "required",
289+ "shape": [-2]
290+ },
291+ {
292+ "name": "indices",
293+ "index": 1,
294+ "dtype": "int32",
295+ "format": "ND",
296+ "paramType": "required",
297+ "shape": [-2]
298+ },
299+ {
300+ "name": "updates",
301+ "index": 2,
302+ "dtype": "int8",
303+ "format": "ND",
304+ "paramType": "required",
305+ "shape": [-2]
306+ }
307+ ],
308+ "outputs": [
309+ {
310+ "name": "var",
311+ "index": 0,
312+ "dtype": "int8",
313+ "format": "ND",
314+ "paramType": "required",
315+ "shape": [-2]
316+ }
317+ ],
318+ "attrs": [
319+ {
320+ "name": "use_locking",
321+ "dtype": "bool",
322+ "value": null
323+ }
324+ ]
325+ },
326+ {
327+ "bin_filename": "ScatterNdUpdate_int8_int64",
328+ "inputs": [
329+ {
330+ "name": "var",
331+ "index": 0,
332+ "dtype": "int8",
333+ "format": "ND",
334+ "paramType": "required",
335+ "shape": [-2]
336+ },
337+ {
338+ "name": "indices",
339+ "index": 1,
340+ "dtype": "int64",
341+ "format": "ND",
342+ "paramType": "required",
343+ "shape": [-2]
344+ },
345+ {
346+ "name": "updates",
347+ "index": 2,
348+ "dtype": "int8",
349+ "format": "ND",
350+ "paramType": "required",
351+ "shape": [-2]
352+ }
353+ ],
354+ "outputs": [
355+ {
356+ "name": "var",
357+ "index": 0,
358+ "dtype": "int8",
359+ "format": "ND",
360+ "paramType": "required",
361+ "shape": [-2]
362+ }
363+ ],
364+ "attrs": [
365+ {
366+ "name": "use_locking",
367+ "dtype": "bool",
368+ "value": null
369+ }
370+ ]
371+ },
372+ {
373+ "bin_filename": "ScatterNdUpdate_int16_int32",
374+ "inputs": [
375+ {
376+ "name": "var",
377+ "index": 0,
378+ "dtype": "int16",
379+ "format": "ND",
380+ "paramType": "required",
381+ "shape": [-2]
382+ },
383+ {
384+ "name": "indices",
385+ "index": 1,
386+ "dtype": "int32",
387+ "format": "ND",
388+ "paramType": "required",
389+ "shape": [-2]
390+ },
391+ {
392+ "name": "updates",
393+ "index": 2,
394+ "dtype": "int16",
395+ "format": "ND",
396+ "paramType": "required",
397+ "shape": [-2]
398+ }
399+ ],
400+ "outputs": [
401+ {
402+ "name": "var",
403+ "index": 0,
404+ "dtype": "int16",
405+ "format": "ND",
406+ "paramType": "required",
407+ "shape": [-2]
408+ }
409+ ],
410+ "attrs": [
411+ {
412+ "name": "use_locking",
413+ "dtype": "bool",
414+ "value": null
415+ }
416+ ]
417+ },
418+ {
419+ "bin_filename": "ScatterNdUpdate_int16_int64",
420+ "inputs": [
421+ {
422+ "name": "var",
423+ "index": 0,
424+ "dtype": "int16",
425+ "format": "ND",
426+ "paramType": "required",
427+ "shape": [-2]
428+ },
429+ {
430+ "name": "indices",
431+ "index": 1,
432+ "dtype": "int64",
433+ "format": "ND",
434+ "paramType": "required",
435+ "shape": [-2]
436+ },
437+ {
438+ "name": "updates",
439+ "index": 2,
440+ "dtype": "int16",
441+ "format": "ND",
442+ "paramType": "required",
443+ "shape": [-2]
444+ }
445+ ],
446+ "outputs": [
447+ {
448+ "name": "var",
449+ "index": 0,
450+ "dtype": "int16",
451+ "format": "ND",
452+ "paramType": "required",
453+ "shape": [-2]
454+ }
455+ ],
456+ "attrs": [
457+ {
458+ "name": "use_locking",
459+ "dtype": "bool",
460+ "value": null
461+ }
462+ ]
463+ },
464+ {
465+ "bin_filename": "ScatterNdUpdate_int32_int32",
466+ "inputs": [
467+ {
468+ "name": "var",
469+ "index": 0,
470+ "dtype": "int32",
471+ "format": "ND",
472+ "paramType": "required",
473+ "shape": [-2]
474+ },
475+ {
476+ "name": "indices",
477+ "index": 1,
478+ "dtype": "int32",
479+ "format": "ND",
480+ "paramType": "required",
481+ "shape": [-2]
482+ },
483+ {
484+ "name": "updates",
485+ "index": 2,
486+ "dtype": "int32",
487+ "format": "ND",
488+ "paramType": "required",
489+ "shape": [-2]
490+ }
491+ ],
492+ "outputs": [
493+ {
494+ "name": "var",
495+ "index": 0,
496+ "dtype": "int32",
497+ "format": "ND",
498+ "paramType": "required",
499+ "shape": [-2]
500+ }
501+ ],
502+ "attrs": [
503+ {
504+ "name": "use_locking",
505+ "dtype": "bool",
506+ "value": null
507+ }
508+ ]
509+ },
510+ {
511+ "bin_filename": "ScatterNdUpdate_int32_int64",
512+ "inputs": [
513+ {
514+ "name": "var",
515+ "index": 0,
516+ "dtype": "int32",
517+ "format": "ND",
518+ "paramType": "required",
519+ "shape": [-2]
520+ },
521+ {
522+ "name": "indices",
523+ "index": 1,
524+ "dtype": "int64",
525+ "format": "ND",
526+ "paramType": "required",
527+ "shape": [-2]
528+ },
529+ {
530+ "name": "updates",
531+ "index": 2,
532+ "dtype": "int32",
533+ "format": "ND",
534+ "paramType": "required",
535+ "shape": [-2]
536+ }
537+ ],
538+ "outputs": [
539+ {
540+ "name": "var",
541+ "index": 0,
542+ "dtype": "int32",
543+ "format": "ND",
544+ "paramType": "required",
545+ "shape": [-2]
546+ }
547+ ],
548+ "attrs": [
549+ {
550+ "name": "use_locking",
551+ "dtype": "bool",
552+ "value": null
553+ }
554+ ]
555+ },
556+ {
557+ "bin_filename": "ScatterNdUpdate_int64_int32",
558+ "inputs": [
559+ {
560+ "name": "var",
561+ "index": 0,
562+ "dtype": "int64",
563+ "format": "ND",
564+ "paramType": "required",
565+ "shape": [-2]
566+ },
567+ {
568+ "name": "indices",
569+ "index": 1,
570+ "dtype": "int32",
571+ "format": "ND",
572+ "paramType": "required",
573+ "shape": [-2]
574+ },
575+ {
576+ "name": "updates",
577+ "index": 2,
578+ "dtype": "int64",
579+ "format": "ND",
580+ "paramType": "required",
581+ "shape": [-2]
582+ }
583+ ],
584+ "outputs": [
585+ {
586+ "name": "var",
587+ "index": 0,
588+ "dtype": "int64",
589+ "format": "ND",
590+ "paramType": "required",
591+ "shape": [-2]
592+ }
593+ ],
594+ "attrs": [
595+ {
596+ "name": "use_locking",
597+ "dtype": "bool",
598+ "value": null
599+ }
600+ ]
601+ },
602+ {
603+ "bin_filename": "ScatterNdUpdate_int64_int64",
604+ "inputs": [
605+ {
606+ "name": "var",
607+ "index": 0,
608+ "dtype": "int64",
609+ "format": "ND",
610+ "paramType": "required",
611+ "shape": [-2]
612+ },
613+ {
614+ "name": "indices",
615+ "index": 1,
616+ "dtype": "int64",
617+ "format": "ND",
618+ "paramType": "required",
619+ "shape": [-2]
620+ },
621+ {
622+ "name": "updates",
623+ "index": 2,
624+ "dtype": "int64",
625+ "format": "ND",
626+ "paramType": "required",
627+ "shape": [-2]
628+ }
629+ ],
630+ "outputs": [
631+ {
632+ "name": "var",
633+ "index": 0,
634+ "dtype": "int64",
635+ "format": "ND",
636+ "paramType": "required",
637+ "shape": [-2]
638+ }
639+ ],
640+ "attrs": [
641+ {
642+ "name": "use_locking",
643+ "dtype": "bool",
644+ "value": null
645+ }
646+ ]
647+ },
648+ {
649+ "bin_filename": "ScatterNdUpdate_bool_int32",
650+ "inputs": [
651+ {
652+ "name": "var",
653+ "index": 0,
654+ "dtype": "bool",
655+ "format": "ND",
656+ "paramType": "required",
657+ "shape": [-2]
658+ },
659+ {
660+ "name": "indices",
661+ "index": 1,
662+ "dtype": "int32",
663+ "format": "ND",
664+ "paramType": "required",
665+ "shape": [-2]
666+ },
667+ {
668+ "name": "updates",
669+ "index": 2,
670+ "dtype": "bool",
671+ "format": "ND",
672+ "paramType": "required",
673+ "shape": [-2]
674+ }
675+ ],
676+ "outputs": [
677+ {
678+ "name": "var",
679+ "index": 0,
680+ "dtype": "bool",
681+ "format": "ND",
682+ "paramType": "required",
683+ "shape": [-2]
684+ }
685+ ],
686+ "attrs": [
687+ {
688+ "name": "use_locking",
689+ "dtype": "bool",
690+ "value": null
691+ }
692+ ]
693+ },
694+ {
695+ "bin_filename": "ScatterNdUpdate_bool_int64",
696+ "inputs": [
697+ {
698+ "name": "var",
699+ "index": 0,
700+ "dtype": "bool",
701+ "format": "ND",
702+ "paramType": "required",
703+ "shape": [-2]
704+ },
705+ {
706+ "name": "indices",
707+ "index": 1,
708+ "dtype": "int64",
709+ "format": "ND",
710+ "paramType": "required",
711+ "shape": [-2]
712+ },
713+ {
714+ "name": "updates",
715+ "index": 2,
716+ "dtype": "bool",
717+ "format": "ND",
718+ "paramType": "required",
719+ "shape": [-2]
720+ }
721+ ],
722+ "outputs": [
723+ {
724+ "name": "var",
725+ "index": 0,
726+ "dtype": "bool",
727+ "format": "ND",
728+ "paramType": "required",
729+ "shape": [-2]
730+ }
731+ ],
732+ "attrs": [
733+ {
734+ "name": "use_locking",
735+ "dtype": "bool",
736+ "value": null
737+ }
738+ ]
739+ }
740+ ]
741+}
@@ -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+[ScatterNdUpdate]
13+default=0
@@ -0,0 +1,741 @@
1+{
2+ "op_type": "ScatterNdUpdate",
3+ "op_list": [
4+ {
5+ "bin_filename": "ScatterNdUpdate_float16_int32",
6+ "inputs": [
7+ {
8+ "name": "var",
9+ "index": 0,
10+ "dtype": "float16",
11+ "format": "ND",
12+ "paramType": "required",
13+ "shape": [-2]
14+ },
15+ {
16+ "name": "indices",
17+ "index": 1,
18+ "dtype": "int32",
19+ "format": "ND",
20+ "paramType": "required",
21+ "shape": [-2]
22+ },
23+ {
24+ "name": "updates",
25+ "index": 2,
26+ "dtype": "float16",
27+ "format": "ND",
28+ "paramType": "required",
29+ "shape": [-2]
30+ }
31+ ],
32+ "outputs": [
33+ {
34+ "name": "var",
35+ "index": 0,
36+ "dtype": "float16",
37+ "format": "ND",
38+ "paramType": "required",
39+ "shape": [-2]
40+ }
41+ ],
42+ "attrs": [
43+ {
44+ "name": "use_locking",
45+ "dtype": "bool",
46+ "value": null
47+ }
48+ ]
49+ },
50+ {
51+ "bin_filename": "ScatterNdUpdate_float16_int64",
52+ "inputs": [
53+ {
54+ "name": "var",
55+ "index": 0,
56+ "dtype": "float16",
57+ "format": "ND",
58+ "paramType": "required",
59+ "shape": [-2]
60+ },
61+ {
62+ "name": "indices",
63+ "index": 1,
64+ "dtype": "int64",
65+ "format": "ND",
66+ "paramType": "required",
67+ "shape": [-2]
68+ },
69+ {
70+ "name": "updates",
71+ "index": 2,
72+ "dtype": "float16",
73+ "format": "ND",
74+ "paramType": "required",
75+ "shape": [-2]
76+ }
77+ ],
78+ "outputs": [
79+ {
80+ "name": "var",
81+ "index": 0,
82+ "dtype": "float16",
83+ "format": "ND",
84+ "paramType": "required",
85+ "shape": [-2]
86+ }
87+ ],
88+ "attrs": [
89+ {
90+ "name": "use_locking",
91+ "dtype": "bool",
92+ "value": null
93+ }
94+ ]
95+ },
96+ {
97+ "bin_filename": "ScatterNdUpdate_float32_int32",
98+ "inputs": [
99+ {
100+ "name": "var",
101+ "index": 0,
102+ "dtype": "float32",
103+ "format": "ND",
104+ "paramType": "required",
105+ "shape": [-2]
106+ },
107+ {
108+ "name": "indices",
109+ "index": 1,
110+ "dtype": "int32",
111+ "format": "ND",
112+ "paramType": "required",
113+ "shape": [-2]
114+ },
115+ {
116+ "name": "updates",
117+ "index": 2,
118+ "dtype": "float32",
119+ "format": "ND",
120+ "paramType": "required",
121+ "shape": [-2]
122+ }
123+ ],
124+ "outputs": [
125+ {
126+ "name": "var",
127+ "index": 0,
128+ "dtype": "float32",
129+ "format": "ND",
130+ "paramType": "required",
131+ "shape": [-2]
132+ }
133+ ],
134+ "attrs": [
135+ {
136+ "name": "use_locking",
137+ "dtype": "bool",
138+ "value": null
139+ }
140+ ]
141+ },
142+ {
143+ "bin_filename": "ScatterNdUpdate_float32_int64",
144+ "inputs": [
145+ {
146+ "name": "var",
147+ "index": 0,
148+ "dtype": "float32",
149+ "format": "ND",
150+ "paramType": "required",
151+ "shape": [-2]
152+ },
153+ {
154+ "name": "indices",
155+ "index": 1,
156+ "dtype": "int64",
157+ "format": "ND",
158+ "paramType": "required",
159+ "shape": [-2]
160+ },
161+ {
162+ "name": "updates",
163+ "index": 2,
164+ "dtype": "float32",
165+ "format": "ND",
166+ "paramType": "required",
167+ "shape": [-2]
168+ }
169+ ],
170+ "outputs": [
171+ {
172+ "name": "var",
173+ "index": 0,
174+ "dtype": "float32",
175+ "format": "ND",
176+ "paramType": "required",
177+ "shape": [-2]
178+ }
179+ ],
180+ "attrs": [
181+ {
182+ "name": "use_locking",
183+ "dtype": "bool",
184+ "value": null
185+ }
186+ ]
187+ },
188+ {
189+ "bin_filename": "ScatterNdUpdate_bfloat16_int32",
190+ "inputs": [
191+ {
192+ "name": "var",
193+ "index": 0,
194+ "dtype": "bfloat16",
195+ "format": "ND",
196+ "paramType": "required",
197+ "shape": [-2]
198+ },
199+ {
200+ "name": "indices",
201+ "index": 1,
202+ "dtype": "int32",
203+ "format": "ND",
204+ "paramType": "required",
205+ "shape": [-2]
206+ },
207+ {
208+ "name": "updates",
209+ "index": 2,
210+ "dtype": "bfloat16",
211+ "format": "ND",
212+ "paramType": "required",
213+ "shape": [-2]
214+ }
215+ ],
216+ "outputs": [
217+ {
218+ "name": "var",
219+ "index": 0,
220+ "dtype": "bfloat16",
221+ "format": "ND",
222+ "paramType": "required",
223+ "shape": [-2]
224+ }
225+ ],
226+ "attrs": [
227+ {
228+ "name": "use_locking",
229+ "dtype": "bool",
230+ "value": null
231+ }
232+ ]
233+ },
234+ {
235+ "bin_filename": "ScatterNdUpdate_bfloat16_int64",
236+ "inputs": [
237+ {
238+ "name": "var",
239+ "index": 0,
240+ "dtype": "bfloat16",
241+ "format": "ND",
242+ "paramType": "required",
243+ "shape": [-2]
244+ },
245+ {
246+ "name": "indices",
247+ "index": 1,
248+ "dtype": "int64",
249+ "format": "ND",
250+ "paramType": "required",
251+ "shape": [-2]
252+ },
253+ {
254+ "name": "updates",
255+ "index": 2,
256+ "dtype": "bfloat16",
257+ "format": "ND",
258+ "paramType": "required",
259+ "shape": [-2]
260+ }
261+ ],
262+ "outputs": [
263+ {
264+ "name": "var",
265+ "index": 0,
266+ "dtype": "bfloat16",
267+ "format": "ND",
268+ "paramType": "required",
269+ "shape": [-2]
270+ }
271+ ],
272+ "attrs": [
273+ {
274+ "name": "use_locking",
275+ "dtype": "bool",
276+ "value": null
277+ }
278+ ]
279+ },
280+ {
281+ "bin_filename": "ScatterNdUpdate_int8_int32",
282+ "inputs": [
283+ {
284+ "name": "var",
285+ "index": 0,
286+ "dtype": "int8",
287+ "format": "ND",
288+ "paramType": "required",
289+ "shape": [-2]
290+ },
291+ {
292+ "name": "indices",
293+ "index": 1,
294+ "dtype": "int32",
295+ "format": "ND",
296+ "paramType": "required",
297+ "shape": [-2]
298+ },
299+ {
300+ "name": "updates",
301+ "index": 2,
302+ "dtype": "int8",
303+ "format": "ND",
304+ "paramType": "required",
305+ "shape": [-2]
306+ }
307+ ],
308+ "outputs": [
309+ {
310+ "name": "var",
311+ "index": 0,
312+ "dtype": "int8",
313+ "format": "ND",
314+ "paramType": "required",
315+ "shape": [-2]
316+ }
317+ ],
318+ "attrs": [
319+ {
320+ "name": "use_locking",
321+ "dtype": "bool",
322+ "value": null
323+ }
324+ ]
325+ },
326+ {
327+ "bin_filename": "ScatterNdUpdate_int8_int64",
328+ "inputs": [
329+ {
330+ "name": "var",
331+ "index": 0,
332+ "dtype": "int8",
333+ "format": "ND",
334+ "paramType": "required",
335+ "shape": [-2]
336+ },
337+ {
338+ "name": "indices",
339+ "index": 1,
340+ "dtype": "int64",
341+ "format": "ND",
342+ "paramType": "required",
343+ "shape": [-2]
344+ },
345+ {
346+ "name": "updates",
347+ "index": 2,
348+ "dtype": "int8",
349+ "format": "ND",
350+ "paramType": "required",
351+ "shape": [-2]
352+ }
353+ ],
354+ "outputs": [
355+ {
356+ "name": "var",
357+ "index": 0,
358+ "dtype": "int8",
359+ "format": "ND",
360+ "paramType": "required",
361+ "shape": [-2]
362+ }
363+ ],
364+ "attrs": [
365+ {
366+ "name": "use_locking",
367+ "dtype": "bool",
368+ "value": null
369+ }
370+ ]
371+ },
372+ {
373+ "bin_filename": "ScatterNdUpdate_int16_int32",
374+ "inputs": [
375+ {
376+ "name": "var",
377+ "index": 0,
378+ "dtype": "int16",
379+ "format": "ND",
380+ "paramType": "required",
381+ "shape": [-2]
382+ },
383+ {
384+ "name": "indices",
385+ "index": 1,
386+ "dtype": "int32",
387+ "format": "ND",
388+ "paramType": "required",
389+ "shape": [-2]
390+ },
391+ {
392+ "name": "updates",
393+ "index": 2,
394+ "dtype": "int16",
395+ "format": "ND",
396+ "paramType": "required",
397+ "shape": [-2]
398+ }
399+ ],
400+ "outputs": [
401+ {
402+ "name": "var",
403+ "index": 0,
404+ "dtype": "int16",
405+ "format": "ND",
406+ "paramType": "required",
407+ "shape": [-2]
408+ }
409+ ],
410+ "attrs": [
411+ {
412+ "name": "use_locking",
413+ "dtype": "bool",
414+ "value": null
415+ }
416+ ]
417+ },
418+ {
419+ "bin_filename": "ScatterNdUpdate_int16_int64",
420+ "inputs": [
421+ {
422+ "name": "var",
423+ "index": 0,
424+ "dtype": "int16",
425+ "format": "ND",
426+ "paramType": "required",
427+ "shape": [-2]
428+ },
429+ {
430+ "name": "indices",
431+ "index": 1,
432+ "dtype": "int64",
433+ "format": "ND",
434+ "paramType": "required",
435+ "shape": [-2]
436+ },
437+ {
438+ "name": "updates",
439+ "index": 2,
440+ "dtype": "int16",
441+ "format": "ND",
442+ "paramType": "required",
443+ "shape": [-2]
444+ }
445+ ],
446+ "outputs": [
447+ {
448+ "name": "var",
449+ "index": 0,
450+ "dtype": "int16",
451+ "format": "ND",
452+ "paramType": "required",
453+ "shape": [-2]
454+ }
455+ ],
456+ "attrs": [
457+ {
458+ "name": "use_locking",
459+ "dtype": "bool",
460+ "value": null
461+ }
462+ ]
463+ },
464+ {
465+ "bin_filename": "ScatterNdUpdate_int32_int32",
466+ "inputs": [
467+ {
468+ "name": "var",
469+ "index": 0,
470+ "dtype": "int32",
471+ "format": "ND",
472+ "paramType": "required",
473+ "shape": [-2]
474+ },
475+ {
476+ "name": "indices",
477+ "index": 1,
478+ "dtype": "int32",
479+ "format": "ND",
480+ "paramType": "required",
481+ "shape": [-2]
482+ },
483+ {
484+ "name": "updates",
485+ "index": 2,
486+ "dtype": "int32",
487+ "format": "ND",
488+ "paramType": "required",
489+ "shape": [-2]
490+ }
491+ ],
492+ "outputs": [
493+ {
494+ "name": "var",
495+ "index": 0,
496+ "dtype": "int32",
497+ "format": "ND",
498+ "paramType": "required",
499+ "shape": [-2]
500+ }
501+ ],
502+ "attrs": [
503+ {
504+ "name": "use_locking",
505+ "dtype": "bool",
506+ "value": null
507+ }
508+ ]
509+ },
510+ {
511+ "bin_filename": "ScatterNdUpdate_int32_int64",
512+ "inputs": [
513+ {
514+ "name": "var",
515+ "index": 0,
516+ "dtype": "int32",
517+ "format": "ND",
518+ "paramType": "required",
519+ "shape": [-2]
520+ },
521+ {
522+ "name": "indices",
523+ "index": 1,
524+ "dtype": "int64",
525+ "format": "ND",
526+ "paramType": "required",
527+ "shape": [-2]
528+ },
529+ {
530+ "name": "updates",
531+ "index": 2,
532+ "dtype": "int32",
533+ "format": "ND",
534+ "paramType": "required",
535+ "shape": [-2]
536+ }
537+ ],
538+ "outputs": [
539+ {
540+ "name": "var",
541+ "index": 0,
542+ "dtype": "int32",
543+ "format": "ND",
544+ "paramType": "required",
545+ "shape": [-2]
546+ }
547+ ],
548+ "attrs": [
549+ {
550+ "name": "use_locking",
551+ "dtype": "bool",
552+ "value": null
553+ }
554+ ]
555+ },
556+ {
557+ "bin_filename": "ScatterNdUpdate_int64_int32",
558+ "inputs": [
559+ {
560+ "name": "var",
561+ "index": 0,
562+ "dtype": "int64",
563+ "format": "ND",
564+ "paramType": "required",
565+ "shape": [-2]
566+ },
567+ {
568+ "name": "indices",
569+ "index": 1,
570+ "dtype": "int32",
571+ "format": "ND",
572+ "paramType": "required",
573+ "shape": [-2]
574+ },
575+ {
576+ "name": "updates",
577+ "index": 2,
578+ "dtype": "int64",
579+ "format": "ND",
580+ "paramType": "required",
581+ "shape": [-2]
582+ }
583+ ],
584+ "outputs": [
585+ {
586+ "name": "var",
587+ "index": 0,
588+ "dtype": "int64",
589+ "format": "ND",
590+ "paramType": "required",
591+ "shape": [-2]
592+ }
593+ ],
594+ "attrs": [
595+ {
596+ "name": "use_locking",
597+ "dtype": "bool",
598+ "value": null
599+ }
600+ ]
601+ },
602+ {
603+ "bin_filename": "ScatterNdUpdate_int64_int64",
604+ "inputs": [
605+ {
606+ "name": "var",
607+ "index": 0,
608+ "dtype": "int64",
609+ "format": "ND",
610+ "paramType": "required",
611+ "shape": [-2]
612+ },
613+ {
614+ "name": "indices",
615+ "index": 1,
616+ "dtype": "int64",
617+ "format": "ND",
618+ "paramType": "required",
619+ "shape": [-2]
620+ },
621+ {
622+ "name": "updates",
623+ "index": 2,
624+ "dtype": "int64",
625+ "format": "ND",
626+ "paramType": "required",
627+ "shape": [-2]
628+ }
629+ ],
630+ "outputs": [
631+ {
632+ "name": "var",
633+ "index": 0,
634+ "dtype": "int64",
635+ "format": "ND",
636+ "paramType": "required",
637+ "shape": [-2]
638+ }
639+ ],
640+ "attrs": [
641+ {
642+ "name": "use_locking",
643+ "dtype": "bool",
644+ "value": null
645+ }
646+ ]
647+ },
648+ {
649+ "bin_filename": "ScatterNdUpdate_bool_int32",
650+ "inputs": [
651+ {
652+ "name": "var",
653+ "index": 0,
654+ "dtype": "bool",
655+ "format": "ND",
656+ "paramType": "required",
657+ "shape": [-2]
658+ },
659+ {
660+ "name": "indices",
661+ "index": 1,
662+ "dtype": "int32",
663+ "format": "ND",
664+ "paramType": "required",
665+ "shape": [-2]
666+ },
667+ {
668+ "name": "updates",
669+ "index": 2,
670+ "dtype": "bool",
671+ "format": "ND",
672+ "paramType": "required",
673+ "shape": [-2]
674+ }
675+ ],
676+ "outputs": [
677+ {
678+ "name": "var",
679+ "index": 0,
680+ "dtype": "bool",
681+ "format": "ND",
682+ "paramType": "required",
683+ "shape": [-2]
684+ }
685+ ],
686+ "attrs": [
687+ {
688+ "name": "use_locking",
689+ "dtype": "bool",
690+ "value": null
691+ }
692+ ]
693+ },
694+ {
695+ "bin_filename": "ScatterNdUpdate_bool_int64",
696+ "inputs": [
697+ {
698+ "name": "var",
699+ "index": 0,
700+ "dtype": "bool",
701+ "format": "ND",
702+ "paramType": "required",
703+ "shape": [-2]
704+ },
705+ {
706+ "name": "indices",
707+ "index": 1,
708+ "dtype": "int64",
709+ "format": "ND",
710+ "paramType": "required",
711+ "shape": [-2]
712+ },
713+ {
714+ "name": "updates",
715+ "index": 2,
716+ "dtype": "bool",
717+ "format": "ND",
718+ "paramType": "required",
719+ "shape": [-2]
720+ }
721+ ],
722+ "outputs": [
723+ {
724+ "name": "var",
725+ "index": 0,
726+ "dtype": "bool",
727+ "format": "ND",
728+ "paramType": "required",
729+ "shape": [-2]
730+ }
731+ ],
732+ "attrs": [
733+ {
734+ "name": "use_locking",
735+ "dtype": "bool",
736+ "value": null
737+ }
738+ ]
739+ }
740+ ]
741+}
@@ -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+[ScatterNdUpdate]
13+default=0
@@ -0,0 +1,79 @@
1+/**
2+ * Copyright (c) 2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+/*!
11+ * \file scatter_nd_update.cpp
12+ * \brief ScatterNdUpdate ophost
13+ */
14+#include "register/op_def_registry.h"
15+ 
16+namespace ops {
17+class ScatterNdUpdate : public OpDef {
18+ public:
19+ explicit ScatterNdUpdate(const char* name) : OpDef(name) {
20+ this->Input("var")
21+ .ParamType(REQUIRED)
22+ .DataType(
23+ {ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_BOOL, ge::DT_INT64, ge::DT_INT32, ge::DT_INT16, ge::DT_INT8,
24+ ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_BOOL, ge::DT_INT64, ge::DT_INT32, ge::DT_INT16, ge::DT_INT8})
25+ .Format(
26+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
27+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
28+ .UnknownShapeFormat(
29+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
30+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND});
31+ this->Input("indices")
32+ .ParamType(REQUIRED)
33+ .DataType(
34+ {ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32, ge::DT_INT32,
35+ ge::DT_INT64, ge::DT_INT64, ge::DT_INT64, ge::DT_INT64, ge::DT_INT64, ge::DT_INT64, ge::DT_INT64, ge::DT_INT64})
36+ .Format(
37+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
38+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
39+ .UnknownShapeFormat(
40+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
41+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND});
42+ this->Input("updates")
43+ .ParamType(REQUIRED)
44+ .DataType(
45+ {ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_BOOL, ge::DT_INT64, ge::DT_INT32, ge::DT_INT16, ge::DT_INT8,
46+ ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_BOOL, ge::DT_INT64, ge::DT_INT32, ge::DT_INT16, ge::DT_INT8})
47+ .Format(
48+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
49+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
50+ .UnknownShapeFormat(
51+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
52+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND});
53+ this->Output("var")
54+ .ParamType(REQUIRED)
55+ .DataType(
56+ {ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_BOOL, ge::DT_INT64, ge::DT_INT32, ge::DT_INT16, ge::DT_INT8,
57+ ge::DT_FLOAT16, ge::DT_FLOAT, ge::DT_BF16, ge::DT_BOOL, ge::DT_INT64, ge::DT_INT32, ge::DT_INT16, ge::DT_INT8})
58+ .Format(
59+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
60+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND})
61+ .UnknownShapeFormat(
62+ {ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND,
63+ ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND, ge::FORMAT_ND});
64+
65+ this->Attr("use_locking").AttrType(OPTIONAL).Bool(false);
66+ OpAICoreConfig aicore_config;
67+ aicore_config.DynamicCompileStaticFlag(true)
68+ .DynamicFormatFlag(true)
69+ .DynamicRankSupportFlag(true)
70+ .DynamicShapeSupportFlag(true)
71+ .NeedCheckSupportFlag(false)
72+ .PrecisionReduceFlag(true);
73+ this->AICore().AddConfig("ascend910b", aicore_config);
74+ this->AICore().AddConfig("ascend910_93", aicore_config);
75+ }
76+};
77+ 
78+OP_ADD(ScatterNdUpdate);
79+} // namespace ops
@@ -0,0 +1,259 @@
1+/**
2+ * Copyright (c) 2025-2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file scatter_nd_update.h
13+ * \brief Scatter Kernel (Sort)
14+ */
15+ 
16+#include "kernel_operator.h"
17+#include "kernel_tiling/kernel_tiling.h"
18+#include "scatter_nd_update_common.h"
19+ 
20+namespace ScatterNdUpdate {
21+template <typename T, bool isViewStride0 = false>
22+class ScatterNdUpdateKernel {
23+public:
24+ __aicore__ inline ScatterNdUpdateKernel() = delete;
25+ __aicore__ inline ScatterNdUpdateKernel(
26+ GM_ADDR updates, GM_ADDR output, GM_ADDR workSpace, const ScatterNdUpdateArch32TilingData& tiling, TPipe& pipe)
27+ {
28+ InitParams(tiling);
29+ InitBuffers(pipe);
30+ SetGmAddr(updates, output, workSpace, tiling);
31+ }
32+ 
33+ __aicore__ inline void InitParams(const ScatterNdUpdateArch32TilingData& tiling)
34+ {
35+ blockIdx_ = GetBlockIdx();
36+ CalcBlockDistribution(
37+ blockIdx_, tiling.scatterTiling.frontNum, tiling.scatterTiling.frontRow, tiling.scatterTiling.tailRow,
38+ computeRow_, start_);
39+ end_ = start_ + computeRow_;
40+ blockNum_ = tiling.linearIndexTiling.blockNum;
41+ blockLength_ = tiling.linearIndexTiling.blockLength;
42+ blockRemainLength_ = tiling.linearIndexTiling.blockRemainLength;
43+ coreNum_ = tiling.linearIndexTiling.coreNum;
44+ 
45+ scatterLength_ = tiling.scatterTiling.scatterLength;
46+ scatterAlignLength_ = tiling.scatterTiling.scatterAlignLength;
47+ ubLengthForUpdates_ = tiling.scatterTiling.ubLengthForUpdates;
48+ formDim_ = tiling.scatterTiling.formDim;
49+ copyRow_ = tiling.scatterTiling.copyRow;
50+ scatterTileNum_ = tiling.scatterTiling.scatterTileNum;
51+ scatterTileLength_ = tiling.scatterTiling.scatterTileLength;
52+ scatterTileTail_ = tiling.scatterTiling.scatterTileTail;
53+ scatterTileAlignLength_ = tiling.scatterTiling.scatterTileAlignLength;
54+ 
55+ varStride0Elements_ = tiling.viewTiling.varStride0Elements;
56+ firstDimStrideRows_ = tiling.viewTiling.firstDimStrideRows;
57+ }
58+ 
59+ __aicore__ inline void InitBuffers(TPipe& pipe)
60+ {
61+ pipe.InitBuffer(indiceQue_, DOUBLE_BUFFER, blockLength_ * sizeof(int));
62+ pipe.InitBuffer(posIdxQue_, DOUBLE_BUFFER, blockLength_ * sizeof(int));
63+ pipe.InitBuffer(updateQue_, DOUBLE_BUFFER, ubLengthForUpdates_ * sizeof(T));
64+ }
65+ 
66+ __aicore__ inline void SetGmAddr(
67+ GM_ADDR updates, GM_ADDR output, GM_ADDR workSpace, const ScatterNdUpdateArch32TilingData& tiling)
68+ {
69+ sortedIndicesGm_.SetGlobalBuffer((__gm__ int*)workSpace);
70+ posIndicesGm_.SetGlobalBuffer((__gm__ int*)workSpace + tiling.linearIndexTiling.sortWorkspace);
71+ updatesGm_.SetGlobalBuffer((__gm__ T*)updates);
72+ outputGm_.SetGlobalBuffer((__gm__ T*)output);
73+ }
74+ 
75+ __aicore__ inline void Process()
76+ {
77+ for (uint64_t i = 0; i < blockNum_; ++i) {
78+ CopyIndicesIn(i, false);
79+ Compute(i, false);
80+ PipeMte3ToS();
81+ }
82+ if (blockRemainLength_ != 0) {
83+ CopyIndicesIn(blockNum_, true);
84+ Compute(blockNum_, true);
85+ PipeMte3ToS();
86+ }
87+ }
88+ 
89+ __aicore__ inline void CopyIndicesIn(uint64_t process, bool isTail)
90+ {
91+ uint64_t copyNum = isTail ? blockRemainLength_ : blockLength_;
92+ LocalTensor<int> indiceLocal = indiceQue_.AllocTensor<int>();
93+ LocalTensor<int> posIdxLocal = posIdxQue_.AllocTensor<int>();
94+ uint64_t indicesOffset = isTail ? (blockNum_ * blockLength_) : (process * blockLength_);
95+ DataCopyParams indiceCopyParams{1, static_cast<uint16_t>(copyNum * sizeof(int)), 0, 0};
96+ DataCopyPadParams padParams{true, 0, 0, 0};
97+ DataCopyPad(indiceLocal, sortedIndicesGm_[indicesOffset], indiceCopyParams, padParams);
98+ DataCopyPad(posIdxLocal, posIndicesGm_[indicesOffset], indiceCopyParams, padParams);
99+ PipeMte2ToS();
100+ PipeBarrier<PIPE_V>();
101+ UpdateSearchParam(indiceLocal, isTail);
102+ indiceQue_.EnQue<int>(indiceLocal);
103+ posIdxQue_.EnQue<int>(posIdxLocal);
104+ }
105+ 
106+ __aicore__ inline void CopyUpdateIn(
107+ LocalTensor<T>& updateLocal, uint64_t gmIdx, uint64_t ubIdx, uint64_t tileIdx, uint64_t tileLength)
108+ {
109+ uint64_t gmOffset = gmIdx * scatterLength_ + tileIdx * scatterTileLength_;
110+ uint64_t ubOffset = ubIdx * scatterTileAlignLength_;
111+ DataCopyExtParams updateCopyParams{1, static_cast<uint32_t>(tileLength * sizeof(T)), 0, 0, 0};
112+ DataCopyPadExtParams<T> padParams{true, 0, 0, 0};
113+ DataCopyPad(updateLocal[ubOffset], updatesGm_[gmOffset], updateCopyParams, padParams);
114+ PipeMte2ToS();
115+ }
116+ 
117+ // 降序数组:二分查找边界
118+ __aicore__ inline int64_t findFirstLt(LocalTensor<int>& indiceLocal, int64_t target, bool isTail)
119+ {
120+ int64_t left = 0;
121+ int64_t right = (isTail ? blockRemainLength_ : blockLength_) - 1;
122+ int64_t res = isTail ? blockRemainLength_ : blockLength_;
123+ while (left <= right) {
124+ int64_t mid = left + (right - left) / 2;
125+ int64_t value = indiceLocal.GetValue(mid);
126+ if (value < target) {
127+ res = mid;
128+ right = mid - 1;
129+ } else {
130+ left = mid + 1;
131+ }
132+ }
133+ return res;
134+ }
135+ 
136+ __aicore__ inline int64_t findLastGe(LocalTensor<int>& indiceLocal, int64_t target, bool isTail)
137+ {
138+ int64_t left = 0;
139+ int64_t right = (isTail ? blockRemainLength_ : blockLength_) - 1;
140+ int64_t res = -1;
141+ while (left <= right) {
142+ int64_t mid = left + (right - left) / 2;
143+ int64_t value = indiceLocal.GetValue(mid);
144+ if (value >= target) {
145+ res = mid;
146+ left = mid + 1;
147+ } else {
148+ right = mid - 1;
149+ }
150+ }
151+ return res;
152+ }
153+ 
154+ __aicore__ inline void UpdateSearchParam(LocalTensor<int>& indiceLocal, bool isTail)
155+ {
156+ int64_t searchNum = isTail ? blockRemainLength_ : blockLength_;
157+ leftBound_ = findFirstLt(indiceLocal, end_, isTail);
158+ rightBound_ = findLastGe(indiceLocal, start_, isTail);
159+ isValidBound_ = (leftBound_ < searchNum && rightBound_ != -1 && leftBound_ <= rightBound_);
160+ }
161+ 
162+ __aicore__ inline void Compute(uint64_t process, bool isTail)
163+ {
164+ LocalTensor<int> indiceLocal = indiceQue_.DeQue<int>();
165+ LocalTensor<int> posIdxLocal = posIdxQue_.DeQue<int>();
166+ 
167+ if (!isValidBound_) {
168+ indiceQue_.FreeTensor<int>(indiceLocal);
169+ posIdxQue_.FreeTensor<int>(posIdxLocal);
170+ return;
171+ }
172+ 
173+ for (uint64_t tileIdx = 0; tileIdx < scatterTileNum_; ++tileIdx) {
174+ uint64_t tileLength = (tileIdx == scatterTileNum_ - 1) ? scatterTileTail_ : scatterTileLength_;
175+ 
176+ uint64_t inUbNum = 0;
177+ LocalTensor<T> updateLocal;
178+ 
179+ lastProcessedIdx_ = -1;
180+ 
181+ for (int64_t i = rightBound_; i >= leftBound_; --i) {
182+ if (inUbNum == 0) {
183+ updateLocal = updateQue_.AllocTensor<T>();
184+ }
185+ int64_t posIdx = posIdxLocal.GetValue(i);
186+ CopyUpdateIn(updateLocal, posIdx, inUbNum, tileIdx, tileLength);
187+ inUbNum++;
188+ 
189+ if (inUbNum == copyRow_) {
190+ updateQue_.EnQue<T>(updateLocal);
191+ CopyOut(inUbNum, i, indiceLocal, posIdxLocal, tileIdx, tileLength);
192+ inUbNum = 0;
193+ }
194+ if (i == leftBound_ && inUbNum != 0) {
195+ updateQue_.EnQue<T>(updateLocal);
196+ CopyOut(inUbNum, i, indiceLocal, posIdxLocal, tileIdx, tileLength);
197+ }
198+ }
199+ }
200+ 
201+ indiceQue_.FreeTensor<int>(indiceLocal);
202+ posIdxQue_.FreeTensor<int>(posIdxLocal);
203+ }
204+ 
205+ __aicore__ inline void CopyOut(
206+ uint64_t inUbNum, int64_t curIdx, LocalTensor<int>& indiceLocal, LocalTensor<int>& posIdxLocal,
207+ uint64_t tileIdx, uint64_t tileLength)
208+ {
209+ LocalTensor<T> updateLocal = updateQue_.DeQue<T>();
210+ DataCopyExtParams outParams{1, static_cast<uint32_t>(tileLength * sizeof(T)), 0, 0, 0};
211+ for (int64_t i = curIdx + inUbNum - 1; i >= curIdx; --i) {
212+ int64_t curIdxValue = indiceLocal.GetValue(i);
213+ if (curIdxValue == lastProcessedIdx_)
214+ continue;
215+ lastProcessedIdx_ = curIdxValue;
216+ uint64_t outOffset = ResolveOutOffset<isViewStride0>(
217+ static_cast<uint64_t>(curIdxValue), scatterLength_, firstDimStrideRows_, varStride0Elements_,
218+ tileIdx * scatterTileLength_);
219+ uint64_t updateOffset = (curIdx + inUbNum - 1 - i) * scatterTileAlignLength_;
220+ DataCopyPad(outputGm_[outOffset], updateLocal[updateOffset], outParams);
221+ }
222+ PipeMte3ToS();
223+ updateQue_.FreeTensor<T>(updateLocal);
224+ }
225+ 
226+private:
227+ GlobalTensor<int> sortedIndicesGm_;
228+ GlobalTensor<int> posIndicesGm_;
229+ GlobalTensor<T> updatesGm_;
230+ GlobalTensor<T> outputGm_;
231+ TQue<TPosition::VECIN, DOUBLE_BUFFER> indiceQue_;
232+ TQue<TPosition::VECIN, DOUBLE_BUFFER> posIdxQue_;
233+ TQue<TPosition::VECOUT, DOUBLE_BUFFER> updateQue_;
234+ 
235+ uint64_t blockIdx_;
236+ uint64_t computeRow_;
237+ uint64_t start_;
238+ uint64_t end_;
239+ uint64_t blockNum_;
240+ uint64_t blockLength_;
241+ uint64_t blockRemainLength_;
242+ uint64_t scatterLength_;
243+ uint64_t scatterAlignLength_;
244+ uint64_t ubLengthForUpdates_;
245+ uint64_t formDim_;
246+ uint64_t copyRow_;
247+ uint64_t coreNum_;
248+ uint64_t scatterTileNum_;
249+ uint64_t scatterTileLength_;
250+ uint64_t scatterTileTail_;
251+ uint64_t scatterTileAlignLength_;
252+ int64_t leftBound_;
253+ int64_t rightBound_;
254+ bool isValidBound_;
255+ int64_t lastProcessedIdx_;
256+ uint64_t varStride0Elements_;
257+ uint64_t firstDimStrideRows_;
258+};
259+} // namespace ScatterNdUpdate
@@ -0,0 +1,145 @@
1+/**
2+ * Copyright (c) 2025-2026 Huawei Technologies Co., Ltd.
3+ * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4+ * CANN Open Software License Agreement Version 2.0 (the "License").
5+ * Please refer to the License for details. You may not use this file except in compliance with the License.
6+ * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7+ * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8+ * See LICENSE in the root of the software repository for the full text of the License.
9+ */
10+ 
11+/*!
12+ * \file scatter_nd_update_common.h
13+ * \brief ScatterNdUpdate 公共定义和工具函数
14+ */
15+ 
16+#ifndef SCATTER_ND_UPDATE_COMMON_H
17+#define SCATTER_ND_UPDATE_COMMON_H
18+ 
19+#include "kernel_operator.h"
20+ 
21+namespace ScatterNdUpdate {
22+using namespace AscendC;
23+ 
24+// 公共常量定义
25+constexpr uint64_t DOUBLE_BUFFER = 1;
26+constexpr uint64_t SORT_RES_NUM = 2;
27+constexpr uint64_t SORT_TMP_NUM = 3;
28+constexpr uint64_t ALIGNED_BLOCK_NUM = 32;
29+constexpr uint64_t ALIGN_NUM = 8; // 32 字节对齐 = 8 个 int32
30+constexpr uint64_t ALIGNED_SIZE = 512;
31+ 
32+// 公共同步函数
33+__aicore__ inline void PipeMte2ToS()
34+{
35+ event_t eventID = static_cast<event_t>(GetTPipePtr()->FetchEventID(HardEvent::MTE2_S));
36+ SetFlag<HardEvent::MTE2_S>(eventID);
37+ WaitFlag<HardEvent::MTE2_S>(eventID);
38+}
39+ 
40+__aicore__ inline void PipeMte3ToS()
41+{
42+ event_t eventID = static_cast<event_t>(GetTPipePtr()->FetchEventID(HardEvent::MTE3_S));
43+ SetFlag<HardEvent::MTE3_S>(eventID);
44+ WaitFlag<HardEvent::MTE3_S>(eventID);
45+}
46+ 
47+__aicore__ inline void PipeVToMte3()
48+{
49+ event_t eventID = static_cast<event_t>(GetTPipePtr()->FetchEventID(HardEvent::V_MTE3));
50+ SetFlag<HardEvent::V_MTE3>(eventID);
51+ WaitFlag<HardEvent::V_MTE3>(eventID);
52+}
53+ 
54+__aicore__ inline void PipeVToS()
55+{
56+ event_t eventID = static_cast<event_t>(GetTPipePtr()->FetchEventID(HardEvent::V_S));
57+ SetFlag<HardEvent::V_S>(eventID);
58+ WaitFlag<HardEvent::V_S>(eventID);
59+}
60+ 
61+__aicore__ inline uint64_t ComputeViewedRowOffset(
62+ uint64_t linearIndex, uint64_t firstDimStrideRows, uint64_t varStride0Elements, uint64_t scatterLength)
63+{
64+ if (firstDimStrideRows == 0) {
65+ return linearIndex * scatterLength;
66+ }
67+ uint64_t i0 = linearIndex / firstDimStrideRows;
68+ uint64_t rest = linearIndex - i0 * firstDimStrideRows;
69+ return i0 * varStride0Elements + rest * scatterLength;
70+}
71+ 
72+// 统一处理 view-stride0 与连续两条路径的输出偏移计算。
73+template <bool isViewStride0>
74+__aicore__ inline uint64_t ResolveOutOffset(
75+ uint64_t linearIndex, uint64_t scatterLength, uint64_t firstDimStrideRows, uint64_t varStride0Elements,
76+ uint64_t tileOffsetElements)
77+{
78+ if constexpr (isViewStride0) {
79+ return ComputeViewedRowOffset(linearIndex, firstDimStrideRows, varStride0Elements, scatterLength) +
80+ tileOffsetElements;
81+ } else {
82+ return linearIndex * scatterLength + tileOffsetElements;
83+ }
84+}
85+ 
86+// 计算 block 分布参数
87+__aicore__ inline void CalcBlockDistribution(
88+ uint64_t blockIdx, uint64_t frontNum, uint64_t frontRow, uint64_t tailRow, uint64_t& computeRow, uint64_t& start)
89+{
90+ if (blockIdx >= frontNum) {
91+ computeRow = tailRow;
92+ start = frontNum * frontRow + (blockIdx - frontNum) * computeRow;
93+ } else {
94+ computeRow = frontRow;
95+ start = blockIdx * computeRow;
96+ }
97+}
98+ 
99+__aicore__ inline void ComputeLinearIndexFromIndices(
100+ LocalTensor<int>& indicesLocal, LocalTensor<int>& indicesOriginLocal, LocalTensor<int>& addTmpLocal,
101+ LocalTensor<int>& rangeLocal, const uint64_t* indicesMask, uint64_t indexDim, uint64_t rows)
102+{
103+ int32_t mulValue = static_cast<int32_t>(indexDim * sizeof(int));
104+ Duplicate<int>(indicesLocal, 0, rows);
105+ CreateVecIndex(rangeLocal, (int)0, rows);
106+ PipeBarrier<PIPE_V>();
107+ Muls(rangeLocal, rangeLocal, mulValue, rows);
108+ PipeBarrier<PIPE_V>();
109+ for (uint64_t i = 0; i < indexDim; ++i) {
110+ if (i != 0) {
111+ Adds(rangeLocal, rangeLocal, (int)(sizeof(int)), rows);
112+ PipeBarrier<PIPE_V>();
113+ }
114+ LocalTensor<uint32_t> rangeCasted = rangeLocal.ReinterpretCast<uint32_t>();
115+ Gather(addTmpLocal, indicesOriginLocal, rangeCasted, (uint32_t)0, (uint32_t)rows);
116+ PipeBarrier<PIPE_V>();
117+ Muls(addTmpLocal, addTmpLocal, (int)indicesMask[i], rows);
118+ PipeBarrier<PIPE_V>();
119+ Add(indicesLocal, indicesLocal, addTmpLocal, rows);
120+ PipeBarrier<PIPE_V>();
121+ }
122+}
123+ 
124+template <typename T, bool isViewStride0>
125+__aicore__ inline void DoScatterCopy(
126+ LocalTensor<T>& updateLocal, GlobalTensor<T>& updatesGm, GlobalTensor<T>& outputGm, uint64_t gmOffset,
127+ uint64_t tileLength, int64_t linearIndex, uint64_t tileIdx, uint64_t scatterTileLength, uint64_t firstDimStrideRows,
128+ uint64_t varStride0Elements, uint64_t scatterLength)
129+{
130+ DataCopyExtParams updateCopyParams{1, static_cast<uint32_t>(tileLength * sizeof(T)), 0, 0, 0};
131+ DataCopyPadExtParams<T> padParams{true, 0, 0, 0};
132+ DataCopyPad(updateLocal, updatesGm[gmOffset], updateCopyParams, padParams);
133+ PipeMte2ToS();
134+ 
135+ uint64_t outOffset = ResolveOutOffset<isViewStride0>(
136+ static_cast<uint64_t>(linearIndex), scatterLength, firstDimStrideRows, varStride0Elements,
137+ tileIdx * scatterTileLength);
138+ DataCopyExtParams outParams{1, static_cast<uint32_t>(tileLength * sizeof(T)), 0, 0, 0};
139+ DataCopyPad(outputGm[outOffset], updateLocal, outParams);
140+ PipeMte3ToS();
141+}
142+ 
143+} // namespace ScatterNdUpdate
144+ 
145+#endif // SCATTER_ND_UPDATE_COMMON_H
Mindex/scatter_nd_update/tests/ut/op_host/test_aclnn_inplace_put.cpp+1-1文件内容审核中,请稍后刷新重试