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

Generated by: LCOV version 2.0-1