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