Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : #include "log.h"
12 : #include "ins_coll_alg_registry.h"
13 : #ifndef CCL_KERNEL_AICPU
14 : #include "ccu_temp_scatter_mesh_2D.h"
15 : #endif
16 : #include "topo_match_concurr_mesh.h"
17 : #include "ins_scatter_sole_executor.h"
18 :
19 : namespace Hccl {
20 : template <typename AlgTopoMatch, typename InsAlgTemplate>
21 0 : InsScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::InsScatterSoleExecutor() : InsCollAlgBase()
22 : {
23 0 : }
24 :
25 : template <typename AlgTopoMatch, typename InsAlgTemplate>
26 0 : InsScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::~InsScatterSoleExecutor()
27 : {
28 0 : }
29 :
30 : template <typename AlgTopoMatch, typename InsAlgTemplate>
31 0 : HcclResult InsScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::CalcResOffload(const RankGraph *rankGraph,
32 : const u64 &dataSize,
33 : CollOffloadOpResReq &resReq)
34 : {
35 : // Topo Match
36 0 : AlgTopoMatch topoMatch(myRank_, rankSize_, rankGraph, devType_);
37 0 : CHK_RET(topoMatch.MatchTopo(vTopo_, virtRanks_, virtRankMap_));
38 :
39 : // instantiate a template
40 0 : InsAlgTemplate tempAlg(myRank_, rankSize_, vTopo_, virtRankMap_);
41 : // 通过判断哪层通信域能有到所有remoteRank的path,判断当前算法跑在哪一层
42 0 : std::map<u32, u32>rank2PathNumMap;
43 0 : HCCL_INFO("[InsV2ScatterSoleExecutor] CalcRes SetPathNumMap");
44 0 : CHK_RET(SetPathNumMapByRankGraphMultiLevel(rankGraph, virtRanks_, myRank_, rank2PathNumMap));
45 0 : tempAlg.setPathNumMap(rank2PathNumMap);
46 0 : tempAlg.SetDmaMode(dmaMode_);
47 0 : tempAlg.SetRoot(root_);
48 :
49 0 : if ( tempAlg.GetExpandedMode() == DeviceMode::CCU ) {
50 0 : resReq.requiredScratchMemSize = dataSize * rankSize_;
51 0 : HCCL_DEBUG("[InsScatterSoleExecutor][CalcResOffload][CCU] reqiredScratchSize:[%llu], dataSize:[%llu], rankSize:[%llu]", resReq.requiredScratchMemSize, dataSize, rankSize_);
52 : }
53 : else {
54 : (void)dataSize;
55 0 : resReq.requiredScratchMemSize = 0;
56 : }
57 :
58 : // calculate required insQueues and prepare queue
59 0 : AlgTempResReq tempResReq;
60 0 : if (enableDetour_) {
61 0 : HCCL_DEBUG("[InsCollAlgFactory] [InsScatterSoleExecutor], CalcRes with detouring enabled.");
62 0 : CHK_RET(tempAlg.CalcResDetour(rankGraph, tempResReq));
63 : } else {
64 0 : HCCL_DEBUG("[InsCollAlgFactory] [InsScatterSoleExecutor], CalcRes with detouring disabled.");
65 0 : CHK_RET(tempAlg.CalcRes(tempResReq));
66 : }
67 :
68 0 : resReq.requiredSubQueNum = tempResReq.streamNum - 1;
69 :
70 0 : return HcclResult::HCCL_SUCCESS;
71 0 : }
72 :
73 : template <typename AlgTopoMatch, typename InsAlgTemplate>
74 0 : HcclResult InsScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::CalcRes(const RankGraph *rankGraph,
75 : CollAlgResReq &algResReq)
76 : {
77 : // Topo Match
78 0 : AlgTopoMatch topoMatch(myRank_, rankSize_, rankGraph, devType_);
79 0 : CHK_RET(topoMatch.MatchTopo(vTopo_, virtRanks_, virtRankMap_));
80 0 : algResReq.topoInfo.UpdateSingleLevelTopo(virtRanks_, virtRankMap_, vTopo_);
81 :
82 : // instantiate a template
83 0 : InsAlgTemplate tempAlg(myRank_, rankSize_, vTopo_, virtRankMap_);
84 : // 通过判断哪层通信域能有到所有remoteRank的path,判断当前算法跑在哪一层
85 0 : std::map<u32, u32>rank2PathNumMap;
86 0 : HCCL_INFO("[InsV2ScatterSoleExecutor] CalcRes SetPathNumMap");
87 0 : CHK_RET(SetPathNumMapByRankGraphMultiLevel(rankGraph, virtRanks_, myRank_, rank2PathNumMap));
88 0 : tempAlg.setPathNumMap(rank2PathNumMap);
89 0 : tempAlg.SetDmaMode(dmaMode_);
90 0 : tempAlg.SetRoot(root_);
91 :
92 : // calculate required insQues and prepare queue
93 0 : AlgTempResReq tempResReq;
94 0 : if (enableDetour_) {
95 0 : HCCL_DEBUG("[InsCollAlgFactory] [InsScatterSoleExecutor] Rank[%d], CalcRes with detouring enabled.", myRank_);
96 0 : CHK_RET(tempAlg.CalcResDetour(rankGraph, tempResReq));
97 : } else {
98 0 : HCCL_DEBUG("[InsCollAlgFactory] [InsScatterSoleExecutor] Rank[%d], CalcRes with detouring disabled.", myRank_);
99 0 : CHK_RET(tempAlg.CalcRes(tempResReq));
100 : }
101 0 : CHK_RET(CalcLinkInfo(myRank_, rankGraph, tempResReq.links, algResReq.levelRankPairs));
102 0 : algResReq.primQueueNum = tempResReq.streamNum;
103 0 : algResReq.queueNotifys = tempResReq.queNotifys;
104 0 : algResReq.localWaitGroupCntNotify = tempResReq.localWaitGroupCntNotify;
105 0 : algResReq.localBcastPostCntNotify = tempResReq.localBcastPostCntNotify;
106 0 : HCCL_DEBUG("[InsCollAlgFactory] [InsScatterSoleExecutor] Rank[%d], requiredQueNum [%u].", myRank_, algResReq.primQueueNum);
107 0 : CHK_RET(CalcResLinks(myRank_, rankGraph, linkPriority_, tempResReq.links, algResReq.links));
108 :
109 0 : return HcclResult::HCCL_SUCCESS;
110 0 : }
111 :
112 : // dataSize_ as input
113 : template <typename AlgTopoMatch, typename InsAlgTemplate>
114 0 : HcclResult InsScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::Orchestrate(const RankGraph *rankGraph,
115 : const CollAlgOperator &op,
116 : const CollAlgParams ¶ms,
117 : InsQuePtr insQue)
118 : {
119 0 : HCCL_INFO("[InsScatterSoleExecutor]ScatterSoleExecutor Orchestrate begin");
120 : // init and check params
121 0 : CHK_RET(Init(op, params, insQue));
122 :
123 : // Topo Match
124 0 : AlgTopoMatch topoMatch(myRank_, rankSize_, rankGraph, devType_);
125 0 : CHK_RET(topoMatch.MatchTopo(vTopo_, virtRanks_, virtRankMap_));
126 0 : HCCL_INFO("[InsScatterSoleExecutor] Rank[%d], [%s].", myRank_, topoMatch.Describe().c_str());
127 0 : dataType_ = op.dataType;
128 : // instantiate a template
129 0 : InsAlgTemplate tempAlg(myRank_, rankSize_, vTopo_, virtRankMap_);
130 0 : tempAlg.SetDmaMode(dmaMode_);
131 0 : tempAlg.SetCollOp(op); // ccu需要传递op信息
132 0 : tempAlg.SetRoot(root_);
133 0 : tempAlg.SetDataType(dataType_);
134 : // 通过判断哪层通信域能有到所有remoteRank的path,判断当前算法跑在哪一层
135 0 : std::map<u32, u32>rank2PathNumMap;
136 0 : HCCL_INFO("[InsV2ScatterSoleExecutor] CalcRes SetPathNumMap");
137 0 : CHK_RET(SetPathNumMapByRankGraphMultiLevel(rankGraph, virtRanks_, myRank_, rank2PathNumMap));
138 0 : tempAlg.setPathNumMap(rank2PathNumMap);
139 : // calculate required insQues and prepare queue
140 0 : AlgTempResReq tempResReq;
141 0 : if (enableDetour_) {
142 0 : tempAlg.SetDataType(dataType_);
143 0 : CHK_RET(tempAlg.CalcResDetour(rankGraph, tempResReq));
144 : } else {
145 0 : CHK_RET(tempAlg.CalcRes(tempResReq));
146 : }
147 :
148 0 : CHK_RET(InitQueue(tempResReq.queNum, requiredQue_));
149 0 : HCCL_DEBUG("[InsCollAlgFactory] [InsScatterSoleExecutor] Rank[%d], template [%s], requiredQue Num [%u].", myRank_,
150 : tempAlg.Describe().c_str(), tempResReq.queNum);
151 :
152 0 : CHK_RET(PrepResLinks(myRank_, rankGraph, linkPriority_, tempResReq.links, tempResLinks_));
153 :
154 : // 令Scatter算子的dataSize_为outputSize
155 0 : u32 dataSizePerVolume = DataTypeSizeGet(dataType_);
156 0 : dataSize_ = dataCount_ * dataSizePerVolume;
157 0 : HCCL_DEBUG("[InsScatterSoleExecutor][Orchestrate] dataSize[%llu]", dataSize_);
158 :
159 0 : if ( tempAlg.GetExpandedMode() == DeviceMode::CCU) {
160 0 : HCCL_DEBUG("[InsScatterSoleExecutor] Rank[%d], Generating Instruction Queues for CCU.", myRank_);
161 0 : CHK_RET(GenInsQues4Ccu(tempAlg));
162 0 : return HcclResult::HCCL_SUCCESS;
163 : }
164 0 : if (opMode_ == OpMode::OFFLOAD) {
165 0 : HCCL_DEBUG("[InsCollAlgFactory] [InsScatterSoleExecutor] Rank[%d], Generating Instruction Queues in OFFLOAD Mode for HOST.", myRank_);
166 0 : CHK_RET(GenInsQues4Offload(tempAlg));
167 : } else { // OPBASE
168 0 : HCCL_DEBUG("[InsCollAlgFactory] [InsScatterSoleExecutor] Rank[%d], Generating Instruction Queues in OPBASE Mode for HOST.", myRank_);
169 0 : CHK_RET(GenInsQues4Opbase(tempAlg));
170 : }
171 0 : return HcclResult::HCCL_SUCCESS;
172 0 : }
173 :
174 : // 算子执行aicpu接口
175 : template <typename AlgTopoMatch, typename InsAlgTemplate>
176 0 : HcclResult InsScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::Orchestrate(const AlgTopoInfo &topoInfo,
177 : const CollAlgOperator &op,
178 : const CollAlgParams ¶ms,
179 : ConnectedLinkMgr *linkMgr,
180 : InsQuePtr insQue)
181 : {
182 0 : HCCL_INFO("[InsCollAlgFactory] [InsScatterSoleExecutor] [InsScatterSoleExecutor] AiCpu Orchestrate begins.");
183 : // 参数校验和初始化
184 0 : CHK_RET(Init(op, params, insQue));
185 :
186 : // soleEsecutor 只支持单层拓扑, 所以只取第 0 级通信域的信息
187 0 : vTopo_ = topoInfo.vTopo[0]; // 本通信域内的通信平面
188 0 : virtRankMap_ = topoInfo.virtRankMap[0]; // 本通信域内的 rank 映射表
189 0 : virtRanks_ = topoInfo.virtRanks[0]; // 本通信域内的 rank 集合
190 0 : dataTypeSize_ = DataTypeSizeGet(dataType_);
191 0 : dataSize_ = dataCount_ * dataTypeSize_;
192 0 : dataType_ = op.dataType;
193 0 : CHK_PRT_RET(dataTypeSize_ == 0,
194 : HCCL_ERROR("Scatter_[CollAlgFactory] Rank [%d], Invalid dataTypeSize_ [%u].", myRank_, dataTypeSize_),
195 : HcclResult::HCCL_E_INTERNAL);
196 :
197 : // 实例化算法模板类
198 0 : HCCL_DEBUG("Scatter_[InsScatterSoleExecutor] Rank[%d], Init insAlgTemplate with rankSize [%u] and dmaMode [%s].",
199 : myRank_, rankSize_, dmaMode_.Describe().c_str());
200 0 : InsAlgTemplate tempAlg(myRank_, rankSize_, vTopo_, virtRankMap_);
201 0 : tempAlg.SetDataType(dataType_);
202 : // 通过判断哪层通信域能有到所有remoteRank的path,判断当前算法跑在哪一层
203 0 : std::map<u32, u32>rank2PathNumMap;
204 0 : HCCL_INFO("[InsV2ScatterSoleExecutor] CalcRes SetPathNumMap");
205 0 : CHK_RET(SetPathNumMapByLinkMgrMultiLevel(linkMgr, virtRanks_, myRank_, rank2PathNumMap));
206 0 : tempAlg.setPathNumMap(rank2PathNumMap);
207 0 : tempAlg.SetDmaMode(dmaMode_);
208 0 : tempAlg.SetCollOp(op); // ccu需要传递op信息
209 0 : tempAlg.SetRoot(root_);
210 :
211 : // 计算算法模板所需资源
212 0 : AlgTempResReq tempResReq;
213 0 : if (enableDetour_) {
214 0 : HCCL_DEBUG("[InsCollAlgFactory] [InsScatterSoleExecutor] Rank[%d], CalcRes with detouring enabled for Orchestrate.", myRank_);
215 0 : CHK_RET(tempAlg.CalcResDetour(linkMgr, tempResReq));
216 : } else {
217 0 : HCCL_DEBUG("[InsCollAlgFactory] [InsScatterSoleExecutor] Rank[%d], CalcRes with detouring disabled for Orchestrate.", myRank_);
218 0 : CHK_RET(tempAlg.CalcRes(tempResReq));
219 : }
220 :
221 : // 申请算法模板所需资源
222 0 : CHK_RET(InitQueue(tempResReq.queNum, requiredQue_));
223 0 : CHK_RET(PrepResLinks(myRank_, tempResReq.links, linkMgr, tempResLinks_));
224 :
225 : // 令Scatter算子的dataSize_为outputSize
226 0 : u32 dataSizePerVolume = DataTypeSizeGet(dataType_);
227 0 : dataSize_ = dataCount_ * dataSizePerVolume;
228 :
229 0 : if (opMode_ == OpMode::OFFLOAD) {
230 0 : HCCL_DEBUG("[InsScatterSoleExecutor] Rank[%d], Generating Instruction Queues in OFFLOAD Mode for AICPU.",
231 : myRank_);
232 0 : CHK_RET(GenInsQues4Offload(tempAlg));
233 : } else { // OPBASE
234 0 : HCCL_DEBUG("[InsScatterSoleExecutor] Rank[%d], Generating Instruction Queues in OPBASE Mode for AICPU.",
235 : myRank_);
236 0 : CHK_RET(GenInsQues4Opbase(tempAlg));
237 : }
238 :
239 0 : return HcclResult::HCCL_SUCCESS;
240 0 : }
241 :
242 : template <typename AlgTopoMatch, typename InsAlgTemplate>
243 0 : HcclResult InsScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::GenInsQues4Offload(InsAlgTemplate &tempAlg)
244 : {
245 0 : RankSliceInfo sliceInfoVec;
246 0 : AllignInfo allignInfo = {enableAllign_, allignSize_, dataType_};
247 0 : CHK_RET(tempAlg.CalcSliceInfo(allignInfo, dataSize_, sliceInfoVec));
248 0 : HCCL_DEBUG("[InsCollAlgFactory] Rank[%d], done calculating slice information.", myRank_);
249 :
250 0 : BuffInfo buffInfo;
251 0 : buffInfo.inBuffType = BufferType::INPUT;
252 0 : buffInfo.outBuffType = BufferType::OUTPUT;
253 0 : buffInfo.inBuffBaseOff = 0;
254 0 : buffInfo.outBuffBaseOff = 0;
255 0 : HCCL_DEBUG("[CollAlgFactory] AlgTemplate is [%s]", tempAlg.Describe().c_str());
256 0 : HCCL_DEBUG("[InsCollAlgFactory] Rank[%d], input buffer type [%s], output buffer type [%s], input buffer base "
257 : "offset [%u], output buffer base offset [%u].",
258 : myRank_, buffInfo.inBuffType.Describe().c_str(), buffInfo.outBuffType.Describe().c_str(),
259 : buffInfo.inBuffBaseOff, buffInfo.outBuffBaseOff);
260 :
261 0 : TempFuncs tempFuncs;
262 0 : tempFuncs.opMode = opMode_;
263 0 : tempFuncs.enableCounterNotify = IsEnableCounterNotify();
264 0 : tempFuncs.isForepart = true; // only have one Temp, soleExecutor is always true
265 0 : tempFuncs.isBottom = true; // only have one Temp, soleExecutor is always true
266 0 : HCCL_DEBUG("[CollAlgFactory] AlgTemplate is [%s]", tempAlg.Describe().c_str());
267 :
268 0 : CHK_RET(tempAlg.Run(tempFuncs, sliceInfoVec, buffInfo, tempResLinks_, requiredQue_));
269 0 : HCCL_DEBUG("[InsCollAlgFactory] Rank[%d], done generating instruction queues.", myRank_);
270 :
271 0 : return HcclResult::HCCL_SUCCESS;
272 0 : }
273 :
274 : template <typename AlgTopoMatch, typename InsAlgTemplate>
275 0 : HcclResult InsScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::GenInsQues4Opbase(InsAlgTemplate &tempAlg)
276 : {
277 0 : HCCL_DEBUG("[CollAlgFactory] AlgTemplate is [%s]", tempAlg.Describe().c_str());
278 0 : u32 dataSizePerVolume = DataTypeSizeGet(dataType_);
279 0 : CHK_PRT_RET(dataSizePerVolume == 0,
280 : HCCL_ERROR("[CollAlgFactory] Rank [%d], Invalid dataSizePerVolume [%u].", myRank_, dataSizePerVolume),
281 : HcclResult::HCCL_E_INTERNAL);
282 :
283 0 : CHK_PRT_RET(rankSize_ == 0, HCCL_ERROR("[CollAlgFactory] RankSize is zero!"), HcclResult::HCCL_E_PARA);
284 : // maxTmpMemSize_为整个Scratch的大小
285 0 : u64 scratchOutputMemSize
286 0 : = static_cast<u64>(floor(maxTmpMemSize_ / (rankSize_ * dataSizePerVolume)) * dataSizePerVolume);
287 :
288 0 : CHK_PRT_RET(scratchOutputMemSize == 0,
289 : HCCL_ERROR("[CollAlgFactory] Rank [%d], Invalid input maxTmpMemSize [%u].", myRank_, maxTmpMemSize_),
290 : HcclResult::HCCL_E_PARA);
291 :
292 : // 统一管理基地址偏移
293 0 : BuffInfo buffInfo;
294 0 : buffInfo.outBuffType = BufferType::SCRATCH;
295 0 : buffInfo.inBuffBaseOff = 0;
296 0 : buffInfo.outBuffBaseOff = 0;
297 0 : buffInfo.scratchBuffBaseOff = 0;
298 :
299 0 : TempFuncs tempFuncs;
300 0 : tempFuncs.opMode = opMode_;
301 0 : tempFuncs.enableCounterNotify = IsEnableCounterNotify();
302 0 : tempFuncs.isForepart = true; // Usr Buff to CCL Buff required
303 0 : tempFuncs.isBottom = true; // CCL Buff to Usr Buff required
304 :
305 : // 计算CCL的循环次数,dataSize_为Scatter的outputSize(小的),看CCLout与ScatterOut的倍数关系
306 0 : u64 sendRecvTimes = (dataSize_ / scratchOutputMemSize) + ((dataSize_ % scratchOutputMemSize) == 0 ? 0 : 1);
307 0 : HCCL_INFO("[insScatterSoleExecutor] Rank [%d], sendRecvTimes [%u].", myRank_, sendRecvTimes);
308 :
309 0 : for (u32 idx = 0; idx < sendRecvTimes; idx++) {
310 : // 本轮的ScratchOut的大小(小的)
311 0 : u64 currDataSize = (idx == (sendRecvTimes - 1)) ? (dataSize_ - idx * scratchOutputMemSize) : scratchOutputMemSize;
312 :
313 0 : RankSliceInfo sliceInfoVec;
314 0 : AllignInfo allignInfo = {enableAllign_, allignSize_, dataType_};
315 :
316 : //每轮cclLoop,准备好usrData的input本地拷贝到scratch的dataSlices,和scratch本地拷贝到output的dataSlices;存放在tempFunc.usrData中
317 0 : UsrData usrData;
318 0 : u64 usrInOffset = idx * scratchOutputMemSize;
319 0 : u64 usrInRankStride = dataSize_;
320 0 : for ( RankId r : virtRanks_ ) {
321 0 : u32 rankId = virtRankMap_[r];
322 0 : usrData.usrInSlices.emplace_back( DataSlice(BufferType::INPUT, usrInOffset + rankId * usrInRankStride, currDataSize) );
323 0 : usrData.scratchInSlices.emplace_back( DataSlice(BufferType::SCRATCH, rankId * currDataSize, currDataSize) );
324 : }
325 :
326 0 : usrData.scratchOutSlices.emplace_back( DataSlice(BufferType::SCRATCH, myRank_ * currDataSize, currDataSize) );
327 0 : usrData.usrOutSlices.emplace_back( DataSlice(BufferType::OUTPUT, usrInOffset, currDataSize) );
328 0 : tempFuncs.usrData = usrData;
329 :
330 : // 计算SliceInfo,nhr也按照mesh的方式,分rankSize片,每片的大小为curDataSize(按照output计算)
331 0 : CHK_RET(tempAlg.CalcSliceInfo(allignInfo, currDataSize, sliceInfoVec));
332 0 : CHK_RET(tempAlg.Run(tempFuncs, sliceInfoVec, buffInfo, tempResLinks_, requiredQue_));
333 : }
334 :
335 0 : return HcclResult::HCCL_SUCCESS;
336 0 : }
337 :
338 : template <typename AlgTopoMatch, typename InsAlgTemplate>
339 0 : HcclResult InsScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::GenInsQues4Ccu(InsAlgTemplate &tempAlg)
340 : {
341 0 : HCCL_DEBUG("[ScatterSoleExecutor][GenInsQues4Ccu] Gen InsQue start");
342 0 : u32 dataSizePerVolume = DataTypeSizeGet(dataType_);
343 0 : CHK_PRT_RET(dataSizePerVolume == 0,
344 : HCCL_ERROR("[CollAlgFactory] Rank [%d], Invalid dataSizePerVolume [%u].", myRank_, dataSizePerVolume),
345 : HcclResult::HCCL_E_INTERNAL);
346 :
347 : // maxTmpMemSize_为整个Scratch的大小,按scatter的output的计算
348 0 : u64 scratchOutputMemSize
349 0 : = static_cast<u64>(floor(maxTmpMemSize_ / (rankSize_ * dataSizePerVolume)) * dataSizePerVolume);
350 :
351 0 : CHK_PRT_RET(scratchOutputMemSize == 0,
352 : HCCL_ERROR("[CollAlgFactory] Rank [%d], Invalid input maxTmpMemSize [%u].", myRank_, maxTmpMemSize_),
353 : HcclResult::HCCL_E_PARA);
354 :
355 : // 统一管理基地址偏移
356 0 : BuffInfo buffInfo;
357 0 : buffInfo.inBuffBaseOff = 0;
358 0 : buffInfo.outBuffBaseOff = 0;
359 0 : buffInfo.scratchBuffBaseOff = 0;
360 :
361 : // CCLBuf的切分,UB的最大传输值的切分,统一在executor中处理
362 : // dataSize_为Scatter的outputSize(小的,已含DataType)
363 0 : uint64_t tempMaxSliceSize = tempAlg.GetMaxSliceSize();
364 0 : uint64_t blockSize = dataSize_ < tempMaxSliceSize ? dataSize_ : tempMaxSliceSize;
365 0 : blockSize = blockSize < scratchOutputMemSize ? blockSize : scratchOutputMemSize; // 按blockSize切分,则可以同时满足UB传输上限、CCLbuff上限
366 : // 将dataSize_按照blockSize切分
367 0 : u32 loopTimes = ( dataSize_ / blockSize ) + ((dataSize_ % blockSize) == 0 ? 0 : 1);
368 0 : HCCL_DEBUG("[ins_scatter_sole_executor][GenInsQues4Ccu] dataSize_[%llu], blockSize[%llu], loopTimes[%u], scratchOutputMemSize[%u], maxTmpMemSize[%u] ", dataSize_, blockSize, loopTimes, scratchOutputMemSize, maxTmpMemSize_);
369 0 : TempFuncs tempFuncs;
370 0 : for (uint64_t idx = 0; idx < loopTimes; idx++) {
371 0 : uint64_t sliceSize = ( (idx == loopTimes-1) ? (dataSize_ - idx * blockSize ) : blockSize);
372 0 : uint64_t offset = idx * blockSize;
373 : // tempAlg从op_中可以获取input,output,scratch的基地址, 从dataSize_获取Stride
374 : // 从buffInfo中可以获取每次的偏移
375 0 : buffInfo.inBuffBaseOff = offset;
376 0 : buffInfo.outBuffBaseOff = offset;
377 0 : RankSliceInfo sliceInfoVec;
378 0 : AllignInfo allignInfo = {enableAllign_, allignSize_, dataType_};
379 : // 从sliceInfoVec中获取sliceSize
380 0 : CHK_RET(tempAlg.CalcSliceInfo(allignInfo, sliceSize, sliceInfoVec));
381 0 : CHK_RET(tempAlg.Run(tempFuncs, sliceInfoVec, buffInfo, tempResLinks_, requiredQue_));
382 : }
383 0 : return HcclResult::HCCL_SUCCESS;
384 0 : }
385 :
386 : #ifndef CCL_KERNEL_AICPU
387 : INS_REGISTER_IMPL_BY_TEMP(OpType::SCATTER, CcuScatterMesh2D, InsScatterSoleExecutor, TopoMatchConcurrMesh,
388 : CcuTempScatterMesh2D);
389 : #endif
390 : } // namespace Hccl
|