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 "ins_v2_scatter_sole_executor.h"
12 : #include "ins_temp_scatter_mesh_2d.h"
13 : #include "topo_match_concurr_mesh.h"
14 : #include "topo_match_nhr.h"
15 : #include "log.h"
16 : #include "ins_coll_alg_registry.h"
17 : #include "topo_match_mesh.h"
18 : #include "ins_temp_scatter_mesh_1d.h"
19 : #include "ins_temp_scatter_nhr.h"
20 : #ifndef CCL_KERNEL_AICPU
21 : #include "aiv_temp_scatter_mesh_1D.h"
22 : #include "ccu_temp_scatter_nhr_1D_mem2mem.h"
23 : #include "ccu_temp_scatter_mesh_1D.h"
24 : #endif
25 :
26 : namespace Hccl {
27 : constexpr u64 MAX_OFFLOAD_SCRATCH_SIZE = 200 * 1024 * 1024; // 200M
28 :
29 : template <typename AlgTopoMatch, typename InsAlgTemplate>
30 0 : InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::InsV2ScatterSoleExecutor() : InsCollAlgBase()
31 0 : {}
32 :
33 : template <typename AlgTopoMatch, typename InsAlgTemplate>
34 0 : InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::~InsV2ScatterSoleExecutor()
35 0 : {}
36 :
37 : template <typename AlgTopoMatch, typename InsAlgTemplate>
38 0 : HcclResult InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::InitCommInfo(const RankGraph* rankGraph)
39 : {
40 0 : AlgTopoMatch topoMatch(myRank_, rankSize_, rankGraph, devType_);
41 0 : CHK_RET(topoMatch.MatchTopo(vTopo_, virtRanks_, virtRankMap_));
42 0 : return HcclResult::HCCL_SUCCESS;
43 0 : }
44 :
45 : template <typename AlgTopoMatch, typename InsAlgTemplate>
46 0 : HcclResult InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::InitCommInfo(const AlgTopoInfo& topoInfo)
47 : {
48 0 : if (topoInfo.vTopo.empty()) {
49 0 : HCCL_ERROR("[InsV2ScatterSoleExecutor][InitCommInfo] vTopo is empty.");
50 0 : return HcclResult::HCCL_E_PARA;
51 : }
52 0 : vTopo_ = topoInfo.vTopo[0]; // 本通信域内的通信平面
53 :
54 0 : if (topoInfo.virtRankMap.empty()) {
55 0 : HCCL_ERROR("[InsV2ScatterSoleExecutor][InitCommInfo] virtRankMap is empty.");
56 0 : return HcclResult::HCCL_E_PARA;
57 : }
58 0 : virtRankMap_ = topoInfo.virtRankMap[0]; // 本通信域内的 rank 映射表
59 :
60 0 : if (topoInfo.virtRanks.empty()) {
61 0 : HCCL_ERROR("[InsV2ScatterSoleExecutor][InitCommInfo] virtRanks is empty.");
62 0 : return HcclResult::HCCL_E_PARA;
63 : }
64 0 : virtRanks_ = topoInfo.virtRanks[0]; // 本通信域内的 rank 集合
65 :
66 0 : return HcclResult::HCCL_SUCCESS;
67 : }
68 :
69 : template <typename AlgTopoMatch, typename InsAlgTemplate>
70 : HcclResult
71 0 : InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::CreateTemplates(std::shared_ptr<InsAlgTemplate>& algTemplatePtr)
72 : {
73 0 : HCCL_DEBUG("[InsV2ScatterSoleExecutor][CreateTemplates]");
74 0 : algTemplatePtr = std::make_shared<InsAlgTemplate>(myRank_, rankSize_, vTopo_, virtRankMap_);
75 0 : CHK_PTR_NULL(algTemplatePtr); // 检查是否成功分配内存
76 0 : algTemplatePtr->SetDmaMode(dmaMode_);
77 0 : algTemplatePtr->SetDataType(dataType_);
78 0 : algTemplatePtr->SetCollOp(op_);
79 0 : algTemplatePtr->SetRoot(op_.root);
80 0 : return HcclResult::HCCL_SUCCESS;
81 : }
82 :
83 : template <typename AlgTopoMatch, typename InsAlgTemplate>
84 0 : HcclResult InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::GetTemplateResRequest(
85 : const RankGraph* rankGraph, std::shared_ptr<InsAlgTemplate>& algTemplate, AlgTempResReq& tempResReq) const
86 : {
87 0 : if (enableDetour_) {
88 0 : HCCL_DEBUG(
89 : "[InsV2ScatterSoleExecutor][GetTemplateResRequest] [%s] Rank[%d], CalcRes with detouring enabled.",
90 : __func__, myRank_);
91 0 : CHK_RET(algTemplate->CalcResDetour(rankGraph, tempResReq));
92 : } else {
93 0 : HCCL_DEBUG(
94 : "[InsV2ScatterSoleExecutor][GetTemplateResRequest] [%s] Rank[%d], CalcRes with detouring disabled.",
95 : __func__, myRank_);
96 0 : CHK_RET(algTemplate->CalcRes(tempResReq));
97 : }
98 0 : return HcclResult::HCCL_SUCCESS;
99 : }
100 :
101 : template <typename AlgTopoMatch, typename InsAlgTemplate>
102 0 : HcclResult InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::GetTemplateResRequest(
103 : ConnectedLinkMgr* linkMgr, std::shared_ptr<InsAlgTemplate>& algTemplate, AlgTempResReq& tempResReq) const
104 : {
105 0 : if (enableDetour_) {
106 0 : HCCL_DEBUG("[InsV2ScatterSoleExecutor] [%s] Rank[%d]. CalcRes with detouring enabled.", __func__, myRank_);
107 0 : CHK_RET(algTemplate->CalcResDetour(linkMgr, tempResReq));
108 : } else {
109 0 : HCCL_DEBUG("[InsV2ScatterSoleExecutor] [%s] Rank[%d]. CalcRes with detouring disabled.", __func__, myRank_);
110 0 : CHK_RET(algTemplate->CalcRes(tempResReq));
111 : }
112 0 : return HcclResult::HCCL_SUCCESS;
113 : }
114 :
115 : // HOST 侧算法入口
116 : template <typename AlgTopoMatch, typename InsAlgTemplate>
117 0 : HcclResult InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::Orchestrate(
118 : const RankGraph* rankGraph, const CollAlgOperator& op, const CollAlgParams& params, InsQuePtr insQue)
119 : {
120 0 : HCCL_DEBUG("[InsV2ScatterSoleExecutor][Orchestrate] Orchestrate HOST Start");
121 0 : CHK_RET(Init(op, params, insQue));
122 0 : CHK_RET(InitCommInfo(rankGraph));
123 0 : dataType_ = op.dataType;
124 0 : std::shared_ptr<InsAlgTemplate> algTemplate = nullptr;
125 0 : CHK_RET(CreateTemplates(algTemplate));
126 0 : algTemplate->SetDataType(dataType_);
127 0 : std::map<u32, u32> rank2PathNumMap;
128 0 : CHK_RET(SetPathNumMapByRankGraphMultiLevel(rankGraph, virtRanks_, myRank_, rank2PathNumMap));
129 0 : algTemplate->setPathNumMap(rank2PathNumMap);
130 0 : AlgTempResReq tempResReq;
131 0 : CHK_RET(GetTemplateResRequest(rankGraph, algTemplate, tempResReq));
132 :
133 0 : HCCL_DEBUG(
134 : "[InsV2ScatterSoleExecutor][Orchestrate] Rank[%d], template [%s], requiredQue Num [%u].", myRank_,
135 : algTemplate->Describe().c_str(), tempResReq.queNum);
136 0 : CHK_RET(InitQueue(tempResReq.queNum, tempInsQue_));
137 0 : CHK_RET(PrepResLinks(myRank_, rankGraph, linkPriority_, tempResReq.links, tempResLinks_));
138 0 : CHK_RET(OrchestrateLoop(algTemplate));
139 0 : return HcclResult::HCCL_SUCCESS;
140 0 : }
141 :
142 : // AICPU 侧算法入口
143 : template <typename AlgTopoMatch, typename InsAlgTemplate>
144 0 : HcclResult InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::Orchestrate(
145 : const AlgTopoInfo& topoInfo, const CollAlgOperator& op, const CollAlgParams& params, ConnectedLinkMgr* linkMgr,
146 : InsQuePtr insQue)
147 : {
148 0 : HCCL_DEBUG("[InsV2ScatterSoleExecutor][Orchestrate] Orchestrate AICPU Start");
149 0 : CHK_RET(Init(op, params, insQue));
150 0 : CHK_RET(InitCommInfo(topoInfo));
151 0 : dataType_ = op.dataType;
152 0 : std::shared_ptr<InsAlgTemplate> algTemplate = nullptr;
153 0 : CHK_RET(CreateTemplates(algTemplate));
154 0 : algTemplate->SetDataType(dataType_);
155 0 : std::map<u32, u32> rank2PathNumMap;
156 0 : CHK_RET(SetPathNumMapByLinkMgrMultiLevel(linkMgr, virtRanks_, myRank_, rank2PathNumMap));
157 0 : algTemplate->setPathNumMap(rank2PathNumMap);
158 0 : AlgTempResReq tempResReq;
159 0 : CHK_RET(GetTemplateResRequest(linkMgr, algTemplate, tempResReq));
160 :
161 0 : HCCL_DEBUG(
162 : "[InsV2ScatterSoleExecutor][Orchestrate] Rank[%d], template [%s], requiredQue Num [%u].", myRank_,
163 : algTemplate->Describe().c_str(), tempResReq.queNum);
164 0 : CHK_RET(InitQueue(tempResReq.queNum, tempInsQue_));
165 0 : CHK_RET(PrepResLinks(myRank_, tempResReq.links, linkMgr, tempResLinks_));
166 0 : CHK_RET(OrchestrateLoop(algTemplate));
167 0 : return HcclResult::HCCL_SUCCESS;
168 0 : }
169 :
170 : // 切分数据并调用 template
171 : template <typename AlgTopoMatch, typename InsAlgTemplate>
172 : HcclResult
173 0 : InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::OrchestrateLoop(std::shared_ptr<InsAlgTemplate> algTemplate)
174 : {
175 0 : HCCL_INFO("[InsV2ScatterSoleExecutor][OrchestrateOpbase] Start, template[%s]", algTemplate->Describe().c_str());
176 0 : u32 dataSizePerVolume = DataTypeSizeGet(dataType_);
177 0 : dataSize_ = dataCount_ * dataSizePerVolume;
178 0 : TemplateDataParams tempAlgParams;
179 0 : tempAlgParams.buffInfo.outBuffType = BufferType::OUTPUT;
180 0 : tempAlgParams.buffInfo.scratBuffType = BufferType::SCRATCH;
181 0 : tempAlgParams.buffInfo.inBuffType = BufferType::INPUT;
182 0 : tempAlgParams.repeatNum = 1; // 不需要重复
183 0 : tempAlgParams.inputRepeatStride = 0;
184 0 : tempAlgParams.outputRepeatStride = 0;
185 0 : tempAlgParams.buffInfo.scratchBuffBaseOff = 0;
186 0 : tempAlgParams.inputSliceStride = dataSize_; // 输入数据仅有 1 个 slice, 不需要 stride
187 0 : tempAlgParams.outputSliceStride = 0; // 每张卡的数据间隔为算子输入大小
188 :
189 0 : TempFuncs tempFuncs;
190 0 : tempFuncs.isBottom = true;
191 0 : tempFuncs.opMode = opMode_;
192 0 : tempFuncs.enableCounterNotify = IsEnableCounterNotify();
193 0 : tempFuncs.isForepart = true;
194 :
195 0 : u64 maxDataSizePerLoop = 0;
196 0 : u64 transportBoundDataSize = UB_MAX_DATA_SIZE; // algTemplate->CalcLoopMaxCount();
197 0 : u32 templateScratchMultiplier = algTemplate->CalcScratchMultiple(BufferType::INPUT, BufferType::OUTPUT);
198 0 : if (templateScratchMultiplier != 0) {
199 0 : u64 scratchBoundDataSize = maxTmpMemSize_ / templateScratchMultiplier;
200 0 : maxDataSizePerLoop = std::min(transportBoundDataSize, scratchBoundDataSize);
201 : } else {
202 0 : maxDataSizePerLoop = transportBoundDataSize;
203 : }
204 0 : u64 maxDataCountPerLoop = maxDataSizePerLoop / dataTypeSize_;
205 0 : HCCL_INFO(
206 : "[InsV2ScatterSoleExecutor][Orchestrate] maxDataCountPerLoop[%llu], maxDataSizePerLoop[%llu], "
207 : "transportBoundDataSize[%llu], templateScratchMultiplier[%llu]",
208 : maxDataCountPerLoop, maxDataSizePerLoop, transportBoundDataSize, templateScratchMultiplier);
209 0 : CHK_PRT_RET(
210 : maxDataCountPerLoop == 0, HCCL_ERROR("[InsV2ScatterSoleExecutor][Orchestrate] maxDataCountPerLoop is 0"),
211 : HCCL_E_INTERNAL);
212 :
213 0 : u64 processedDataCount = 0;
214 0 : u64 loopTimes = dataCount_ / maxDataCountPerLoop + static_cast<u64>(dataCount_ % maxDataCountPerLoop != 0);
215 0 : for (u64 loop = 0; loop < loopTimes; loop++) {
216 0 : u64 currDataCount = (loop == loopTimes - 1) ? dataCount_ - processedDataCount : maxDataCountPerLoop;
217 0 : tempAlgParams.buffInfo.inBuffBaseOff = processedDataCount * dataTypeSize_;
218 0 : tempAlgParams.buffInfo.outBuffBaseOff = processedDataCount * dataTypeSize_;
219 0 : tempAlgParams.sliceSize = currDataCount * dataTypeSize_;
220 0 : tempAlgParams.tailSize = tempAlgParams.sliceSize;
221 :
222 0 : CHK_RET(algTemplate->GenExtIns(tempFuncs, tempAlgParams, tempResLinks_, tempInsQue_));
223 0 : processedDataCount += currDataCount;
224 : }
225 :
226 0 : return HcclResult::HCCL_SUCCESS;
227 0 : }
228 :
229 : template <typename AlgTopoMatch, typename InsAlgTemplate>
230 : HcclResult
231 0 : InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::CalcRes(const RankGraph* rankGraph, CollAlgResReq& algResReq)
232 : {
233 : // Topo Match
234 0 : CHK_RET(InitCommInfo(rankGraph));
235 :
236 : // instantiate a template
237 0 : InsAlgTemplate tempAlg(myRank_, rankSize_, vTopo_, virtRankMap_);
238 :
239 0 : std::shared_ptr<InsAlgTemplate> algTemplate = nullptr;
240 0 : CHK_RET(CreateTemplates(algTemplate));
241 : // 通过判断哪层通信域能有到所有remoteRank的path,判断当前算法跑在哪一层
242 0 : std::map<u32, u32> rank2PathNumMap;
243 0 : HCCL_INFO("[InsV2ScatterSoleExecutor] CalcRes SetPathNumMap");
244 0 : CHK_RET(SetPathNumMapByRankGraphMultiLevel(rankGraph, virtRanks_, myRank_, rank2PathNumMap));
245 0 : algTemplate->setPathNumMap(rank2PathNumMap);
246 0 : AlgTempResReq tempResReq;
247 0 : CHK_RET(GetTemplateResRequest(rankGraph, algTemplate, tempResReq));
248 :
249 0 : CHK_RET(CalcLinkInfo(myRank_, rankGraph, tempResReq.links, algResReq.levelRankPairs));
250 0 : algResReq.topoInfo.UpdateSingleLevelTopo(virtRanks_, virtRankMap_, vTopo_);
251 0 : algResReq.primQueueNum = tempResReq.streamNum;
252 0 : algResReq.queueNotifys = tempResReq.queNotifys;
253 0 : algResReq.localWaitGroupCntNotify = tempResReq.localWaitGroupCntNotify;
254 0 : algResReq.localBcastPostCntNotify = tempResReq.localBcastPostCntNotify;
255 0 : HCCL_DEBUG("[%s] Rank[%d], requiredQueNum [%u].", __func__, myRank_, algResReq.primQueueNum);
256 0 : CHK_RET(CalcResLinks(myRank_, rankGraph, linkPriority_, tempResReq.links, algResReq.links));
257 :
258 0 : return HcclResult::HCCL_SUCCESS;
259 0 : }
260 :
261 : template <typename AlgTopoMatch, typename InsAlgTemplate>
262 0 : HcclResult InsV2ScatterSoleExecutor<AlgTopoMatch, InsAlgTemplate>::CalcResOffload(
263 : const RankGraph* rankGraph, const u64& dataSize, CollOffloadOpResReq& resReq)
264 : {
265 : (void)dataSize;
266 : (void)rankGraph;
267 : (void)resReq;
268 0 : HCCL_ERROR("[Scatter][CalcResOffload] Scatter is not supported in offload mode!");
269 :
270 0 : return HcclResult::HCCL_E_NOT_SUPPORT;
271 : }
272 :
273 : INS_REGISTER_IMPL_BY_TEMP(
274 : OpType::SCATTER, InsScatterMesh2D, InsV2ScatterSoleExecutor, TopoMatchConcurrMesh, InsTempScatterMesh2D);
275 : INS_REGISTER_IMPL_BY_TEMP(OpType::SCATTER, InsScatterNHR, InsV2ScatterSoleExecutor, TopoMatchNHR, InsTempScatterNHR);
276 : INS_REGISTER_IMPL_BY_TEMP(
277 : OpType::SCATTER, InsScatterMesh1D, InsV2ScatterSoleExecutor, TopoMatchMesh, InsTempScatterMesh1D);
278 : #ifndef CCL_KERNEL_AICPU
279 : INS_REGISTER_IMPL_BY_TEMP(
280 : OpType::SCATTER, CcuScatterNHRMem2Mem1D, InsV2ScatterSoleExecutor, TopoMatchMesh, CcuTempScatterNHRMem2Mem1D);
281 : INS_REGISTER_IMPL_BY_TEMP(
282 : OpType::SCATTER, CcuScatterMesh1D, InsV2ScatterSoleExecutor, TopoMatchMesh, CcuTempScatterMesh1D);
283 : INS_REGISTER_IMPL_BY_TEMP(
284 : OpType::SCATTER, AivScatterMesh1D, InsV2ScatterSoleExecutor, TopoMatchMesh, AivTempScatterMesh1D);
285 : #endif
286 : } // namespace Hccl
|