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 <algorithm>
12 : #include <array>
13 : #include <iterator>
14 : #include <set>
15 : #include "rank_graph_builder.h"
16 : #include "detour_service.h"
17 : #include "hccp_ctx.h"
18 : #include "json_parser.h"
19 : #include "phy_topo_builder.h"
20 : #include "rdma_handle_manager.h"
21 :
22 : namespace hcomm {
23 : HcclResult HccpRaGetDevBaseAttr(void* ctxHandle, struct DevBaseAttr* attr);
24 : }
25 :
26 : namespace Hccl {
27 :
28 : using namespace std;
29 :
30 : constexpr u32 PEER2NET_LINK_HOP = 2;
31 :
32 15 : unique_ptr<RankGraph> RankGraphBuilder::Build(const string& ranktableM, const string& topoPath, RankId myRank)
33 : {
34 15 : PhyTopoBuilder::GetInstance().Build(topoPath);
35 15 : topoInfo_ = PhyTopoBuilder::GetInstance().GetTopoInfo();
36 :
37 : JsonParser rankTableParser;
38 15 : RankTableInfo rankTableInfo;
39 15 : rankTableParser.ParseString(ranktableM, rankTableInfo);
40 15 : rankTable_ = make_unique<RankTableInfo>(rankTableInfo);
41 :
42 15 : this->myRank_ = myRank;
43 15 : BuildRankGraph();
44 :
45 45 : HCCL_INFO("[RankGraphBuilder] Build VirtualTopo success!");
46 15 : rankGraph_->Dump();
47 30 : return std::move(rankGraph_);
48 15 : }
49 :
50 1 : unique_ptr<RankGraph> RankGraphBuilder::Build(const RankTableInfo& ranktable, const string& topoPath, RankId myRank)
51 : {
52 1 : PhyTopoBuilder::GetInstance().Build(topoPath);
53 1 : topoInfo_ = PhyTopoBuilder::GetInstance().GetTopoInfo();
54 1 : rankTable_ = make_unique<RankTableInfo>(ranktable);
55 :
56 1 : myRank_ = myRank;
57 1 : BuildRankGraph();
58 :
59 1 : HCCL_INFO("[RankGraphBuilder] Build VirtualTopo success!");
60 1 : rankGraph_->Dump();
61 1 : return std::move(rankGraph_);
62 : }
63 :
64 236 : const RankLevelInfo& RankGraphBuilder::GetRankLevelInfoByNetLayer(const NewRankInfo& rankInfo, u32 netLayer) const
65 : {
66 236 : auto it = std::find_if(
67 368 : rankInfo.rankLevelInfos.begin(), rankInfo.rankLevelInfos.end(), [netLayer](const RankLevelInfo& levelInfo) {
68 368 : return levelInfo.netLayer == netLayer;
69 : });
70 236 : if (it == rankInfo.rankLevelInfos.end()) {
71 0 : THROW<InvalidParamsException>(StringFormat(
72 : "[RankGraphBuilder][GetRankLevelInfoByNetLayer] rankId[%u] netLayer[%u] does not exist in ranktable.",
73 0 : rankInfo.rankId, netLayer));
74 : }
75 472 : return *it;
76 : }
77 :
78 82 : u32 RankGraphBuilder::GetLocalDeviceId() const
79 : {
80 82 : if (rankGraph_ == nullptr) {
81 0 : THROW<NullPtrException>(StringFormat("[RankGraphBuilder][GetLocalDeviceId] rankGraph is nullptr"));
82 : }
83 82 : auto peer = rankGraph_->GetPeer(myRank_);
84 82 : if (peer == nullptr) {
85 0 : THROW<NullPtrException>(StringFormat("[RankGraphBuilder][GetLocalDeviceId] local peer is nullptr"));
86 : }
87 164 : return peer->GetDeviceId();
88 82 : }
89 :
90 32 : std::vector<shared_ptr<PhyTopo::Link>> GetPeer2NetPhyLinks(LocalId localId)
91 : {
92 32 : const shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyGraph = PhyTopo::GetInstance()->GetTopoGraph();
93 32 : if (phyGraph == nullptr) {
94 0 : THROW<InvalidParamsException>(
95 0 : StringFormat("[RankGraphBuilder][GetPhyLink] physical topo graph is null for localId[%d].", localId));
96 : }
97 32 : std::vector<shared_ptr<PhyTopo::Link>> links;
98 : // 统一物理图包含多种边,此处仅收集 PEER2NET 边。
99 32 : phyGraph->TraverseEdge(PhyTopo::Peer::GetId(localId), [&](shared_ptr<PhyTopo::Link> link) {
100 141 : if (link != nullptr && link->GetType() == LinkType::PEER2NET) {
101 65 : links.push_back(link);
102 : }
103 141 : });
104 :
105 32 : if (links.empty()) {
106 0 : THROW<InvalidParamsException>(
107 0 : StringFormat("[RankGraphBuilder][GetPhyLink] SourceNode localId[%d] edge does not exist.", localId));
108 : }
109 32 : return links;
110 32 : }
111 :
112 142 : bool IsPeer2NetLinkMatched(const shared_ptr<PhyTopo::Link>& link, const AddressInfo& addrInfo)
113 : {
114 142 : if (link == nullptr || link->GetType() != LinkType::PEER2NET || link->GetSourceIFace() == nullptr) {
115 0 : return false;
116 : }
117 : // 端口有交集时,该物理边才属于当前 RankTable 地址。
118 142 : const auto& phyPorts = link->GetSourceIFace()->GetPorts();
119 142 : return std::any_of(addrInfo.ports.begin(), addrInfo.ports.end(), [&phyPorts](const std::string& port) {
120 190 : return phyPorts.count(port) != 0;
121 142 : });
122 142 : }
123 :
124 68 : std::vector<shared_ptr<PhyTopo::Link>> GetMatchedPeer2NetPhyLinks(
125 : const vector<shared_ptr<PhyTopo::Link>>& links, const AddressInfo& addrInfo,
126 : const std::map<PlaneId, LinkProtocol>& planeUbProtocols)
127 : {
128 68 : vector<shared_ptr<PhyTopo::Link>> matchedLinks;
129 68 : matchedLinks.reserve(links.size());
130 68 : const auto protocolIter = planeUbProtocols.find(addrInfo.planeId);
131 68 : const bool hasPlaneUbProtocol = protocolIter != planeUbProtocols.end();
132 : const LinkProtocol planeUbProtocol
133 68 : = hasPlaneUbProtocol ? protocolIter->second : LinkProtocol(LinkProtocol::INVALID);
134 68 : std::copy_if(
135 : links.begin(), links.end(), std::back_inserter(matchedLinks),
136 142 : [&addrInfo, hasPlaneUbProtocol, planeUbProtocol](const shared_ptr<PhyTopo::Link>& link) {
137 142 : if (!IsPeer2NetLinkMatched(link, addrInfo)) {
138 48 : return false;
139 : }
140 94 : return !hasPlaneUbProtocol || link->GetLinkProtocols().count(planeUbProtocol) != 0;
141 : });
142 68 : return matchedLinks;
143 0 : }
144 :
145 : namespace {
146 :
147 : bool
148 16 : IsSamePhyInterface(const shared_ptr<PhyTopo::ConnInterface>& lhs, const shared_ptr<PhyTopo::ConnInterface>& rhs)
149 : {
150 16 : if (lhs == nullptr || rhs == nullptr) {
151 0 : return lhs == rhs;
152 : }
153 16 : return *lhs == *rhs;
154 : }
155 :
156 8 : bool IsSamePeer2NetLinkExceptTopoInstId(const shared_ptr<PhyTopo::Link>& lhs, const shared_ptr<PhyTopo::Link>& rhs)
157 : {
158 8 : if (lhs == nullptr || rhs == nullptr) {
159 0 : return lhs == rhs;
160 : }
161 32 : return lhs->GetSourceNode() == rhs->GetSourceNode() && lhs->GetTargetNode() == rhs->GetTargetNode()
162 16 : && lhs->GetType() == rhs->GetType() && lhs->GetLinkProtocols() == rhs->GetLinkProtocols()
163 8 : && lhs->GetLinkDirection() == rhs->GetLinkDirection() && lhs->GetTopoType() == rhs->GetTopoType()
164 16 : && lhs->GetHop() == rhs->GetHop() && IsSamePhyInterface(lhs->GetSourceIFace(), rhs->GetSourceIFace())
165 32 : && IsSamePhyInterface(lhs->GetTargetIFace(), rhs->GetTargetIFace());
166 : }
167 :
168 : std::vector<shared_ptr<PhyTopo::Link>>
169 68 : DeduplicatePeer2NetPhyLinks(std::vector<shared_ptr<PhyTopo::Link>> matchedLinks)
170 : {
171 68 : std::vector<shared_ptr<PhyTopo::Link>> uniqueLinks;
172 68 : uniqueLinks.reserve(matchedLinks.size());
173 144 : for (const auto& link : matchedLinks) {
174 : const auto duplicate
175 76 : = std::find_if(uniqueLinks.begin(), uniqueLinks.end(), [&link](const auto& uniqueLink) {
176 8 : return IsSamePeer2NetLinkExceptTopoInstId(link, uniqueLink);
177 : });
178 76 : if (duplicate == uniqueLinks.end()) {
179 68 : uniqueLinks.emplace_back(link);
180 68 : continue;
181 : }
182 8 : const u32 oldTopoInstId = (*duplicate)->GetTopoInstId();
183 8 : const u32 newTopoInstId = link->GetTopoInstId();
184 8 : if (newTopoInstId < oldTopoInstId) {
185 8 : *duplicate = link;
186 : }
187 : // 等价物理边共用一条逻辑边,并保留较小的拓扑实例 ID。
188 8 : HCCL_DEBUG(
189 : "[RankGraphBuilder][DeduplicatePeer2NetPhyLinks] ignore topoInstId[%u], keep topoInstId[%u].",
190 : std::max(oldTopoInstId, newTopoInstId), std::min(oldTopoInstId, newTopoInstId));
191 : }
192 68 : return uniqueLinks;
193 0 : }
194 :
195 68 : std::vector<shared_ptr<PhyTopo::Link>> GetMatchedPeer2NetPhyLinksForLayer(
196 : u32 netLayer, const vector<shared_ptr<PhyTopo::Link>>& links, const AddressInfo& addrInfo,
197 : const std::map<PlaneId, LinkProtocol>& planeUbProtocols)
198 : {
199 : std::vector<shared_ptr<PhyTopo::Link>> matchedLinks
200 68 : = GetMatchedPeer2NetPhyLinks(links, addrInfo, planeUbProtocols);
201 68 : if (netLayer == 0) {
202 : // layer 0 保持 topo 描述语义,只对 RankTable 定义的高层网络去重。
203 0 : return matchedLinks;
204 : }
205 68 : return DeduplicatePeer2NetPhyLinks(std::move(matchedLinks));
206 68 : }
207 :
208 68 : shared_ptr<NetInstance::Fabric> GetOrCreateFabricNode(
209 : FabricId fabId, const PlaneId& planeId, vector<shared_ptr<NetInstance::Fabric>>& fabNodes,
210 : const shared_ptr<NetInstance>& netInst)
211 : {
212 68 : if (fabNodes[fabId] == nullptr) {
213 22 : fabNodes[fabId] = make_shared<NetInstance::Fabric>(fabId, planeId);
214 22 : netInst->AddNode(fabNodes[fabId]);
215 : }
216 68 : return fabNodes[fabId];
217 : }
218 :
219 : } // namespace
220 :
221 58 : const vector<shared_ptr<PhyTopo::Link>>& RankGraphBuilder::GetPeer2NetPhyLinksCached(LocalId localId)
222 : {
223 58 : auto iter = peer2NetPhyLinksCache_.find(localId);
224 58 : if (iter == peer2NetPhyLinksCache_.end()) {
225 32 : iter = peer2NetPhyLinksCache_.emplace(localId, GetPeer2NetPhyLinks(localId)).first;
226 : }
227 116 : return iter->second;
228 : }
229 :
230 10 : LinkProtocol RankGraphBuilder::ResolveUbProtocolByEid(const AddressInfo& addrInfo, bool& supportsRtp) const
231 : {
232 10 : if (addrInfo.addrType != AddrType::EID) {
233 0 : THROW<InvalidParamsException>(StringFormat(
234 : "[RankGraphBuilder][ResolveUbProtocolByEid] addr[%s] is not an EID, cannot distinguish UB protocol.",
235 0 : addrInfo.addr.Describe().c_str()));
236 : }
237 :
238 10 : const auto rdmaHandle = RdmaHandleManager::GetInstance().GetByIp(GetLocalDeviceId(), addrInfo.addr);
239 10 : if (rdmaHandle == nullptr) {
240 0 : THROW<NullPtrException>(StringFormat(
241 : "[RankGraphBuilder][ResolveUbProtocolByEid] get context failed for EID[%s].",
242 0 : addrInfo.addr.Describe().c_str()));
243 : }
244 :
245 10 : DevBaseAttr devBaseAttr{};
246 10 : const HcclResult ret = hcomm::HccpRaGetDevBaseAttr(rdmaHandle, &devBaseAttr);
247 10 : if (ret != HCCL_SUCCESS) {
248 0 : THROW<InternalException>(StringFormat(
249 : "[RankGraphBuilder][ResolveUbProtocolByEid] get device base attr failed for EID[%s], ret[%d].",
250 0 : addrInfo.addr.Describe().c_str(), static_cast<int>(ret)));
251 : }
252 :
253 10 : bool hasCtp = false;
254 10 : bool hasRtp = false;
255 170 : for (u32 priority = 0U; priority < static_cast<u32>(MAX_PRIORITY_CNT); ++priority) {
256 160 : const CtxSlInfo& priorityInfo = devBaseAttr.ub.priorityInfo[priority];
257 160 : hasCtp = hasCtp || priorityInfo.tpType.bs.ctp != 0;
258 160 : hasRtp = hasRtp || priorityInfo.tpType.bs.rtp != 0;
259 : }
260 :
261 : // topo 中 UB_CTP 边同时承载 UB_MEM;EID 支持 CTP 时优先保留该边,
262 : // 仅当 EID 不支持 CTP 但支持 RTP 时匹配 UB_TP 边。
263 10 : supportsRtp = hasRtp;
264 10 : if (hasCtp) {
265 8 : HCCL_INFO(
266 : "[RankGraphBuilder][ResolveUbProtocolByEid] EID[%s] protocol[UB_CTP], hasCtp[%d], hasRtp[%d].",
267 : addrInfo.addr.Describe().c_str(), static_cast<int>(hasCtp), static_cast<int>(hasRtp));
268 8 : return LinkProtocol::UB_CTP;
269 : }
270 2 : if (hasRtp) {
271 2 : HCCL_INFO(
272 : "[RankGraphBuilder][ResolveUbProtocolByEid] EID[%s] protocol[UB_TP], hasCtp[%d], hasRtp[%d].",
273 : addrInfo.addr.Describe().c_str(), static_cast<int>(hasCtp), static_cast<int>(hasRtp));
274 2 : return LinkProtocol::UB_TP;
275 : }
276 :
277 0 : THROW<InvalidParamsException>(StringFormat(
278 : "[RankGraphBuilder][ResolveUbProtocolByEid] EID[%s] has neither CTP nor RTP in priorityInfo.",
279 0 : addrInfo.addr.Describe().c_str()));
280 : }
281 :
282 17 : std::map<PlaneId, LinkProtocol> RankGraphBuilder::ResolvePlaneUbProtocols(u32 netLayer, std::set<PlaneId>& ctpRtpPlanes)
283 : {
284 17 : const auto& levelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[myRank_], netLayer);
285 :
286 17 : ctpRtpPlanes.clear();
287 17 : std::map<PlaneId, LinkProtocol> planeProtocols;
288 17 : std::map<PlaneId, bool> planeExposeUbTp;
289 39 : for (const AddressInfo& addrInfo : levelInfo.rankAddrs) {
290 22 : if (addrInfo.addr == IpAddress() || addrInfo.addrType != AddrType::EID) {
291 12 : continue;
292 : }
293 10 : bool supportsRtp = false;
294 10 : const LinkProtocol currentProtocol = ResolveUbProtocolByEid(addrInfo, supportsRtp);
295 10 : const bool exposeUbTp = currentProtocol == LinkProtocol::UB_CTP && supportsRtp;
296 10 : HCCL_INFO(
297 : "[RankGraphBuilder][ResolvePlaneUbProtocols] netLayer[%u] planeId[%s] EID[%s] protocol[%s].", netLayer,
298 : addrInfo.planeId.c_str(), addrInfo.addr.Describe().c_str(), currentProtocol.Describe().c_str());
299 10 : const auto result = planeProtocols.emplace(addrInfo.planeId, currentProtocol);
300 10 : if (!result.second && result.first->second != currentProtocol) {
301 0 : THROW<InvalidParamsException>(StringFormat(
302 : "[RankGraphBuilder][ResolvePlaneUbProtocols] netLayer[%u] planeId[%s] contains mixed UB "
303 : "protocols[%s, %s].",
304 0 : netLayer, addrInfo.planeId.c_str(), result.first->second.Describe().c_str(),
305 0 : currentProtocol.Describe().c_str()));
306 : }
307 10 : const auto capabilityResult = planeExposeUbTp.emplace(addrInfo.planeId, exposeUbTp);
308 10 : if (!capabilityResult.second && capabilityResult.first->second != exposeUbTp) {
309 0 : THROW<InvalidParamsException>(StringFormat(
310 : "[RankGraphBuilder][ResolvePlaneUbProtocols] netLayer[%u] planeId[%s] contains mixed UB "
311 : "capabilities, exposeUbTp[%d, %d].",
312 0 : netLayer, addrInfo.planeId.c_str(), static_cast<int>(capabilityResult.first->second),
313 : static_cast<int>(exposeUbTp)));
314 : }
315 10 : if (exposeUbTp) {
316 6 : ctpRtpPlanes.insert(addrInfo.planeId);
317 : }
318 : }
319 17 : return planeProtocols;
320 17 : }
321 :
322 68 : void RankGraphBuilder::AddPeer2NetLink(
323 : const u32 netLayer, const string& netInstId, RankId rankId, const AddressInfo& addrInfo,
324 : const shared_ptr<NetInstance::Fabric>& fabNode, const vector<shared_ptr<PhyTopo::Link>>& matchedLinks,
325 : bool exposeUbTp)
326 : {
327 136 : for (shared_ptr<PhyTopo::Link> link : matchedLinks) {
328 68 : if (link == nullptr || link->GetSourceIFace() == nullptr) {
329 0 : continue;
330 : }
331 68 : std::set<std::string> ports = link->GetSourceIFace()->GetPorts();
332 68 : std::set<std::string> rankGraphPorts;
333 68 : std::set_intersection(
334 : ports.begin(), ports.end(), addrInfo.ports.begin(), addrInfo.ports.end(),
335 : std::inserter(rankGraphPorts, rankGraphPorts.begin()));
336 :
337 68 : if (rankGraphPorts.empty()) {
338 : // 该地址在topo里没有对应边
339 0 : continue;
340 : }
341 : // 获取topoInstId topoType
342 68 : u32 topoInstId = link->GetTopoInstId();
343 68 : auto topoType = link->GetTopoType();
344 68 : std::set<LinkProtocol> linkProtocols = link->GetLinkProtocols();
345 68 : if (exposeUbTp && linkProtocols.count(LinkProtocol::UB_CTP) != 0) {
346 : // CTP/RTP 共存时仍复用 CTP 物理边,仅扩展逻辑协议能力。
347 12 : linkProtocols.insert(LinkProtocol::UB_TP);
348 : }
349 :
350 : // 构造 RankGraph 的 PeerIface
351 : shared_ptr<NetInstance::ConnInterface> peerIface = make_shared<NetInstance::ConnInterface>(
352 136 : addrInfo.addr, rankGraphPorts, link->GetSourceIFace()->GetPos(), LinkType::PEER2NET, linkProtocols,
353 68 : topoType, topoInstId);
354 : // 获取 rankId 对应 PeerNode
355 68 : shared_ptr<NetInstance::Peer> peerNode = peers_.at(rankId);
356 68 : peerNode->AddConnInterface(netLayer, peerIface);
357 :
358 : // 构造 peer2netLink 和 net2peerLink 两条link
359 : shared_ptr<NetInstance::Link> peer2netLink = make_shared<NetInstance::Link>(
360 0 : peerNode, fabNode, peerIface, nullptr, LinkType::PEER2NET, linkProtocols, LinkDirection::BOTH,
361 68 : PEER2NET_LINK_HOP);
362 : shared_ptr<NetInstance::Link> net2peerLink = make_shared<NetInstance::Link>(
363 0 : fabNode, peerNode, nullptr, peerIface, LinkType::PEER2NET, linkProtocols, LinkDirection::BOTH,
364 68 : PEER2NET_LINK_HOP);
365 :
366 : // 插入 link
367 68 : tempNetInsts_[netLayer][netInstId]->AddLink(peer2netLink);
368 68 : tempNetInsts_[netLayer][netInstId]->AddLink(net2peerLink);
369 :
370 : // 将rank插入到当前netInstance对应的topoInstance中
371 68 : tempNetInsts_[netLayer][netInstId]->UpdateTopoInst(topoInstId, topoType, rankId);
372 :
373 : // 只打印当前卡的rank_id和eid对应关系
374 68 : if (rankId == myRank_) {
375 42 : HCCL_RUN_INFO(
376 : "[RankGraphBuilder][AddPeer2NetLink] Add Peer2NetLink Net2PeerLink success. level[%u] "
377 : "netInstId[%s] rankId[%u] planeId[%s] AddrStr[%s],topoInstId[%u],topoType[%u]",
378 : netLayer, netInstId.c_str(), rankId, fabNode->GetPlaneId().c_str(), addrInfo.addr.Describe().c_str(),
379 : topoInstId, topoType);
380 : }
381 68 : }
382 68 : }
383 :
384 17 : void RankGraphBuilder::AddFabricInfo(u32 netLayer)
385 : {
386 17 : auto netInst = rankGraph_->GetNetInstanceByRankId(netLayer, myRank_);
387 17 : if (netInst == nullptr) {
388 0 : THROW<NullPtrException>(
389 0 : StringFormat("[RankGraphBuilder][AddFabricInfo] rankGraph->GetNetInstanceByRankId is nullptr"));
390 : }
391 :
392 17 : if (netInst->GetNetType() != NetType::CLOS) {
393 0 : THROW<NotSupportException>(
394 0 : StringFormat("[RankGraphBuilder][AddFabricInfo] NetInstance is not CLOS, not support add fabric."));
395 : }
396 17 : string netInstId = netInst->GetNetInstId();
397 17 : const auto& myLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[myRank_], netLayer);
398 : // 根据planeId确认Fabric个数,每个fabricId对应一个planeId
399 17 : std::map<PlaneId, FabricId> planeId2Node = GetFabricsFromAddrInfo(myLevelInfo.rankAddrs);
400 :
401 17 : if (planeId2Node.size() == 0) {
402 0 : HCCL_WARNING(
403 : "[RankGraphBuilder][AddFabricInfo] current rankId[%d] netLayer[%u] group no net plane", myRank_, netLayer);
404 0 : return;
405 : }
406 : // topo 不再携带 net_layer;以本地 EID 的协议查询结果筛选对应物理边。
407 17 : std::set<PlaneId> ctpRtpPlanes;
408 17 : const std::map<PlaneId, LinkProtocol> planeUbProtocols = ResolvePlaneUbProtocols(netLayer, ctpRtpPlanes);
409 17 : vector<shared_ptr<NetInstance::Fabric>> fabNodes(planeId2Node.size(), nullptr);
410 17 : const shared_ptr<NetInstance>& buildingNetInst = tempNetInsts_[netLayer][netInstId];
411 :
412 : // 遍历每一个rankId,每个rankId都增加 peer2net 和 net2peer 两条链路
413 75 : for (RankId srcRankId : netInst->GetRankIds()) {
414 58 : const auto& srcLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[srcRankId], netLayer);
415 : // rankId对应的物理逻辑localId
416 58 : LocalId localId = rankGraph_->GetLocalId(srcRankId);
417 : // 从物理拓扑图中找出 localId 的所有 peer2Net 边。
418 58 : const auto& links = GetPeer2NetPhyLinksCached(localId);
419 : // 遍历ranktable中的addr,有几个addr就有几条peer2net的边
420 126 : for (const AddressInfo& addrInfo : srcLevelInfo.rankAddrs) {
421 68 : if (addrInfo.addr == IpAddress() || planeId2Node.count(addrInfo.planeId) == 0) {
422 0 : continue;
423 : }
424 : const vector<shared_ptr<PhyTopo::Link>> matchedLinks
425 68 : = GetMatchedPeer2NetPhyLinksForLayer(netLayer, links, addrInfo, planeUbProtocols);
426 68 : if (matchedLinks.empty()) {
427 0 : continue;
428 : }
429 68 : FabricId fabId = planeId2Node[addrInfo.planeId];
430 : // 若 fabNodes[fabId] 不存在则创建 如果存在则获取fabNode
431 : shared_ptr<NetInstance::Fabric> fabNode
432 68 : = GetOrCreateFabricNode(fabId, addrInfo.planeId, fabNodes, buildingNetInst);
433 : // 插入peer和fabric的peer2net和net2peer两条link
434 68 : AddPeer2NetLink(
435 : netLayer, netInstId, srcRankId, addrInfo, fabNode, matchedLinks,
436 68 : ctpRtpPlanes.count(addrInfo.planeId) != 0);
437 68 : }
438 17 : }
439 :
440 37 : HCCL_DEBUG(
441 : "[RankGraphBuilder][AddFabricInfo] netLayer [%u] netInstId[%s] Add Fabric Info success!", netLayer,
442 : netInstId.c_str());
443 17 : }
444 :
445 24 : void RankGraphBuilder::AddTopoDescFabricInfo()
446 : {
447 : // 1. 获取物理拓扑图
448 24 : auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph();
449 24 : if (phyTopoGraph == nullptr) {
450 0 : THROW<NullPtrException>(StringFormat("[RankGraphBuilder][AddTopoDescFabricInfo] phyTopoGraph is nullptr"));
451 : }
452 54 : HCCL_INFO("[RankGraphBuilder][AddTopoDescFabricInfo] Successfully retrieved phyTopoGraph");
453 :
454 : // 2. 获取当前 NetInstance
455 24 : NetInstance* innerNetInstance = rankGraph_->GetNetInstanceByRankId(0, myRank_);
456 24 : if (innerNetInstance == nullptr) {
457 0 : THROW<NullPtrException>(
458 0 : StringFormat("[RankGraphBuilder][AddTopoDescFabricInfo] rankGraph->GetNetInstanceByRankId is nullptr"));
459 : }
460 24 : std::string netInstId = innerNetInstance->GetNetInstId();
461 24 : std::set<RankId> rankIds = innerNetInstance->GetRankIds();
462 :
463 : // Group Layer 0 Fabric nodes by topoInstId so PCIe d2h links without RankTable addresses remain in RankGraph.
464 24 : std::map<u32, shared_ptr<NetInstance::Fabric>> fabNodes;
465 24 : const u32 localDeviceId = GetLocalDeviceId();
466 :
467 : // 3. 遍历所有 rank 节点,根据 topoInstId 创建 Fabric。
468 85 : for (RankId rankId : rankIds) {
469 61 : LocalId localId = rankGraph_->GetLocalId(rankId);
470 61 : auto peer2netEdges = phyTopoGraph->GetEdges(localId, PhyTopo::Fabric::GetId());
471 :
472 149 : HCCL_RUN_INFO(
473 : "[RankGraphBuilder][AddTopoDescFabricInfo] Processing rank %d (localId: %u), found %zu peer2net edges",
474 : rankId, localId, peer2netEdges.size());
475 :
476 212 : for (const auto& link : peer2netEdges) {
477 151 : if (link == nullptr || link->GetType() != LinkType::PEER2NET || link->GetSourceIFace() == nullptr) {
478 89 : continue;
479 : }
480 151 : const u32 topoInstId = link->GetTopoInstId();
481 151 : const TopoType topoType = link->GetTopoType();
482 151 : shared_ptr<NetInstance::Peer> peerNode = peers_.at(rankId);
483 : const vector<shared_ptr<NetInstance::ConnInterface>> peerIfaces = ConstructConnIFromPhyTopoConnIAndPortMap(
484 151 : link->GetSourceIFace(), peerNode->GetPortAddrMapLayer0(), topoType, topoInstId, localDeviceId);
485 151 : if (peerIfaces.empty()) {
486 89 : continue;
487 : }
488 :
489 62 : if (fabNodes.count(topoInstId) == 0) {
490 33 : shared_ptr<NetInstance::Fabric> fabNode = make_shared<NetInstance::Fabric>(topoInstId);
491 33 : innerNetInstance->AddNode(fabNode);
492 33 : fabNodes[topoInstId] = fabNode;
493 93 : HCCL_INFO("[RankGraphBuilder][AddTopoDescFabricInfo] create Fabric for topoInstId[%u]", topoInstId);
494 33 : }
495 :
496 136 : for (const auto& peerIface : peerIfaces) {
497 74 : peerNode->AddConnInterface(0, peerIface);
498 : shared_ptr<NetInstance::Link> peer2netLink = make_shared<NetInstance::Link>(
499 148 : peerNode, fabNodes[topoInstId], peerIface, nullptr, LinkType::PEER2NET, link->GetLinkProtocols(),
500 148 : LinkDirection::BOTH, PEER2NET_LINK_HOP);
501 : shared_ptr<NetInstance::Link> net2peerLink = make_shared<NetInstance::Link>(
502 148 : fabNodes[topoInstId], peerNode, nullptr, peerIface, LinkType::PEER2NET, link->GetLinkProtocols(),
503 148 : LinkDirection::BOTH, PEER2NET_LINK_HOP);
504 74 : tempNetInsts_[0][netInstId]->AddLink(peer2netLink);
505 74 : tempNetInsts_[0][netInstId]->AddLink(net2peerLink);
506 74 : tempNetInsts_[0][netInstId]->UpdateTopoInst(topoInstId, topoType, rankId);
507 74 : }
508 240 : }
509 61 : }
510 54 : HCCL_INFO("[RankGraphBuilder][AddTopoDescFabricInfo] Successfully completed fabric link construction");
511 24 : }
512 :
513 17 : std::map<PlaneId, FabricId> GetFabricsFromAddrInfo(const std::vector<AddressInfo>& rankAddrs)
514 : {
515 17 : std::map<PlaneId, FabricId> planeId2FabricId;
516 39 : for (const auto& addrInfo : rankAddrs) {
517 22 : if (planeId2FabricId.count(addrInfo.planeId) == 0) {
518 22 : FabricId fabId = planeId2FabricId.size();
519 22 : planeId2FabricId[addrInfo.planeId] = fabId;
520 : }
521 : }
522 17 : return planeId2FabricId;
523 0 : }
524 :
525 : // 根据ranktable构造添加peers和NetInstances, NetInstance添加nodes和links(peer2net)
526 : // 1. 创建NetInstance ( 每个NetInstance 添加 Rank, Node, Link);
527 : // 2. RankGraph中添加NetInstance, Peer, Fabric,
528 25 : void RankGraphBuilder::BuildFromRankTable()
529 : {
530 25 : peer2NetPhyLinksCache_.clear();
531 : // 保存NetInstance指针以便后续执行Add操作
532 25 : tempNetInsts_.resize(MAX_NET_LAYER); // 为了方便修改RankGraph的NetInstance,共享指针。
533 :
534 : // 遍历rankTable每一个rank, virtualTopo添加Peers
535 88 : for (const auto& rankInfo : rankTable_->ranks) {
536 63 : updaterFor64Plus1_.SaveReplaceInfo(rankInfo); // 暂存备份替换信息
537 63 : RankId rankId = rankInfo.rankId;
538 : shared_ptr<NetInstance::Peer> peer = make_shared<NetInstance::Peer>(
539 63 : rankId, rankInfo.localId, rankInfo.replacedLocalId, rankInfo.deviceId, rankInfo.devicePort,
540 63 : rankInfo.hostPort);
541 63 : rankGraph_->AddPeer(peer);
542 63 : peers_.emplace(rankId, peer); // rankid2peer
543 :
544 : // 构造当前rank的每个LevelInfo所在NetInstance, 添加 RankId 和 Peer
545 185 : for (const auto& levelInfo : rankInfo.rankLevelInfos) {
546 : // rankLevelInfo.level、id对应NetInstance,若不存在则创建
547 : auto curNetInstance = GetOrCreateNetInstance(
548 122 : levelInfo.netLayer, levelInfo.netInstId, levelInfo.netType, tempNetInsts_, rankGraph_.get());
549 122 : if (curNetInstance == nullptr) {
550 0 : continue;
551 : }
552 : // NetInstance add Peer
553 122 : curNetInstance->AddRankId(rankId);
554 122 : curNetInstance->AddNode(peer);
555 : // Peer add NetInstance
556 122 : peer->AddNetInstance(curNetInstance);
557 122 : if (levelInfo.netLayer == 0) {
558 63 : peer->SetPortPortAddrMapLayer0(levelInfo.portAddrMap);
559 : }
560 290 : HCCL_DEBUG(
561 : "[RankGraphBuilder][BuildFromRankTable] rankLevelInfo : rankId[%d] level[%u] "
562 : "netInstId[%s] fabricType[%s].",
563 : rankId, levelInfo.netLayer, levelInfo.netInstId.c_str(), levelInfo.netType.Describe().c_str());
564 122 : }
565 63 : }
566 :
567 : // 对 myrank 所在每个level的NetInstance 添加 Fabrics 和 links(peer2net)
568 25 : set<u32> myLevels = rankGraph_->GetLevels(myRank_);
569 55 : HCCL_DEBUG("myRank netType: level size %u", myLevels.size());
570 68 : for (u32 level : myLevels) {
571 43 : if (level == 0) {
572 25 : AddTopoDescFabricInfo();
573 : } else {
574 18 : AddFabricInfo(level);
575 : }
576 : }
577 :
578 : // 初始化innerRanks
579 25 : rankGraph_->InitInnerRanks();
580 :
581 55 : HCCL_DEBUG("[RankGraphBuilder][BuildFromRankTable] Build VirtualTopo from RankTable success!");
582 25 : }
583 :
584 25 : void RankGraphBuilder::SetEndpointDesc()
585 : {
586 25 : std::shared_ptr<NetInstance::Peer> peer = peers_[myRank_];
587 25 : CHK_PRT_THROW(
588 : peer == nullptr, HCCL_ERROR("[RankGraphBuilder::%s] fail", __func__), NullPtrException, "peer is null");
589 : // 获取 peer 的 Iface
590 25 : std::set<u32> layers = peer->GetLevels();
591 68 : for (const auto& layer : layers) {
592 43 : auto ifacesVec = peer->GetIfacesByLayer(layer);
593 125 : for (const auto& iface : ifacesVec) {
594 82 : const auto& ports = iface->GetPorts();
595 82 : std::string portsStr;
596 204 : for (auto portIter = ports.begin(); portIter != ports.end(); ++portIter) {
597 122 : if (portIter != ports.begin()) {
598 40 : portsStr += ",";
599 : }
600 122 : portsStr += *portIter;
601 : }
602 202 : HCCL_INFO(
603 : "[RankGraphBuilder::SetEndpointDesc] layer[%u] topoInstId[%u] bwCoeff[%zu] ports[%s]", layer,
604 : iface->GetTopoInstId(), ports.size(), portsStr.c_str());
605 :
606 82 : const auto& protocols = iface->GetLinkProtocols();
607 178 : for (const auto& protocol : protocols) {
608 96 : EndpointDesc desc{};
609 :
610 96 : HcclResult ret = GetCommAddr(desc.commAddr, iface->GetAddr());
611 96 : CHK_PRT_THROW(
612 : ret != HCCL_SUCCESS, HCCL_ERROR("[RankGraphBuilder::%s] fail", __func__), InternalException,
613 : "GetCommAddr fail");
614 :
615 96 : desc.protocol = LinkProtocolToCommProtocol(protocol);
616 96 : desc.loc.locType = AddrPositionToEndpointLoc(iface->GetPos());
617 :
618 216 : HCCL_INFO(
619 : "[RankGraphBuilder::SetEndpointDesc] local type[%d] protocol[%d]", desc.loc.locType, desc.protocol);
620 :
621 96 : peer->SetEndpointToIface(layer, iface->GetTopoInstId(), desc.commAddr, desc.protocol, iface);
622 : }
623 82 : }
624 43 : }
625 25 : }
626 :
627 0 : std::shared_ptr<NetInstance> RankGraphBuilder::GetNetInstance(const RankLevelInfo& levelInfo)
628 : {
629 0 : auto it = tempNetInsts_[levelInfo.netLayer].find(levelInfo.netInstId);
630 0 : if (it == tempNetInsts_[levelInfo.netLayer].end()) {
631 0 : return nullptr;
632 : }
633 : // 若NetInstance存在, type不一致则报错
634 0 : NetType netType = it->second->GetNetType();
635 0 : if (netType != levelInfo.netType) {
636 0 : HCCL_WARNING(
637 : "[CreateNetInstance]FabType [%s] and [%s] no match", netType.Describe().c_str(),
638 : levelInfo.netType.Describe().c_str());
639 0 : return nullptr;
640 : }
641 0 : return it->second;
642 : }
643 :
644 0 : std::shared_ptr<NetInstance> RankGraphBuilder::CreateNetInstance(const RankLevelInfo& levelInfo)
645 : {
646 0 : std::shared_ptr<NetInstance> netInst;
647 0 : if (levelInfo.netType == NetType::TOPO_FILE_DESC) {
648 0 : netInst = std::make_shared<InnerNetInstance>(levelInfo.netLayer, levelInfo.netInstId);
649 0 : } else if (levelInfo.netType == NetType::CLOS) {
650 0 : netInst = std::make_shared<ClosNetInstance>(levelInfo.netLayer, levelInfo.netInstId);
651 : } else {
652 0 : THROW<NotSupportException>(
653 0 : StringFormat("[RankGraphBuilder][CreateNetInstance] netType: %s is not support", levelInfo.netType));
654 : }
655 0 : return netInst;
656 0 : }
657 :
658 : // 从phytopo和ranktable中读取数据共同构建peer2peer的边。
659 24 : void RankGraphBuilder::BuildPeer2PeerLinks()
660 : {
661 24 : auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph();
662 24 : if (phyTopoGraph == nullptr) {
663 0 : THROW<NullPtrException>(StringFormat("[RankGraphBuilder][BuildPeer2PeerLinks] phyTopoGraph is nullptr"));
664 : }
665 : // 遍历innerNetInstance中的每两个rankId之间是否存在边,存在则添加peer2peerlink
666 24 : NetInstance* innerNetInstance = rankGraph_->GetNetInstanceByRankId(0, myRank_);
667 24 : if (innerNetInstance == nullptr) {
668 0 : THROW<NullPtrException>(StringFormat("[RankGraphBuilder][BuildPeer2PeerLinks] innerNetInstance is nullptr"));
669 : }
670 24 : set<RankId> rankIds = innerNetInstance->GetRankIds();
671 :
672 24 : auto localDeviceId = GetLocalDeviceId();
673 85 : for (const auto srcRankId : rankIds) {
674 244 : for (const auto dstRankId : rankIds) {
675 183 : if (srcRankId == dstRankId) {
676 67 : continue;
677 : }
678 :
679 : // 得到phyTopoGraph中对应的localId
680 122 : LocalId srcLocalId = rankGraph_->GetLocalId(srcRankId);
681 122 : LocalId dstLocalId = rankGraph_->GetLocalId(dstRankId);
682 122 : if (srcLocalId == BACKUP_LOCAL_ID || dstLocalId == BACKUP_LOCAL_ID) {
683 6 : continue;
684 : }
685 :
686 : std::vector<shared_ptr<PhyTopo::Link>> phyLinks
687 116 : = GetPeer2PeerPhyLinks(phyTopoGraph, srcLocalId, dstLocalId);
688 : // 按 RankTable layer 0 端口筛选物理 P2P 边并补齐地址。
689 :
690 116 : shared_ptr<NetInstance::Peer> srcPeer = peers_.at(srcRankId);
691 116 : shared_ptr<NetInstance::Peer> dstPeer = peers_.at(dstRankId);
692 :
693 220 : for (shared_ptr<PhyTopo::Link> phyLink : phyLinks) {
694 : auto sourceIfaces = ConstructConnIFromPhyTopoConnIAndPortMap(
695 208 : phyLink->GetSourceIFace(), srcPeer->GetPortAddrMapLayer0(), phyLink->GetTopoType(),
696 208 : phyLink->GetTopoInstId(), localDeviceId);
697 : auto targetIfaces = ConstructConnIFromPhyTopoConnIAndPortMap(
698 208 : phyLink->GetTargetIFace(), dstPeer->GetPortAddrMapLayer0(), phyLink->GetTopoType(),
699 208 : phyLink->GetTopoInstId(), localDeviceId);
700 104 : if (sourceIfaces.empty() || targetIfaces.empty()) {
701 : // 没有可用的接口。
702 0 : HCCL_WARNING(
703 : "[RankGraphBuilder][BuildPeer2PeerLinks] no available interface, "
704 : "srcRankId[%u] dstRankId[%u].",
705 : srcRankId, dstRankId);
706 0 : continue;
707 0 : }
708 104 : srcPeer->AddConnInterfaces(0, sourceIfaces);
709 104 : dstPeer->AddConnInterfaces(0, targetIfaces);
710 : std::vector<shared_ptr<NetInstance::Link>> links
711 104 : = ConstructLinks(srcPeer, dstPeer, sourceIfaces, targetIfaces, phyLink);
712 208 : for (auto link : links) {
713 104 : innerNetInstance->AddLink(link);
714 104 : }
715 104 : }
716 116 : }
717 : }
718 24 : }
719 :
720 24 : void RankGraphBuilder::UpdateTopoInstForMyRankOnly()
721 : {
722 24 : auto innerNetInstance = rankGraph_->GetNetInstanceByRankId(0, myRank_);
723 24 : if (innerNetInstance == nullptr) {
724 0 : THROW<NullPtrException>(
725 0 : StringFormat("[RankGraphBuilder][UpdateTopoInstForMyRankOnly] innerNetInstance is nullptr"));
726 : }
727 :
728 24 : auto netInstId = innerNetInstance->GetNetInstId();
729 24 : set<RankId> rankIds = innerNetInstance->GetRankIds();
730 :
731 24 : auto localDeviceId = GetLocalDeviceId();
732 24 : auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph();
733 24 : if (phyTopoGraph == nullptr) {
734 0 : THROW<NullPtrException>(
735 0 : StringFormat("[RankGraphBuilder][UpdateTopoInstForMyRankOnly] phyTopoGraph is nullptr"));
736 : }
737 24 : if (rankIds.size() == 1) {
738 : // 单卡场景直接返回1DMESH
739 3 : RankId singleId = *rankIds.begin();
740 3 : tempNetInsts_[0][netInstId]->UpdateTopoInst(0, TopoType::MESH_1D, singleId);
741 3 : return;
742 : }
743 :
744 79 : for (const auto srcRankId : rankIds) {
745 238 : for (const auto dstRankId : rankIds) {
746 : // 只处理涉及 myRank_ 的边
747 180 : if (srcRankId == dstRankId || (srcRankId != myRank_ && dstRankId != myRank_)) {
748 108 : continue;
749 : }
750 :
751 74 : LocalId srcLocalId = rankGraph_->GetLocalId(srcRankId);
752 74 : LocalId dstLocalId = rankGraph_->GetLocalId(dstRankId);
753 74 : if (srcLocalId == BACKUP_LOCAL_ID || dstLocalId == BACKUP_LOCAL_ID) {
754 2 : continue;
755 : }
756 :
757 : std::vector<shared_ptr<PhyTopo::Link>> phyLinks
758 72 : = GetPeer2PeerPhyLinks(phyTopoGraph, srcLocalId, dstLocalId);
759 : // 通过 RankTable layer 0 端口映射物理 P2P 链路。
760 72 : const auto& srcLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[srcRankId], 0);
761 72 : const auto& dstLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[dstRankId], 0);
762 :
763 136 : for (shared_ptr<PhyTopo::Link> phyLink : phyLinks) {
764 : auto sourceIfaces = ConstructConnIFromPhyTopoConnIAndPortMap(
765 128 : phyLink->GetSourceIFace(), srcLevelInfo.portAddrMap, phyLink->GetTopoType(),
766 128 : phyLink->GetTopoInstId(), localDeviceId);
767 : auto targetIfaces = ConstructConnIFromPhyTopoConnIAndPortMap(
768 128 : phyLink->GetTargetIFace(), dstLevelInfo.portAddrMap, phyLink->GetTopoType(),
769 128 : phyLink->GetTopoInstId(), localDeviceId);
770 64 : if (sourceIfaces.empty() || targetIfaces.empty()) {
771 0 : continue;
772 : }
773 64 : tempNetInsts_[0][netInstId]->UpdateTopoInst(
774 : phyLink->GetTopoInstId(), phyLink->GetTopoType(), dstRankId);
775 64 : }
776 72 : }
777 : }
778 30 : }
779 :
780 489 : std::vector<std::shared_ptr<NetInstance::ConnInterface>> ConstructConnIFromPhyTopoConnIAndPortMap(
781 : std::shared_ptr<PhyTopo::ConnInterface> phyConnIFace,
782 : const std::map<std::string, std::vector<IpAddress>>& portAddrMap, const TopoType topoType, const u32 topoInstId,
783 : u32 localDeviceId)
784 : {
785 489 : std::vector<std::shared_ptr<NetInstance::ConnInterface>> netConnIFaces;
786 489 : std::set<string> phyPorts = phyConnIFace->GetPorts();
787 489 : std::map<IpAddress, std::set<string>> addr2Ports;
788 : // 非 PCIe 端口仅保留 RankTable 中存在的物理端口。
789 1133 : for (auto port : phyPorts) {
790 644 : if (*(phyConnIFace->GetLinkProtocols().begin()) == LinkProtocol::PCIE) {
791 1 : IpAddress tempIp;
792 1 : HrtRaSocketGetVnicIpInfos(localDeviceId, DeviceIdType::DEVICE_ID_TYPE_PHY_ID, localDeviceId, tempIp);
793 1 : auto it = addr2Ports.find(tempIp);
794 1 : if (it == addr2Ports.end()) {
795 1 : std::set<std::string> newPorts;
796 1 : newPorts.insert("d2h");
797 1 : addr2Ports[tempIp] = newPorts;
798 1 : } else {
799 0 : it->second.insert("d2h");
800 : }
801 : } else {
802 643 : auto itPort = portAddrMap.find(port);
803 643 : if (itPort == portAddrMap.end()) {
804 437 : HCCL_WARNING(
805 : "[RankGraphBuilder][ConstructConnIFromPhyTopoConnIAndPortMap] topo use port [%s] not find addrs in "
806 : "ranktable.",
807 : port.c_str());
808 229 : continue;
809 104 : }
810 828 : for (auto addr : itPort->second) {
811 414 : auto it = addr2Ports.find(addr);
812 414 : if (it == addr2Ports.end()) {
813 410 : std::set<std::string> newPorts;
814 410 : newPorts.insert(port);
815 410 : addr2Ports[addr] = newPorts;
816 410 : } else {
817 12 : it->second.insert("8080");
818 : }
819 : }
820 : }
821 644 : }
822 :
823 900 : for (auto it = addr2Ports.begin(); it != addr2Ports.end(); ++it) {
824 411 : auto linkType = *(phyConnIFace->GetLinkProtocols().begin()) == LinkProtocol::PCIE ? LinkType::PEER2NET :
825 411 : LinkType::PEER2PEER;
826 : shared_ptr<NetInstance::ConnInterface> netConnIFace = make_shared<NetInstance::ConnInterface>(
827 822 : it->first, it->second, phyConnIFace->GetPos(), linkType, phyConnIFace->GetLinkProtocols(), topoType,
828 411 : topoInstId);
829 411 : netConnIFaces.push_back(netConnIFace);
830 411 : }
831 489 : return netConnIFaces;
832 489 : }
833 :
834 104 : std::vector<shared_ptr<NetInstance::Link>> ConstructLinks(
835 : shared_ptr<NetInstance::Peer> srcPeer, shared_ptr<NetInstance::Peer> dstPeer,
836 : std::vector<std::shared_ptr<NetInstance::ConnInterface>> sourceIfaces,
837 : std::vector<std::shared_ptr<NetInstance::ConnInterface>> targetIfaces, shared_ptr<PhyTopo::Link> phyLink)
838 : {
839 104 : std::vector<shared_ptr<NetInstance::Link>> links;
840 208 : for (auto sourceIFace : sourceIfaces) {
841 208 : for (auto targetIFace : targetIfaces) {
842 : shared_ptr<NetInstance::Link> link = make_shared<NetInstance::Link>(
843 104 : srcPeer, dstPeer, sourceIFace, targetIFace, LinkType::PEER2PEER, phyLink->GetLinkProtocols());
844 104 : links.push_back(link);
845 104 : }
846 104 : }
847 104 : return links;
848 0 : }
849 :
850 188 : std::vector<std::shared_ptr<PhyTopo::Link>> GetPeer2PeerPhyLinks(
851 : std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyTopoGraph, LocalId srcLocalId, LocalId dstLocalId)
852 : {
853 188 : std::vector<shared_ptr<PhyTopo::Link>> links;
854 188 : if (!phyTopoGraph->HasNode(srcLocalId) || !phyTopoGraph->HasNode(dstLocalId)) {
855 0 : HCCL_WARNING(
856 : "[RankGraphBuilder][BuildFromPhytopo] srcLocalId[%u] dstLocalId[%u] not exist in phyTopoGraph.", srcLocalId,
857 : dstLocalId);
858 0 : return links;
859 : }
860 : // 得到phyTopoGraph对应的NodeId
861 188 : NodeId srcNodeId = PhyTopo::Peer::GetId(srcLocalId);
862 188 : NodeId dstNodeId = PhyTopo::Peer::GetId(dstLocalId);
863 :
864 188 : phyTopoGraph->TraverseEdge(srcNodeId, dstNodeId, [&](shared_ptr<PhyTopo::Link> link) {
865 168 : if (link != nullptr && link->GetType() == LinkType::PEER2PEER) {
866 168 : links.push_back(link);
867 : }
868 168 : });
869 188 : if (links.empty()) {
870 40 : HCCL_WARNING(
871 : "[RankGraphBuilder][GetPeer2PeerPhyLinks] srcLocalId[%u] dstLocalId[%u] edge does not exist.", srcLocalId,
872 : dstLocalId);
873 : }
874 188 : return links;
875 0 : }
876 :
877 27 : void RankGraphBuilder::CheckMyRankInRankTable() const
878 : {
879 27 : if (myRank_ >= static_cast<s32>(rankTable_->rankCount)) {
880 1 : THROW<InvalidParamsException>(StringFormat(
881 : "[RankGraphBuilder][CheckMyRankInRankTable]"
882 : "myRank[%d] is not in rankTable rankCount[%u].",
883 1 : myRank_, rankTable_->rankCount));
884 : }
885 26 : }
886 :
887 27 : void RankGraphBuilder::BuildRankGraph()
888 : {
889 : // 创建VirtualTopo
890 27 : rankGraph_ = make_unique<RankGraph>(myRank_);
891 :
892 : // 校验myRank在rankTable中
893 27 : CheckMyRankInRankTable();
894 :
895 : // 根据ranktable构造添加peers和NetInstances, 每个NetInstance添加nodes和links(peer2net)
896 26 : BuildFromRankTable();
897 :
898 : // 根据phytopo构造添加InnerGroup中的links(peer2peer), 不包括备份节点
899 26 : BuildPeer2PeerLinks();
900 :
901 : // 使用备份D时需要修改虚拟拓扑
902 26 : updaterFor64Plus1_.UpdateRankGraph(rankGraph_.get(), rankTable_.get());
903 :
904 : // 为myrank的peer2peer更新topoInst
905 26 : UpdateTopoInstForMyRankOnly();
906 :
907 : // 添加绕路 绕路获取
908 26 : DetourService::GetInstance().InsertDetourLinks(rankGraph_.get(), rankTable_.get());
909 :
910 : // 设置endpoint
911 26 : SetEndpointDesc();
912 :
913 : // 构造完成
914 26 : rankGraph_->InitFinish();
915 26 : }
916 :
917 7 : std::unique_ptr<RankTableInfo> RankGraphBuilder::GetRankTableInfo() { return move(rankTable_); }
918 :
919 5 : std::shared_ptr<TopoInfo> RankGraphBuilder::GetTopoInfo() { return topoInfo_; }
920 :
921 : unique_ptr<RankGraph>
922 10 : RankGraphBuilder::RecoverBuild(const RankTableInfo& rankTableInfo, const TopoInfo& topoInfo, RankId myRank)
923 : {
924 10 : topoInfo_ = std::make_shared<TopoInfo>(topoInfo);
925 10 : PhyTopoBuilder::GetInstance().RecoverBuild(*topoInfo_);
926 :
927 10 : rankTable_ = make_unique<RankTableInfo>(rankTableInfo);
928 10 : HCCL_INFO(
929 : "[%s] RankTable[%s] RankTableInfo[%s]", __func__, rankTable_->Describe().c_str(),
930 : rankTableInfo.Describe().c_str());
931 :
932 10 : this->myRank_ = myRank;
933 10 : BuildRankGraph();
934 :
935 9 : HCCL_INFO("[RankGraphBuilder] Build VirtualTopo success!");
936 9 : rankGraph_->Dump();
937 9 : return std::move(rankGraph_);
938 : }
939 :
940 : } // namespace Hccl
|