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 "rank_table_info.h"
12 :
13 : #include <unordered_set>
14 : #include <unordered_map>
15 : #include <sstream>
16 : #include <string>
17 : #include "json_parser.h"
18 : #include "invalid_params_exception.h"
19 : #include "exception_util.h"
20 : #include "adapter_error_manager_pub.h"
21 :
22 : namespace Hccl {
23 :
24 24 : void RankTableInfo::Check()
25 : {
26 24 : if (version != "2.0") {
27 1 : HCCL_ERROR("[RankTableInfo::%s] failed with version [%s] is not \"2.0\".", __func__ , version.c_str());
28 14 : RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
29 : std::vector<std::string>({version, "version", "2.0"}));
30 1 : THROW<InvalidParamsException>(
31 3 : StringFormat("[RankTableInfo::%s] failed with version is not \"2.0\" in ranktable file.", __func__));
32 : }
33 :
34 23 : if (rankCount > MAX_RANKCOUNT) {
35 13 : RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
36 : std::vector<std::string>({std::to_string(rankCount), "rankCount", "lower than " + std::to_string(MAX_RANKCOUNT)}));
37 2 : THROW<InvalidParamsException>(StringFormat(
38 : "[RankTableInfo::%s] failed with rankCount [%u] exceeds maximum limit of [%u]",
39 : __func__, rankCount, MAX_RANKCOUNT));
40 : }
41 :
42 22 : if (rankCount == 0) {
43 14 : RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
44 : std::vector<std::string>({std::to_string(rankCount), "rankCount", "should not be 0"}));
45 2 : THROW<InvalidParamsException>(StringFormat(
46 : "[RankTableInfo::%s] failed with rankCount [%u] exceeds minimum limit of [%u]",__func__, rankCount, 0));
47 : }
48 :
49 21 : if (rankCount != ranks.size()) {
50 14 : RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
51 : std::vector<std::string>({std::to_string(rankCount), "rankCount","rankCount is equal to rankSize[" + std::to_string(ranks.size()) + "]"}));
52 2 : THROW<InvalidParamsException>(StringFormat("[RankTableInfo::%s] failed with rankCount is not equal "
53 : "to rank_list size. version[%s], rankCount[%u], ranks.size[%u]",
54 : __func__, version.c_str(), rankCount, ranks.size()));
55 : }
56 :
57 20 : std::unordered_set<u32> rankIdSet;
58 20 : std::unordered_set<u32> localIdSet;
59 20 : u32 recordedReplaceLocalId{UNDEFIEND_LOCAL_ID};
60 66 : for (auto &rank : ranks) {
61 49 : if (static_cast<u32>(rank.rankId) >= rankCount) {
62 14 : RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
63 : std::vector<std::string>({std::to_string(rank.rankId), "rankId", "[0," + std::to_string(rankCount) + ")"}));
64 2 : THROW<InvalidParamsException>(StringFormat("[Parse][ClusterInfo][RankTableInfo::%s] failed with rank_id is "
65 : "out of range. version[%s], rankCount[%u], rank_id[%d]",
66 : __func__, version.c_str(), rankCount, rank.rankId));
67 : }
68 48 : if (rankIdSet.count(rank.rankId) > 0) {
69 14 : RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
70 : std::vector<std::string>({std::to_string(rank.rankId), "rankId", "rank_id is not repeat."}));
71 2 : THROW<InvalidParamsException>(StringFormat("[Parse][ClusterInfo][RankTableInfo::%s] failed with rank_id is "
72 : "repeat. version[%s], rankCount[%u], rank_id[%d]",
73 : __func__, version.c_str(), rankCount, rank.rankId));
74 : }
75 47 : rankIdSet.insert(rank.rankId);
76 :
77 47 : if (rank.localId != BACKUP_LOCAL_ID && rank.localId != rank.replacedLocalId) {
78 14 : RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
79 : std::vector<std::string>({std::to_string(rank.replacedLocalId), "replacedLocalId",
80 : "replacedLocalId equal to locaId[" + std::to_string(rank.localId) + "]"}));
81 2 : THROW<InvalidParamsException>(StringFormat("[Parse][ClusterInfo][RankTableInfo::Check] "
82 : "failed with replacedLocalId[%u] not equal to localId[%u].", rank.replacedLocalId, rank.localId));
83 46 : } else if (rank.localId == BACKUP_LOCAL_ID) {
84 1 : if (recordedReplaceLocalId == UNDEFIEND_LOCAL_ID) {
85 1 : recordedReplaceLocalId = rank.replacedLocalId;
86 : } else {
87 0 : RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
88 : std::vector<std::string>({"NA", "NA", "multiple replaced rank is configured."}));
89 0 : THROW<InvalidParamsException>(StringFormat("[Parse][ClusterInfo][RankTableInfo::Check] "
90 : "multiple replaced rank is configured"));
91 : }
92 : } else {
93 45 : localIdSet.emplace(rank.localId);
94 : }
95 : }
96 :
97 62 : for (u32 rankRange = 0; rankRange < rankCount; rankRange++) {
98 45 : if (rankIdSet.find(rankRange) == rankIdSet.end()) {
99 0 : RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
100 : std::vector<std::string>({std::to_string(rankRange),"rankId", "rank_id is continuous."}));
101 0 : THROW<InvalidParamsException>(StringFormat("[Parse][ClusterInfo][RankTableInfo::%s] failed with rank_id is "
102 : "not continuous. version[%s], rankCount[%u], rankRange[%d]",
103 : __func__, version.c_str(), rankCount, rankRange));
104 : }
105 : }
106 :
107 17 : std::vector<std::unordered_map<std::string, u32>> verifyRankAddr;
108 62 : for (auto &rank : ranks) {
109 130 : for (auto &levelInfo : rank.rankLevelInfos) {
110 85 : InsertToRank(levelInfo.netInstId, levelInfo.rankAddrs.size(), verifyRankAddr, levelInfo.netLayer);
111 : }
112 : }
113 :
114 17 : if(localIdSet.find(recordedReplaceLocalId) != localIdSet.end()) {
115 0 : RPT_INPUT_ERR(true, "EI0014", std::vector<std::string>({"value", "variable", "expect"}),
116 : std::vector<std::string>({std::to_string(recordedReplaceLocalId), "recordedReplacedLocalId",
117 : "failed with configuring same local_id with replaced one simutaneously."}));
118 0 : THROW<InvalidParamsException>(StringFormat("[Parse][ClusterInfo][RankTableInfo::%s] failed with configuring "
119 : "same local_id[%u] with replaced one simutaneously",
120 : __func__, recordedReplaceLocalId));
121 : }
122 40 : }
123 :
124 27 : void RankTableInfo::Deserialize(const nlohmann::json &rankTableInfoJson, bool isCheck)
125 : {
126 27 : std::string msgVersion = "error occurs when parser object of propName \"version\"";
127 28 : TRY_CATCH_THROW(InvalidParamsException, msgVersion, version = GetJsonProperty(rankTableInfoJson, "version"););
128 26 : std::string msgStatus = "error occurs when parser object of propName \"status\"";
129 :
130 26 : std::string detourStr;
131 26 : std::string msgDetour = "error occurs when parser object of propName \"detour\"";
132 26 : TRY_CATCH_THROW(InvalidParamsException, msgDetour, detourStr = GetJsonProperty(rankTableInfoJson, "detour", false););
133 26 : if (detourStr == "true") {
134 20 : detour = true;
135 6 : } else if (detourStr == "false" || detourStr == "") {
136 5 : detour = false;
137 : } else {
138 2 : THROW<InvalidParamsException>(StringFormat("Invalid detour value [%s]", detourStr.c_str()));
139 : }
140 :
141 25 : std::string msgRankcount = "error occurs when parser object of propName \"rank_count\"";
142 26 : TRY_CATCH_THROW(InvalidParamsException, msgRankcount, rankCount = GetJsonPropertyUInt(rankTableInfoJson, "rank_count"););
143 :
144 24 : nlohmann::json rankJsons;
145 24 : std::string msgRanklist = "error occurs when parser object of propName \"rank_list\"";
146 24 : TRY_CATCH_THROW(InvalidParamsException, msgRanklist,
147 : GetJsonPropertyList(rankTableInfoJson, "rank_list", rankJsons););
148 77 : for (auto &rankJson : rankJsons) {
149 53 : NewRankInfo rankInfo;
150 53 : rankInfo.Deserialize(rankJson);
151 53 : ranks.emplace_back(rankInfo);
152 53 : }
153 :
154 : // check
155 24 : if (isCheck) {
156 23 : Check();
157 : }
158 70 : }
159 :
160 85 : void RankTableInfo::CheckAndInsert(const std::string &levelId, u32 rankAddrSize,
161 : std::unordered_map<std::string, u32> &idRankSizeMap) const
162 : {
163 85 : if (idRankSizeMap.find(levelId) != idRankSizeMap.end() && idRankSizeMap[levelId] != rankAddrSize) {
164 0 : THROW<InvalidParamsException>(StringFormat("[RankTableInfo::%s] failed with the size of "
165 : "rank_addrs with the same id is different. leveId[%s],"
166 : "rankAddrSize[%u]",
167 : __func__, levelId.c_str(), rankAddrSize));
168 : }
169 85 : idRankSizeMap[levelId] = rankAddrSize;
170 85 : }
171 :
172 85 : void RankTableInfo::InsertToRank(const std::string &levelId, u32 rankAddrSize,
173 : std::vector<std::unordered_map<std::string, u32>> &rankLists, u32 levelNum) const
174 : {
175 85 : if (rankLists.size() <= levelNum) {
176 27 : rankLists.resize(levelNum + 1);
177 : }
178 85 : CheckAndInsert(levelId, rankAddrSize, rankLists[levelNum]);
179 85 : }
180 :
181 35 : std::string RankTableInfo::Describe() const
182 : {
183 35 : return StringFormat("RankTableInfo[version=%s, rankCount=%u, ranks size=%d]", version.c_str(), rankCount,
184 35 : ranks.size());
185 : }
186 :
187 14 : void RankTableInfo::Dump() const
188 : {
189 28 : HCCL_DEBUG("RankTableInfo Dump:");
190 28 : HCCL_DEBUG("%s", Describe().c_str());
191 28 : HCCL_DEBUG("ranks:");
192 21 : for (const auto& rank : ranks) {
193 7 : HCCL_DEBUG("%s", rank.Describe().c_str());
194 14 : for (const auto& levelInfo : rank.rankLevelInfos) {
195 7 : HCCL_DEBUG(" %s", levelInfo.Describe().c_str());
196 : }
197 : }
198 14 : }
199 :
200 6 : RankTableInfo::RankTableInfo(BinaryStream& binaryStream){
201 6 : binaryStream >> version >> rankCount;
202 6 : size_t ranksSize = 0;
203 6 : binaryStream >> ranksSize;
204 8 : HCCL_INFO("[%s] version[%s] rankCount[%u] ranks size[%u]", __func__, version.c_str(), rankCount, ranksSize);
205 13 : for(u32 i = 0; i < ranksSize; i++){
206 7 : NewRankInfo rankInfo(binaryStream);
207 7 : ranks.emplace_back(rankInfo);
208 7 : }
209 6 : binaryStream>>detour;
210 6 : }
211 :
212 13 : void RankTableInfo::GetBinStream(bool isContainLocId, BinaryStream& binaryStream) const{
213 13 : if(ranks.size() == 0) {
214 0 : std::string msg = StringFormat("ranks size is zero.");
215 0 : THROW<InvalidParamsException>(msg);
216 0 : }
217 25 : HCCL_INFO("[%s] version[%s] rankCount[%u] ranks size[%u]", __func__, version.c_str(), rankCount, ranks.size());
218 :
219 13 : binaryStream << version << rankCount;
220 13 : binaryStream << ranks.size();
221 42 : for(auto& it: ranks){
222 29 : it.GetBinStream(isContainLocId, binaryStream);
223 : }
224 13 : binaryStream<<detour;
225 13 : }
226 :
227 1 : vector<char> RankTableInfo::GetUniqueId(bool isContainLocId) const
228 : {
229 1 : if(ranks.size() == 0) {
230 0 : std::string msg = StringFormat("ranks size is zero.");
231 0 : THROW<InvalidParamsException>(msg);
232 0 : }
233 1 : std::vector<char> result(0);
234 :
235 1 : BinaryStream binaryStream;
236 1 : binaryStream << version << rankCount;
237 :
238 1 : u32 ranksSize = ranks.size();
239 1 : binaryStream << ranksSize;
240 2 : for(auto& it: ranks) {
241 1 : it.GetBinStream(isContainLocId, binaryStream);
242 : }
243 :
244 1 : binaryStream.Dump(result);
245 1 : return result;
246 1 : }
247 :
248 1 : void RankTableInfo::UpdateRankTable(const RankTableInfo &localRankInfo)
249 : {
250 : // version
251 1 : if (detour) {
252 0 : CHK_PRT_THROW(localRankInfo.detour != true,
253 : HCCL_ERROR("[%s] detour cfg is not same with other ranks.", __func__),
254 : InvalidParamsException,
255 : "updateRankTableInfo error");
256 : }
257 1 : detour = localRankInfo.detour;
258 1 : if (rankCount == 0) {
259 1 : version = localRankInfo.version;
260 : } else {
261 0 : CHK_PRT_THROW(version != localRankInfo.version,
262 : HCCL_ERROR("[%s] version[%s] error, local version[%s] .", __func__, version.c_str(), localRankInfo.version.c_str()),
263 : InvalidParamsException, "updateRankTableInfo error");
264 : }
265 :
266 : // ranks size
267 1 : CHK_PRT_THROW(localRankInfo.ranks.size() == 0, HCCL_ERROR("[%s] ranks size is zero.", __func__),
268 : InvalidParamsException, "updateRankTableInfo error");
269 :
270 1 : ranks.insert(ranks.end(), localRankInfo.ranks.begin(), localRankInfo.ranks.end());
271 1 : rankCount++;
272 :
273 1 : HCCL_INFO("[%s] success, current rankTableInfo[%s]", __func__, Describe().c_str());
274 1 : }
275 :
276 5 : std::unordered_map<u32, std::unordered_map<IpAddress, u32>> RankTableInfo::GetRankDeviceListenPortMap()
277 : {
278 5 : std::unordered_map<u32, std::unordered_map<IpAddress, u32>> ranklListenPortMap;
279 25 : for (auto &rankinfo : ranks) {
280 20 : std::unordered_map<IpAddress, u32> listenPortMap;
281 80 : for (auto &rankLevelInfo : rankinfo.rankLevelInfos) {
282 160 : for (auto &rankAddr : rankLevelInfo.rankAddrs) {
283 100 : listenPortMap.insert(std::make_pair(rankAddr.addr, rankAddr.socketPort_));
284 : }
285 : }
286 20 : listenPortMap.insert(std::make_pair(DEVICE_PORT_KEY_IPADDRESS, rankinfo.devicePort));
287 20 : ranklListenPortMap.insert(std::make_pair(rankinfo.rankId, listenPortMap));
288 20 : }
289 5 : return ranklListenPortMap;
290 0 : }
291 :
292 : } // namespace Hccl
|