LCOV - code coverage report
Current view: top level - coll_communicator_mgr/rank_graph/rank_graph_builder - detour_service.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 28.7 % 195 56
Test Date: 2026-07-28 12:11:00 Functions: 50.0 % 14 7

            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 "detour_service.h"
      12              : #include "env_config/env_config.h"
      13              : #include "detour_rules.h"
      14              : #include "not_support_exception.h"
      15              : 
      16              : namespace Hccl {
      17              : 
      18              : using namespace std;
      19              : 
      20              : constexpr u32 DETOUR_NODE_NUM    = 8;
      21              : constexpr u32 DETOUR_NODE_NUM_2P = 2;
      22              : constexpr u32 DETOUR_NODE_NUM_4P = 4;
      23              : 
      24           19 : DetourService &DetourService::GetInstance()
      25              : {
      26           19 :     static DetourService detourService(PhyTopo::GetInstance().get());
      27           19 :     return detourService;
      28              : }
      29              : 
      30            2 : DetourService::DetourService(const PhyTopo *phyTopo)
      31              : {
      32            2 :     this->phyTopo = phyTopo;
      33            2 : }
      34              : 
      35              : struct DetourData {
      36              :     NodeId                     detourPhyPeerId{0};
      37              :     NodeId                     srcPhyPeerId{0};
      38              :     NodeId                     dstPhyPeerId{0};
      39              :     shared_ptr<NetInstance::Peer> srcNetInstPeer{nullptr};
      40              :     shared_ptr<NetInstance::Peer> dstNetInstPeer{nullptr};
      41              : };
      42              : 
      43            0 : vector<shared_ptr<PhyTopo::Link>> GetLinks(NodeId srcId, NodeId dstId,
      44              :                                            const shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> &phyTopoGraph)
      45              : {
      46            0 :     vector<shared_ptr<PhyTopo::Link>> links;
      47            0 :     if (phyTopoGraph == nullptr) {
      48            0 :         THROW<NullPtrException>(StringFormat("[GetLinks] phyTopoGraphis nullptr"));
      49              :     }
      50            0 :     phyTopoGraph->TraverseEdge(srcId, dstId, [&](shared_ptr<PhyTopo::Link> link) {
      51            0 :         if (link != nullptr) {
      52            0 :             links.emplace_back(link);
      53            0 :             return;
      54              :         }
      55              :     });
      56              : 
      57            0 :     return links;
      58            0 : }
      59              : 
      60            0 : void AddDetourLink(NetInstance *innerNetInst, const DetourData &data,
      61              :                    const shared_ptr<Graph<PhyTopo::Node, PhyTopo::Link>> &phyTopoGraph,
      62              :                    const RankTableInfo *rankTable)
      63              : {
      64            0 :     vector<shared_ptr<PhyTopo::Link>> src2detVec = GetLinks(data.srcPhyPeerId, data.detourPhyPeerId, phyTopoGraph);
      65            0 :     vector<shared_ptr<PhyTopo::Link>> det2dstVec = GetLinks(data.detourPhyPeerId, data.dstPhyPeerId, phyTopoGraph);
      66            0 :     if (src2detVec.size() == 0 || det2dstVec.size() == 0) {
      67            0 :         return;
      68              :     }
      69            0 :     if(innerNetInst == nullptr) {
      70            0 :         THROW<NullPtrException>(StringFormat("[AddDetourLink] innerGroup is nullptr"));
      71              :     }
      72            0 :     u32 hop = 2; // 目前绕路hop一定是2
      73            0 :     for (const auto &src2detLink : src2detVec) {
      74            0 :         for (const auto &det2dstLink : det2dstVec) {
      75            0 :             LinkType     linkType     = src2detLink->GetType();
      76            0 :             std::set<LinkProtocol> linkProtocols = src2detLink->GetLinkProtocols();
      77            0 :             if (linkType != det2dstLink->GetType()) {
      78            0 :                 HCCL_WARNING(
      79              :                     "[DetourService][InsertDetourLinks][AddDetourLink] src2det[%s] det2dst[%s] linkType no match",
      80              :                     linkType.Describe().c_str(), det2dstLink->GetType().Describe().c_str());
      81            0 :                 continue;
      82            0 :             };
      83              :             // todo 是不是应该改为判断两个set是否有交集,取绕路的协议集合? 修改了一下,llt再check一下
      84            0 :             std::set<LinkProtocol> newLinkProtocols;
      85            0 :             std::set_intersection(linkProtocols.begin(), linkProtocols.end(), 
      86            0 :                                   det2dstLink->GetLinkProtocols().begin(), det2dstLink->GetLinkProtocols().end(), 
      87              :                                   std::inserter(newLinkProtocols, newLinkProtocols.begin()));
      88              : 
      89            0 :             if (newLinkProtocols.empty()) {
      90              :                 // todo 先改编译,后面再实现日志打印
      91            0 :                 continue;
      92              :             };
      93              : 
      94              :             // 从Link中获取端口集合
      95            0 :             if (src2detLink->GetSourceIFace() == nullptr || det2dstLink->GetTargetIFace() == nullptr) {
      96            0 :                 THROW<InvalidParamsException>("[DetourService][InsertDetourLinks][AddDetourLink] source ConnInterface is nullptr");
      97              :             }
      98            0 :             std::set<string> src2detPorts = src2detLink->GetSourceIFace()->GetPorts();
      99            0 :             std::set<string> det2dstPorts = det2dstLink->GetTargetIFace()->GetPorts();
     100            0 :             if (src2detPorts.size() != 1 || det2dstPorts.size() != 1) {
     101            0 :                 THROW<InvalidParamsException>("[DetourService][InsertDetourLinks][AddDetourLink] Peer to Peer port num error");
     102              :             }
     103              :             
     104              :             // 取出对应的端口,然后去ranktableInfo中查对应端口的地址信息
     105              :             // todo 逻辑判断一下只取第一个端口是否正确? 
     106            0 :             IpAddress src2detAddr = data.srcNetInstPeer->GetPortAddrMapLayer0()[*src2detPorts.begin()][0];
     107            0 :             IpAddress det2dstAddr = data.dstNetInstPeer->GetPortAddrMapLayer0()[*det2dstPorts.begin()][0];
     108              : 
     109              :             // 构造InterFace对象用于后续生成Link
     110              :             shared_ptr<NetInstance::ConnInterface> sourceIface = make_shared<NetInstance::ConnInterface>(src2detAddr, 
     111            0 :                 src2detPorts, src2detLink->GetSourceIFace()->GetPos(), LinkType::PEER2PEER, src2detLink->GetLinkProtocols(), src2detLink->GetTopoType(), src2detLink->GetTopoInstId());
     112              :             shared_ptr<NetInstance::ConnInterface> targetIface = make_shared<NetInstance::ConnInterface>(det2dstAddr,
     113            0 :                 det2dstPorts, det2dstLink->GetSourceIFace()->GetPos(), LinkType::PEER2PEER, det2dstLink->GetLinkProtocols(), det2dstLink->GetTopoType(), det2dstLink->GetTopoInstId());
     114              : 
     115              :             // 构造Link加入NetInstance中
     116              :             shared_ptr<NetInstance::Link> sendEdge
     117            0 :                 = make_shared<NetInstance::Link>(data.srcNetInstPeer, data.dstNetInstPeer, sourceIface, targetIface, linkType,
     118            0 :                                               newLinkProtocols, LinkDirection::SEND_ONLY, hop);
     119              :             shared_ptr<NetInstance::Link> recvEdge
     120            0 :                 = make_shared<NetInstance::Link>(data.dstNetInstPeer, data.srcNetInstPeer, targetIface, sourceIface, linkType,
     121            0 :                                               newLinkProtocols, LinkDirection::RECV_ONLY, hop);
     122            0 :             innerNetInst->AddLink(sendEdge);
     123            0 :             innerNetInst->AddLink(recvEdge);
     124              : 
     125            0 :             data.srcNetInstPeer->AddConnInterface(0, sourceIface);
     126            0 :             if(data.dstNetInstPeer == nullptr) {
     127            0 :                 THROW<NullPtrException>(StringFormat("[DetourService][InsertDetourLinks][AddDetourLink] dstVirtPeer is nullptr"));
     128              :             }
     129            0 :             data.dstNetInstPeer->AddConnInterface(0, targetIface);
     130              : 
     131            0 :             HCCL_DEBUG("[DetourService][AddDetourLink] add SEND_ONLY and RECV_ONLY two links: linkType[%s]"
     132              :                        " sourceIfaceAddress[%s] targetIfaceAddress[%s]",
     133              :                        linkType.Describe().c_str(),sourceIface->GetAddr().Describe().c_str(), 
     134              :                        targetIface->GetAddr().Describe().c_str());
     135            0 :         }
     136              :     }
     137              : 
     138            0 :     HCCL_DEBUG("[DetourService][AddDetourLink] srcRankId[%llu] dstRankId[%llu] srcLocalId[%llu] detourLocalId[%llu] "
     139              :                "dstLocalId[%llu] src2detVec.size[%u] det2dstVec.size[%u]",
     140              :                data.srcNetInstPeer->GetNodeId(), data.dstNetInstPeer->GetNodeId(), data.srcPhyPeerId, data.detourPhyPeerId,
     141              :                data.dstPhyPeerId, src2detVec.size(), det2dstVec.size());
     142            0 : }
     143              : 
     144           18 : std::vector<LocalId> GetInnerLocalIds(const RankGraph *rankGraph)
     145              : {
     146           18 :     if (rankGraph == nullptr) {
     147            0 :         THROW<NullPtrException>(StringFormat("[GetInnerLocalIds] rankGraph is nullptr"));
     148              :     }
     149           18 :     const NetInstance *innerNetInst = rankGraph->GetNetInstanceByRankId(0, rankGraph->GetMyRank());
     150           18 :     if (innerNetInst == nullptr) {
     151            0 :         THROW<NullPtrException>(StringFormat("[GetInnerLocalIds] innerNetInst is nullptr"));
     152              :     }
     153           18 :     set<RankId> innerRanks = innerNetInst->GetRankIds();
     154           18 :     std::vector<LocalId> localIds;
     155           68 :     for (auto &rankId : innerRanks) {
     156           50 :         localIds.emplace_back(rankGraph->GetLocalId(rankId));
     157              :     }
     158           18 :     return localIds;
     159           18 : }
     160              : 
     161            0 : bool IsInSameRow(const std::vector<LocalId> &localIds)
     162              : {
     163            0 :     int preRowId = -1;
     164            0 :     for (auto &localId : localIds) {
     165            0 :         int curRowId = localId / DETOUR_NODE_NUM;
     166            0 :         if (preRowId == -1) {
     167            0 :             preRowId = curRowId;
     168              :         } else {
     169            0 :             if (curRowId != preRowId) {
     170            0 :                 return false;
     171              :             }
     172              :         }
     173              :     }
     174            0 :     return true;
     175              : }
     176              : 
     177            0 : bool IsInSameCol(const std::vector<LocalId> &localIds)
     178              : {
     179            0 :     int preColId = -1;
     180            0 :     for (auto &localId : localIds) {
     181            0 :         int curColId = localId % DETOUR_NODE_NUM;
     182            0 :         if (preColId == -1) {
     183            0 :             preColId = curColId;
     184              :         } else {
     185            0 :             if (curColId != preColId) {
     186            0 :                 return false;
     187              :             }
     188              :         }
     189              :     }
     190            0 :     return true;
     191              : }
     192              : 
     193            0 : bool GetTableIds(const std::vector<LocalId> &localIds, std::unordered_map<LocalId, u32> &tableIds,
     194              :                  std::set<u32> &tableIdSet)
     195              : {
     196            0 :     if (IsInSameRow(localIds)) {
     197            0 :         for (auto &localId : localIds) {
     198            0 :             u32 tableId       = localId % DETOUR_NODE_NUM;
     199            0 :             tableIds[localId] = tableId;
     200            0 :             tableIdSet.emplace(tableId);
     201              :         }
     202            0 :     } else if (IsInSameCol(localIds)) {
     203            0 :         for (auto &localId : localIds) {
     204            0 :             u32 tableId       = localId / DETOUR_NODE_NUM;
     205            0 :             tableIds[localId] = tableId;
     206            0 :             tableIdSet.emplace(tableId);
     207              :         }
     208              :     } else {
     209            0 :         HCCL_WARNING("[DetourService][GetTableIds] The ranks localIds are not in the same row or column.");
     210            0 :         return false;
     211              :     }
     212            0 :     return true;
     213              : }
     214              : 
     215            4 : void SetDetourTable4P(const std::set<u32>                                             &tableIdSet,
     216              :                       unordered_map<LocalId, unordered_map<LocalId, vector<LocalId>>> &detourTable)
     217              : {
     218           12 :     if (tableIdSet == std::set<u32>{0, 1, 2, 3}) { // tableId必须为 0 1 2 3,才能使用DETOUR4PTABLE_0123绕路
     219            1 :         detourTable = GetDetour4PTable0123();
     220            1 :         HCCL_DEBUG("[DetourService] selected detour table is DETOUR4PTABLE_0123");
     221            9 :     } else if (tableIdSet == std::set<u32>{4, 5, 6, 7}) { // tableId必须为 4 5 6 7,才能使用DETOUR4PTABLE_4567绕路
     222            1 :         detourTable = GetDetour4PTable4567();
     223            1 :         HCCL_DEBUG("[DetourService] selected detour table is DETOUR4PTABLE_4567");
     224            6 :     } else if (tableIdSet == std::set<u32>{0, 2, 4, 6}) { // tableId必须为 0 2 4 6,才能使用DETOUR4PTABLE_0246绕路
     225            1 :         detourTable = GetDetour4PTable0246();
     226            1 :         HCCL_DEBUG("[DetourService] selected detour table is DETOUR4PTABLE_0246");
     227            3 :     } else if (tableIdSet == std::set<u32>{1, 3, 5, 7}) { // tableId必须为 1 3 5 7,才能使用DETOUR4PTABLE_1357绕路
     228            1 :         detourTable = GetDetour4PTable1357();
     229            1 :         HCCL_DEBUG("[DetourService] selected detour table is DETOUR4PTABLE_1357");
     230              :     } else {
     231            0 :         HCCL_WARNING("no matched detourTable found");
     232              :     }
     233            4 : }
     234              : 
     235            2 : void SetDetourTable2P(const std::set<u32>                                             &tableIdSet,
     236              :                       unordered_map<LocalId, unordered_map<LocalId, vector<LocalId>>> &detourTable)
     237              : {
     238            9 :     if (tableIdSet == std::set<u32>{0, 1} || tableIdSet == std::set<u32>{2, 3} || 
     239            9 :         tableIdSet == std::set<u32>{4, 5} || tableIdSet == std::set<u32>{6, 7}) {
     240            1 :         detourTable = GetDetour2PTable01();
     241            3 :     } else if (tableIdSet == std::set<u32>{0, 4} || tableIdSet == std::set<u32>{1, 5} ||
     242            2 :         tableIdSet == std::set<u32>{2, 6} || tableIdSet == std::set<u32>{3, 7}) {
     243            1 :         detourTable = GetDetour2PTable04();
     244              :     } else {
     245            0 :         HCCL_WARNING("[DetourService][%s]no matched detourTable found", __func__);
     246              :     }
     247            2 : }
     248              : 
     249           18 : void GetDetourTableAndTableIds(const std::vector<LocalId>                                           &localIds,
     250              :                                std::unordered_map<LocalId, unordered_map<LocalId, vector<LocalId>>> &detourTable,
     251              :                                std::unordered_map<LocalId, u32>                                     &tableIds,
     252              :                                const RankTableInfo                                                  *rankTable)
     253              : {
     254           18 :     std::set<u32>  tableIdSet;
     255           18 :     HcclDetourType detourType = EnvConfig::GetInstance().GetDetourConfig().GetDetourType();
     256           18 :     if (rankTable->detour == false){
     257            4 :         detourType = HcclDetourType::HCCL_DETOUR_DISABLE;
     258              :     }
     259           18 :     switch (detourType) {
     260            0 :         case HcclDetourType::HCCL_DETOUR_ENABLE_2P: {
     261            0 :             if (localIds.size() != DETOUR_NODE_NUM_2P) {
     262            0 :                 return;
     263              :             }
     264            0 :             bool res = GetTableIds(localIds, tableIds, tableIdSet);
     265            0 :             if (res) {
     266            0 :                 SetDetourTable2P(tableIdSet, detourTable);
     267            0 :                 HCCL_DEBUG("[DetourService] selected detour type is DETOUR2PTABLE");
     268              :             } else {
     269            0 :                 HCCL_WARNING("[DetourService] detourtype [%s] does not support.", detourType.Describe().c_str());
     270              :             }
     271            0 :             break;
     272              :         }
     273            0 :         case HcclDetourType::HCCL_DETOUR_ENABLE_4P: {
     274            0 :             if (localIds.size() != DETOUR_NODE_NUM_4P) {
     275            0 :                 return;
     276              :             }
     277            0 :             bool res = GetTableIds(localIds, tableIds, tableIdSet);
     278            0 :             if (res) {
     279            0 :                 SetDetourTable4P(tableIdSet, detourTable);
     280              :             } else {
     281            0 :                 HCCL_WARNING("[DetourService] detourtype [%s] does not support.", detourType.Describe().c_str());
     282              :             }
     283            0 :             break;
     284              :         }
     285           18 :         case HcclDetourType::HCCL_DETOUR_DISABLE: {
     286           46 :             HCCL_DEBUG("[DetourService] detour is disable");
     287           18 :             break;
     288              :         }
     289            0 :         default: {
     290            0 :             THROW<NotSupportException>(
     291            0 :                 StringFormat("[DetourService] detourtype [%s] does not support.", detourType.Describe().c_str()));
     292              :         }
     293              :     }
     294           18 : }
     295              : 
     296            0 : void AddDetourLinks(const PhyTopo *phyTopo, RankGraph *rankGraph,
     297              :                     std::unordered_map<LocalId, unordered_map<LocalId, vector<LocalId>>> &detourTable,
     298              :                     std::unordered_map<LocalId, u32>                                     &tableIds, 
     299              :                     const RankTableInfo                                                  *rankTable)
     300              : {
     301            0 :     auto phyTopoGraph = phyTopo->GetTopoGraph(0);
     302            0 :     NetInstance *innerNetInst = rankGraph->GetNetInstanceByRankId(0, rankGraph->GetMyRank());
     303            0 :     if (innerNetInst == nullptr) {
     304            0 :         THROW<NullPtrException>(StringFormat("[DetourService] innerNetInst is nullptr"));
     305              :     }
     306            0 :     set<RankId> innerRanks = innerNetInst->GetRankIds();
     307            0 :     for (const auto &srcRankId : innerRanks) {
     308            0 :         LocalId srcLocalId = rankGraph->GetLocalId(srcRankId);
     309            0 :         u32     srcTableId = tableIds[srcLocalId];
     310            0 :         for (const auto &dstRankId : innerRanks) {
     311            0 :             LocalId dstLocalId = rankGraph->GetLocalId(dstRankId);
     312            0 :             u32     dstTableId = tableIds[dstLocalId];
     313              : 
     314            0 :             if (detourTable.count(srcTableId) == 0 || detourTable[srcTableId].count(dstTableId) == 0) {
     315            0 :                 continue;
     316              :             }
     317              : 
     318            0 :             auto detourTableIds = detourTable[srcTableId][dstTableId];
     319            0 :             for (auto &detourTableId : detourTableIds) {
     320            0 :                 LocalId detourLocalId = detourTableId + srcLocalId - srcTableId;
     321              : 
     322              :                 // 插入detourlink
     323            0 :                 DetourData detourData;
     324            0 :                 detourData.detourPhyPeerId = PhyTopo::Peer::GetId(detourLocalId); // 绕路可能没有绕路节点的rankid
     325            0 :                 detourData.srcPhyPeerId    = PhyTopo::Peer::GetId(srcLocalId);
     326            0 :                 detourData.dstPhyPeerId    = PhyTopo::Peer::GetId(dstLocalId);
     327            0 :                 detourData.srcNetInstPeer  = rankGraph->GetPeer(srcRankId);
     328            0 :                 detourData.dstNetInstPeer  = rankGraph->GetPeer(dstRankId);
     329              : 
     330            0 :                 AddDetourLink(innerNetInst, detourData, phyTopoGraph, rankTable);
     331            0 :             }
     332            0 :         }
     333              :     }
     334            0 : }
     335              : 
     336           18 : void DetourService::InsertDetourLinks(RankGraph *rankGraph, const RankTableInfo *rankTable)
     337              : {
     338           18 :     std::unordered_map<LocalId, u32>                                     tableIds;
     339           18 :     std::unordered_map<LocalId, unordered_map<LocalId, vector<LocalId>>> detourTable;
     340              : 
     341              :     // 获取innerGroup的localIds
     342           18 :     std::vector<LocalId> localIds = GetInnerLocalIds(rankGraph);
     343              :     // 获取当前localIds的tableId和detourTable
     344           18 :     GetDetourTableAndTableIds(localIds, detourTable, tableIds, rankTable);
     345              : 
     346           18 :     if (!detourTable.empty()) {
     347              :         // 添加绕路links
     348            0 :         AddDetourLinks(phyTopo, rankGraph, detourTable, tableIds, rankTable);
     349              :     } else {
     350           46 :         HCCL_WARNING("no detour links found");
     351              :     }
     352           18 : }
     353              : 
     354              : } // namespace Hccl
        

Generated by: LCOV version 2.0-1