LCOV - code coverage report
Current view: top level - coll_communicator_mgr/rank_graph/phy_topo_builder - phy_topo_builder.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 89.4 % 160 143
Test Date: 2026-07-28 12:11:00 Functions: 100.0 % 13 13

            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 "phy_topo_builder.h"
      12              : #include "log.h"
      13              : #include "json_parser.h"
      14              : #include "exception_util.h"
      15              : #include "null_ptr_exception.h"
      16              : #include "invalid_params_exception.h"
      17              : #include "adapter_error_manager_pub.h"
      18              : 
      19              : namespace Hccl {
      20              : 
      21           48 : PhyTopoBuilder &PhyTopoBuilder::GetInstance()
      22              : {
      23           48 :     static PhyTopoBuilder phyTopoBuilder;
      24           48 :     return phyTopoBuilder;
      25              : }
      26              : 
      27              : // 根据nodeType和localId创建节点
      28           70 : std::shared_ptr<PhyTopo::Node> CreateNode(const PhyTopo::Node::NodeType nodeType, const LocalId localId)
      29              : {
      30           70 :     if (nodeType == PhyTopo::Node::NodeType::PEER) {
      31           54 :         return std::make_shared<PhyTopo::Peer>(localId);
      32              :     } else {
      33           16 :         return std::make_shared<PhyTopo::Fabric>();
      34              :     }
      35              : }
      36              : 
      37           15 : void PhyTopoBuilder::Build(const std::string &topoPath)
      38              : {
      39           15 :     std::lock_guard<std::mutex> lock(phyTopoMutex);
      40              :     
      41           15 :     if (PhyTopo::GetInstance()->IsInitFinished()) {
      42           33 :         HCCL_INFO("PhyTopo has been initialized and does not need to be rebuilt");
      43           11 :         return;
      44              :     }
      45              : 
      46            4 :     if (topoPath.empty()) {
      47            0 :         RPT_INPUT_ERR(true, "EI0004", std::vector<std::string>({"ranktable_path", "error_reason"}),
      48              :                       std::vector<std::string>({"Please check the path configuration of the topo json file.",
      49              :                      "The rankTable file path does not exist, the permission is insufficient, or the JSON format is incorrect."
      50              :                       }));
      51            0 :         THROW<InvalidParamsException>("[PhyTopoBuilder::%s] Topo path is empty.", __func__);
      52              :     }
      53              : 
      54           12 :     HCCL_DEBUG("[PhyTopoBuilder::%s]Start to build physic topo.", __func__);
      55              : 
      56            4 :     auto topoInfo = LoadTopoInfo(topoPath);
      57              :     // 根据topoInfo,按netLayer构造Graph
      58           10 :     for (const auto &iter : topoInfo->edges) {
      59            6 :         auto netLayer = iter.first;
      60            6 :         auto graph = CreateGraph(iter.second);
      61            6 :         PhyTopo::GetInstance()->AddTopoGraph(netLayer, graph);
      62           18 :         HCCL_DEBUG("[PhyTopoBuilder::%s]Build netLayer[%u] topo graph success.", __func__, netLayer);
      63            6 :     }
      64              : 
      65              :     // 遍历peerList,把peerList中的localId构造peer节点,加到layer-0的graph中
      66            4 :     auto graph = PhyTopo::GetInstance()->GetTopoGraph(0);
      67            4 :     if (graph == nullptr) {
      68            0 :         HCCL_INFO("[PhyTopoBuilder::%s] layer0 graph is nullptr, build now", __func__);
      69            0 :         graph = make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>();
      70            0 :         PhyTopo::GetInstance()->AddTopoGraph(0, graph);
      71              :     }
      72           19 :     for (const auto &iter : topoInfo->peers) {
      73              :         // 判断当前layer0的graph有没有这个节点
      74           15 :         if (!graph->HasNode(iter.localId)) {
      75            0 :             auto node = CreateNode(PhyTopo::Node::NodeType::PEER, iter.localId);
      76            0 :             graph->AddNode(iter.localId, node);
      77            0 :         }
      78              :     }
      79              : 
      80            4 :     PhyTopo::GetInstance()->InitFinish();
      81              : 
      82           12 :     HCCL_DEBUG("[PhyTopoBuilder::%s]build physic topo success.", __func__);
      83            4 :     PhyTopo::GetInstance()->Dump();
      84           15 : }
      85              : 
      86            7 : std::shared_ptr<TopoInfo> PhyTopoBuilder::LoadTopoInfo(const std::string &topoPath)
      87              : {
      88            7 :     std::shared_ptr<TopoInfo> topoInfo = std::make_shared<TopoInfo>();
      89              :     // 检查是否为非法路径以及size的大小。
      90              :     struct stat fileStat;
      91            7 :     if (stat(topoPath.c_str(), &fileStat) != 0) {
      92            2 :         HCCL_ERROR("[PhyTopoBuilder][LoadTopoInfo] Get file stat failed, file path:%s, errno:%d, error: %s",
      93              :                     topoPath.c_str(), errno, strerror(errno));
      94            2 :         THROW<InvalidParamsException>("[PhyTopoBuilder][LoadTopoInfo]Get file stat failed, file path:%s, errno:%d, error: %s",
      95            2 :                                             topoPath.c_str(), errno, strerror(errno));
      96              :     }
      97              : 
      98            5 :     u64 topoFileSize = static_cast<u64>(fileStat.st_size);
      99            5 :     if (topoFileSize > SUPPORT_MAX_TOPOFILE_SIZE || topoFileSize <= 0) {
     100            1 :         HCCL_ERROR("[PhyTopoBuilder][LoadTopoInfo] topoFileSize size: %llu, topoFile must be greater than 0 and less than %u", topoFileSize, SUPPORT_MAX_TOPOFILE_SIZE);
     101            2 :         THROW<InvalidParamsException>(StringFormat(
     102              :             "[PhyTopoBuilder][LoadTopoInfo]file %s size (%llu bytes) exceeds max allowed size (%u bytes)",
     103              :              topoPath.c_str(), topoFileSize, SUPPORT_MAX_TOPOFILE_SIZE));
     104              :     }
     105              :     
     106              :     JsonParser                topoParser;
     107            4 :     topoParser.ParseFile(topoPath, *topoInfo);
     108            4 :     topoInfo_ = topoInfo;
     109            4 :     return topoInfo;
     110            3 : }
     111              : 
     112           52 : shared_ptr<PhyTopo::Link> CreatePeer2PeerLink(const LinkParams &params)
     113              : {
     114           52 :     LinkType linkType = LinkType::PEER2PEER;
     115              :     auto srcIface =
     116           52 :         std::make_shared<PhyTopo::ConnInterface>(params.localAPorts, params.position, linkType, params.protocols);
     117              :     auto dstIface =
     118           52 :         std::make_shared<PhyTopo::ConnInterface>(params.localBPorts, params.position, linkType, params.protocols);
     119           52 :     PhyTopo::LinkAttributes linkAttrs;
     120           52 :     linkAttrs.linktype = linkType;
     121           52 :     linkAttrs.protocols = params.protocols;
     122              :     auto link = std::make_shared<PhyTopo::Link>(
     123           52 :         params.srcNode, params.dstNode, linkAttrs, params.topoType, params.topoInstanceId);
     124           52 :     link->SetSourceIface(srcIface);
     125           52 :     params.srcNode->AddConnInterface(srcIface);
     126           52 :     link->SetTargetIface(dstIface);
     127           52 :     params.dstNode->AddConnInterface(dstIface);
     128          104 :     return {link};
     129           52 : }
     130              : 
     131              : 
     132          116 : shared_ptr<PhyTopo::Link> CreatePeer2NetLink(const LinkParams &params)
     133              : {
     134          116 :     LinkType linkType = LinkType::PEER2NET;
     135          116 :     auto srcIface = std::make_shared<PhyTopo::ConnInterface>(params.localAPorts, params.position, linkType, params.protocols);
     136              :     // fabric 没有ports
     137          116 :     std::set<std::string> ports{};
     138          116 :     auto dstIface =std::make_shared<PhyTopo::ConnInterface>(ports, params.position, linkType, params.protocols);
     139          116 :     PhyTopo::LinkAttributes linkAttrs;
     140          116 :     linkAttrs.linktype = linkType;
     141          116 :     linkAttrs.protocols = params.protocols;
     142              :     auto link = std::make_shared<PhyTopo::Link>(
     143          116 :         params.srcNode, params.dstNode, linkAttrs, params.topoType, params.topoInstanceId);
     144          116 :     link->SetSourceIface(srcIface);
     145          116 :     params.srcNode->AddConnInterface(srcIface);
     146          116 :     link->SetTargetIface(dstIface);
     147          116 :     params.dstNode->AddConnInterface(dstIface);
     148          232 :     return {link};
     149          116 : }
     150              : 
     151              : // 根据链路类型建链
     152          168 : shared_ptr<PhyTopo::Link> CreateLink(const LinkType linkType, const LinkParams &params)
     153              : {
     154          168 :     if (linkType == LinkType::PEER2PEER) {
     155           52 :         return CreatePeer2PeerLink(params);
     156              :     } else {
     157          116 :         return CreatePeer2NetLink(params);
     158              :     }
     159              : }
     160              : 
     161          168 : NodeId GetNodeId(const PhyTopo::Node::NodeType nodeType, LocalId localId) 
     162              : {
     163          168 :     switch (nodeType) {
     164          110 :         case  PhyTopo::Node::NodeType::PEER:
     165          110 :             return PhyTopo::Peer::GetId(localId);
     166           58 :         case  PhyTopo::Node::NodeType::FABRIC:
     167           58 :             return PhyTopo::Fabric::GetId();
     168            0 :         default:
     169            0 :             THROW<InvalidParamsException>(StringFormat("[PhyTopoBuilder]Invalid NodeType."));
     170              :             return 0;
     171              :     }
     172              : }
     173              : 
     174           21 : std::shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> PhyTopoBuilder::CreateGraph(
     175              :     const std::vector<EdgeInfo> &edges) const
     176              : {
     177           21 :     auto graph = std::make_shared<Graph<PhyTopo::Node, PhyTopo::Link>>();
     178              : 
     179          105 :     for (const auto &edgeInfo : edges) {
     180           84 :         std::shared_ptr<PhyTopo::Node> nodeA;
     181           84 :         std::shared_ptr<PhyTopo::Node> nodeB;
     182              : 
     183              :         // 生成 nodeAId,localA 始终为 PEER 类型
     184           84 :         NodeId nodeAId = GetNodeId(PhyTopo::Node::NodeType::PEER, edgeInfo.localA);
     185              :         // 获取或创建 nodeA
     186           84 :         if (!graph->HasNode(nodeAId)) {
     187           35 :             nodeA = CreateNode(PhyTopo::Node::NodeType::PEER, edgeInfo.localA);
     188           35 :             graph->AddNode(nodeAId, nodeA);
     189           61 :             HCCL_DEBUG("[PhyTopoBuilder::%s] Add node[%llu] success.", __func__, nodeAId);
     190              :         } else {
     191              :             // 使用 TraverseNode 查找 nodeA
     192           49 :             graph->TraverseNode([&nodeA, nodeAId](NodeId id, const std::shared_ptr<PhyTopo::Node> &n) {
     193          185 :                 if (id == nodeAId) {
     194           49 :                     nodeA = n;
     195              :                 }
     196          185 :             });
     197           49 :             if (nodeA == nullptr) {
     198            0 :                 HCCL_ERROR("[PhyTopoBuilder::CreateGraph] nodeAId [%llu] not found.", nodeAId);
     199            0 :                 THROW<NullPtrException>(
     200            0 :                     StringFormat("[PhyTopoBuilder::CreateGraph] Unable to find node [%llu].", nodeAId));
     201              :             }
     202              :         }
     203              : 
     204              :         // 根据 linkType 生成 nodeBId
     205           84 :         PhyTopo::Node::NodeType nodeBType;
     206           84 :         if (edgeInfo.linkType == LinkType::PEER2PEER) {
     207           26 :             nodeBType = PhyTopo::Node::NodeType::PEER;
     208              :         } else {
     209           58 :             nodeBType = PhyTopo::Node::NodeType::FABRIC;
     210              :         }
     211              : 
     212           84 :         NodeId nodeBId = GetNodeId(nodeBType, edgeInfo.localB);
     213              :         // 获取或创建 nodeB
     214           84 :         if (!graph->HasNode(nodeBId)) {
     215           35 :             nodeB = CreateNode(nodeBType, edgeInfo.localB);
     216           35 :             graph->AddNode(nodeBId, nodeB);
     217           63 :             HCCL_DEBUG("[PhyTopoBuilder::%s] Add node[%llu] success.", __func__, nodeBId);
     218              :         } else {
     219              :             // 使用 TraverseNode 查找 nodeB
     220           49 :             graph->TraverseNode([&nodeB, nodeBId](NodeId id, const std::shared_ptr<PhyTopo::Node> &n) {
     221          206 :                 if (id == nodeBId) {
     222           49 :                     nodeB = n;
     223              :                 }
     224          206 :             });
     225           49 :             if (nodeB == nullptr) {
     226            0 :                 HCCL_ERROR("[PhyTopoBuilder::CreateGraph] nodeBId [%llu] not found.", nodeBId);
     227            0 :                 THROW<NullPtrException>(
     228            0 :                     StringFormat("[PhyTopoBuilder::CreateGraph] Unable to find node [%llu].", nodeBId));
     229              :             }
     230              :         }
     231              : 
     232              :         // 双向分别创建link
     233              :         LinkParams abLinkParams{
     234              :             nodeA,
     235              :             nodeB,
     236           84 :             edgeInfo.localAPorts,
     237           84 :             edgeInfo.localBPorts,
     238              :             edgeInfo.position,
     239              :             edgeInfo.topoType,
     240           84 :             edgeInfo.topoInstId,
     241           84 :             edgeInfo.protocols
     242           84 :         };
     243           84 :         auto abLinks = CreateLink(edgeInfo.linkType, abLinkParams);
     244           84 :         graph->AddEdge(nodeAId, nodeBId, abLinks);
     245              :         LinkParams baLinkParams{
     246              :             nodeB,
     247              :             nodeA,
     248           84 :             edgeInfo.localBPorts,
     249           84 :             edgeInfo.localAPorts,
     250              :             edgeInfo.position,
     251              :             edgeInfo.topoType,
     252           84 :             edgeInfo.topoInstId,
     253           84 :             edgeInfo.protocols
     254           84 :         };
     255           84 :         auto baLinks = CreateLink(edgeInfo.linkType, baLinkParams);
     256           84 :         graph->AddEdge(nodeBId, nodeAId, baLinks);
     257           84 :     }
     258              : 
     259           21 :     return graph;
     260            0 : }
     261              : 
     262              : 
     263           11 : void PhyTopoBuilder::RecoverBuild(const TopoInfo &topoInfo)
     264              : {
     265           11 :     std::lock_guard<std::mutex> lock(phyTopoMutex);
     266              : 
     267              :     // PhyTopo::GetInstance()->ResetInstance();
     268           11 :     if (PhyTopo::GetInstance()->IsInitFinished()) {
     269            1 :         return;
     270              :     }
     271              :     // 根据topoInfo,按netLayer构造Graph
     272           21 :     for (const auto &iter : topoInfo.edges) {
     273           11 :         auto netLayer = iter.first;
     274           11 :         auto graph = CreateGraph(iter.second);
     275           11 :         PhyTopo::GetInstance()->AddTopoGraph(netLayer, graph);
     276           11 :         HCCL_DEBUG("[PhyTopoBuilder::%s]Build netLayer[%u] topo graph success.", __func__, netLayer);
     277           11 :     }
     278              : 
     279           10 :     PhyTopo::GetInstance()->InitFinish();
     280              : 
     281           10 :     HCCL_DEBUG("[PhyTopoBuilder::%s]build physic topo success.", __func__);
     282           10 :     PhyTopo::GetInstance()->Dump();
     283           11 : }
     284              : 
     285           15 : std::shared_ptr<TopoInfo> PhyTopoBuilder::GetTopoInfo() const
     286              : {
     287           15 :     return topoInfo_;
     288              : }
     289              : 
     290              : } // namespace Hccl
        

Generated by: LCOV version 2.0-1