LCOV - code coverage report
Current view: top level - legacy/ascend950/framework/communicator - diff_rank_updater.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 82.9 % 111 92
Test Date: 2026-08-04 10:52:23 Functions: 100.0 % 5 5

            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 "diff_rank_updater.h"
      12              : #include <fstream>
      13              : #include <sstream>
      14              : #include <vector>
      15              : #include <string>
      16              : #include <linux/limits.h>
      17              : #include "changed_rank_info.h"
      18              : #include "rank_table_info.h"
      19              : #include "json_parser.h"
      20              : 
      21              : using namespace Hccl;
      22              : 
      23              : // 64+1替换前校验
      24            1 : static HcclResult Check64Plus1Replace(const NewRankInfo &changeRank, const NewRankInfo &snapshotRank)
      25              : {
      26            1 :     if (changeRank.replacedLocalId == snapshotRank.localId && changeRank.rankId == snapshotRank.rankId) {
      27            1 :         if ((changeRank.localId == BACKUP_LOCAL_ID && snapshotRank.localId != BACKUP_LOCAL_ID) ||
      28            0 :             (changeRank.localId != BACKUP_LOCAL_ID && snapshotRank.localId == BACKUP_LOCAL_ID)) {
      29            1 :             return HCCL_SUCCESS;
      30              :         }
      31              :     }
      32            0 :     HCCL_ERROR("[%s] 64+1 replacement check failed.", __func__);
      33            0 :     return HCCL_E_PARA;
      34              : }
      35              : 
      36              : // 整框替换前校验,传入全量的Rank数组changeRanks和snapshotRanks和下标数组changeRankIndex和snapshotRankIndex
      37              : // 通过下标数组里的下标,可以找到对应R0Id的newRankInfo
      38            1 : static HcclResult CheckPodReplace(vector<NewRankInfo> &changeRanks, const vector<u32> &changeRankIndex, 
      39              :      vector<NewRankInfo> &snapshotRanks, const vector<u32> &snapshotRankIndex) 
      40              : {
      41              :     // 将changeRankId存入map,key为rankId,value为下标
      42            1 :     unordered_map<u32, u32> changeRankMap;
      43            5 :     for (u32 i = 0; i < changeRankIndex.size(); ++i) {
      44            4 :         u32  changeRankId = changeRanks[changeRankIndex[i]].rankId;
      45            4 :         changeRankMap[changeRankId] = changeRankIndex[i];
      46              :     }
      47              : 
      48              :     // 根据替换前后的rankId相同,校验rankId是否全部存在
      49              :     // 再将替换前后的下标对存入rankPair,校验是否满足整框替换的条件
      50            1 :     vector<pair<u32, u32>> rankPair;
      51            5 :     for (u32 i = 0; i < snapshotRankIndex.size(); ++i) {
      52            4 :         u32 snapshotRankId = snapshotRanks[snapshotRankIndex[i]].rankId;
      53            4 :         if (changeRankMap.find(snapshotRankId) == changeRankMap.end()) {
      54            0 :             HCCL_ERROR("[%s] full frame replacement check failed, rankId[%d] not found.", __func__, snapshotRanks[snapshotRankIndex[i]].rankId);
      55            0 :             return HCCL_E_PARA;
      56              :         } else {
      57            4 :             rankPair.push_back({snapshotRankIndex[i], changeRankMap[snapshotRankId]});
      58              :         }
      59              :     }
      60              : 
      61              :     // 每组rank替换,需要校验以下四种情况
      62              :     // 1、正常场景 整框替换为 备份场景
      63              :     // 2、备份场景 整框替换为 正常场景
      64              :     // 3、正常场景 整框替换为 正常场景
      65              :     // 4、备份场景 整框替换为 备份场景
      66            5 :     for (u32 i = 0; i < rankPair.size(); ++i) {
      67            4 :         NewRankInfo& snapshotRank = snapshotRanks[rankPair[i].first]; 
      68            4 :         NewRankInfo& changeRank = changeRanks[rankPair[i].second];
      69            4 :         bool isChangeReplace = false;
      70            4 :         bool isSnapshotReplace = false;
      71              :         
      72            4 :         if (snapshotRank.localId == changeRank.localId) {
      73            4 :             continue;
      74            0 :         } else if (changeRank.localId == BACKUP_LOCAL_ID && changeRank.replacedLocalId == snapshotRank.localId && !isChangeReplace) {
      75            0 :             isChangeReplace = true;
      76            0 :             continue;
      77            0 :         } else if (snapshotRank.localId == BACKUP_LOCAL_ID && snapshotRank.replacedLocalId == changeRank.localId && !isSnapshotReplace) {
      78            0 :             isSnapshotReplace = true;
      79            0 :             continue;
      80              :         } else {
      81            0 :             HCCL_ERROR("[%s] full frame replacement check failed, localId[%d] not match, rankId[%d].", __func__, snapshotRank.localId, snapshotRank.rankId);
      82            0 :             return HCCL_E_PARA;
      83              :         }
      84              :     }
      85            1 :     return HCCL_SUCCESS;
      86            1 : }
      87              : 
      88            4 : static HcclResult ParseChangeInfo(const char *changeInfo, ChangedRankInfo &changeTable)
      89              : {
      90           12 :     HCCL_INFO("[%s] start.", __func__);
      91              :     // 获取真实路径
      92            4 :     char resolvedPath[PATH_MAX] = {0};
      93            4 :     if (realpath(changeInfo, resolvedPath) == nullptr) {
      94            6 :         HCCL_ERROR("RanktableRealPath: %s is not a valid real path.", changeInfo);
      95            2 :         return HCCL_E_PARA;
      96              :     }
      97              : 
      98              :     // 读取文件、校验文件是否存在
      99            6 :     HCCL_INFO("[%s] waiting for json file load complete", __func__);
     100            2 :     ifstream infoFile(resolvedPath, ifstream::in);
     101            2 :     if (!infoFile) {
     102            0 :         HCCL_ERROR("open file %s failed.", resolvedPath);
     103            0 :         return HCCL_E_OPEN_FILE_FAILURE;
     104              :     }
     105              : 
     106              :     // 获取ranktableM
     107            2 :     stringstream rankTableStr;
     108            2 :     rankTableStr << infoFile.rdbuf();
     109            2 :     string ranktableM = rankTableStr.str();
     110              : 
     111              :     // 解析ranktable
     112              :     JsonParser rankTableParser;
     113            2 :     rankTableParser.ParseString(ranktableM, changeTable);
     114              : 
     115            6 :     HCCL_INFO("[%s] end.", __func__);
     116            2 :     return HCCL_SUCCESS;
     117            2 : }
     118            2 : static HcclResult GetRankMapAndChangeMap(unordered_map<string, vector<u32>> &rankTableMap,
     119              :                                   unordered_map<string, vector<u32>> &changedRankMap, RankTableInfo &rankTableInfo,
     120              :                                   ChangedRankInfo &changeTable)
     121              : {
     122            6 :     HCCL_INFO("[%s] start.", __func__);
     123              :     // 将changeTable和rankTable按R0 id分组
     124            7 :     for (u32 i = 0; i < changeTable.ranks.size(); ++i) {
     125            5 :         const auto &rank = changeTable.ranks[i];
     126              :         // 遍历rankLevelInfos中的每个RankLevelInfo
     127            5 :         for (const auto &levelInfo : rank.rankLevelInfos) {
     128            5 :             if (levelInfo.netLayer == 0) {
     129            5 :                 changedRankMap[levelInfo.netInstId].push_back(i);
     130            5 :                 break;
     131              :             }
     132              :         }
     133              :     }
     134              : 
     135           10 :     for (u32 i = 0; i < rankTableInfo.ranks.size(); ++i) {
     136            8 :         const auto &rank = rankTableInfo.ranks[i];
     137              :         // 遍历rankLevelInfos中的每个RankLevelInfo
     138            8 :         for (const auto &levelInfo : rank.rankLevelInfos) {
     139            8 :             if (levelInfo.netLayer == 0) {
     140            8 :                 rankTableMap[levelInfo.netInstId].push_back(i);
     141            8 :                 break;
     142              :             }
     143              :         }
     144              :     }
     145              : 
     146            6 :     HCCL_INFO("[%s] end.", __func__);
     147            2 :     return HCCL_SUCCESS;
     148              : }
     149            4 : HcclResult Hccl::DiffRankUpdater(const char *changeInfo, RankTableInfo &rankTableInfo)
     150              : {
     151            4 :     CHK_PTR_NULL(changeInfo);
     152           12 :     HCCL_INFO("[%s] Start to update rankTableInfo by changeInfo changeInfo[%s]", __func__, changeInfo);
     153            4 :     rankTableInfo.Dump();
     154              : 
     155            4 :     ChangedRankInfo changeTable;
     156           10 :     CHK_RET(ParseChangeInfo(changeInfo, changeTable));
     157              : 
     158              :     // 将changeTable和rankTable按R0 id分组
     159            2 :     unordered_map<string, vector<u32>> changedRankMap;
     160            2 :     unordered_map<string, vector<u32>> rankTableMap;
     161            2 :     CHK_RET(GetRankMapAndChangeMap(rankTableMap, changedRankMap, rankTableInfo, changeTable));
     162              : 
     163            2 :     vector<pair<u32, u32>> needChangeRank;
     164            4 :     for (auto &rankInfo : rankTableMap) {
     165              :         // 获取R0 id
     166            2 :         std::string levelZeroId = rankInfo.first;
     167              : 
     168              :         // 获取对应的changedRankInfo的Rank数量
     169            2 :         u32 changeCount   = changedRankMap[levelZeroId].size();
     170            2 :         u32 snapshotCount = rankTableMap[levelZeroId].size();
     171              : 
     172              :         // 确定替换策略
     173            2 :         if (changeCount == 0) {
     174            0 :             HCCL_INFO("[%s] Level[%s] No changes to apply.", __func__, levelZeroId.c_str());
     175            0 :             continue;
     176            2 :         } else if (changeCount == snapshotCount) {
     177              :             // 整框替换
     178            3 :             HCCL_INFO("[%s] Level[%s] Performing full frame replacement.", __func__, levelZeroId.c_str());
     179            1 :             CHK_RET(CheckPodReplace(changeTable.ranks, changedRankMap[levelZeroId], rankTableInfo.ranks,
     180              :                                   rankTableMap[levelZeroId]));
     181              : 
     182            5 :             for (u32 i = 0; i < snapshotCount; ++i) {
     183            4 :                 needChangeRank.push_back({changedRankMap[levelZeroId][i], rankTableMap[levelZeroId][i]});
     184              :             }
     185            1 :         } else if (changeCount == 1) {
     186              :             // 64+1替换
     187            3 :             HCCL_INFO("[%s] Level[%s] Performing 64+1 replacement.", __func__, levelZeroId.c_str());
     188            1 :             auto changeRankId = changeTable.ranks[changedRankMap[levelZeroId][0]].rankId;
     189            2 :             for (u32 i = 0; i < snapshotCount; ++i) {
     190            2 :                 if (changeRankId == rankTableInfo.ranks[rankTableMap[levelZeroId][i]].rankId) {
     191            1 :                     CHK_RET(Check64Plus1Replace(changeTable.ranks[changedRankMap[levelZeroId][0]],
     192              :                                         rankTableInfo.ranks[rankTableMap[levelZeroId][i]]));
     193              : 
     194            1 :                     needChangeRank.push_back({changedRankMap[levelZeroId][0], rankTableMap[levelZeroId][i]});
     195            1 :                     break;
     196              :                 }
     197              :             }
     198              :         } else {
     199            0 :             HCCL_ERROR(
     200              :                 "[%s] Level[%s] Invalid number of changed ranks. Must be 0, 1, or equal to the snapshot count (%u).",
     201              :                 __func__, levelZeroId.c_str(), snapshotCount);
     202            0 :             return HCCL_E_PARA;
     203              :         }
     204            2 :     }
     205              : 
     206              :     // 更新rankTableInfo
     207            7 :     for (auto &rankInfo : needChangeRank) {
     208            5 :         auto &rank = rankTableInfo.ranks[rankInfo.second];
     209            5 :         rank       = changeTable.ranks[rankInfo.first];
     210              :     }
     211              : 
     212            2 :     rankTableInfo.Check();
     213              : 
     214            6 :     HCCL_INFO("Update rankTableInfo by changeInfo success");
     215            2 :     rankTableInfo.Dump();
     216            2 :     return HCCL_SUCCESS;
     217            4 : }
        

Generated by: LCOV version 2.0-1