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 <cmath>
12 :
13 : #include "log.h"
14 :
15 : #include "coll_alg_registry.h"
16 : #include "temp_all_gather_mesh.h"
17 : #include "topo_match_mesh.h"
18 : #include "topo_match_concurr_mesh.h"
19 : #include "temp_all_gather_concurr_mesh.h"
20 : #include "all_gather_sole_executor.h"
21 :
22 : namespace Hccl {
23 : template <typename AlgTopoMatch, typename AlgTemplate>
24 0 : AllGatherSoleExecutor<AlgTopoMatch, AlgTemplate>::AllGatherSoleExecutor() : CollAlgBase()
25 : {
26 0 : }
27 :
28 : template <typename AlgTopoMatch, typename AlgTemplate>
29 0 : AllGatherSoleExecutor<AlgTopoMatch, AlgTemplate>::~AllGatherSoleExecutor()
30 : {
31 0 : }
32 :
33 : template <typename AlgTopoMatch, typename AlgTemplate>
34 0 : HcclResult AllGatherSoleExecutor<AlgTopoMatch, AlgTemplate>::CalcResOffload(const RankGraph *rankGraph,
35 : const u64 &dataSize,
36 : CollOffloadOpResReq &resReq)
37 : {
38 : (void)dataSize;
39 0 : resReq.requiredScratchMemSize = 0;
40 :
41 : // Topo Match
42 0 : AlgTopoMatch topoMatch(myRank_, rankSize_, rankGraph, devType_);
43 0 : CHK_RET(topoMatch.MatchTopo(vTopo_, virtRanks_, virtRankMap_));
44 :
45 : // instantiate a template
46 0 : AlgTemplate tempAlg(myRank_, rankSize_, vTopo_, virtRankMap_);
47 :
48 : // calculate required primQues and prepare queue
49 0 : AlgTempResReq tempResReq;
50 0 : if (enableDetour_) {
51 0 : CHK_RET(tempAlg.CalcResDetour(rankGraph, tempResReq));
52 : } else {
53 0 : CHK_RET(tempAlg.CalcRes(tempResReq));
54 : }
55 :
56 0 : resReq.requiredSubQueNum = tempResReq.queNum - 1;
57 :
58 0 : return HcclResult::HCCL_SUCCESS;
59 0 : }
60 :
61 : // dataSize_ as input
62 : template <typename AlgTopoMatch, typename AlgTemplate>
63 0 : HcclResult AllGatherSoleExecutor<AlgTopoMatch, AlgTemplate>::GenPrimQues(const RankGraph *rankGraph,
64 : const CollAlgOperator &op,
65 : const CollAlgParams ¶ms,
66 : PrimQuePtr primQue)
67 : {
68 : // init and check params
69 0 : CHK_RET(Init(op, params, primQue));
70 :
71 : // Topo Match
72 0 : AlgTopoMatch topoMatch(myRank_, rankSize_, rankGraph, devType_);
73 0 : CHK_RET(topoMatch.MatchTopo(vTopo_, virtRanks_, virtRankMap_));
74 0 : HCCL_INFO("[CollAlgFactory] Rank[%d], [%s].", myRank_, topoMatch.Describe().c_str());
75 :
76 : // instantiate a template
77 0 : AlgTemplate tempAlg(myRank_, rankSize_, vTopo_, virtRankMap_);
78 0 : tempAlg.SetDmaMode(dmaMode_);
79 :
80 : // calculate required primQues and prepare queue
81 0 : AlgTempResReq tempResReq;
82 0 : if (enableDetour_) {
83 0 : tempAlg.SetDataType(dataType_);
84 0 : CHK_RET(tempAlg.CalcResDetour(rankGraph, tempResReq));
85 : } else {
86 0 : CHK_RET(tempAlg.CalcRes(tempResReq));
87 : }
88 :
89 0 : CHK_RET(InitQueue(tempResReq.queNum, requiredQue_));
90 0 : HCCL_INFO("[CollAlgFactory] Rank[%d], template [%s], requiredQue Num [%u].", myRank_, tempAlg.Describe().c_str(),
91 : tempResReq.queNum);
92 :
93 0 : CHK_RET(PrepResLinks(myRank_, rankGraph, linkPriority_, tempResReq.links, tempResLinks_));
94 :
95 0 : u32 dataSizePerVolume = DataTypeSizeGet(dataType_);
96 0 : dataSize_ = dataCount_ * dataSizePerVolume;
97 :
98 0 : if (opMode_ == OpMode::OFFLOAD) {
99 0 : HCCL_INFO("[CollAlgFactory] Rank[%d], Generating Primitive Queues in OFFLOAD Mode for HOST.", myRank_);
100 0 : CHK_RET(GenPrimQues4Offload(tempAlg));
101 : } else { // OPBASE
102 0 : HCCL_INFO("[CollAlgFactory] Rank[%d], Generating Primitive Queues in OPBASE Mode for HOST.", myRank_);
103 0 : CHK_RET(GenPrimQues4Opbase(dataSizePerVolume, tempAlg));
104 : }
105 :
106 0 : return HcclResult::HCCL_SUCCESS;
107 0 : }
108 :
109 : template <typename AlgTopoMatch, typename AlgTemplate>
110 0 : HcclResult AllGatherSoleExecutor<AlgTopoMatch, AlgTemplate>::CalcRes(const RankGraph *rankGraph,
111 : CollAlgResReq &algResReq)
112 : {
113 : // Topo Match
114 0 : AlgTopoMatch topoMatch(myRank_, rankSize_, rankGraph, devType_);
115 0 : CHK_RET(topoMatch.MatchTopo(vTopo_, virtRanks_, virtRankMap_));
116 0 : algResReq.topoInfo.UpdateSingleLevelTopo(virtRanks_, virtRankMap_, vTopo_);
117 :
118 : // instantiate a template
119 0 : AlgTemplate tempAlg(myRank_, rankSize_, vTopo_, virtRankMap_);
120 :
121 : // calculate required primQues and prepare queue
122 0 : AlgTempResReq tempResReq;
123 0 : if (enableDetour_) {
124 0 : CHK_RET(tempAlg.CalcResDetour(rankGraph, tempResReq));
125 : } else {
126 0 : CHK_RET(tempAlg.CalcRes(tempResReq));
127 : }
128 :
129 0 : algResReq.primQueueNum = tempResReq.queNum;
130 0 : CHK_RET(CalcResLinks(myRank_, rankGraph, linkPriority_, tempResReq.links, algResReq.links));
131 :
132 0 : return HcclResult::HCCL_SUCCESS;
133 0 : }
134 :
135 : template <typename AlgTopoMatch, typename AlgTemplate>
136 0 : HcclResult AllGatherSoleExecutor<AlgTopoMatch, AlgTemplate>::GenPrimQuesAIC(const AlgTopoInfo &topoInfo,
137 : const CollAlgOperator &op,
138 : const CollAlgParams ¶ms,
139 : ConnectedLinkMgr *linkMgr,
140 : PrimQuePtr primQue)
141 : {
142 : // init and check params
143 0 : CHK_RET(Init(op, params, primQue));
144 :
145 : // instantiate a template
146 0 : AlgTemplate tempAlg(myRank_, rankSize_, topoInfo.vTopo[0], topoInfo.virtRankMap[0]);
147 0 : tempAlg.SetDmaMode(dmaMode_);
148 0 : virtRankMap_ = topoInfo.virtRankMap[0];
149 :
150 : // calculate required primQues and prepare queue
151 0 : AlgTempResReq tempResReq;
152 0 : if (enableDetour_) {
153 0 : tempAlg.SetDataType(dataType_);
154 0 : CHK_RET(tempAlg.CalcResDetour(linkMgr, tempResReq));
155 : } else {
156 0 : CHK_RET(tempAlg.CalcRes(tempResReq));
157 : }
158 :
159 0 : CHK_RET(InitQueue(tempResReq.queNum, requiredQue_));
160 0 : HCCL_INFO("[CollAlgFactory] Rank[%d], template [%s], requiredQue Num [%u].", myRank_, tempAlg.Describe().c_str(),
161 : tempResReq.queNum);
162 :
163 0 : CHK_RET(PrepResLinks(myRank_, tempResReq.links, linkMgr, tempResLinks_));
164 :
165 0 : u32 dataSizePerVolume = DataTypeSizeGet(dataType_);
166 0 : dataSize_ = dataCount_ * dataSizePerVolume;
167 :
168 0 : if (opMode_ == OpMode::OFFLOAD) {
169 0 : HCCL_INFO("[CollAlgFactory] Rank[%d], Generating Primitive Queues in OFFLOAD Mode for AICPU.", myRank_);
170 0 : CHK_RET(GenPrimQues4Offload(tempAlg));
171 : } else { // OPBASE
172 0 : HCCL_INFO("[CollAlgFactory] Rank[%d], Generating Primitive Queues in OPBASE Mode for AICPU.", myRank_);
173 0 : CHK_RET(GenPrimQues4Opbase(dataSizePerVolume, tempAlg));
174 : }
175 :
176 0 : return HcclResult::HCCL_SUCCESS;
177 0 : }
178 :
179 : template <typename AlgTopoMatch, typename AlgTemplate>
180 0 : HcclResult AllGatherSoleExecutor<AlgTopoMatch, AlgTemplate>::GenPrimQues4Offload(AlgTemplateBase &tempAlg)
181 : {
182 0 : RankSliceInfo sliceInfoVec;
183 0 : AllignInfo allignInfo = {enableAllign_, allignSize_, dataType_};
184 0 : CHK_RET(tempAlg.CalcSliceInfo(allignInfo, dataSize_, sliceInfoVec));
185 :
186 0 : BuffInfo buffInfo;
187 0 : buffInfo.inBuffType = BufferType::INPUT;
188 0 : buffInfo.outBuffType = BufferType::OUTPUT;
189 0 : buffInfo.inBuffBaseOff = 0;
190 0 : buffInfo.outBuffBaseOff = 0;
191 :
192 0 : TempFuncs tempFuncs;
193 0 : tempFuncs.opMode = opMode_;
194 0 : tempFuncs.enableCounterNotify = IsEnableCounterNotify();
195 :
196 0 : CHK_RET(tempAlg.GenPrimQue(tempFuncs, sliceInfoVec, buffInfo, tempResLinks_, requiredQue_));
197 :
198 0 : return HcclResult::HCCL_SUCCESS;
199 0 : }
200 :
201 : template <typename AlgTopoMatch, typename AlgTemplate>
202 0 : HcclResult AllGatherSoleExecutor<AlgTopoMatch, AlgTemplate>::GenPrimQues4Opbase(const u32 dataSizePerVolume,
203 : AlgTemplateBase &tempAlg)
204 : {
205 0 : CHK_PRT_RET(dataSizePerVolume == 0,
206 : HCCL_ERROR("[CollAlgFactory] Rank [%d], Invalid dataSizePerVolume [%u].", myRank_, dataSizePerVolume),
207 : HcclResult::HCCL_E_INTERNAL);
208 :
209 0 : u32 scratchInputMemSize
210 0 : = static_cast<int>((rankSize_ % dataSizePerVolume == 0)
211 0 : ? floor(maxTmpMemSize_ / rankSize_)
212 0 : : floor(maxTmpMemSize_ / (rankSize_ * dataSizePerVolume)) * dataSizePerVolume);
213 :
214 0 : CHK_PRT_RET(scratchInputMemSize == 0,
215 : HCCL_ERROR("[CollAlgFactory] Rank [%d], Invalid input maxTmpMemSize [%u].", myRank_, maxTmpMemSize_),
216 : HcclResult::HCCL_E_PARA);
217 :
218 0 : BuffInfo buffInfo;
219 0 : buffInfo.inBuffType = BufferType::SCRATCH;
220 0 : buffInfo.outBuffType = BufferType::SCRATCH;
221 0 : buffInfo.inBuffBaseOff = 0;
222 0 : buffInfo.outBuffBaseOff = 0;
223 :
224 0 : u32 sendRecvTimes = (dataSize_ / scratchInputMemSize) + ((dataSize_ % scratchInputMemSize) == 0 ? 0 : 1);
225 0 : HCCL_INFO("[CollAlgFactory] Rank [%d], sendRecvTimes [%u].", myRank_, sendRecvTimes);
226 :
227 0 : for (u32 idx = 0; idx < sendRecvTimes; idx++) {
228 0 : u64 currDataSize = (idx == (sendRecvTimes - 1)) ? (dataSize_ - idx * scratchInputMemSize) : scratchInputMemSize;
229 :
230 0 : RankSliceInfo sliceInfoVec;
231 0 : AllignInfo allignInfo = {enableAllign_, allignSize_, dataType_};
232 0 : CHK_RET(tempAlg.CalcSliceInfo(allignInfo, currDataSize, sliceInfoVec));
233 :
234 0 : TempFuncs tempFuncs;
235 0 : tempFuncs.opMode = opMode_;
236 0 : tempFuncs.enableCounterNotify = IsEnableCounterNotify();
237 0 : tempFuncs.isForepart = true; // Usr Buff to CCL Buff required
238 0 : tempFuncs.isBottom = true; // CCL Buff to Usr Buff required
239 :
240 0 : UsrData usrData;
241 0 : DataSlice usrInSlice = DataSlice(BufferType::INPUT, idx * scratchInputMemSize, currDataSize);
242 0 : DataSlice scratchInSlice = DataSlice(BufferType::SCRATCH, virtRankMap_[myRank_] * currDataSize, currDataSize);
243 0 : usrData.usrInSlices.push_back(usrInSlice);
244 0 : usrData.scratchInSlices.push_back(scratchInSlice);
245 :
246 0 : for (u32 rankIdx = 0; rankIdx < rankSize_; rankIdx++) {
247 0 : DataSlice scratchOutSlice
248 0 : = DataSlice(BufferType::SCRATCH, virtRankMap_[rankIdx] * currDataSize, currDataSize);
249 0 : DataSlice usrOutSlice = DataSlice(
250 0 : BufferType::OUTPUT, virtRankMap_[rankIdx] * dataSize_ + idx * scratchInputMemSize, currDataSize);
251 0 : usrData.scratchOutSlices.push_back(scratchOutSlice);
252 0 : usrData.usrOutSlices.push_back(usrOutSlice);
253 : }
254 :
255 0 : tempFuncs.usrData = usrData;
256 0 : CHK_RET(tempAlg.GenPrimQue(tempFuncs, sliceInfoVec, buffInfo, tempResLinks_, requiredQue_));
257 : }
258 :
259 0 : return HcclResult::HCCL_SUCCESS;
260 : }
261 :
262 : REGISTER_IMPL_BY_TEMP(OpType::ALLGATHER, AllGatherMesh, AllGatherSoleExecutor, TopoMatchMesh, TempAllGatherMesh);
263 : REGISTER_IMPL_BY_TEMP(OpType::ALLGATHER, AllGatherConcurrMesh, AllGatherSoleExecutor, TopoMatchConcurrMesh,
264 : TempAllGatherConcurrMesh);
265 : } // namespace Hccl
|