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: 83.7 % 387 324
Test Date: 2026-07-28 12:11:00 Functions: 92.3 % 26 24

            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 "rank_graph_builder.h"
      14              : #include "detour_service.h"
      15              : #include "json_parser.h"
      16              : #include "phy_topo_builder.h"
      17              : 
      18              : namespace Hccl {
      19              : 
      20              : using namespace std;
      21              : 
      22           14 : unique_ptr<RankGraph> RankGraphBuilder::Build(const string &ranktableM, const string &topoPath, RankId myRank)
      23              : {
      24           14 :     PhyTopoBuilder::GetInstance().Build(topoPath);
      25           14 :     topoInfo_ = PhyTopoBuilder::GetInstance().GetTopoInfo();
      26              : 
      27              :     JsonParser    rankTableParser;
      28           14 :     RankTableInfo rankTableInfo;
      29           14 :     rankTableParser.ParseString(ranktableM, rankTableInfo);
      30           14 :     rankTable_ = make_unique<RankTableInfo>(rankTableInfo);
      31              : 
      32           14 :     this->myRank_ = myRank;
      33           14 :     BuildRankGraph();
      34              : 
      35           42 :     HCCL_INFO("[RankGraphBuilder] Build VirtualTopo success!");
      36           14 :     rankGraph_->Dump();
      37           28 :     return std::move(rankGraph_);
      38           14 : }
      39              : 
      40            1 : unique_ptr<RankGraph> RankGraphBuilder::Build(const RankTableInfo &ranktable, const string &topoPath, RankId myRank)
      41              : {
      42            1 :     PhyTopoBuilder::GetInstance().Build(topoPath);
      43            1 :     topoInfo_  = PhyTopoBuilder::GetInstance().GetTopoInfo();
      44            1 :     rankTable_ = make_unique<RankTableInfo>(ranktable);
      45              : 
      46            1 :     myRank_ = myRank;
      47            1 :     BuildRankGraph();
      48              : 
      49            0 :     HCCL_INFO("[RankGraphBuilder] Build VirtualTopo success!");
      50            0 :     rankGraph_->Dump();
      51            0 :     return std::move(rankGraph_);
      52              : }
      53              : 
      54           60 : const RankLevelInfo &RankGraphBuilder::GetRankLevelInfoByNetLayer(const NewRankInfo &rankInfo, u32 netLayer) const
      55              : {
      56           60 :     auto it = std::find_if(rankInfo.rankLevelInfos.begin(), rankInfo.rankLevelInfos.end(),
      57          150 :         [netLayer](const RankLevelInfo &levelInfo) {
      58          150 :             return levelInfo.netLayer == netLayer;
      59              :         });
      60           60 :     if (it == rankInfo.rankLevelInfos.end()) {
      61            0 :         THROW<InvalidParamsException>(StringFormat(
      62              :             "[RankGraphBuilder][GetRankLevelInfoByNetLayer] rankId[%u] netLayer[%u] does not exist in ranktable.",
      63            0 :             rankInfo.rankId, netLayer));
      64              :     }
      65          120 :     return *it;
      66              : }
      67              : 
      68           48 : std::vector<shared_ptr<PhyTopo::Link>> GetPeer2NetPhyLinks(u32 netLayer, LocalId localId)
      69              : {
      70           48 :     const shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyGraph = PhyTopo::GetInstance()->GetTopoGraph(netLayer);
      71           48 :     if (phyGraph == nullptr) {
      72            0 :         THROW<InvalidParamsException>(StringFormat("[RankGraphBuilder][GetPhyLink] localId[%d] is not level[%u] in"
      73              :                                                    " topo.json, not match rankTable.",
      74              :                                                    localId, netLayer));
      75              :     }
      76           48 :     std::vector<shared_ptr<PhyTopo::Link>> links;
      77           48 :     phyGraph->TraverseEdge(PhyTopo::Peer::GetId(localId), [&](shared_ptr<PhyTopo::Link> link) {
      78           48 :         if (link != nullptr) {
      79           48 :             links.push_back(link);
      80              :         }
      81           48 :     });
      82              : 
      83           48 :     if (links.empty()) {
      84            0 :         THROW<InvalidParamsException>(
      85            0 :             StringFormat("[RankGraphBuilder][GetPhyLink] SourceNode localId[%d] edge does not exist.", localId));
      86              :     }
      87           48 :     return links;
      88           48 : }
      89              : 
      90           48 : void RankGraphBuilder::AddPeer2NetLink(const u32 netLayer,  const string &netInstId, RankId rankId, const AddressInfo &addrInfo,
      91              :                                       const shared_ptr<NetInstance::Fabric> &fabNode, const vector<shared_ptr<PhyTopo::Link>> &links)
      92              : {
      93           96 :     for (shared_ptr<PhyTopo::Link> link : links) {
      94           48 :         if (link->GetSourceIFace() == nullptr) {
      95            0 :             continue;
      96              :         }
      97           48 :         std::set<std::string> ports = link->GetSourceIFace()->GetPorts();
      98           48 :         std::set<std::string> rankGraphPorts;
      99           48 :         std::set_intersection(ports.begin(), ports.end(), addrInfo.ports.begin(), addrInfo.ports.end(), 
     100              :             std::inserter(rankGraphPorts, rankGraphPorts.begin()));
     101              :         
     102           48 :         if (rankGraphPorts.empty()) {
     103              :             // 该地址在topo里没有对应边
     104            0 :             continue;
     105              :         }
     106              :         // 获取topoInstId topoType
     107           48 :         u32 topoInstId = link->GetTopoInstId();
     108           48 :         auto  topoType = link->GetTopoType();
     109              : 
     110              :         // 构造 RankGraph 的 PeerIface
     111              :         shared_ptr<NetInstance::ConnInterface> peerIface = make_shared<NetInstance::ConnInterface>(
     112           48 :             addrInfo.addr, rankGraphPorts, link->GetSourceIFace()->GetPos(), LinkType::PEER2NET, link->GetLinkProtocols(), topoType, topoInstId);
     113              :         // 获取 rankId 对应 PeerNode
     114           48 :         shared_ptr<NetInstance::Peer> peerNode = peers_.at(rankId);
     115           48 :         peerNode->AddConnInterface(netLayer, peerIface);
     116              : 
     117              :         // 构造 peer2netLink 和 net2peerLink 两条link
     118              :         shared_ptr<NetInstance::Link> peer2netLink =
     119            0 :             make_shared<NetInstance::Link>(peerNode, fabNode, peerIface, nullptr, LinkType::PEER2NET,
     120           48 :                                            link->GetLinkProtocols(), LinkDirection::BOTH, 2);
     121              :         shared_ptr<NetInstance::Link> net2peerLink =
     122            0 :             make_shared<NetInstance::Link>(fabNode, peerNode, nullptr, peerIface, LinkType::PEER2NET,
     123           48 :                                            link->GetLinkProtocols(), LinkDirection::BOTH, 2);
     124              : 
     125              :         // 插入 link
     126           48 :         tempNetInsts_[netLayer][netInstId]->AddLink(peer2netLink);
     127           48 :         tempNetInsts_[netLayer][netInstId]->AddLink(net2peerLink);
     128              : 
     129              :         // 将rank插入到当前netInstance对应的topoInstance中
     130           48 :         tempNetInsts_[netLayer][netInstId]->UpdateTopoInst(topoInstId, topoType, rankId);
     131              : 
     132              :         // 只打印当前卡的rank_id和eid对应关系
     133           48 :         if (rankId == myRank_) {
     134           32 :             HCCL_RUN_INFO("[RankGraphBuilder][AddPeer2NetLink] Add Peer2NetLink Net2PeerLink success. level[%u] "
     135              :                        "netInstId[%s] rankId[%u] planeId[%s] AddrStr[%s],topoInstId[%u],topoType[%u]",
     136              :                 netLayer,  netInstId.c_str(), rankId, fabNode->GetPlaneId().c_str(), addrInfo.addr.Describe().c_str(),
     137              :                 topoInstId, topoType);
     138              :         }
     139           48 :     }
     140           48 : }
     141              : 
     142           12 : void RankGraphBuilder::AddFabricInfo(u32 netLayer)
     143              : {
     144           12 :     auto netInst = rankGraph_->GetNetInstanceByRankId(netLayer, myRank_);
     145           12 :     if (netInst == nullptr) {
     146            0 :         THROW<NullPtrException>(StringFormat("[RankGraphBuilder][AddFabricInfo] rankGraph->GetNetInstanceByRankId is nullptr"));
     147              :     } 
     148              : 
     149           12 :     if (netInst->GetNetType() != NetType::CLOS) {
     150            0 :         THROW<NotSupportException>(StringFormat("[RankGraphBuilder][AddFabricInfo] NetInstance is not CLOS, not support add fabric."));
     151              :     }
     152           12 :     set<RankId> inRanks = netInst->GetRankIds();
     153           12 :     string      netInstId = netInst->GetNetInstId();
     154           12 :     const auto &myLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[myRank_], netLayer);
     155              :     // 根据planeId确认Fabric个数,每个fabricId对应一个planeId
     156           12 :     std::map<PlaneId, FabricId> planeId2Node = GetFabricsFromAddrInfo(myLevelInfo.rankAddrs);
     157              : 
     158           12 :     if (planeId2Node.size() == 0) {
     159            0 :         HCCL_WARNING("[RankGraphBuilder][AddFabricInfo] current rankId[%d] netLayer[%u] group no net plane", myRank_, netLayer);
     160            0 :         return;
     161              :     }
     162           12 :     vector<shared_ptr<NetInstance::Fabric>> fabNodes(planeId2Node.size(), nullptr);
     163              : 
     164              :     // 遍历每一个rankId,每个rankId都增加 peer2net 和 net2peer 两条链路
     165           60 :     for (RankId srcRankId : inRanks) {
     166           48 :         const auto &srcLevelInfo = GetRankLevelInfoByNetLayer(rankTable_->ranks[srcRankId], netLayer);
     167           48 :         const vector<AddressInfo> &addrs = srcLevelInfo.rankAddrs;
     168              :         // rankId对应的物理逻辑localId
     169           48 :         LocalId localId  = rankGraph_->GetLocalId(srcRankId);
     170              :         // 从物理拓扑图中找出 localId在 netLayer 中所有的peer2Net的边。
     171           48 :         std::vector<shared_ptr<PhyTopo::Link>> links = GetPeer2NetPhyLinks(netLayer, localId);
     172              :         // 遍历ranktable中的addr,有几个addr就有几条peer2net的边
     173           96 :         for (AddressInfo addrInfo: addrs) {
     174           48 :             if (addrInfo.addr == IpAddress()) {
     175            0 :                 continue;
     176              :             }
     177              : 
     178           48 :             if (planeId2Node.count(addrInfo.planeId) == 0) {
     179            0 :                 continue;
     180              :             }
     181           48 :             FabricId fabId = planeId2Node[addrInfo.planeId];
     182              :             // 若 fabNodes[fabId] 不存在则创建 如果存在则获取fabNode
     183           48 :             shared_ptr<NetInstance::Fabric> fabNode;
     184           48 :             if (fabNodes[fabId] == nullptr) {
     185           12 :                 fabNode = make_shared<NetInstance::Fabric>(fabId, addrInfo.planeId);
     186           12 :                 tempNetInsts_[netLayer][netInstId]->AddNode(fabNode);
     187           12 :                 fabNodes[fabId] = fabNode;
     188              :             } else {
     189           36 :                 fabNode = fabNodes[fabId];
     190              :             }
     191              :             // 插入peer和fabric的peer2net和net2peer两条link
     192           48 :             AddPeer2NetLink(netLayer, netInstId, srcRankId, addrInfo, fabNode, links);
     193           48 :         }
     194           48 :     }
     195              : 
     196           32 :     HCCL_DEBUG("[RankGraphBuilder][AddFabricInfo] netLayer [%u] netInstId[%s] Add Fabric Info success!", netLayer,
     197              :                netInstId.c_str());
     198           12 : }
     199              : 
     200           18 : void RankGraphBuilder::AddTopoDescFabricInfo()
     201              : {
     202              :     // 1. 获取物理拓扑图
     203           18 :     auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(0);
     204           18 :     if (phyTopoGraph == nullptr) {
     205            0 :         THROW<NullPtrException>(StringFormat("[RankGraphBuilder][AddTopoDescFabricInfo] phyTopoGraph is nullptr"));
     206              :     }
     207           46 :     HCCL_INFO("[RankGraphBuilder][AddTopoDescFabricInfo] Successfully retrieved phyTopoGraph");
     208              : 
     209              :     // 2. 获取当前 NetInstance
     210           18 :     NetInstance* innerNetInstance = rankGraph_->GetNetInstanceByRankId(0, myRank_);
     211           18 :     if (innerNetInstance == nullptr) {
     212            0 :         THROW<NullPtrException>(
     213            0 :             StringFormat("[RankGraphBuilder][AddTopoDescFabricInfo] rankGraph->GetNetInstanceByRankId is nullptr"));
     214              :     }
     215           18 :     std::string netInstId = innerNetInstance->GetNetInstId();
     216           18 :     std::set<RankId> rankIds = innerNetInstance->GetRankIds();
     217              : 
     218              :     // 存储所有fabric节点,key为topoInstId
     219           18 :     std::map<u32, std::shared_ptr<NetInstance::Fabric>> fabNodes;
     220              : 
     221           18 :     auto peer = rankGraph_->GetPeer(rankGraph_->GetMyRank());
     222           18 :     auto localDeviceId = peer->GetDeviceId();
     223              : 
     224              :     // 3. 遍历所有rank节点,根据topoInstId创建fabric节点
     225           68 :     for (RankId rankId : rankIds) {
     226           50 :         LocalId localId = rankGraph_->GetLocalId(rankId);
     227           50 :         auto peer2netEdges = phyTopoGraph->GetEdges(localId, PhyTopo::Fabric::GetId());
     228              : 
     229          134 :         HCCL_RUN_INFO(
     230              :             "[RankGraphBuilder][AddTopoDescFabricInfo] Processing rank %d (localId: %u), found %zu peer2net edges",
     231              :             rankId, localId, peer2netEdges.size());
     232              : 
     233          126 :         for (const auto& link : peer2netEdges) {
     234           76 :             u32 topoInstId = link->GetTopoInstId();
     235           76 :             auto topoType = link->GetTopoType();
     236              : 
     237              :             // 创建Fabric节点
     238           76 :             if (fabNodes.find(topoInstId) == fabNodes.end()) {
     239           34 :                 auto fabNodePtr = std::make_shared<NetInstance::Fabric>(topoInstId);
     240           34 :                 innerNetInstance->AddNode(fabNodePtr);
     241           34 :                 fabNodes[topoInstId] = fabNodePtr;
     242           98 :                 HCCL_INFO("[RankGraphBuilder][AddTopoDescFabricInfo] Created new Fabric node for topoInstId: %u",
     243              :                           topoInstId);
     244           34 :             }
     245              : 
     246              :             // 获取 peer 节点
     247           76 :             auto peerNode = peers_.at(rankId);
     248              : 
     249              :             // 构造连接接口
     250              :             auto peerIfaces =
     251           76 :                 ConstructConnIFromPhyTopoConnIAndPortMap(link->GetSourceIFace(), peerNode->GetPortAddrMapLayer0(), topoType, topoInstId, localDeviceId);
     252              : 
     253          136 :             for (const auto& iface : peerIfaces) {
     254           60 :                 peerNode->AddConnInterface(0, iface);
     255              :             }
     256           76 :             auto fabNodePtr = fabNodes[topoInstId];
     257              :             // 构造 peer2netLink 和 net2peerLink(双向)
     258          136 :             for (const auto& iface : peerIfaces) {
     259            0 :                 auto peer2netLink = std::make_shared<NetInstance::Link>(peerNode, fabNodePtr, iface, nullptr,
     260          120 :                                                                         LinkType::PEER2NET, link->GetLinkProtocols(),
     261          120 :                                                                         LinkDirection::BOTH, 2);
     262              : 
     263            0 :                 auto net2peerLink = std::make_shared<NetInstance::Link>(fabNodePtr, peerNode, nullptr, iface,
     264          120 :                                                                         LinkType::PEER2NET, link->GetLinkProtocols(),
     265          120 :                                                                         LinkDirection::BOTH, 2);
     266              : 
     267              :                 // 插入 link
     268           60 :                 tempNetInsts_[0][netInstId]->AddLink(peer2netLink);
     269           60 :                 tempNetInsts_[0][netInstId]->AddLink(net2peerLink);
     270           60 :                 tempNetInsts_[0][netInstId]->UpdateTopoInst(topoInstId, topoType, rankId);
     271          172 :                 HCCL_RUN_INFO("[RankGraphBuilder][AddTopoDescFabricInfo] netLayer0 rankId[%u] netInstId[%s] Add Fabric "
     272              :                               "Info success!",
     273              :                               rankId, netInstId.c_str());
     274           60 :             }
     275           76 :         }
     276           50 :     }
     277           46 :     HCCL_INFO("[RankGraphBuilder][AddTopoDescFabricInfo] Successfully completed fabric link construction");
     278           18 : }
     279              : 
     280           12 : std::map<PlaneId, FabricId> GetFabricsFromAddrInfo(const std::vector<AddressInfo>& rankAddrs)
     281              : {
     282           12 :     std::map<PlaneId, FabricId> planeId2FabricId;
     283           24 :     for (const auto& addrInfo : rankAddrs) {
     284           12 :         if (planeId2FabricId.count(addrInfo.planeId) == 0) {
     285           12 :             FabricId fabId = planeId2FabricId.size();
     286           12 :             planeId2FabricId[addrInfo.planeId] = fabId;
     287              :         }
     288              :     }
     289           12 :     return planeId2FabricId;
     290            0 : }
     291              : 
     292           99 : void RankGraphBuilder::CheckNetLayerFromPhyTopo(const u32 netLayer) const
     293              : {
     294           99 :     if (!PhyTopo::GetInstance()->IsNetLayerExisted(netLayer)) {
     295            1 :         THROW<InvalidParamsException>(StringFormat("[RankGraphBuilder][CheckNetLayerFromPhyTopo]"
     296              :             "netLayer[%u] not exist in topo.", netLayer));
     297              :     }
     298           98 : }
     299              : 
     300              : // 根据ranktable构造添加peers和NetInstances, NetInstance添加nodes和links(peer2net)
     301              : // 1. 创建NetInstance ( 每个NetInstance 添加 Rank, Node, Link);
     302              : // 2. RankGraph中添加NetInstance, Peer, Fabric,
     303           19 : void RankGraphBuilder::BuildFromRankTable()
     304              : {
     305              :     // 保存NetInstance指针以便后续执行Add操作
     306           19 :     tempNetInsts_.resize(MAX_NET_LAYER);   //为了方便修改RankGraph的NetInstance,共享指针。
     307              : 
     308              :     // 遍历rankTable每一个rank, virtualTopo添加Peers
     309           69 :     for (const auto &rankInfo : rankTable_->ranks) {
     310           51 :         updaterFor64Plus1_.SaveReplaceInfo(rankInfo);   // 暂存备份替换信息
     311           51 :         RankId rankId = rankInfo.rankId;
     312           51 :         shared_ptr<NetInstance::Peer> peer = make_shared<NetInstance::Peer>(rankId, rankInfo.localId, rankInfo.replacedLocalId, rankInfo.deviceId, rankInfo.devicePort, rankInfo.hostPort);
     313           51 :         rankGraph_->AddPeer(peer);
     314           51 :         peers_.emplace(rankId, peer);  // rankid2peer
     315              : 
     316              :         // 构造当前rank的每个LevelInfo所在NetInstance, 添加 RankId 和 Peer
     317          149 :         for (const auto &levelInfo : rankInfo.rankLevelInfos) {
     318              :             // 校验netLayer是否在topo中
     319           99 :             CheckNetLayerFromPhyTopo(levelInfo.netLayer);
     320              :             // rankLevelInfo.level、id对应NetInstance,若不存在则创建
     321           98 :             auto curNetInstance = GetOrCreateNetInstance(levelInfo.netLayer, levelInfo.netInstId, levelInfo.netType, tempNetInsts_, rankGraph_.get());
     322           98 :             if (curNetInstance == nullptr) {
     323            0 :                 continue;
     324              :             }
     325              :             // NetInstance add Peer
     326           98 :             curNetInstance->AddRankId(rankId);
     327           98 :             curNetInstance->AddNode(peer);
     328              :             // Peer add NetInstance
     329           98 :             peer->AddNetInstance(curNetInstance);
     330           98 :             if (levelInfo.netLayer == 0) {
     331           50 :                 peer->SetPortPortAddrMapLayer0(levelInfo.portAddrMap);
     332              :             }
     333          262 :             HCCL_DEBUG("[RankGraphBuilder][BuildFromRankTable] rankLevelInfo : rankId[%d] level[%u] "
     334              :                        "netInstId[%s] fabricType[%s].",
     335              :                        rankId, levelInfo.netLayer, levelInfo.netInstId.c_str(),
     336              :                        levelInfo.netType.Describe().c_str());
     337           98 :         }
     338           51 :     }
     339              : 
     340              :     // 对 myrank 所在每个level的NetInstance 添加 Fabrics 和 links(peer2net)
     341           18 :     set<u32> myLevels = rankGraph_->GetLevels(myRank_);
     342           46 :     HCCL_DEBUG("myRank netType: level size %u", myLevels.size());
     343           48 :     for (u32 level : myLevels) {
     344           30 :         if (level == 0) {
     345           18 :             AddTopoDescFabricInfo();
     346              :         } else {
     347           12 :             AddFabricInfo(level);
     348              :         }
     349              :     }
     350              : 
     351              :     // 初始化innerRanks
     352           18 :     rankGraph_->InitInnerRanks();
     353              : 
     354           46 :     HCCL_DEBUG("[RankGraphBuilder][BuildFromRankTable] Build VirtualTopo from RankTable success!");
     355           18 : }
     356              : 
     357           18 : void RankGraphBuilder::SetEndpointDesc()
     358              : {
     359           18 :     std::shared_ptr<NetInstance::Peer> peer = peers_[myRank_];
     360           18 :     CHK_PRT_THROW(peer == nullptr, HCCL_ERROR("[RankGraphBuilder::%s] fail", __func__), NullPtrException, "peer is null" );
     361              :     // 获取 peer 的 Iface
     362           18 :     std::set<u32> layers = peer->GetLevels();
     363           48 :     for (const auto& layer : layers) {
     364           30 :         auto ifacesVec = peer->GetIfacesByLayer(layer);
     365           89 :         for (const auto& iface : ifacesVec) {
     366           59 :             const auto& protocols = iface->GetLinkProtocols();
     367          118 :             for (const auto& protocol : protocols) {
     368           59 :                 EndpointDesc desc{};
     369              : 
     370           59 :                 HcclResult ret = GetCommAddr(desc.commAddr, iface->GetAddr());
     371           59 :                 CHK_PRT_THROW(ret != HCCL_SUCCESS, HCCL_ERROR("[RankGraphBuilder::%s] fail", __func__), InternalException, "GetCommAddr fail" );
     372              : 
     373           59 :                 desc.protocol = LinkProtocolToCommProtocol(protocol);
     374           59 :                 desc.loc.locType = AddrPositionToEndpointLoc(iface->GetPos());
     375              : 
     376          165 :                 HCCL_INFO("[RankGraphBuilder::SetEndpointDesc] local type[%d] protocol[%d]",
     377              :                           desc.loc.locType, desc.protocol);
     378              : 
     379           59 :                 peer->SetEndpointToIface(desc.commAddr, desc.protocol, iface);
     380              :             }
     381           59 :         }
     382           30 :     }
     383           18 : }
     384              : 
     385            0 : std::shared_ptr<NetInstance> RankGraphBuilder::GetNetInstance(const RankLevelInfo &levelInfo){
     386            0 :     auto it = tempNetInsts_[levelInfo.netLayer].find(levelInfo.netInstId);
     387            0 :     if (it == tempNetInsts_[levelInfo.netLayer].end()) {
     388            0 :         return nullptr;
     389              :     }
     390              :     // 若NetInstance存在, type不一致则报错
     391            0 :     NetType netType = it->second->GetNetType();
     392            0 :     if (netType != levelInfo.netType) {
     393            0 :         HCCL_WARNING("[CreateNetInstance]FabType [%s] and [%s] no match", netType.Describe().c_str(),
     394              :                         levelInfo.netType.Describe().c_str());
     395            0 :         return nullptr;
     396              :     }
     397            0 :     return it->second;
     398              : }
     399              : 
     400            0 : std::shared_ptr<NetInstance> RankGraphBuilder::CreateNetInstance(const RankLevelInfo &levelInfo)
     401              : {
     402            0 :     std::shared_ptr<NetInstance> netInst;
     403            0 :     if (levelInfo.netType == NetType::TOPO_FILE_DESC) {
     404            0 :         netInst = std::make_shared<InnerNetInstance>(levelInfo.netLayer, levelInfo.netInstId);
     405            0 :     } else if (levelInfo.netType == NetType::CLOS) {
     406            0 :         netInst = std::make_shared<ClosNetInstance>(levelInfo.netLayer, levelInfo.netInstId);
     407              :     } else {
     408            0 :         THROW<NotSupportException>(StringFormat("[RankGraphBuilder][CreateNetInstance] netType: %s is not support", levelInfo.netType));
     409              :     }
     410            0 :     return netInst;
     411            0 : }
     412              : 
     413              : // 从phytopo和ranktable中读取数据共同构建peer2peer的边。
     414           18 : void RankGraphBuilder::BuildPeer2PeerLinks()
     415              : {
     416           18 :     auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(0);
     417           18 :     if (phyTopoGraph == nullptr) {
     418            0 :         THROW<NullPtrException>(StringFormat("[RankGraphBuilder][BuildPeer2PeerLinks] phyTopoGraph is nullptr"));
     419              :     }
     420              :     // 遍历innerNetInstance中的每两个rankId之间是否存在边,存在则添加peer2peerlink
     421           18 :     NetInstance *innerNetInstance = rankGraph_->GetNetInstanceByRankId(0, myRank_);
     422           18 :     if (innerNetInstance == nullptr) {
     423            0 :         THROW<NullPtrException>(StringFormat("[RankGraphBuilder][BuildPeer2PeerLinks] innerNetInstance is nullptr"));
     424              :     }
     425           18 :     set<RankId> rankIds = innerNetInstance->GetRankIds();
     426              : 
     427           18 :     auto peer = rankGraph_->GetPeer(rankGraph_->GetMyRank());
     428           18 :     auto localDeviceId = peer->GetDeviceId();
     429           68 :     for (const auto srcRankId : rankIds) {
     430          212 :         for (const auto dstRankId : rankIds) {
     431          162 :            if (srcRankId == dstRankId) {
     432           56 :                 continue;
     433              :            }
     434              : 
     435              :            // 得到phyTopoGraph中对应的localId
     436          112 :            LocalId srcLocalId = rankGraph_->GetLocalId(srcRankId);
     437          112 :            LocalId dstLocalId = rankGraph_->GetLocalId(dstRankId);
     438          112 :            if (srcLocalId == BACKUP_LOCAL_ID || dstLocalId == BACKUP_LOCAL_ID) {
     439            6 :                 continue;
     440              :            }
     441              : 
     442          106 :            std::vector<shared_ptr<PhyTopo::Link>> phyLinks = GetPeer2PeerPhyLinks(phyTopoGraph, srcLocalId, dstLocalId);
     443              :            // 根据ports在ranktable找对对应的地址,几个地址就有几条link。
     444              : 
     445          106 :            shared_ptr<NetInstance::Peer> srcPeer = peers_.at(srcRankId);
     446          106 :            shared_ptr<NetInstance::Peer> dstPeer = peers_.at(dstRankId);
     447              : 
     448          200 :            for (shared_ptr<PhyTopo::Link> phyLink : phyLinks) {
     449              :                 auto sourceIfaces = ConstructConnIFromPhyTopoConnIAndPortMap(
     450           94 :                     phyLink->GetSourceIFace(), srcPeer->GetPortAddrMapLayer0(), phyLink->GetTopoType(), phyLink->GetTopoInstId(), localDeviceId);
     451              :                 auto targetIfaces = ConstructConnIFromPhyTopoConnIAndPortMap(
     452           94 :                     phyLink->GetTargetIFace(), dstPeer->GetPortAddrMapLayer0(), phyLink->GetTopoType(), phyLink->GetTopoInstId(), localDeviceId);
     453           94 :                 if (sourceIfaces.empty() || targetIfaces.empty()) {
     454              :                     // 没有可用的接口。
     455            0 :                     HCCL_WARNING("[RankGraphBuilder][BuildPeer2PeerLinks] no available interface, "
     456              :                         "srcRankId[%u] dstRankId[%u].", srcRankId, dstRankId);
     457            0 :                     continue;
     458            0 :                 }
     459           94 :                 srcPeer->AddConnInterfaces(0, sourceIfaces);
     460           94 :                 dstPeer->AddConnInterfaces(0, targetIfaces);
     461              :                 std::vector<shared_ptr<NetInstance::Link>> links =
     462           94 :                     ConstructLinks(srcPeer, dstPeer, sourceIfaces, targetIfaces, phyLink);
     463          188 :                 for (auto link : links) {
     464           94 :                     innerNetInstance->AddLink(link);
     465           94 :                 }
     466           94 :            }
     467          106 :         }
     468              :     }
     469           18 : }
     470              : 
     471           18 : void RankGraphBuilder::UpdateTopoInstForMyRankOnly()
     472              : {
     473           18 :     auto innerNetInstance = rankGraph_->GetNetInstanceByRankId(0, myRank_);
     474           18 :     if (innerNetInstance == nullptr) {
     475            0 :         THROW<NullPtrException>(StringFormat("[RankGraphBuilder][UpdateTopoInstForMyRankOnly] innerNetInstance is nullptr"));
     476              :     }
     477              : 
     478           18 :     auto netInstId = innerNetInstance->GetNetInstId();
     479           18 :     set<RankId> rankIds = innerNetInstance->GetRankIds();
     480              : 
     481           18 :     auto phyTopoGraph = PhyTopo::GetInstance()->GetTopoGraph(0);
     482           18 :     if (phyTopoGraph == nullptr) {
     483            0 :         THROW<NullPtrException>(StringFormat("[RankGraphBuilder][UpdateTopoInstForMyRankOnly] phyTopoGraph is nullptr"));
     484              :     }
     485           18 :     if (rankIds.size() == 1) {
     486              :         // 单卡场景直接返回1DMESH
     487            2 :         RankId singleId = *rankIds.begin();
     488            2 :         tempNetInsts_[0][netInstId]->UpdateTopoInst(0, TopoType::MESH_1D, singleId);
     489            2 :         return;
     490              :     }
     491              : 
     492           64 :     for (const auto srcRankId : rankIds) {
     493          208 :         for (const auto dstRankId : rankIds) {
     494              :             // 只处理涉及 myRank_ 的边
     495          160 :             if (srcRankId != myRank_ && dstRankId != myRank_) {
     496           80 :                 continue;
     497              :             }
     498              : 
     499           80 :             LocalId srcLocalId = rankGraph_->GetLocalId(srcRankId);
     500           80 :             LocalId dstLocalId = rankGraph_->GetLocalId(dstRankId);
     501              : 
     502           80 :             std::vector<shared_ptr<PhyTopo::Link>> phyLinks = GetPeer2PeerPhyLinks(phyTopoGraph, srcLocalId, dstLocalId);
     503              : 
     504          134 :             for (shared_ptr<PhyTopo::Link> phyLink : phyLinks) {
     505           54 :                 u32 topoInstId = phyLink->GetTopoInstId();
     506           54 :                 auto topoType = phyLink->GetTopoType();
     507           54 :                 tempNetInsts_[0][netInstId]->UpdateTopoInst(topoInstId, topoType, dstRankId);
     508           54 :             }
     509           80 :         }
     510              :     }
     511           22 : }
     512              : 
     513          264 : std::vector<std::shared_ptr<NetInstance::ConnInterface>> ConstructConnIFromPhyTopoConnIAndPortMap(
     514              :         std::shared_ptr<PhyTopo::ConnInterface> phyConnIFace, const std::map<std::string, std::vector<IpAddress>>& portAddrMap, 
     515              :         const TopoType topoType, const u32 topoInstId, u32 localDeviceId) {
     516          264 :     std::vector<std::shared_ptr<NetInstance::ConnInterface>> netConnIFaces;
     517          264 :     std::set<string> phyPorts = phyConnIFace->GetPorts();
     518          264 :     std::map<IpAddress, std::set<string>> addr2Ports;
     519          544 :     for (auto port: phyPorts) {
     520          280 :         if (*(phyConnIFace->GetLinkProtocols().begin()) == LinkProtocol::PCIE) {
     521            0 :             IpAddress tempIp;
     522            0 :             HrtRaSocketGetVnicIpInfos(localDeviceId, DeviceIdType::DEVICE_ID_TYPE_PHY_ID, localDeviceId, tempIp);
     523            0 :             auto it = addr2Ports.find(tempIp);
     524            0 :             if (it == addr2Ports.end()) {
     525            0 :                 std::set<std::string> newPorts;
     526            0 :                 newPorts.insert("d2h");
     527            0 :                 addr2Ports[tempIp] = newPorts;
     528            0 :             } else {
     529            0 :                 it->second.insert("d2h");
     530              :             }
     531              :         } else {
     532          280 :             auto itPort = portAddrMap.find(port);
     533          280 :             if (itPort == portAddrMap.end()) {
     534           84 :                 HCCL_WARNING("[RankGraphBuilder][ConstructConnIFromPhyTopoConnIAndPortMap] topo use port [%s] not find addrs in ranktable.", port.c_str());
     535           28 :                 continue;
     536           28 :             }
     537          504 :             for (auto addr : itPort->second) {
     538          252 :                 auto it = addr2Ports.find(addr);
     539          252 :                 if (it == addr2Ports.end()) {
     540          248 :                     std::set<std::string> newPorts;
     541          248 :                     newPorts.insert(port);
     542          248 :                     addr2Ports[addr] = newPorts;
     543          248 :                 } else {
     544           12 :                     it->second.insert("8080");
     545              :                 }
     546              :             }
     547              :         }
     548          280 :     }
     549              : 
     550          512 :     for (auto it = addr2Ports.begin(); it != addr2Ports.end(); ++it) {
     551          248 :         auto linkType = *(phyConnIFace->GetLinkProtocols().begin()) == LinkProtocol::PCIE ? LinkType::PEER2NET : LinkType::PEER2PEER;
     552              :         shared_ptr<NetInstance::ConnInterface> netConnIFace =
     553          248 :             make_shared<NetInstance::ConnInterface>(it->first, it->second, phyConnIFace->GetPos(), linkType,
     554          496 :                                                     phyConnIFace->GetLinkProtocols(), topoType, topoInstId);
     555          248 :         netConnIFaces.push_back(netConnIFace);
     556          248 :     }
     557          264 :     return netConnIFaces;
     558          264 : }
     559              : 
     560           94 : std::vector<shared_ptr<NetInstance::Link>> ConstructLinks(shared_ptr<NetInstance::Peer> srcPeer, shared_ptr<NetInstance::Peer> dstPeer,
     561              :         std::vector<std::shared_ptr<NetInstance::ConnInterface>> sourceIfaces,
     562              :         std::vector<std::shared_ptr<NetInstance::ConnInterface>> targetIfaces, shared_ptr<PhyTopo::Link> phyLink) 
     563              : {
     564           94 :     std::vector<shared_ptr<NetInstance::Link>> links;
     565          188 :     for (auto sourceIFace : sourceIfaces) {
     566          188 :         for (auto targetIFace : targetIfaces) {
     567              :             shared_ptr<NetInstance::Link> link = make_shared<NetInstance::Link>(srcPeer, dstPeer, sourceIFace, targetIFace,
     568           94 :                                                                           LinkType::PEER2PEER, phyLink->GetLinkProtocols());
     569           94 :             links.push_back(link);
     570           94 :         }
     571           94 :     }
     572           94 :     return links;
     573            0 : }
     574              : 
     575          186 : std::vector<std::shared_ptr<PhyTopo::Link>> GetPeer2PeerPhyLinks(std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> phyTopoGraph, LocalId srcLocalId, LocalId dstLocalId)
     576              : {
     577          186 :     std::vector<shared_ptr<PhyTopo::Link>> links;
     578          186 :     if (!phyTopoGraph->HasNode(srcLocalId) || !phyTopoGraph->HasNode(dstLocalId)) {
     579            0 :         HCCL_WARNING("[RankGraphBuilder][BuildFromPhytopo] srcLocalId[%u] dstLocalId[%u] not exist in phyTopoGraph.",
     580              :             srcLocalId,
     581              :             dstLocalId);
     582            0 :         return links;
     583              :     }
     584              :     // 得到phyTopoGraph对应的NodeId
     585          186 :     NodeId srcNodeId = PhyTopo::Peer::GetId(srcLocalId);
     586          186 :     NodeId dstNodeId = PhyTopo::Peer::GetId(dstLocalId);
     587              : 
     588          186 :     phyTopoGraph->TraverseEdge(srcNodeId, dstNodeId, [&](shared_ptr<PhyTopo::Link> link) {
     589          148 :         if (link != nullptr) {
     590          148 :             links.push_back(link);
     591              :         }
     592          148 :     });
     593          186 :     if (links.empty()) {
     594           90 :         HCCL_WARNING(
     595              :             "[RankGraphBuilder][GetPeer2PeerPhyLinks] srcLocalId[%u] dstLocalId[%u] edge does not exist.", srcLocalId, dstLocalId);
     596              :     }
     597          186 :     return links;
     598            0 : }
     599              : 
     600           21 : void RankGraphBuilder::CheckMyRankInRankTable() const
     601              : {
     602           21 :     if (myRank_ >= static_cast<s32>(rankTable_->rankCount)) {
     603            1 :         THROW<InvalidParamsException>(StringFormat("[RankGraphBuilder][CheckMyRankInRankTable]"
     604            1 :             "myRank[%d] is not in rankTable rankCount[%u].", myRank_, rankTable_->rankCount));
     605              :     }
     606           20 : }
     607              : 
     608           21 : void RankGraphBuilder::BuildRankGraph()
     609              : {
     610              :     // 创建VirtualTopo
     611           21 :     rankGraph_ = make_unique<RankGraph>(myRank_);
     612              : 
     613              :     // 校验myRank在rankTable中
     614           21 :     CheckMyRankInRankTable();
     615              : 
     616              :     // 根据ranktable构造添加peers和NetInstances, 每个NetInstance添加nodes和links(peer2net)
     617           20 :     BuildFromRankTable();
     618              : 
     619              :     // 根据phytopo构造添加InnerGroup中的links(peer2peer), 不包括备份节点
     620           19 :     BuildPeer2PeerLinks();
     621              : 
     622              :     // 使用备份D时需要修改虚拟拓扑
     623           19 :     updaterFor64Plus1_.UpdateRankGraph(rankGraph_.get(), rankTable_.get());
     624              : 
     625              :     // 为myrank的peer2peer更新topoInst
     626           19 :     UpdateTopoInstForMyRankOnly();
     627              : 
     628              :     // 添加绕路 绕路获取
     629           19 :     DetourService::GetInstance().InsertDetourLinks(rankGraph_.get(), rankTable_.get());
     630              : 
     631              :     // 设置endpoint
     632           19 :     SetEndpointDesc();
     633              : 
     634              :     // 构造完成
     635           19 :     rankGraph_->InitFinish();
     636           19 : }
     637              : 
     638            6 : std::unique_ptr<RankTableInfo> RankGraphBuilder::GetRankTableInfo()
     639              : {
     640            6 :     return move(rankTable_);
     641              : }
     642              : 
     643            5 : std::shared_ptr<TopoInfo> RankGraphBuilder::GetTopoInfo()
     644              : {
     645            5 :     return  topoInfo_;
     646              : }
     647              : 
     648            5 : unique_ptr<RankGraph> RankGraphBuilder::RecoverBuild(const RankTableInfo &rankTableInfo,const TopoInfo &topoInfo, RankId myRank)
     649              : {
     650            5 :     topoInfo_ = std::make_shared<TopoInfo>(topoInfo);
     651            5 :     PhyTopoBuilder::GetInstance().RecoverBuild(*topoInfo_);
     652              : 
     653            5 :     rankTable_ = make_unique<RankTableInfo>(rankTableInfo);
     654            5 :     HCCL_INFO("[%s] RankTable[%s] RankTableInfo[%s]", __func__, rankTable_->Describe().c_str(),
     655              :               rankTableInfo.Describe().c_str());
     656              : 
     657            5 :     this->myRank_ = myRank;
     658            5 :     BuildRankGraph();
     659              : 
     660            4 :     HCCL_INFO("[RankGraphBuilder] Build VirtualTopo success!");
     661            4 :     rankGraph_->Dump();
     662            4 :     return std::move(rankGraph_);
     663              : }
     664              : 
     665              : } // namespace Hccl
        

Generated by: LCOV version 2.0-1