LCOV - code coverage report
Current view: top level - coll_communicator_mgr/rank_graph/rank_graph_builder - rank_graph_builder.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 85.3 % 532 454
Test Date: 2026-08-25 19:18:03 Functions: 94.9 % 39 37

            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
        

Generated by: LCOV version 2.0-1