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