LCOV - code coverage report
Current view: top level - legacy/ascend910/framework/common/src/topo - topoinfo_parse.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 73.5 % 226 166
Test Date: 2026-08-18 17:47:01 Functions: 94.7 % 19 18

            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 "topoinfo_parse.h"
      12              : #include <string>
      13              : #include <unordered_set>
      14              : #include <algorithm>
      15              : // ltm指定config路径
      16              : #include "common/src/config.h"
      17              : 
      18              : using namespace std;
      19              : 
      20              : struct HcclAiServerValid4PRanksVectorHashFuc {
      21          398 :     std::size_t operator()(const std::vector<s32> key) const
      22              :     {
      23          398 :         size_t ret = 0;
      24         1990 :         for (auto it : key) {
      25         1592 :             ret ^= it;
      26              :         }
      27          398 :         return ret;
      28              :     }
      29              : };
      30              : 
      31              : // aiserver内连接信息rank合法选择
      32              : const std::unordered_set<std::vector<s32>, HcclAiServerValid4PRanksVectorHashFuc> HCCL_AISERVER_VAILD_4P_RANKS
      33              :     = {{0, 1, 4, 5}, {0, 2, 4, 6}, {0, 3, 4, 7}, {1, 2, 5, 6}, {1, 3, 5, 7}, {2, 3, 6, 7}, {0, 1, 2, 3}, {4, 5, 6, 7}};
      34              : 
      35              : namespace hccl {
      36          532 : TopoInfoParse::TopoInfoParse() {}
      37              : 
      38          532 : TopoInfoParse::~TopoInfoParse() {}
      39              : 
      40          496 : HcclResult TopoInfoParse::Init(const RankTable_t& rankTable, const std::string& serverId, const u32 deviceNumPerServer)
      41              : {
      42          496 :     CHK_PRT_RET(deviceNumPerServer == 0, HCCL_ERROR("cur device num per server is 0"), HCCL_E_PARA);
      43          496 :     deviceNum_ = rankTable.deviceNum;
      44          496 :     serverNum_ = rankTable.serverNum;
      45          496 :     superPodNum_ = rankTable.superPodNum;
      46          496 :     serverId_ = serverId;
      47          499 :     nicDeploy_ = rankTable.nicDeploy;
      48          499 :     deviceNumPerServer_ = deviceNumPerServer;
      49          499 :     multiServerDiffDeviceNumMode_ = (serverNum_ * deviceNumPerServer_) == deviceNum_ ? false : true;
      50          499 :     CHK_RET(hrtGetDeviceType(deviceType_));
      51              : 
      52          499 :     DevType curDevType = rankTable.rankList.begin()->deviceInfo.deviceType;
      53         1995 :     for (auto rankInfo : rankTable.rankList) {
      54         1496 :         RankInfo curRankInfo;
      55         1496 :         curRankInfo.devicePhyId = rankInfo.deviceInfo.devicePhyId;
      56         1496 :         curRankInfo.deviceType = rankInfo.deviceInfo.deviceType;
      57         1496 :         curRankInfo.serverId = rankInfo.serverId;
      58         1496 :         curRankInfo.userRank = rankInfo.rankId;
      59         1496 :         curRankInfo.nicIp = rankInfo.deviceInfo.deviceIp;
      60         1493 :         curRankInfo.superDeviceId = rankInfo.superDeviceId;
      61         1493 :         curRankInfo.superPodId = rankInfo.superPodId;
      62         1493 :         rankList_.push_back(curRankInfo);
      63              : 
      64         1493 :         if (curDevType != rankInfo.deviceInfo.deviceType) {
      65            0 :             isDiffDeviceType_ = true;
      66              :         }
      67         1493 :     }
      68          499 :     return HCCL_SUCCESS;
      69              : }
      70              : 
      71              : HcclResult
      72           33 : TopoInfoParse::Init(const std::vector<RankInfo>& rankList, const std::string& serverId, const u32 deviceNumPerServer)
      73              : {
      74           33 :     CHK_PRT_RET(deviceNumPerServer == 0, HCCL_ERROR("cur device num per server is 0"), HCCL_E_PARA);
      75           33 :     rankList_ = rankList;
      76           33 :     serverId_ = serverId;
      77           33 :     deviceNumPerServer_ = deviceNumPerServer;
      78           33 :     CHK_RET(GetDevNum(rankList, deviceNum_));
      79           33 :     CHK_RET(GetServerNum(rankList, serverNum_));
      80           33 :     CHK_RET(GetSuperPodNum(rankList, superPodNum_));
      81           33 :     multiServerDiffDeviceNumMode_ = (serverNum_ * deviceNumPerServer_) == deviceNum_ ? false : true;
      82           33 :     CHK_RET(hrtGetDeviceType(deviceType_));
      83              : 
      84           33 :     DevType curDevType = rankList.begin()->deviceType;
      85          190 :     for (auto rankInfo : rankList) {
      86          157 :         if (curDevType != rankInfo.deviceType) {
      87            0 :             isDiffDeviceType_ = true;
      88              :         }
      89          157 :     }
      90           33 :     return HCCL_SUCCESS;
      91              : }
      92              : 
      93          532 : HcclResult TopoInfoParse::GetServerInnerLinkInfo(
      94              :     std::unordered_map<u32, u32>& pairLinkCounter,
      95              :     std::unordered_map<u32, std::unordered_map<int, std::vector<int>>>& pairLinkInfo)
      96              : {
      97          532 :     std::vector<RankInfo> serverInnerInfo;
      98          532 :     CHK_RET(TransformRankInfoByServerId(serverInnerInfo));
      99              : 
     100          531 :     CHK_PRT_RET(
     101              :         serverInnerInfo.size() == 0,
     102              :         HCCL_ERROR(
     103              :             "[Get][ServerInnerLinkInfo]server info input is empty, "
     104              :             "serverid[%s]",
     105              :             serverId_.c_str()),
     106              :         HCCL_E_PARA);
     107          532 :     pairLinkInfo.clear();
     108          532 :     pairLinkCounter[static_cast<u32>(LinkTypeInServer::HCCS_TYPE)] = 0;
     109          532 :     pairLinkCounter[static_cast<u32>(LinkTypeInServer::PXI_TYPE)] = 0;
     110          531 :     pairLinkCounter[static_cast<u32>(LinkTypeInServer::SIO_TYPE)] = 0;
     111          530 :     pairLinkCounter[static_cast<u32>(LinkTypeInServer::HCCS_SW_TYPE)] = 0;
     112         1868 :     for (auto& it_local : serverInnerInfo) {
     113         7147 :         for (auto& it_dest : serverInnerInfo) {
     114         5808 :             if (it_local.devicePhyId == it_dest.devicePhyId || it_local.devicePhyId == HOST_DEVICE_ID
     115         4473 :                 || it_dest.devicePhyId == HOST_DEVICE_ID) {
     116         1333 :                 continue;
     117              :             }
     118              :             LinkTypeInServer linkType;
     119         4475 :             CHK_RET(hrtGetPairDeviceLinkType(it_local.devicePhyId, it_dest.devicePhyId, linkType));
     120         4493 :             pairLinkInfo[static_cast<u32>(linkType)][it_local.devicePhyId].push_back(it_dest.devicePhyId);
     121         4479 :             pairLinkCounter[static_cast<u32>(linkType)]++;
     122              :         }
     123              :     }
     124          770 :     for (auto it : pairLinkInfo) {
     125          243 :         HCCL_DEBUG("pair link information linkType[%u], size[%llu]", it.first, it.second.size());
     126          243 :     }
     127         2660 :     for (auto it : pairLinkCounter) {
     128         2120 :         HCCL_DEBUG("pair link counter information linkType[%u], size[%llu]", it.first, it.second);
     129              :     }
     130          531 :     return HCCL_SUCCESS;
     131          531 : }
     132              : 
     133          532 : HcclResult TopoInfoParse::TransformRankInfoByServerId(std::vector<hccl::RankInfo>& serverInnerInfo)
     134              : {
     135              :     // 按server重新组织rank信息,便于后续校验及信息填写
     136         2185 :     for (auto tmpRankInfo : rankList_) {
     137         1653 :         if (tmpRankInfo.serverId == serverId_) {
     138         1342 :             serverInnerInfo.push_back(tmpRankInfo);
     139              :         }
     140         1653 :     }
     141              :     // 按设备Id从小到大的顺序排序
     142          532 :     std::sort(serverInnerInfo.begin(), serverInnerInfo.end(), [](const RankInfo& left, const RankInfo& right) {
     143         1610 :         return left.devicePhyId < right.devicePhyId;
     144              :     });
     145          531 :     return HCCL_SUCCESS;
     146              : }
     147              : 
     148              : // nicIdx不只是校验,还有修改
     149          499 : HcclResult TopoInfoParse::ParseAndCheck(std::vector<u32>& nicIdx)
     150              : {
     151          499 :     CHK_RET(CheckInterServerDeviceId());
     152          498 :     CHK_RET(CheckRankTableNicInfo(nicIdx));
     153          497 :     CHK_RET(CheckServerInnerRankInfo());
     154          498 :     return HCCL_SUCCESS;
     155              : }
     156              : 
     157           20 : HcclResult TopoInfoParse::Check()
     158              : {
     159           20 :     CHK_RET(CheckInterServerDeviceId());
     160           20 :     CHK_RET(CheckServerInnerRankInfo());
     161           20 :     return HCCL_SUCCESS;
     162              : }
     163              : 
     164              : // server间device选取是否对称校验
     165          519 : HcclResult TopoInfoParse::CheckInterServerDeviceId()
     166              : {
     167          519 :     if (serverNum_ == 0) {
     168            0 :         HCCL_ERROR("[Check][DeviceId]errNo[0x%016llx] server num is zero", HCOM_ERROR_CODE(HCCL_E_PARA));
     169            0 :         return HCCL_E_PARA;
     170              :     }
     171          519 :     std::map<std::string, std::set<s32>> serverDeviceMapList;
     172         2116 :     for (auto it = rankList_.begin(); it != rankList_.end(); it++) {
     173         1593 :         std::string tmpServerId = it->serverId;
     174         1597 :         auto search = serverDeviceMapList.find(tmpServerId);
     175         1593 :         if (search != serverDeviceMapList.end()) {
     176          883 :             auto rs = serverDeviceMapList[tmpServerId].insert(it->devicePhyId);
     177          885 :             if (it->devicePhyId == HOST_DEVICE_ID) {
     178            0 :                 continue;
     179              :             }
     180          885 :             if (!rs.second) {
     181            0 :                 RPT_INPUT_ERR(
     182              :                     true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
     183              :                     std::vector<std::string>(
     184              :                         {std::to_string(it->devicePhyId), " \"Device Id of server Id " + it->serverId + " \" ",
     185              :                          "is unique"}));
     186            0 :                 HCCL_ERROR(
     187              :                     "[%s][%s]errNo[0x%016llx] check ranklist[%u], device id repeat for one server",
     188              :                     LOG_KEYWORDS_INIT_GROUP.c_str(), LOG_KEYWORDS_RANKTABLE_CHECK.c_str(), HCOM_ERROR_CODE(HCCL_E_PARA),
     189              :                     it->userRank);
     190            0 :                 return HCCL_E_PARA;
     191              :             }
     192              :         } else {
     193          706 :             std::set<s32> deviceSet;
     194          706 :             deviceSet.insert(it->devicePhyId);
     195          706 :             serverDeviceMapList.insert(std::pair<std::string, std::set<s32>>(tmpServerId, deviceSet));
     196          703 :         }
     197         1588 :     }
     198          519 :     if (serverDeviceMapList.size() == 0) {
     199            0 :         HCCL_ERROR(
     200              :             "[Check][DeviceId]errNo[0x%016llx] for all ranklist, server num is zero", HCOM_ERROR_CODE(HCCL_E_PARA));
     201            0 :         return HCCL_E_PARA;
     202              :     }
     203          519 :     return HCCL_SUCCESS;
     204          517 : }
     205              : 
     206          499 : HcclResult TopoInfoParse::CheckAndAssignNicInfo(std::vector<u32>& nicIdx)
     207              : {
     208          499 :     if (isDiffDeviceType_) {
     209              :         // 混合组网
     210            0 :         return HCCL_SUCCESS;
     211          499 :     } else if (serverNum_ == 1 || superPodNum_ == 1) {
     212          397 :         nicIdx.clear();
     213         1455 :         for (u32 index = 0; index < rankList_.size(); index++) {
     214         1061 :             if (serverId_ == rankList_[index].serverId && (rankList_[index].devicePhyId != HOST_DEVICE_ID)) {
     215         1063 :                 nicIdx.push_back(static_cast<u32>(rankList_[index].devicePhyId));
     216              :             }
     217              :         }
     218          394 :         std::sort(nicIdx.begin(), nicIdx.end());
     219          497 :     } else if (deviceNumPerServer_ == HCCL_AISERVER_DEVICE_NUM && !multiServerDiffDeviceNumMode_) {
     220            0 :         CHK_PRT_RET(nicIdx.size() == 0, HCCL_ERROR("[CheckAndAssign][NicInfo]nic idx size is 0"), HCCL_E_PARA);
     221            0 :         CHK_PRT_RET(deviceNum_ == 0, HCCL_ERROR("[CheckAndAssign][NicInfo]device num is 0"), HCCL_E_PARA);
     222              : 
     223            0 :         bool bRet = deviceNum_ % nicIdx.size() != 0; // 在n台server中,校验网口总数是否为1n/2n/4n/8n
     224            0 :         CHK_PRT_RET(bRet, HCCL_ERROR("[CheckAndAssign][NicInfo]nic total num[%zu] error", nicIdx.size()), HCCL_E_PARA);
     225              : 
     226            0 :         if (nicIdx.size() != deviceNumPerServer_) {
     227              :             // 网口裁剪
     228              :             // 按server重新组织rank信息
     229            0 :             std::map<std::string, std::vector<u32>> severNicsMap;
     230            0 :             for (size_t index = 0; index < rankList_.size(); ++index) {
     231            0 :                 std::string serverId = rankList_[index].serverId;
     232              : 
     233            0 :                 if (rankList_[index].nicIp.size() == 0 || rankList_[index].nicIp[0].IsInvalid()) {
     234            0 :                     continue;
     235              :                 }
     236              :                 // 以serverID为索引,将server下的ranks放入vector
     237            0 :                 auto itr = severNicsMap.find(serverId);
     238            0 :                 if (itr != severNicsMap.end()) {
     239            0 :                     itr->second.push_back(rankList_[index].devicePhyId);
     240              :                 } else {
     241            0 :                     std::vector<u32> nicList;
     242            0 :                     nicList.push_back(rankList_[index].devicePhyId);
     243            0 :                     std::pair<std::string, std::vector<u32>> nicInfoPair(serverId, nicList);
     244            0 :                     severNicsMap.insert(nicInfoPair);
     245            0 :                 }
     246            0 :             }
     247              : 
     248              :             // 每个server下的nicList按设备Id从小到大的顺序排序
     249            0 :             for (auto& iter : severNicsMap) {
     250            0 :                 std::sort(iter.second.begin(), iter.second.end());
     251            0 :                 if (nicIdx != iter.second) {
     252            0 :                     HCCL_ERROR("nic list should be the same between servers");
     253            0 :                     return HCCL_E_PARA;
     254              :                 }
     255              :             }
     256            0 :         } else {
     257              :             // 网口满配
     258            0 :             return HCCL_SUCCESS;
     259              :         }
     260              :     }
     261          497 :     return HCCL_SUCCESS;
     262              : }
     263              : 
     264              : // nicIdx做填充,nicIdx也是deviceId,deviceId做过的校验这里不再重复
     265          499 : HcclResult TopoInfoParse::CheckRankTableNicInfo(std::vector<u32>& nicIdx)
     266              : {
     267              :     // 在8P均使用的情况下校验nic的选择信息是否正确
     268          499 :     if (nicDeploy_ == NICDeployment::NIC_DEPLOYMENT_DEVICE) {
     269          499 :         CHK_RET(CheckAndAssignNicInfo(nicIdx));
     270            0 :     } else if (
     271            0 :         nicDeploy_ == NICDeployment::NIC_DEPLOYMENT_HOST && serverNum_ == deviceNum_ / HCCL_AISERVER_DEVICE_NUM) {
     272            0 :         nicIdx.assign({0, 1, 2, 3, 4, 5, 6, 7}); // 如果每个server8个rank且为host nic,则网口为满配
     273              :     }
     274          497 :     return HCCL_SUCCESS;
     275              : }
     276              : 
     277              : // 校验server内4p场景下deivce选取是否合法,2p与标卡场景重合
     278          517 : HcclResult TopoInfoParse::CheckServerInnerRankInfo()
     279              : {
     280              :     // 校验server内device选取
     281          517 :     std::vector<s32> serverInnerDeviceInfo;
     282         2109 :     for (u32 index = 0; index < rankList_.size(); index++) {
     283         1592 :         if (serverId_ == rankList_[index].serverId && rankList_[index].devicePhyId != HOST_DEVICE_ID) {
     284              :             /* 同一server的标识IP 是一样的,所以可以以此推算出平均dev个数 */
     285         1321 :             serverInnerDeviceInfo.push_back(rankList_[index].devicePhyId);
     286              :         }
     287              :     }
     288          517 :     std::sort(serverInnerDeviceInfo.begin(), serverInnerDeviceInfo.end());
     289              : 
     290          518 :     if (deviceType_ == DevType::DEV_TYPE_910) {
     291          381 :         if (deviceNumPerServer_ != HCCL_DEVICE_NUM_FOUR) {
     292          359 :             return HCCL_SUCCESS;
     293              :         }
     294           22 :         std::string selectedDevice = "selected devices:";
     295          110 :         for (auto devicePhyId : serverInnerDeviceInfo) {
     296           88 :             selectedDevice += std::to_string(devicePhyId);
     297           88 :             selectedDevice += " ";
     298              :         }
     299           22 :         if (HCCL_AISERVER_VAILD_4P_RANKS.find(serverInnerDeviceInfo) == HCCL_AISERVER_VAILD_4P_RANKS.end()) {
     300            0 :             std::string errormessage = "Value " + selectedDevice
     301            0 :                                        + " for rankTable "
     302            0 :                                          "variable \"Device Id of server Id "
     303            0 :                                        + serverId_ + " \" is invalid, expected value is unique.";
     304            0 :             errormessage += selectedDevice;
     305            0 :             RPT_INPUT_ERR(
     306              :                 true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
     307              :                 std::vector<std::string>(
     308              :                     {selectedDevice, " \"Device Id of server Id " + serverId_ + " \" ", "is unique"}));
     309            0 :             HCCL_ERROR(
     310              :                 "[%s][%s] %s", LOG_KEYWORDS_INIT_GROUP.c_str(), LOG_KEYWORDS_RANKTABLE_CHECK.c_str(),
     311              :                 errormessage.c_str());
     312            0 :             return HCCL_E_PARA;
     313            0 :         }
     314           22 :         HCCL_DEBUG("%s", selectedDevice.c_str());
     315           22 :     }
     316              : 
     317          159 :     return HCCL_SUCCESS;
     318          518 : }
     319              : 
     320          532 : HcclResult TopoInfoParse::IsAllRankSamePlane(bool& isAllRankSamePlane)
     321              : {
     322              :     // 只有1个rank,不考虑
     323          532 :     if (rankList_.size() == 1) {
     324          206 :         isAllRankSamePlane = true;
     325          206 :         return HCCL_SUCCESS;
     326              :     }
     327              : 
     328          326 :     auto isSameDevId = [&]() -> bool {
     329          326 :         s32 maxModuleDevNum = deviceType_ == DevType::DEV_TYPE_910B ? HCCL_DEVICE_NUM_EIGHT : MAX_MODULE_DEVICE_NUM;
     330          487 :         for (size_t index = 0; index < rankList_.size() - 1; ++index) {
     331          419 :             if (rankList_[index].devicePhyId % maxModuleDevNum != rankList_[index + 1].devicePhyId % maxModuleDevNum) {
     332          258 :                 return false;
     333              :             }
     334              :         }
     335           68 :         return true;
     336          326 :     };
     337              : 
     338          326 :     isAllRankSamePlane = isSameDevId();
     339          326 :     HCCL_DEBUG("[TopoInfoParse]curr comm isAllRankSamePlane[%d]", isAllRankSamePlane);
     340          326 :     return HCCL_SUCCESS;
     341              : }
     342              : 
     343          531 : HcclResult TopoInfoParse::IsSingleMeshAggregation(bool& isSingleMeshAggregation)
     344              : {
     345          531 :     if (deviceNumPerServer_ == deviceNum_) {
     346              :         // rank间都是hccs链接,则表明在同一个mesh cube中
     347          424 :         CHK_RET(IsAllRankConnectedWithHCCS(isSingleMeshAggregation));
     348              :     } else {
     349          107 :         isSingleMeshAggregation = false;
     350              :     }
     351          531 :     HCCL_DEBUG("[TopoInfoParse]curr comm isSingleMeshAggregation[%d]", isSingleMeshAggregation);
     352          532 :     return HCCL_SUCCESS;
     353              : }
     354              : 
     355          424 : HcclResult TopoInfoParse::IsAllRankConnectedWithHCCS(bool& isAllRankConnectedWithHCCS)
     356              : {
     357         1607 :     for (u32 i = 0; i < rankList_.size(); i++) {
     358         3334 :         for (u32 j = i + 1; j < rankList_.size(); j++) {
     359         2148 :             LinkTypeInServer linkType = LinkTypeInServer::RESERVED_LINK_TYPE;
     360         2148 :             if (rankList_[i].devicePhyId != HOST_DEVICE_ID && rankList_[j].devicePhyId != HOST_DEVICE_ID) {
     361         2148 :                 CHK_RET(hrtGetPairDeviceLinkType(rankList_[i].devicePhyId, rankList_[j].devicePhyId, linkType));
     362              :             }
     363         2153 :             if (linkType == LinkTypeInServer::PXI_TYPE) {
     364            0 :                 isAllRankConnectedWithHCCS = false;
     365            0 :                 return HCCL_SUCCESS;
     366              :             }
     367              :         }
     368              :     }
     369          426 :     isAllRankConnectedWithHCCS = true;
     370          426 :     return HCCL_SUCCESS;
     371              : }
     372              : 
     373            0 : HcclResult TopoInfoParse::GetDeviceNumInPerMeshAggregation(u32 devicePhyId, u32& perAggregationNum)
     374              : {
     375              :     // 每个rank本身加上和他通过hccs互联的rank表示当前server Aggregation中的rank数量
     376            0 :     perAggregationNum = 1;
     377            0 :     for (u32 i = 0; i < rankList_.size(); i++) {
     378            0 :         if (serverId_ == rankList_[i].serverId && rankList_[i].devicePhyId != static_cast<s32>(devicePhyId)) {
     379              :             LinkTypeInServer linkType;
     380            0 :             CHK_RET(hrtGetPairDeviceLinkType(devicePhyId, rankList_[i].devicePhyId, linkType));
     381            0 :             if (linkType == LinkTypeInServer::HCCS_TYPE) {
     382            0 :                 perAggregationNum++;
     383              :             }
     384              :         }
     385              :     }
     386            0 :     HCCL_DEBUG(
     387              :         "[TopoInfoParse][GetDeviceNumInPerMeshAggregation]serverId[%s] devicePhyId[%u] perAggregationNum[%u]",
     388              :         serverId_.c_str(), devicePhyId, perAggregationNum);
     389              : 
     390            0 :     return HCCL_SUCCESS;
     391              : }
     392              : } // namespace hccl
        

Generated by: LCOV version 2.0-1