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 "env_func.h"
12 : #include <climits>
13 : #include <fstream>
14 : #include <linux/limits.h>
15 : #include <cctype>
16 : #include <algorithm>
17 : #include <sstream>
18 : #include <array>
19 :
20 : #include "sal.h"
21 : #include "string_util.h"
22 : #include "base_config.h"
23 : #include "orion_adapter_rts.h"
24 : #include "adapter_error_manager_pub.h"
25 :
26 : namespace Hccl {
27 :
28 : /*----------------------------- cast functions -------------------------*/
29 :
30 10 : bool CastBin2Bool(const std::string &s)
31 : {
32 10 : bool b = true;
33 10 : if (s == "0") {
34 3 : b = false;
35 7 : } else if (s == "1") {
36 3 : b = true;
37 : } else {
38 4 : THROW<InvalidParamsException>(StringFormat("Env config \"%s\" is not valid. Should be 0 or 1", s.c_str()));
39 : }
40 6 : return b;
41 : }
42 :
43 2 : u32 CastBin2UInt(const std::string &s)
44 : {
45 2 : u32 b = std::stoi(s);
46 2 : if (b > HCCL_CCU_FLAG_NUM) {
47 2 : THROW<InvalidParamsException>(StringFormat("Env config \"%s\" is not valid. Should be 0 or 1 or 2", s.c_str()));
48 : }
49 3 : HCCL_INFO("[CastBin2UInt] string[%s] to u32[%u]", s.c_str(), b);
50 1 : return b;
51 : }
52 :
53 :
54 2 : static HcclResult SplitHcclSocketIfName(const std::string &socketIfName, std::vector<std::string> &configIfNames)
55 : {
56 2 : std::size_t start = 0;
57 2 : std::size_t end = socketIfName.find(",");
58 4 : while (end != std::string::npos) {
59 2 : if (start == 0 && end == 0) {
60 0 : HCCL_ERROR("[Split][HcclSocketIfName] configIfNames config is invalid.");
61 0 : return HCCL_E_PARA;
62 : }
63 2 : configIfNames.push_back(socketIfName.substr(start, end - start));
64 2 : start = end + 1;
65 2 : end = socketIfName.find(",", start);
66 : }
67 : // 处理最后一个部分
68 2 : if (start < socketIfName.length()) {
69 2 : configIfNames.push_back(socketIfName.substr(start));
70 0 : } else if (start == 0) {
71 0 : HCCL_ERROR("[Split][HcclSocketIfName] configIfNames config is invalid.");
72 0 : return HCCL_E_PARA;
73 : }
74 2 : return HCCL_SUCCESS;
75 : }
76 :
77 : // 临时方案,且当前未使用,测试期望在此拦截该环境变量所有异常值
78 2 : SocketIfName CastSocketIfName(const std::string &s)
79 : {
80 2 : SocketIfName hcclSocketIfNameGroup{};
81 2 : hcclSocketIfNameGroup.configIfNameStr = s;
82 2 : std::string hcclSocketIfName = s;
83 2 : std::string remainSocketIfName = hcclSocketIfName;
84 2 : bool searchNot = false;
85 2 : bool searchExact = false;
86 :
87 2 : if (hcclSocketIfName.length() != 0) {
88 : // 获取HCCL_SOCKET_IFNAME环境变量匹配规则
89 2 : if (!hcclSocketIfName.empty() && hcclSocketIfName.at(0) == '^') {
90 1 : searchNot = true;
91 : // 获取从1位置开始剩余部分环境变量内容
92 1 : remainSocketIfName = hcclSocketIfName.substr(1);
93 : }
94 :
95 2 : if (!remainSocketIfName.empty() && remainSocketIfName.at(0) == '=') {
96 2 : searchExact = true;
97 2 : remainSocketIfName = remainSocketIfName.substr(1);
98 : }
99 :
100 : // 获取用户输入的网卡名列表(使用逗号隔开),将网卡名列表存放到vector变量中
101 2 : HcclResult ret = SplitHcclSocketIfName(remainSocketIfName, hcclSocketIfNameGroup.configIfNames);
102 2 : if(ret != HCCL_SUCCESS) {
103 0 : THROW<InvalidParamsException>(StringFormat("environmental variable HCCL_SOCKET_IFNAME[%s] is invalid. "\
104 : "please check.", s.c_str()));
105 : }
106 6 : HCCL_INFO("HCCL_SOCKET_IFNAME set by environment to [%s]", hcclSocketIfName.c_str());
107 : } else {
108 0 : HCCL_INFO("HCCL_SOCKET_IFNAME set by default to [%s]", hcclSocketIfName.c_str());
109 : }
110 2 : hcclSocketIfNameGroup.searchNot = searchNot;
111 2 : hcclSocketIfNameGroup.searchExact = searchExact;
112 2 : return hcclSocketIfNameGroup;
113 2 : }
114 :
115 36 : bool SplitString(std::string &totalStr, std::string &prefixStr, const std::string &delim)
116 : {
117 36 : std::size_t found = totalStr.find(delim);
118 36 : if (found == std::string::npos) {
119 14 : return false;
120 : }
121 22 : prefixStr = totalStr.substr(0, found);
122 22 : totalStr = totalStr.substr(found + 1);
123 22 : return true;
124 : }
125 :
126 30 : void GetUIntFromStr(const std::string &digitStr, u32 &val)
127 : {
128 30 : bool isAllDigits = std::all_of(digitStr.begin(), digitStr.end(), ::isdigit);
129 30 : CHK_PRT_THROW(!isAllDigits, HCCL_ERROR("[GetUIntFromStr] str[%s] is not all digit.",
130 : digitStr.c_str()), InvalidParamsException, "parser portRange fail.");
131 30 : auto ret = SalStrToULong(digitStr.c_str(), HCCL_BASE_DECIMAL, val);
132 30 : CHK_PRT_THROW(ret != HCCL_SUCCESS, HCCL_ERROR("[GetUIntFromStr] str[%s] is a invalid number.",
133 : digitStr.c_str()), InvalidParamsException, "parser portRange fail.");
134 30 : }
135 :
136 18 : void SplitSinglePortRange(const std::string &envName, std::string &rangeStr, SocketPortRange &portRange)
137 : {
138 18 : std::string rangeMin{};
139 18 : const std::string delim = "-";
140 18 : if (SplitString(rangeStr, rangeMin, delim)) {
141 12 : GetUIntFromStr(rangeMin, portRange.min);
142 12 : GetUIntFromStr(rangeStr, portRange.max);
143 : } else {
144 6 : GetUIntFromStr(rangeStr, portRange.min);
145 6 : portRange.max = portRange.min;
146 : }
147 52 : HCCL_INFO("[SplitSinglePortRange] Load hccl socket port range [%u, %u] from %s",
148 : portRange.min, portRange.max, envName.c_str());
149 18 : }
150 :
151 8 : void CheckSocketPortRangeValid(const std::string &envName, const std::vector<SocketPortRange> &portRanges)
152 : {
153 8 : std::vector<SocketPortRange> rangeVec(portRanges.begin(), portRanges.end());
154 8 : std::sort(rangeVec.begin(), rangeVec.end(), [](SocketPortRange &a, SocketPortRange &b) {
155 18 : return (a.min == b.min) ? (a.max < b.max) : (a.min < b.min);
156 : });
157 16 : for (size_t i = 0; i < rangeVec.size(); ++i) {
158 : // the socket range should not be inverted
159 18 : CHK_PRT_THROW(rangeVec[i].min > rangeVec[i].max,
160 : HCCL_ERROR("[%s] In %s, in socket port range [%u, %u], the lower bound is greater than"
161 : " the upper bound.", __func__, envName.c_str(), rangeVec[i].min, rangeVec[i].max),
162 : InvalidParamsException, "check portRange fail.");
163 :
164 : // the socket range should not include the reserved port for auto listening.
165 22 : CHK_PRT_THROW((rangeVec[i].min <= HCCL_SOCKET_PORT_RANGE_AUTO),
166 : HCCL_ERROR("[%s] In %s, socket port range [%u, %u] includes the reserved port number [%u]. "
167 : "please do not use port [%u] in socket port range.", __func__, envName.c_str(),
168 : rangeVec[i].min, rangeVec[i].max, HCCL_SOCKET_PORT_RANGE_AUTO, HCCL_SOCKET_PORT_RANGE_AUTO),
169 : InvalidParamsException, "check portRange fail.");
170 :
171 : // the socket range should not exceed the maximum port number
172 15 : CHK_PRT_THROW(rangeVec[i].max > MAX_PORT_NUMBER,
173 : HCCL_ERROR("[%s] In %s, in socket port range [%u, %u], the upper bound exceed max port number[%u].",
174 : __func__, envName.c_str(), rangeVec[i].min, rangeVec[i].max, MAX_PORT_NUMBER),
175 : InvalidParamsException, "check portRange fail.");
176 :
177 : // the socket range should not be overlapped
178 14 : CHK_PRT_THROW(i != 0 && rangeVec[i - 1].max >= rangeVec[i].min,
179 : HCCL_ERROR("[%s] In %s, socket port range [%u, %u] is conflict with socket port range [%u, %u].",
180 : __func__, envName.c_str(), rangeVec[i - 1].min, rangeVec[i - 1].max, rangeVec[i].min, rangeVec[i].max),
181 : InvalidParamsException, "check portRange fail.");
182 : }
183 8 : }
184 :
185 8 : void SplitHcclSocketPortRange(const std::string &envName, std::string &portRangeConfig,
186 : std::vector<SocketPortRange> &portRangeVec)
187 : {
188 8 : std::string rangeStr{};
189 8 : const std::string delim = ",";
190 18 : while (SplitString(portRangeConfig, rangeStr, delim)) {
191 10 : SocketPortRange portRange = {};
192 10 : SplitSinglePortRange(envName, rangeStr, portRange);
193 10 : portRangeVec.emplace_back(portRange);
194 : }
195 8 : SocketPortRange portRange = {};
196 8 : SplitSinglePortRange(envName, portRangeConfig, portRange);
197 8 : portRangeVec.emplace_back(portRange);
198 :
199 8 : CheckSocketPortRangeValid(envName, portRangeVec);
200 13 : }
201 :
202 3 : void PrintSocketPortRange(const std::string &envName, const std::vector<SocketPortRange> &portRangeVec)
203 : {
204 : // assemble port ranges into a string to print the result range
205 3 : std::ostringstream portRangeOss;
206 8 : for (auto range : portRangeVec) {
207 5 : portRangeOss << " [" << std::to_string(range.min) << ", " << std::to_string(range.max) << "]";
208 : }
209 7 : HCCL_INFO("%s is set to%s.", envName.c_str(), portRangeOss.str().c_str());
210 3 : }
211 :
212 9 : std::vector<SocketPortRange> CastSocketPortRange(const std::string &s, const std::string &envName)
213 : {
214 9 : std::vector<SocketPortRange> hcclSocketPortRange;
215 : // the environment variable is not set
216 9 : std::string socketPortRange = s;
217 9 : if (socketPortRange.length() == 0) {
218 0 : return hcclSocketPortRange;
219 : }
220 :
221 : // the socket port range is set to auto, then the os will listen on the ports dymamically and automatically.
222 9 : if (socketPortRange == HCCL_AUTO_PORT_CONFIG) {
223 1 : SocketPortRange autoSocketPortRange = {
224 : HCCL_SOCKET_PORT_RANGE_AUTO,
225 : HCCL_SOCKET_PORT_RANGE_AUTO
226 : };
227 1 : hcclSocketPortRange.emplace_back(autoSocketPortRange);
228 :
229 3 : HCCL_INFO("HCCL_HOST_SOCKET_PORT_RANGE is set to %s as [%u, %u].", HCCL_AUTO_PORT_CONFIG,
230 : autoSocketPortRange.min, autoSocketPortRange.max);
231 1 : return hcclSocketPortRange;
232 : }
233 :
234 : // the environment variable is set to an empty string
235 8 : socketPortRange.erase(std::remove(socketPortRange.begin(), socketPortRange.end(), ' '), socketPortRange.end());
236 8 : if (socketPortRange.empty()) {
237 0 : return hcclSocketPortRange;
238 : }
239 :
240 : // load ranges from string
241 8 : SplitHcclSocketPortRange(envName, socketPortRange, hcclSocketPortRange);
242 3 : CHK_PRT_THROW(hcclSocketPortRange.size() == 0,
243 : HCCL_ERROR("Load empty port range from HCCL_HOST_SOCKET_PORT_RANGE, should not empty, please check."),
244 : InvalidParamsException, "parser portRange fail.");
245 :
246 3 : PrintSocketPortRange(envName, hcclSocketPortRange);
247 3 : return hcclSocketPortRange;
248 14 : }
249 :
250 : constexpr u32 HCCL_RDMA_TC_BASE = 4; // RDMATrafficClass需要是4的整数倍
251 4 : void CheckRDMATrafficClass(const u32 &rdmaTrafficClass)
252 : {
253 4 : if (rdmaTrafficClass % HCCL_RDMA_TC_BASE != 0) {
254 1 : RPT_ENV_ERR(true, "EI0001", std::vector<std::string>({"value", "env", "expect"}),
255 : std::vector<std::string>({std::to_string(rdmaTrafficClass), "HCCL_RDMA_TC", "value should be multiple of four"}));
256 3 : HCCL_ERROR("rdmaTrafficClass[%u] is not a multiple of [%u]", rdmaTrafficClass, HCCL_RDMA_TC_BASE);
257 1 : THROW<InvalidParamsException>(
258 2 : StringFormat("rdmaTrafficClass[%u] is not a multiple of [%u]", rdmaTrafficClass, HCCL_RDMA_TC_BASE));
259 : }
260 3 : }
261 :
262 : constexpr u32 BYTES_PER_KB = 1024; // 单位换算
263 2 : void ConvertUnitQpThreshold(u32 &multiQpThreshold)
264 : {
265 6 : HCCL_RUN_INFO("[Init][TransferUnitQpThreshold]Env config HCCL_MULTI_QP_THRESHOLD is %u[KB], converted to %u[B] for "
266 : "subsequant use.", multiQpThreshold, multiQpThreshold * BYTES_PER_KB);
267 2 : multiQpThreshold *= BYTES_PER_KB;
268 2 : }
269 :
270 1 : static void ParseAlgoLevel(const std::string &algoLevel, u32 &level, HcclAlgoType &algoType)
271 : {
272 1 : std::size_t found = algoLevel.find(':');
273 1 : if ((found == 0) || (found == (algoLevel.length() - 1))) {
274 0 : THROW<InvalidParamsException>("algo config is invalid.");
275 : }
276 1 : if (found == std::string::npos) {
277 1 : THROW<InvalidParamsException>("algoLevel cannot find \":\".");
278 : }
279 :
280 0 : std::string orginalLevel = algoLevel.substr(0, found);
281 0 : std::string orginalAlgo = algoLevel.substr(found + 1);
282 :
283 : const std::map<std::string, u32> hcclAlgoLevelMap = {{"level0", HCCL_ALGO_LEVEL_0},
284 : {"level1", HCCL_ALGO_LEVEL_1},
285 : {"level2", HCCL_ALGO_LEVEL_2},
286 0 : {"level3", HCCL_ALGO_LEVEL_3}};
287 :
288 : const std::map<std::string, HcclAlgoType> hcclAlgoTypeMap = {
289 0 : {"null", HcclAlgoType::HCCL_ALGO_TYPE_NULL},
290 0 : {"ring", HcclAlgoType::HCCL_ALGO_TYPE_RING},
291 0 : {"pipeline", HcclAlgoType::HCCL_ALGO_TYPE_PIPELINE},
292 0 : {"fullmesh", HcclAlgoType::HCCL_ALGO_TYPE_FULLMESH},
293 0 : {"H-D_R", HcclAlgoType::HCCL_ALGO_TYPE_HDR},
294 0 : {"pairwise", HcclAlgoType::HCCL_ALGO_TYPE_PAIRWISE},
295 0 : {"NHR", HcclAlgoType::HCCL_ALGO_TYPE_NHR},
296 0 : {"NB", HcclAlgoType::HCCL_ALGO_TYPE_NB},
297 0 : {"NA", HcclAlgoType::HCCL_ALGO_TYPE_NA},
298 0 : {"NHR_V1", HcclAlgoType::HCCL_ALGO_TYPE_NHR_V1},
299 0 : {"AHC", HcclAlgoType::HCCL_ALGO_TYPE_AHC},
300 0 : };
301 :
302 0 : auto iterAlgoLevel = hcclAlgoLevelMap.find(orginalLevel);
303 0 : if (iterAlgoLevel == hcclAlgoLevelMap.end()) {
304 0 : THROW<InvalidParamsException>(
305 0 : StringFormat("algo config is invalid, level %s is not supported.", orginalLevel.c_str()));
306 : }
307 :
308 0 : auto iterAlgoType = hcclAlgoTypeMap.find(orginalAlgo);
309 0 : if (iterAlgoType == hcclAlgoTypeMap.end()) {
310 0 : THROW<InvalidParamsException>(
311 0 : StringFormat("algo config is invalid, algo %s is not supported.", orginalAlgo.c_str()));
312 : }
313 :
314 0 : level = iterAlgoLevel->second;
315 0 : algoType = iterAlgoType->second;
316 0 : }
317 :
318 1 : std::vector<HcclAlgoType> CastAlgoTypeVec(const std::string &s)
319 : {
320 1 : std::vector<HcclAlgoType> algoTypeVec(HCCL_ALGO_LEVEL_NUM);
321 1 : std::string algoConfig = s;
322 1 : algoConfig.erase(std::remove(algoConfig.begin(), algoConfig.end(), ' '), algoConfig.end());
323 :
324 5 : for (u32 i = 0; i < HCCL_ALGO_LEVEL_NUM; i++) {
325 4 : algoTypeVec[i] = HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT;
326 : }
327 :
328 1 : if (algoConfig.empty()) {
329 0 : HCCL_RUN_INFO("hccl algo config is empty, HCCL use built-in algo selection.");
330 0 : return algoTypeVec;
331 : }
332 :
333 1 : std::vector<std::string> algoLevels = SplitString(algoConfig, ';');
334 1 : if (algoLevels.size() > HCCL_ALGO_LEVEL_NUM) {
335 0 : THROW<InvalidParamsException>(
336 0 : StringFormat("The number of algo levels is greater than %u.", HCCL_ALGO_LEVEL_NUM));
337 : }
338 1 : for (const auto &algoLevel : algoLevels) {
339 1 : u32 level = 0;
340 1 : HcclAlgoType algo = HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT;
341 1 : ParseAlgoLevel(algoLevel, level, algo);
342 : // 检查是否存在重复配置level
343 0 : if (algoTypeVec[level] != HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT) {
344 0 : THROW<InvalidParamsException>(
345 0 : StringFormat("hccl algo config[%s] is invalid. expect: levelX:algo1;levelY:algo2", algoConfig.c_str()));
346 : }
347 0 : algoTypeVec[level] = algo;
348 : }
349 :
350 0 : DevType devType = HrtGetDeviceType(); // 910A3场景只支持level0为ring算法
351 0 : if (devType == DevType::DEV_TYPE_910A3 && algoTypeVec[HCCL_ALGO_LEVEL_0] != HcclAlgoType::HCCL_ALGO_TYPE_RING) {
352 0 : algoTypeVec[HCCL_ALGO_LEVEL_0] = HcclAlgoType::HCCL_ALGO_TYPE_RING;
353 : }
354 :
355 0 : return algoTypeVec;
356 3 : }
357 :
358 5 : HcclResult SplitHcclOpType(const std::string &algoConfig, std::vector<std::string> &algos)
359 : {
360 5 : std::string remainAlgoConfig;
361 5 : std::size_t found = algoConfig.find("/");
362 5 : if ((found == 0) || (found == (algoConfig.length() - 1))) {
363 0 : HCCL_ERROR("[Split][SplitHcclOpType] algo config is invalid.");
364 0 : return HCCL_E_PARA;
365 5 : } else if (found != std::string::npos) {
366 0 : remainAlgoConfig = algoConfig.substr(found + 1);
367 : }
368 5 : algos.push_back(algoConfig.substr(0, found));
369 5 : if (!remainAlgoConfig.empty()) {
370 0 : CHK_RET(SplitHcclOpType(remainAlgoConfig, algos));
371 : }
372 5 : return HCCL_SUCCESS;
373 5 : }
374 :
375 : // 新的逐算法的配置和原有的统一配置只可使用一种,发现同时存在时报错
376 5 : HcclResult CheckAlgoConfigValid(
377 : std::vector<std::string> &algos,
378 : bool& anyCommonConfig,
379 : bool& anySpecificConfig)
380 : {
381 10 : for (std::string& algConfig : algos) {
382 5 : std::size_t found = algConfig.find("=");
383 5 : if ((found == 0) || (found == (algConfig.length() - 1))) {
384 0 : HCCL_ERROR("[Split][CheckAlgoConfigValid] algo config is invalid.");
385 0 : return HCCL_E_PARA;
386 5 : } else if (found != std::string::npos) {
387 1 : anySpecificConfig = true;
388 : } else {
389 4 : anyCommonConfig = true;
390 : }
391 : }
392 5 : if (anyCommonConfig && anySpecificConfig) {
393 0 : HCCL_ERROR("[CheckAlgoConfigValid]should not set both algo config way");
394 0 : return HCCL_E_PARA;
395 : }
396 5 : if (anyCommonConfig && algos.size() > 1) {
397 0 : HCCL_ERROR("[CheckAlgoConfigValid]should only set one common config");
398 0 : return HCCL_E_PARA;
399 : }
400 5 : return HCCL_SUCCESS;
401 : }
402 :
403 6 : HcclResult ParserHcclAlgoLevel(const std::string &algoLevel, u32 &level, HcclAlgoType &algoType)
404 : {
405 6 : std::size_t found = algoLevel.find(":");
406 6 : if ((found == 0) || (found == (algoLevel.length() - 1))) {
407 0 : HCCL_ERROR("[Parser][HcclAlgoLevel] algo config is invalid.");
408 0 : return HCCL_E_PARA;
409 : }
410 6 : if (found == std::string::npos) {
411 2 : THROW<InvalidParamsException>("algoLevel cannot find \":\".");
412 : }
413 :
414 4 : std::string orginalLevel = algoLevel.substr(0, found);
415 4 : std::string orginalAlgo = algoLevel.substr(found + 1);
416 :
417 : const std::map<std::string, u32> hcclAlgoLevelMap = {
418 : {"level0", HCCL_ALGO_LEVEL_0},
419 : {"level1", HCCL_ALGO_LEVEL_1},
420 : {"level2", HCCL_ALGO_LEVEL_2},
421 : {"level3", HCCL_ALGO_LEVEL_3}
422 24 : };
423 :
424 : const std::map<std::string, HcclAlgoType> hcclAlgoTypeMap = {
425 0 : {"null", HcclAlgoType::HCCL_ALGO_TYPE_NULL},
426 0 : {"ring", HcclAlgoType::HCCL_ALGO_TYPE_RING},
427 0 : {"pipeline", HcclAlgoType::HCCL_ALGO_TYPE_PIPELINE},
428 0 : {"fullmesh", HcclAlgoType::HCCL_ALGO_TYPE_FULLMESH},
429 0 : {"H-D_R", HcclAlgoType::HCCL_ALGO_TYPE_HDR},
430 0 : {"pairwise", HcclAlgoType::HCCL_ALGO_TYPE_PAIRWISE},
431 0 : {"NHR", HcclAlgoType::HCCL_ALGO_TYPE_NHR},
432 0 : {"NB", HcclAlgoType::HCCL_ALGO_TYPE_NB},
433 0 : {"NA", HcclAlgoType::HCCL_ALGO_TYPE_NA},
434 0 : {"NHR_V1", HcclAlgoType::HCCL_ALGO_TYPE_NHR_V1},
435 0 : {"AHC", HcclAlgoType::HCCL_ALGO_TYPE_AHC},
436 52 : };
437 :
438 4 : auto iterAlgoLevel = hcclAlgoLevelMap.find(orginalLevel);
439 4 : if (iterAlgoLevel == hcclAlgoLevelMap.end()) {
440 0 : HCCL_ERROR("[Parser][HcclAlgoLevel] algo config is invalid, level %s is not supported.", orginalLevel.c_str());
441 0 : return HCCL_E_PARA;
442 : }
443 :
444 4 : auto iterAlgoType = hcclAlgoTypeMap.find(orginalAlgo);
445 4 : if (iterAlgoType == hcclAlgoTypeMap.end()) {
446 6 : HCCL_ERROR("[Parser][HcclAlgoLevel] algo config is invalid, algo %s is not supported.", orginalAlgo.c_str());
447 2 : return HCCL_E_PARA;
448 : }
449 :
450 2 : level = iterAlgoLevel->second;
451 2 : algoType = iterAlgoType->second;
452 :
453 2 : return HCCL_SUCCESS;
454 12 : }
455 :
456 : const std::map<HcclAlgoType, std::string> HcclAlgoTypeMap = {
457 : {HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT, "default"},
458 : {HcclAlgoType::HCCL_ALGO_TYPE_RING, "ring"},
459 : {HcclAlgoType::HCCL_ALGO_TYPE_PIPELINE, "pipeline"},
460 : {HcclAlgoType::HCCL_ALGO_TYPE_FULLMESH, "fullmesh"},
461 : {HcclAlgoType::HCCL_ALGO_TYPE_HDR, "HDR"},
462 : {HcclAlgoType::HCCL_ALGO_TYPE_PAIRWISE, "pairwise"},
463 : {HcclAlgoType::HCCL_ALGO_TYPE_NHR, "NHR"},
464 : {HcclAlgoType::HCCL_ALGO_TYPE_NB, "NB"},
465 : {HcclAlgoType::HCCL_ALGO_TYPE_NULL, "null"},
466 : {HcclAlgoType::HCCL_ALGO_TYPE_NA, "NA"},
467 : {HcclAlgoType::HCCL_ALGO_TYPE_NHR_V1, "NHR_V1"},
468 : {HcclAlgoType::HCCL_ALGO_TYPE_AHC, "AHC"},
469 : };
470 :
471 8 : HcclResult SplitHcclAlgoLevel(const std::string &algoConfig, std::vector<std::string> &algos)
472 : {
473 8 : std::string remainAlgoConfig;
474 8 : std::size_t found = algoConfig.find(";");
475 8 : if ((found == 0) || (found == (algoConfig.length() - 1))) {
476 0 : HCCL_ERROR("[Split][HcclAlgoLevel] algo config is invalid.");
477 0 : return HCCL_E_PARA;
478 8 : } else if (found != std::string::npos) {
479 3 : remainAlgoConfig = algoConfig.substr(found + 1);
480 : } else {
481 : // 最后一组配置,剩余的字符串为空
482 : }
483 8 : algos.push_back(algoConfig.substr(0, found));
484 :
485 8 : if (algos.size() > HCCL_ALGO_LEVEL_NUM) {
486 0 : HCCL_ERROR("[Split][HcclAlgoLevel] algo config is invalid. algo level is more than %u.", HCCL_ALGO_LEVEL_NUM);
487 0 : return HCCL_E_PARA;
488 : }
489 8 : if (!remainAlgoConfig.empty()) {
490 3 : CHK_RET(SplitHcclAlgoLevel(remainAlgoConfig, algos));
491 : }
492 :
493 8 : return HCCL_SUCCESS;
494 8 : }
495 :
496 5 : HcclResult ParseAlgoString(std::string opName, std::string &algoString, std::vector<HcclAlgoType>& algType)
497 : {
498 5 : algType = std::vector<HcclAlgoType>(HCCL_ALGO_LEVEL_NUM, HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT);
499 5 : std::vector<std::string> algoLevels;
500 5 : HcclResult ret = SplitHcclAlgoLevel(algoString, algoLevels);
501 5 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "\
502 : "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
503 : algoString.c_str()), ret);
504 7 : for (auto algoLevel : algoLevels) {
505 6 : u32 level = 0;
506 6 : HcclAlgoType algo = HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT;
507 6 : ret = ParserHcclAlgoLevel(algoLevel, level, algo);
508 10 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "\
509 : "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
510 : algoString.c_str()), ret);
511 : // 检查是否存在重复配置level
512 2 : if (algType[level] != HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT) {
513 0 : HCCL_ERROR("[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "\
514 : "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
515 : algoString.c_str());
516 0 : return HCCL_E_PARA;
517 : }
518 2 : algType[level] = algo;
519 6 : }
520 1 : auto level0Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_0]);
521 1 : auto level1Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_1]);
522 1 : auto level2Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_2]);
523 1 : auto level3Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_3]);
524 3 : HCCL_RUN_INFO("hccl algo op %s config: level0:%s, level1:%s, level2:%s, level3:%s",
525 : opName.c_str(),
526 : level0Iter->second.c_str(), level1Iter->second.c_str(),
527 : level2Iter->second.c_str(), level3Iter->second.c_str());
528 1 : return HCCL_SUCCESS;
529 5 : }
530 :
531 4 : HcclResult SetCommonAlgType(std::vector<std::string> &algos, std::map<OpType, std::vector<HcclAlgoType>>& hcclAlgoConfig)
532 : {
533 4 : std::vector<HcclAlgoType> algType;
534 18 : CHK_RET(ParseAlgoString("all op type", algos[0], algType));
535 0 : for (auto opType : OP_TYPE_SET) {
536 0 : hcclAlgoConfig[opType] = algType;
537 : }
538 0 : return HCCL_SUCCESS;
539 4 : }
540 :
541 1 : HcclResult SetSpecificAlgType(std::vector<std::string> &algos, std::map<OpType, std::vector<HcclAlgoType>>& hcclAlgoConfig)
542 : {
543 : std::map<std::string, OpType> hcclOpTypeMap = {
544 0 : {"broadcast", OpType::BROADCAST},
545 0 : {"allreduce", OpType::ALLREDUCE},
546 0 : {"reduce", OpType::REDUCE},
547 0 : {"send", OpType::SEND},
548 0 : {"receive", OpType::RECV},
549 0 : {"allgather", OpType::ALLGATHER},
550 0 : {"reducescatter", OpType::REDUCESCATTER},
551 0 : {"alltoall", OpType::ALLTOALL},
552 0 : {"gather", OpType::GATHER},
553 0 : {"scatter", OpType::SCATTER},
554 0 : {"sendrecv", OpType::BATCHSENDRECV},
555 13 : };
556 2 : for (std::string& algConfig : algos) {
557 1 : std::size_t found = algConfig.find("=");
558 1 : std::string opStringName = algConfig.substr(0, found);
559 1 : if (hcclOpTypeMap.find(opStringName) != hcclOpTypeMap.end()) {
560 1 : OpType optype = hcclOpTypeMap[opStringName];
561 1 : std::string remainAlgoConfig = algConfig.substr(found + 1);
562 1 : std::vector<HcclAlgoType> algType;
563 1 : CHK_RET(ParseAlgoString(opStringName, remainAlgoConfig, algType));
564 1 : if (algType[0] == HcclAlgoType::HCCL_ALGO_TYPE_NULL) {
565 0 : HCCL_ERROR("[SetSpecificAlgType] specific config level0 not support null type.");
566 0 : return HCCL_E_PARA;
567 : }
568 1 : hcclAlgoConfig[optype] = algType;
569 1 : } else {
570 0 : HCCL_ERROR("[SetSpecificAlgType] specific config optype[%s] is invalid, please check",
571 : opStringName.c_str());
572 0 : return HCCL_E_PARA;
573 : }
574 1 : }
575 1 : if (hcclAlgoConfig.find(OpType::ALLTOALL) != hcclAlgoConfig.end()) {
576 0 : hcclAlgoConfig[OpType::ALLTOALLV] =
577 0 : hcclAlgoConfig[OpType::ALLTOALL];
578 0 : hcclAlgoConfig[OpType::ALLTOALLVC] =
579 0 : hcclAlgoConfig[OpType::ALLTOALL];
580 : }
581 1 : return HCCL_SUCCESS;
582 2 : }
583 :
584 5 : std::map<OpType, std::vector<HcclAlgoType>> SetHcclAlgoConfig(const std::string &hcclAlgo)
585 : {
586 5 : std::string algoConfig = hcclAlgo;
587 5 : algoConfig.erase(std::remove(algoConfig.begin(), algoConfig.end(), ' '), algoConfig.end());
588 5 : std::map<OpType, std::vector<HcclAlgoType>> hcclAlgoConfig;
589 5 : if (algoConfig.empty()) {
590 0 : HCCL_RUN_INFO("hccl algo config is empty, HCCL use built-in algo selection.");
591 0 : return hcclAlgoConfig;
592 : }
593 5 : std::vector<std::string> algoPerOptype;
594 5 : HcclResult splitRet = SplitHcclOpType(algoConfig, algoPerOptype);
595 5 : if (splitRet != HCCL_SUCCESS) {
596 0 : THROW<InvalidParamsException>(
597 0 : StringFormat("Env HCCL_ALGO config \"%s\" is invalid. example [level0:NA;level1:NHR] or"
598 : "[allreduce=level0:NA;level1:ring/allgather=level0:NA;level1:H-D_R]", hcclAlgo.c_str()));
599 : }
600 :
601 5 : bool anyCommonConfig = false;
602 5 : bool anySpecificConfig = false;
603 5 : HcclResult checkRet = CheckAlgoConfigValid(algoPerOptype, anyCommonConfig, anySpecificConfig);
604 5 : if (checkRet != HCCL_SUCCESS) {
605 0 : THROW<InvalidParamsException>(
606 0 : StringFormat("Env HCCL_ALGO config \"%s\" is invalid. example [level0:NA;level1:NHR] or"
607 : "[allreduce=level0:NA;level1:ring/allgather=level0:NA;level1:H-D_R]", hcclAlgo.c_str()));
608 : }
609 5 : HcclResult ret = HCCL_SUCCESS;
610 5 : if (anyCommonConfig) {
611 4 : ret = SetCommonAlgType(algoPerOptype, hcclAlgoConfig);
612 : } else {
613 1 : ret = SetSpecificAlgType(algoPerOptype, hcclAlgoConfig);
614 : }
615 3 : if (ret != HCCL_SUCCESS) {
616 2 : THROW<InvalidParamsException>(
617 6 : StringFormat("Env HCCL_ALGO config \"%s\" is invalid. example [level0:NA;level1:NHR] or"
618 : "[allreduce=level0:NA;level1:ring/allgather=level0:NA;level1:H-D_R]", hcclAlgo.c_str()));
619 : }
620 1 : return hcclAlgoConfig;
621 13 : }
622 :
623 11 : HcclAccelerator CastHcclAccelerator(const std::string &s)
624 : {
625 11 : HcclAccelerator mode;
626 11 : if (s == "AI_CPU" || s == "AICPU_TS") {
627 3 : mode = HcclAccelerator::AICPU_TS;
628 8 : } else if (s == "AIV") {
629 1 : mode = HcclAccelerator::AIV;
630 7 : } else if (s == "CCU_MS") {
631 1 : mode = HcclAccelerator::CCU_MS;
632 6 : } else if (s == "CCU_SCHED") {
633 2 : mode = HcclAccelerator::CCU_SCHED;
634 : } else {
635 12 : HCCL_ERROR("Env HCCL_OP_EXPANSION_MODE config do not support %s, it should be one of [AI_CPU, AICPU_TS, AIV, CCU_MS, CCU_SCHED].", s.c_str());
636 4 : THROW<InvalidParamsException>(
637 12 : StringFormat("Env HCCL_OP_EXPANSION_MODE config \"%s\" is invalid."
638 : "it should be one of [AI_CPU, AICPU_TS, AIV, CCU_MS, CCU_SCHED].", s.c_str()));
639 : }
640 7 : return mode;
641 : }
642 :
643 5 : s32 CastSocketFamily(const std::string &s)
644 : {
645 : s32 hcclSocketFamily;
646 5 : if (s == "AF_INET") {
647 1 : hcclSocketFamily = AF_INET;
648 4 : } else if (s == "AF_INET6") {
649 2 : hcclSocketFamily = AF_INET6;
650 : } else {
651 2 : hcclSocketFamily = -1;
652 2 : THROW<InvalidParamsException>(
653 4 : StringFormat("environmental variable HCCL_SOCKET_FAMILY[%s] is invalid. it should "
654 : "be \"AF_INET\" or \"AF_INET6\".",
655 : s.c_str()));
656 : }
657 3 : return hcclSocketFamily;
658 : }
659 :
660 11 : std::string GetCannVersionPath(const std::string &cannEnvStr, const std::string &keyStr)
661 : {
662 11 : std::string cannVersionPath;
663 11 : std::string tempPath; // 存放临时路径
664 : // 查找cann安装路径
665 494 : for (u32 i = 0; i < cannEnvStr.length(); ++i) {
666 : // 环境变量中存放的每段路径之间以':'隔开
667 484 : if (cannEnvStr[i] != ':') {
668 483 : tempPath += cannEnvStr[i];
669 : }
670 : // 对存放CANN版本文件的路径进行搜索, 有两种情况
671 : // 一种是*/latest/version.cfg
672 : // 另一种是*/runtime/version.info
673 484 : if (cannEnvStr[i] == ':' || i == cannEnvStr.length() - 1) {
674 12 : size_t found = tempPath.find(keyStr);
675 12 : if (found == string::npos) {
676 11 : tempPath.clear();
677 11 : continue;
678 : }
679 : // 防止出现类似/runtime*/的情况
680 1 : if (tempPath.length() <= found + keyStr.length() || tempPath[found + keyStr.length()] == '/') {
681 1 : cannVersionPath = tempPath.substr(0, found + keyStr.length());
682 1 : break;
683 : }
684 0 : tempPath.clear();
685 : }
686 : }
687 : // 路径为空
688 11 : if (cannVersionPath.empty()) {
689 20 : return "NotFound";
690 : }
691 1 : return cannVersionPath;
692 11 : }
693 :
694 1 : std::string LoadCannVersionInfoFile(const std::string &realName, const std::string &keyStr)
695 : {
696 1 : std::string cannVersion;
697 : // 打开该文件前,判断该文件路径是否有效、规范
698 1 : char realFile[PATH_MAX] = {0};
699 1 : if (realpath(realName.c_str(), realFile) == nullptr) {
700 0 : HCCL_INFO("[CannVersion][Verification]cann version path %s is not a valid real path", realName.c_str());
701 0 : return "";
702 : }
703 3 : HCCL_INFO("Load CannVersion InfoFile in %s", realFile);
704 :
705 : // realFile转str,然后open这个str
706 1 : std::ifstream infile(realFile, std::ifstream::in);
707 :
708 1 : if (!infile.is_open()) {
709 3 : HCCL_INFO("[CannVersion][Verification]%s does not exist.", realFile);
710 2 : return "";
711 : }
712 :
713 : // 逐行读取,结果放在line中,寻找带有keyStr的字符串
714 0 : string line;
715 0 : s32 maxRows = 100; // 在文件中读取的最长行数为100,避免超大文件长时间读取
716 0 : while (getline(infile, line)) {
717 0 : --maxRows;
718 0 : if (maxRows < 0) {
719 0 : HCCL_WARNING("[CannVersion][Verification]version file content is too long.");
720 0 : return "";
721 : }
722 0 : u32 found = line.find(keyStr);
723 : // 版本字段的两种模式
724 : // runtime目录下, version.info文件, Version=1.83.T8.0.B128
725 : // latest目录下, version.cfg文件, runtime_running_version=[1.83.T8.0.B128:CANN-1.83]
726 0 : if (found == 0) {
727 0 : u32 startPos = keyStr.length(); // 版本字符串开始位置
728 0 : u32 endPos = min(line.find(":"), line.length()); // 版本字符串在":"或结尾处结束
729 : // 版本字符串为空
730 0 : if (endPos <= startPos) {
731 0 : HCCL_WARNING("[CannVersion][Verification]cannVersion is invalid.");
732 0 : return "";
733 : }
734 :
735 0 : u32 len = endPos - startPos; // 版本字符串长度
736 0 : cannVersion = line.substr(startPos, len); // 从keyStr截断
737 0 : HCCL_INFO("[Parse][CannVersion]success, CannVersion is %s ", cannVersion.c_str());
738 0 : break;
739 : }
740 : }
741 0 : infile.close();
742 0 : return cannVersion;
743 1 : }
744 :
745 6 : std::string CastCannVersion(const std::string &cannEnv)
746 : {
747 6 : std::string cannVersionPath = GetCannVersionPath(cannEnv, "/runtime");
748 6 : if (cannVersionPath != "NotFound") {
749 1 : cannVersionPath += "/version.info";
750 1 : std::string cannVersion = LoadCannVersionInfoFile(cannVersionPath, "Version=");
751 1 : return cannVersion;
752 0 : }
753 :
754 5 : cannVersionPath = GetCannVersionPath(cannEnv, "/latest");
755 5 : if (cannVersionPath != "NotFound") {
756 0 : cannVersionPath += "/version.cfg";
757 0 : std::string cannVersion = LoadCannVersionInfoFile(cannVersionPath, "runtime_running_version=[");
758 0 : return cannVersion;
759 0 : }
760 :
761 15 : HCCL_INFO("cannot found version file in %s.", cannEnv.c_str());
762 10 : return "";
763 6 : }
764 :
765 18 : std::vector<std::string> SplitDfsConfig(const std::string &str, char delimiter)
766 : {
767 18 : std::vector<std::string> tokens;
768 18 : std::istringstream stream(str);
769 18 : std::string token;
770 :
771 44 : while (std::getline(stream, token, delimiter)) {
772 26 : tokens.push_back(token);
773 : }
774 18 : if (stream.peek() != EOF) {
775 0 : std::string remaining;
776 0 : std::getline(stream, remaining);
777 0 : tokens.push_back(remaining);
778 0 : }
779 18 : if (!str.empty() && str.back() == delimiter) {
780 0 : tokens.push_back("");
781 : }
782 18 : return tokens;
783 18 : }
784 :
785 8 : void CastDfsConfigParseTaskExceptionEnable(bool &taskExceptionEnable, const std::string configValue)
786 : {
787 8 : if (configValue == "off") {
788 2 : taskExceptionEnable = false;
789 6 : HCCL_WARNING("env[HCCL_DFS_CONFIG] task_exception was configed to [%s]", configValue.c_str());
790 6 : } else if (configValue == "on") {
791 5 : taskExceptionEnable = true;
792 : } else {
793 1 : THROW<InvalidParamsException>(StringFormat(
794 : "env[HCCL_DFS_CONFIG] please set task_exception to 'on' or 'off'.", configValue.c_str()));
795 : }
796 7 : }
797 :
798 0 : void CastDfsConfigParseClusterHeartBeatEnable(bool &clusterHeartBeatEnable, const std::string configValue)
799 : {
800 0 : if (configValue == "off") {
801 0 : clusterHeartBeatEnable = false;
802 0 : HCCL_WARNING("env[HCCL_DFS_CONFIG] cluster_heartbeat was configed to [%s]", configValue.c_str());
803 0 : } else if (configValue == "on") {
804 0 : clusterHeartBeatEnable = true;
805 : } else {
806 0 : THROW<InvalidParamsException>(StringFormat(
807 : "env[HCCL_DFS_CONFIG] please set cluster_heartbeat to 'on' or 'off'.", configValue.c_str()));
808 : }
809 0 : }
810 :
811 0 : void CastDfsConfigParseRankConsistentState(int32_t &rankConsistentState, const std::string configValue)
812 : {
813 0 : if (configValue == "off") {
814 0 : rankConsistentState = -1;
815 0 : }else if (configValue == "first")
816 : {
817 0 : rankConsistentState = 0;
818 0 : }else if (configValue == "on")
819 : {
820 0 : rankConsistentState = 1;
821 : }else {
822 0 : THROW<InvalidParamsException>(StringFormat(
823 : "env[HCCL_DFS_CONFIG] please set inconsistent_check to '-1' or '0' or '1'.", configValue.c_str()));
824 : }
825 0 : }
826 :
827 9 : DfsConfig CastDfsConfig(const std::string &dfsConfigEnv)
828 : {
829 9 : constexpr std::size_t DFS_CONFIG_ITEM_NUM = 3;
830 18 : const std::array<std::string, DFS_CONFIG_ITEM_NUM> dfsItemName = {"task_exception", "cluster_heartbeat", "inconsistent_check"};
831 9 : bool taskExceptionEnable = true;
832 9 : bool clusterHeartBeatEnable = true;
833 9 : int32_t rankConsistentState = 0;
834 9 : std::string dfsConfigEnvCopy = dfsConfigEnv;
835 9 : dfsConfigEnvCopy.erase(std::remove(dfsConfigEnvCopy.begin(), dfsConfigEnvCopy.end(), ' '), dfsConfigEnvCopy.end());
836 9 : auto items = SplitDfsConfig(dfsConfigEnvCopy, ',');
837 16 : for (const auto &item : items) {
838 9 : auto itemPair = SplitDfsConfig(item, ':');
839 9 : constexpr std::size_t ITEM_SIZE = 2;
840 9 : if (itemPair.size() != ITEM_SIZE
841 9 : || std::find(dfsItemName.begin(), dfsItemName.end(), itemPair[0]) == dfsItemName.end()) {
842 1 : THROW<InvalidParamsException>(
843 3 : StringFormat("env[HCCL_DFS_CONFIG] value[%s] is invalid, please check, example [task_exception:on]", dfsConfigEnv.c_str()));
844 : }
845 8 : if (itemPair[0] == dfsItemName[0]) {
846 9 : CastDfsConfigParseTaskExceptionEnable(taskExceptionEnable, itemPair[1]);
847 0 : } else if (itemPair[0] == dfsItemName[1]) {
848 0 : CastDfsConfigParseClusterHeartBeatEnable(clusterHeartBeatEnable, itemPair[1]);
849 0 : } else if (itemPair[0] == dfsItemName[2]) {
850 0 : CastDfsConfigParseRankConsistentState(rankConsistentState, itemPair[1]);
851 : }
852 9 : }
853 7 : DfsConfig config{taskExceptionEnable, clusterHeartBeatEnable, rankConsistentState};
854 :
855 7 : return config;
856 13 : }
857 :
858 : /*----------------------------- validate functions -------------------------*/
859 6 : void CheckExecTimeOut(const u32 &timeOut)
860 : {
861 6 : DevType devType = HrtGetDeviceType();
862 17 : if (devType == DevType::DEV_TYPE_910A2 || devType == DevType::DEV_TYPE_910A3 ||
863 17 : devType == DevType::DEV_TYPE_950 || devType == DevType::DEV_TYPE_960) {
864 : // 910A2和910A3算子超时时间范围0s-2147483647s,其中0代表永不超时
865 5 : CheckRange<u32>(timeOut, 0, HCCL_EXEC_TIME_OUT_S_910A3);
866 : } else {
867 : // 非910A2和910A3算子超时时间范围1s-17340s
868 1 : CheckRange<u32>(timeOut, 1, HCCL_EXEC_TIME_OUT_S);
869 : }
870 5 : }
871 :
872 4 : void CheckFilePath(const string &filePath)
873 : {
874 4 : if (filePath.length() >= (PATH_MAX) || filePath.length() == 0) {
875 1 : THROW<InvalidParamsException>(
876 2 : StringFormat("env[HCCL_WHITELIST_FILE] is invalid, len is %u, should be (0,4096)", filePath.length()));
877 : }
878 3 : }
879 :
880 9 : void CheckRdmaTimeout(const u32 &timeout)
881 : {
882 : // HCCL_RDMA_TIMEOUT 合法范围为:[0, 31],超出31按照0进行处理,表示永不超时
883 : // 此处为空实现,原因为非法值在 Str2T<u32> 里面已经处理
884 : (void)timeout;
885 9 : }
886 :
887 : /*-------------------------- post process functions -------------------------*/
888 3 : void SetRealPath(string &filePath)
889 : {
890 3 : char realFile[PATH_MAX] = {0};
891 3 : if (realpath(filePath.c_str(), realFile) == nullptr) {
892 2 : THROW<InvalidParamsException>(StringFormat("[Init][EnvVarParam]path %s is not a valid real path", filePath.c_str()));
893 : }
894 2 : filePath = std::string(realFile);
895 2 : }
896 :
897 5 : void ProcExecTimeOut(u32 &timeOut)
898 : {
899 5 : DevType devType = HrtGetDeviceType();
900 14 : if (devType == DevType::DEV_TYPE_910A2 || devType == DevType::DEV_TYPE_910A3 ||
901 14 : devType == DevType::DEV_TYPE_950 || devType == DevType::DEV_TYPE_960) {
902 4 : return;
903 : }
904 : // 910A芯片限制超时时长为68的倍数
905 1 : s32 intPart = timeOut / HCCL_INTEVAL_EXEC_TIME_OUT_S;
906 1 : intPart = (intPart == 0) ? 1 : intPart;
907 1 : timeOut = intPart * HCCL_INTEVAL_EXEC_TIME_OUT_S;
908 : }
909 :
910 12 : void ProcRdmaTimeout(u32 &timeout)
911 : {
912 : // HCCL_RDMA_TIMEOUT 合法范围为:[0, 31],超出31按照0进行处理,表示永不超时
913 12 : if (timeout > EnvRdmaConfig::HCCL_RDMA_TIMEOUT_MAX) {
914 9 : HCCL_WARNING("HCCL_RDMA_TIMEOUT[%u] exceeds max [%u], reset to [%u]", timeout,
915 : EnvRdmaConfig::HCCL_RDMA_TIMEOUT_MAX, EnvRdmaConfig::HCCL_RDMA_TIMEOUT_MIN);
916 3 : timeout = EnvRdmaConfig::HCCL_RDMA_TIMEOUT_MIN;
917 : }
918 12 : }
919 :
920 : /*-------------------------- detour type -------------------------*/
921 : // 临时方案,特定场景执行算法会报错,后续适配了再放开
922 6 : HcclDetourType CastDetourType(const std::string &s)
923 : {
924 6 : if (s == "detour:1") {
925 6 : HCCL_INFO("HCCL detour type is 2P (detour:1).");
926 2 : return HcclDetourType::HCCL_DETOUR_ENABLE_2P;
927 4 : } else if (s == "detour:0") {
928 3 : HCCL_INFO("HCCL detour type is disable (detour:0).");
929 : } else {
930 3 : THROW<NotSupportException>(StringFormat("environment variable HCCL_DETOUR currently only supports"
931 : " detour:1 and detour:0 or not set."));
932 : }
933 1 : return HcclDetourType::HCCL_DETOUR_DISABLE;
934 : }
935 :
936 : } // namespace Hccl
|