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 "base_selector.h"
12 :
13 :
14 : #include <numeric>
15 :
16 : namespace Hccl {
17 0 : BaseSelector &BaseSelector::SetVirtualTopo(RankGraph *rankGraph)
18 : {
19 0 : rankGraph_ = rankGraph;
20 0 : return *this;
21 : }
22 :
23 0 : BaseSelector &BaseSelector::SetDevType(DevType devType)
24 : {
25 0 : devType_ = devType;
26 0 : return *this;
27 : }
28 :
29 0 : BaseSelector &BaseSelector::SetMyRank(RankId myRank)
30 : {
31 0 : myRank_ = myRank;
32 0 : return *this;
33 : }
34 :
35 0 : BaseSelector &BaseSelector::SetRankSize(u32 rankSize)
36 : {
37 0 : rankSize_ = rankSize;
38 0 : return *this;
39 : }
40 :
41 0 : BaseSelector &BaseSelector::SetSeverId(std::string severId)
42 : {
43 0 : severId_ = severId;
44 0 : return *this;
45 : }
46 :
47 0 : BaseSelector &BaseSelector::SetDeviceNumPerSever(u32 deviceNumPerSever)
48 : {
49 0 : deviceNumPerSever_ = deviceNumPerSever;
50 0 : return *this;
51 : }
52 :
53 0 : BaseSelector &BaseSelector::SetServerNum(u32 serverNum)
54 : {
55 0 : serverNum_ = serverNum;
56 0 : return *this;
57 : }
58 :
59 0 : BaseSelector &BaseSelector::SetIsMc2(bool isMc2)
60 : {
61 0 : isMc2_ = isMc2;
62 0 : return *this;
63 : }
64 :
65 0 : BaseSelector &BaseSelector::SetOpConfig(OpExecuteConfig opConfig)
66 : {
67 0 : opConfig_ = opConfig;
68 0 : return *this;
69 : }
70 :
71 0 : RankGraph *BaseSelector::GetVirtualTopo()
72 : {
73 0 : return rankGraph_;
74 : }
75 :
76 0 : DevType BaseSelector::GetDevType()
77 : {
78 0 : return devType_;
79 : }
80 :
81 0 : RankId BaseSelector::GetMyRank() const
82 : {
83 0 : return myRank_;
84 : }
85 :
86 0 : u32 BaseSelector::GetRankSize() const
87 : {
88 0 : return rankSize_;
89 : }
90 :
91 0 : std::string BaseSelector::GetSeverId()
92 : {
93 0 : return severId_;
94 : }
95 :
96 0 : u32 BaseSelector::GetDeviceNumPerSever() const
97 : {
98 0 : return deviceNumPerSever_;
99 : }
100 :
101 0 : u32 BaseSelector::GetServerNum() const
102 : {
103 0 : return serverNum_;
104 : }
105 :
106 0 : u32 BaseSelector::Gcd(u32 a, u32 b) const
107 : {
108 0 : while (b != 0) {
109 0 : a %= b;
110 0 : std::swap(a, b);
111 : }
112 0 : return a;
113 : }
114 :
115 0 : u32 BaseSelector::GcdOfArray(const std::vector<u32> &numbers) const
116 : {
117 0 : if (numbers.empty()) {
118 0 : return 0;
119 : }
120 0 : u32 result = numbers[0];
121 0 : for (size_t i = 1; i < numbers.size(); ++i) {
122 0 : result = Gcd(result, numbers[i]); // C++17 及以上推荐使用 std::gcd
123 : }
124 0 : return result;
125 : }
126 :
127 0 : u32 BaseSelector::GetLevel0Gcd() {
128 0 : std::vector<u32> instSizeList = {};
129 0 : u32 listSize = 0;
130 0 : rankGraph_->GetNetInstanceList(0, instSizeList, listSize);
131 0 : return GcdOfArray(instSizeList);
132 0 : }
133 :
134 0 : bool BaseSelector::IsAsymmetricTopoShapeLevel1Nhr(
135 : const std::vector<std::vector<u32>> &localIdPerBoard, u32 gcdRankSizeLevel0) const
136 : {
137 : // Level0的gcd为1分支
138 0 : if (gcdRankSizeLevel0 == 1) {
139 0 : return true;
140 : }
141 : // Pod形状不规则分支
142 0 : if (localIdPerBoard.size() > 1) {
143 0 : if (!IsTopoShapeLevel0Regular(localIdPerBoard)) {
144 0 : return true;
145 : }
146 : }
147 0 : return false;
148 : }
149 :
150 0 : bool BaseSelector::IsTopoShapeLevel0Regular(const std::vector<std::vector<u32>> &localIdPerBoard) const
151 : {
152 0 : u32 rankSizeOfFirstBoard = localIdPerBoard[0].size();
153 0 : u32 rankSize = 8;
154 0 : for (u32 boardIdx = 1; boardIdx < localIdPerBoard.size(); ++boardIdx) {
155 : // 条件1:与第一行rank数是否一致
156 0 : if (localIdPerBoard[boardIdx].size() != rankSizeOfFirstBoard) {
157 0 : return false;
158 : }
159 : // 条件2:同一slot内rank数差异是否能被8整除
160 0 : for (u32 slotIdx = 0; slotIdx < rankSizeOfFirstBoard; ++slotIdx) {
161 0 : if ((localIdPerBoard[boardIdx][slotIdx] - localIdPerBoard[0][slotIdx]) % rankSize != 0) {
162 0 : return false;
163 : }
164 : }
165 : }
166 0 : return true;
167 : }
168 :
169 0 : HcclResult BaseSelector::ExtractNetLayerDetails(TopoInfo &topoInfo) const
170 : {
171 0 : CHK_PRT_RET(rankGraph_ == nullptr, HCCL_ERROR("[BaseSelector][ExtractNetLayerDetails] rankGraph_ is null"), HCCL_E_PTR);
172 :
173 0 : auto &topoLevelNum = topoInfo.levelNum;
174 0 : auto &netLayerNum = topoInfo.netLayerDetails.netLayerNum;
175 0 : auto &netLayers = topoInfo.netLayerDetails.netLayers;
176 0 : auto &netInstNumOfLayer = topoInfo.netLayerDetails.netInstNumOfLayer;
177 0 : auto &instSizeListOfLayer = topoInfo.netLayerDetails.instSizeListOfLayer;
178 0 : auto &localNetInsSizeOfLayer = topoInfo.netLayerDetails.localNetInsSizeOfLayer;
179 :
180 0 : netLayers = rankGraph_->GetLevels(myRank_); // 有那几层网络 如:[0,1]
181 0 : netLayerNum = rankGraph_->GetLevelNum();
182 0 : netInstNumOfLayer.resize(netLayerNum); // 每层网络中有几个网络实例
183 0 : instSizeListOfLayer.resize(netLayerNum); // 每层网络中的各个网络实例的大小
184 0 : localNetInsSizeOfLayer.resize(netLayerNum);
185 :
186 : HcclResult ret;
187 : // 获取并校验每一层的网路实例大小
188 0 : for (auto layerIdx : netLayers) {
189 0 : std::vector<u32> &currLayerInstSizeList = instSizeListOfLayer[layerIdx];
190 0 : u32 &currLayerNetInstNum = netInstNumOfLayer[layerIdx];
191 0 : ret = rankGraph_->GetNetInstanceList(layerIdx, currLayerInstSizeList, currLayerNetInstNum);
192 0 : CHK_PRT_RET(ret != HCCL_SUCCESS,
193 : HCCL_ERROR("[BaseSelector][ExtractNetLayerDetails] GetNetInstanceList failed, netLayer[%u]", layerIdx),
194 : ret);
195 0 : for (u32 i = 0; i < currLayerInstSizeList.size(); i++) {
196 0 : HCCL_DEBUG("[BaseSelector][ExtractNetLayerDetails] netInstanceSize[%u] is [%u]", i, currLayerInstSizeList[i]);
197 : }
198 0 : u32 currLayerRankSize = std::accumulate(currLayerInstSizeList.begin(), currLayerInstSizeList.end(), 0);
199 0 : HCCL_INFO("[BaseSelector][ExtractNetLayerDetails] Net layer[%u] instNum[%u]", layerIdx, currLayerNetInstNum);
200 0 : CHK_PRT_RET(currLayerRankSize != rankSize_,
201 : HCCL_ERROR(
202 : "[BaseSelector][ExtractNetLayerDetails] NetLayer[%u], totalRankSize[%u] is not equal to comm rankSize[%u]",
203 : layerIdx,
204 : currLayerRankSize,
205 : rankSize_),
206 : HCCL_E_PARA);
207 0 : localNetInsSizeOfLayer[layerIdx] = rankGraph_->GetLocalInstSize(layerIdx);
208 : }
209 :
210 0 : topoLevelNum = 0;
211 : // 获取最小的能覆盖所有卡的 layer
212 0 : for (auto layerIdx : netLayers) {
213 0 : if (netInstNumOfLayer[layerIdx] == 1) {
214 : // 当本层只有一个网络实例时, 认为这个就是当前的 topoLevelNum
215 0 : topoLevelNum = layerIdx + 1;
216 0 : break;
217 : }
218 : }
219 :
220 0 : HCCL_INFO(
221 : "[BaseSelector][ExtractNetLayerDetails] topoLevelNum[%u], netLayerNum[%u], netLayers.size[%u]",
222 : topoLevelNum, netLayerNum, netLayers.size());
223 :
224 0 : CHK_PRT_RET(topoLevelNum == 0,
225 : HCCL_ERROR(
226 : "[BaseSelector][ExtractNetLayerDetails] topoLevelNum[%u] is invalid, netLayerNum[%u]", topoLevelNum, netLayerNum),
227 : HCCL_E_INTERNAL);
228 0 : return HCCL_SUCCESS;
229 : }
230 :
231 0 : HcclResult BaseSelector::ExtractTopoDetails(TopoInfo &topoInfo) const
232 : {
233 : HcclResult ret;
234 0 : CHK_PRT_RET(rankGraph_ == nullptr, HCCL_ERROR("[BaseSelector][ExtractTopoDetails] rankGraph_ is null"), HCCL_E_PTR);
235 0 : u32 netLayerNum = topoInfo.netLayerDetails.netLayerNum;
236 :
237 : // 初始化每一层的 TopoInstDetails
238 0 : topoInfo.topoInstDetailsOfLayer.resize(netLayerNum);
239 0 : for (u32 netLayerIdx = 0; netLayerIdx < netLayerNum; netLayerIdx++) {
240 0 : auto& currentNetLayerTopoTopoDetail = topoInfo.topoInstDetailsOfLayer[netLayerIdx];
241 0 : auto& currentLayerTopoSize = currentNetLayerTopoTopoDetail.sizeOfTopo;
242 0 : auto& currentLayerTopoType = currentNetLayerTopoTopoDetail.typeOfTopo;
243 0 : auto& currentLayerTopoRanks = currentNetLayerTopoTopoDetail.ranksInTopo;
244 0 : auto& currentLayerTopo2SizeMap = currentNetLayerTopoTopoDetail.rankNumForTopoType;
245 0 : auto& topoInstNum = currentNetLayerTopoTopoDetail.topoInstNum;
246 :
247 0 : std::vector<u32> topoInsts;
248 0 : rankGraph_->GetTopoInstsByLayer(netLayerIdx, topoInsts, topoInstNum);
249 0 : HCCL_INFO("[BaseSelector][ExtractTopoDetails] netLayerIdx[%u], topoInstNum[%u]", netLayerIdx, topoInstNum);
250 : // 初始化当前层的拓扑信息
251 0 : currentLayerTopoSize.resize(topoInstNum);
252 0 : currentLayerTopoType.resize(topoInstNum);
253 0 : currentLayerTopoRanks.resize(topoInstNum);
254 0 : currentLayerTopo2SizeMap.clear();
255 :
256 : // 填充当前层的拓扑信息
257 0 : for (u32 topoInstIdx = 0; topoInstIdx < topoInstNum; topoInstIdx++) {
258 0 : u32& topoInstId = topoInsts[topoInstIdx];
259 0 : u32& topoSize = currentLayerTopoSize[topoInstIdx];
260 0 : TopoType& topoType = currentLayerTopoType[topoInstIdx];
261 0 : std::vector<u32>& ranks= currentLayerTopoRanks[topoInstIdx];
262 :
263 : // 获取拓扑实例的类型
264 0 : ret = rankGraph_->GetTopoType(netLayerIdx, topoInstId, topoType);
265 0 : CHK_PRT_RET(ret != HCCL_SUCCESS,
266 : HCCL_ERROR("[BaseSelector][ExtractTopoDetails] GetTopoType failed, netLayerIdx[%u], topoInstId[%u]",
267 : netLayerIdx, topoInstId), ret);
268 :
269 : // 获取拓扑实例中包含的rank
270 0 : ret = rankGraph_->GetRanksByTopoInst(netLayerIdx, topoInstId, ranks, topoSize);
271 0 : CHK_PRT_RET(ret != HCCL_SUCCESS,
272 : HCCL_ERROR("[BaseSelector][ExtractTopoDetails] GetRanksByTopoInst failed, netLayerIdx[%u], topoInstId[%u]",
273 : netLayerIdx, topoInstId), ret);
274 :
275 : // 将topoInstId按照topoType进行归类
276 0 : currentLayerTopo2SizeMap[topoType].push_back(topoSize);
277 :
278 0 : HCCL_INFO("[BaseSelector][ExtractTopoDetails] netLayerIdx[%u], topoInstIdx[%u] type is[%s], topoInstId is[%u], "
279 : "topoSize is[%u]",
280 : netLayerIdx,
281 : topoInstIdx,
282 : topoType.Describe().c_str(),
283 : topoInstId,
284 : topoSize);
285 : }
286 0 : }
287 0 : return HCCL_SUCCESS;
288 : }
289 :
290 0 : HcclResult BaseSelector::CalcLevel0TopoShape(TopoInfo &topoInfo) const
291 : {
292 0 : u32 netLayer = 0;
293 0 : u32 topoInstNum2 = 2;
294 0 : u32 topoInstNum3 = 3;
295 0 : CHK_PRT_RET(topoInfo.topoInstDetailsOfLayer.size() <= netLayer,
296 : HCCL_ERROR("[BaseSelector][CalcLevel0TopoShape] topoInstNumOfLayer size[%zu] <= netLayer[%u]", topoInfo.topoInstDetailsOfLayer.size(), netLayer),
297 : HCCL_E_INTERNAL);
298 0 : TopoInstDetails &level0TopoInstDetails = topoInfo.topoInstDetailsOfLayer[netLayer];
299 0 : CHK_PRT_RET(topoInfo.netLayerDetails.localNetInsSizeOfLayer.size() <= netLayer,
300 : HCCL_ERROR("[BaseSelector][CalcLevel0TopoShape] localNetInsSizeOfLayer size[%zu] <= netLayer[%u]", topoInfo.netLayerDetails.localNetInsSizeOfLayer.size(), netLayer),
301 : HCCL_E_INTERNAL);
302 0 : u32 level0LocalRankSize = topoInfo.netLayerDetails.localNetInsSizeOfLayer[netLayer];
303 :
304 0 : auto &topoInstNum = level0TopoInstDetails.topoInstNum;
305 0 : auto &rankNumForTopoType = level0TopoInstDetails.rankNumForTopoType;
306 0 : HCCL_INFO("[%s]topoInstNum[%u]", __func__, topoInstNum);
307 0 : for (const auto &iter: rankNumForTopoType) {
308 0 : HCCL_INFO("[%s]topoType[%d] size[%lu]", __func__, iter.first, iter.second.size());
309 : }
310 :
311 0 : if (topoInstNum == 1 && rankNumForTopoType[TopoType::MESH_1D].size() == 1) {
312 : // MESH_1D 拓扑校验
313 0 : CHK_PRT_RET(rankNumForTopoType[TopoType::MESH_1D][0] != level0LocalRankSize,
314 : HCCL_ERROR("[BaseSelector][CalcLevel0TopoShape] MESH_1D rankSize[%u] is not equal to level0LocalRankSize[%u]",
315 : rankNumForTopoType[TopoType::MESH_1D][0],
316 : level0LocalRankSize),
317 : HCCL_E_INTERNAL);
318 0 : topoInfo.level0Shape = Level0Shape::MESH_1D;
319 0 : return HCCL_SUCCESS;
320 0 : } else if (topoInstNum == 1 && rankNumForTopoType[TopoType::CLOS].size() == 1) {
321 : // CLOS 拓扑校验
322 0 : CHK_PRT_RET(rankNumForTopoType[TopoType::CLOS][0] != level0LocalRankSize,
323 : HCCL_ERROR("[BaseSelector][CalcLevel0TopoShape] CLOS rankSize[%u] is not equal to level0LocalRankSize[%u]",
324 : rankNumForTopoType[TopoType::CLOS][0],
325 : level0LocalRankSize),
326 : HCCL_E_INTERNAL);
327 0 : topoInfo.level0Shape = Level0Shape::CLOS;
328 0 : if (IsLevel0PcieMix()) {
329 0 : topoInfo.level0PcieMix = true;
330 : }
331 0 : return HCCL_SUCCESS;
332 0 : } else if (topoInstNum == topoInstNum2 && rankNumForTopoType[TopoType::CLOS].size() == 1 &&
333 0 : rankNumForTopoType[TopoType::MESH_1D].size() == 1) {
334 : // MESH_1D_CLOS 拓扑校验
335 0 : CHK_PRT_RET(rankNumForTopoType[TopoType::CLOS][0] != level0LocalRankSize,
336 : HCCL_ERROR("[BaseSelector][CalcLevel0TopoShape] CLOS rankSize[%u] is not equal to level0LocalRankSize[%u]",
337 : rankNumForTopoType[TopoType::CLOS][0],
338 : level0LocalRankSize),
339 : HCCL_E_INTERNAL);
340 0 : topoInfo.level0Shape = Level0Shape::MESH_1D_CLOS;
341 :
342 0 : if (IsLevel0PcieMix()) {
343 0 : topoInfo.level0PcieMix = true;
344 : }
345 0 : if (rankNumForTopoType[TopoType::CLOS].at(0) > BIG_CLOS_RANGE) {
346 0 : topoInfo.level0BigClosRange = true;
347 : }
348 0 : return HCCL_SUCCESS;
349 0 : } else if (topoInstNum == topoInstNum3 && rankNumForTopoType[TopoType::MESH_1D].size() == topoInstNum2 &&
350 0 : rankNumForTopoType[TopoType::CLOS].size() == 1) {
351 : // MESH_2D 拓扑校验
352 0 : CHK_PRT_RET(rankNumForTopoType[TopoType::MESH_1D][0] * rankNumForTopoType[TopoType::MESH_1D][1] != level0LocalRankSize,
353 : HCCL_ERROR(
354 : "[BaseSelector][CalcLevel0TopoShape] mesh rankSize[%u] * [%u] is not equal to level0LocalRankSize[%u]",
355 : rankNumForTopoType[TopoType::MESH_1D][0],
356 : rankNumForTopoType[TopoType::MESH_1D][1],
357 : level0LocalRankSize),
358 : HCCL_E_INTERNAL);
359 0 : topoInfo.level0Shape = Level0Shape::MESH_2D;
360 0 : return HCCL_SUCCESS;
361 : }
362 0 : HCCL_ERROR("Unknown topo for level 0, topoInstNum[%u]", topoInstNum);
363 0 : return HCCL_E_INTERNAL;
364 : }
365 :
366 0 : void BaseSelector::CalcTopoShape(TopoInfo &topoInfo) const
367 : {
368 0 : CHK_PRT_THROW(ExtractNetLayerDetails(topoInfo) != HCCL_SUCCESS,
369 : HCCL_ERROR("[BaseSelector][CalcTopoShape] ExtractNetLayerDetails Failed"),
370 : InvalidParamsException, "ExtractNetLayerDetails Failed");
371 0 : HCCL_INFO("[BaseSelector][CalcTopoShape] topoInfo.levelNum is [%u]", topoInfo.levelNum);
372 :
373 0 : CHK_PRT_THROW(ExtractTopoDetails(topoInfo) != HCCL_SUCCESS,
374 : HCCL_ERROR("[BaseSelector][CalcTopoShape] ExtractTopoDetails Failed"),
375 : InvalidParamsException, "ExtractTopoDetails Failed");
376 0 : HCCL_INFO("[BaseSelector][ExtractTopoDetails] topoInstDetails size[%zu]", topoInfo.topoInstDetailsOfLayer.size());
377 :
378 0 : CHK_PRT_THROW(CalcLevel0TopoShape(topoInfo),
379 : HCCL_ERROR("[BaseSelector][CalcTopoShape] CalcLevel0TopoShape Failed"),
380 : InvalidParamsException, "CalcLevel0TopoShape Failed");
381 0 : HCCL_INFO("[BaseSelector][CalcTopoShape] topoInfo.level0Shape is [%d], level0PcieMix is [%d], level0BigClosRange is [%d]",
382 : topoInfo.level0Shape, topoInfo.level0PcieMix, topoInfo.level0BigClosRange);
383 0 : }
384 :
385 0 : bool BaseSelector::IsLayerAllConnetedWithTopo(const TopoInfo &topoInfo, const u32 netLayer, const TopoType topoType) const
386 : {
387 0 : CHK_PRT_THROW(rankGraph_ == nullptr,
388 : HCCL_ERROR("[BaseSelector][IsLayerAllConnetedWithTopo] rankGraph is nullptr"),
389 : NullPtrException, "[IsLayerAllConnetedWithTopo] rankGraph is nullptr");
390 :
391 0 : CHK_PRT_RET(topoInfo.netLayerDetails.localNetInsSizeOfLayer.size() <= netLayer,
392 : HCCL_WARNING("[BaseSelector][IsLayerAllConnetedWithTopo] localNetInsSizeOfLayer size[%zu] <= netLayer[%u]",
393 : topoInfo.netLayerDetails.localNetInsSizeOfLayer.size(), netLayer), false);
394 0 : u32 localRankSize = topoInfo.netLayerDetails.localNetInsSizeOfLayer[netLayer];
395 :
396 0 : CHK_PRT_RET(topoInfo.topoInstDetailsOfLayer.size() <= netLayer,
397 : HCCL_WARNING("[BaseSelector][IsLayerAllConnetedWithTopo] topoInstDetailsOfLayer size[%zu] <= netLayer[%u]",
398 : topoInfo.topoInstDetailsOfLayer.size(), netLayer), false);
399 :
400 0 : auto rankNumForTopoTypeItr = topoInfo.topoInstDetailsOfLayer[netLayer].rankNumForTopoType.find(topoType);
401 0 : if (rankNumForTopoTypeItr == topoInfo.topoInstDetailsOfLayer[netLayer].rankNumForTopoType.end()) {
402 0 : return false;
403 : }
404 :
405 0 : for (auto topoRankNum : rankNumForTopoTypeItr->second) {
406 0 : if (topoRankNum == localRankSize) {
407 0 : return true;
408 : }
409 : }
410 0 : return false;
411 : }
412 :
413 0 : bool BaseSelector::IsInputOutputOverlap(const std::shared_ptr<Buffer> &inputMem, const std::shared_ptr<Buffer> &outputMem) const
414 : {
415 0 : CHK_PRT_RET(inputMem == nullptr || outputMem == nullptr,
416 : HCCL_INFO("[Algo][BaseSelector][IsInputOutputOverlap] The input or output buffer is null. Not overlap."),
417 : false);
418 :
419 0 : u64 inputStart = inputMem->GetAddr();
420 0 : u64 outputStart = outputMem->GetAddr();
421 :
422 0 : CHK_PRT_RET(inputStart == 0 || outputStart == 0,
423 : HCCL_INFO("[Algo][BaseSelector][IsInputOutputOverlap] The input or output buffer addr is null. Not overlap."),
424 : false);
425 :
426 0 : u64 inputDataSize = inputMem->GetSize();
427 0 : u64 outputDataSize = outputMem->GetSize();
428 :
429 0 : CHK_PRT_RET(inputDataSize == 0 || outputDataSize == 0,
430 : // 不存在overlap情况
431 : HCCL_INFO("[Algo][BaseSelector][IsInputOutputOverlap] The input or output buffer size is 0. Not overlap."),
432 : false);
433 :
434 0 : u64 inputEnd = inputStart + inputDataSize - 1;
435 0 : u64 outputEnd = outputStart + outputDataSize - 1;
436 :
437 0 : HCCL_DEBUG("[Algo][BaseSelector][IsInputOutputOverlap] inputStart[%llu], inputEnd[%llu], outputStart[%llu], "
438 : "outputEnd[%llu].",
439 : inputStart,
440 : inputEnd,
441 : outputStart,
442 : outputEnd);
443 :
444 0 : CHK_PRT_RET(inputStart <= outputEnd && outputStart <= inputEnd,
445 : HCCL_INFO("[Algo][BaseSelector][IsInputOutputOverlap] inputStart[%llu], inputEnd[%llu], outputStart[%llu], "
446 : "outputEnd[%llu]. Overlap detected.",
447 : inputStart,
448 : inputEnd,
449 : outputStart,
450 : outputEnd),
451 : true);
452 :
453 0 : HCCL_DEBUG("[Algo][BaseSelector][IsInputOutputOverlap]No overlap between input and output memory.");
454 0 : return false;
455 : }
456 :
457 0 : bool BaseSelector::Is2DieFullMesh() const
458 : {
459 0 : u32 netLayer = 0; // 0 级拓扑
460 0 : const NetInstance *netInstance = rankGraph_->GetNetInstanceByRankId(netLayer, myRank_);
461 0 : std::set<RankId> rankSet = netInstance->GetRankIds();
462 0 : if (rankSet.size() <= 2) { // 小于2张卡的话,肯定不是2die全互连
463 0 : return false;
464 : }
465 : // 遍历所有对端,校验是否和所有卡有全连链路,并判断链路中本端端口所所对应的 CCU die 是否一致;
466 0 : u32 dieNum = 2; // 一共2个die
467 0 : std::vector<u32> dieLinkCounter(dieNum, 0);
468 0 : for (RankId rankId : rankSet) {
469 0 : if (rankId == myRank_) {
470 0 : continue;
471 : }
472 0 : std::vector<NetInstance::Path> paths = rankGraph_->GetPaths(netLayer, myRank_, rankId);
473 0 : CHK_PRT_RET(paths.size() == 0 || paths[0].links.size() == 0,
474 : HCCL_INFO("[BaseSelector][Is2DieFullMesh], Can not find path from Local[%d] to Rmt[%d], in netLayer %u. "
475 : "Topo is not mesh",
476 : myRank_,
477 : rankId,
478 : netLayer),
479 : false);
480 0 : NetInstance::Link &link = paths[0].links[0]; // 只取第一条路径的第一条link
481 0 : std::shared_ptr<NetInstance::ConnInterface> connInterface = link.GetSourceIface();
482 0 : u32 dieID = connInterface->GetLocalDieId();
483 0 : CHK_PRT_RET(dieID >= dieNum,
484 : HCCL_WARNING(
485 : "[BaseSelector][Is2DieFullMesh], Link from Local[%d] to Rmt[%d] die id[%u] is out of range[%u].",
486 : myRank_,
487 : rankId,
488 : dieID,
489 : dieNum), false);
490 0 : dieLinkCounter[dieID]++;
491 0 : HCCL_INFO("[BaseSelector][Is2DieFullMesh], Link from Local[%d] to Rmt[%d] use die[%u], current counter[%u]",
492 : myRank_, rankId, dieID, dieLinkCounter[dieID]);
493 0 : }
494 0 : for (u32 i = 0; i < dieNum; i++) {
495 0 : if (dieLinkCounter[i] == 0) {
496 0 : return false;
497 : }
498 : }
499 0 : return true;
500 0 : }
501 :
502 0 : bool BaseSelector::IsLevel0PcieMix() const
503 : {
504 0 : u32 netLayer = 0; // 0 级拓扑
505 0 : const NetInstance *netInstance = rankGraph_->GetNetInstanceByRankId(netLayer, myRank_);
506 0 : std::set<RankId> rankSet = netInstance->GetRankIds();
507 0 : for (RankId rankId : rankSet) {
508 0 : if (rankId == myRank_) {
509 0 : continue;
510 : }
511 0 : std::vector<NetInstance::Path> paths = rankGraph_->GetPaths(netLayer, myRank_, rankId);
512 0 : CHK_PRT_RET(paths.size() == 0 || paths[0].links.size() == 0,
513 : HCCL_INFO("[BaseSelector][IsLevel0PcieMix], Can not find path from Local[%d] to Rmt[%d], in netLayer %u. "
514 : "Topo is not mesh",
515 : myRank_,
516 : rankId,
517 : netLayer),
518 : false);
519 0 : NetInstance::Link &link = paths[0].links[0]; // 只取第一条路径的第一条link
520 0 : std::shared_ptr<NetInstance::ConnInterface> connInterface = link.GetSourceIface();
521 0 : std::set<LinkProtocol> linkProtocolsSet = connInterface->GetLinkProtocols();
522 : // 判断协议类型包含PCIE
523 0 : if (linkProtocolsSet.find(LinkProtocol::PCIE) != linkProtocolsSet.end()) {
524 0 : HCCL_INFO("IsLevel0PcieMix[true]");
525 0 : return true;
526 : }
527 0 : }
528 0 : HCCL_INFO("IsLevel0PcieMix[false]");
529 0 : return false;
530 0 : }
531 : } // namespace Hccl
|