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