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