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 <mutex>
12 : #include <sstream>
13 : #include <string>
14 : #include <cmath>
15 : #include "alg_env_config.h"
16 :
17 : using namespace hccl;
18 :
19 : static std::mutex g_algEnvConfigMutex;
20 :
21 0 : HcclResult ResetAlgEnvConfigInitState()
22 : {
23 0 : std::lock_guard<std::mutex> lock(g_algEnvConfigMutex);
24 0 : g_algEnvConfig.SetDefaultParams();
25 0 : return HCCL_SUCCESS;
26 0 : }
27 :
28 333742 : const std::vector<HcclAlgoType> GetExternalInputHcclAlgoConfig(HcclCMDType opType)
29 : {
30 333742 : std::lock_guard<std::mutex> lock(g_algEnvConfigMutex);
31 668103 : return g_algEnvConfig.hcclAlgoConfig[opType];
32 334053 : }
33 :
34 42 : HcclResult SetCommonAlgType(std::vector<std::string> &algos)
35 : {
36 42 : std::lock_guard<std::mutex> lock(g_algEnvConfigMutex);
37 42 : std::vector<HcclAlgoType> algType;
38 126 : CHK_RET(ParseAlgoString("all op type", algos[0], algType));
39 4410 : for (u32 opType = 0; opType < static_cast<u32>(HcclCMDType::HCCL_CMD_MAX); opType++) {
40 4368 : g_algEnvConfig.hcclAlgoConfig[static_cast<HcclCMDType>(opType)] = algType;
41 : }
42 42 : return HCCL_SUCCESS;
43 42 : }
44 :
45 0 : HcclResult SetSpecificAlgType(std::vector<std::string> &algos)
46 : {
47 0 : std::lock_guard<std::mutex> lock(g_algEnvConfigMutex);
48 0 : for (std::string& algConfig : algos) {
49 0 : std::size_t found = algConfig.find("=");
50 0 : std::string opStringName = algConfig.substr(0, found);
51 0 : if (opStringName == "others") {
52 0 : std::vector<HcclAlgoType> algType;
53 0 : std::string remainAlgoConfig = algConfig.substr(found + 1);
54 0 : CHK_RET(ParseAlgoString("others op type", remainAlgoConfig, algType));
55 0 : for (u32 opType = 0; opType < static_cast<u32>(HcclCMDType::HCCL_CMD_MAX); opType++) {
56 0 : g_algEnvConfig.hcclAlgoConfig[static_cast<HcclCMDType>(opType)] = algType;
57 : }
58 0 : }
59 0 : }
60 : std::map<std::string, HcclCMDType> hcclOpTypeMap = {
61 0 : {"broadcast", HcclCMDType::HCCL_CMD_BROADCAST},
62 0 : {"allreduce", HcclCMDType::HCCL_CMD_ALLREDUCE},
63 0 : {"reduce", HcclCMDType::HCCL_CMD_REDUCE},
64 0 : {"send", HcclCMDType::HCCL_CMD_SEND},
65 0 : {"receive", HcclCMDType::HCCL_CMD_RECEIVE},
66 0 : {"allgather", HcclCMDType::HCCL_CMD_ALLGATHER},
67 0 : {"reducescatter", HcclCMDType::HCCL_CMD_REDUCE_SCATTER},
68 0 : {"alltoall", HcclCMDType::HCCL_CMD_ALLTOALL},
69 0 : {"gather", HcclCMDType::HCCL_CMD_GATHER},
70 0 : {"scatter", HcclCMDType::HCCL_CMD_SCATTER},
71 0 : {"sendrecv", HcclCMDType::HCCL_CMD_BATCH_SEND_RECV},
72 0 : };
73 0 : for (std::string& algConfig : algos) {
74 0 : std::size_t found = algConfig.find("=");
75 0 : std::string opStringName = algConfig.substr(0, found);
76 0 : if (hcclOpTypeMap.find(opStringName) != hcclOpTypeMap.end()) {
77 0 : HcclCMDType optype = hcclOpTypeMap[opStringName];
78 0 : std::string remainAlgoConfig = algConfig.substr(found + 1);
79 0 : std::vector<HcclAlgoType> algType;
80 0 : CHK_RET(ParseAlgoString(opStringName, remainAlgoConfig, algType));
81 0 : if (algType[0] == HcclAlgoType::HCCL_ALGO_TYPE_NULL) {
82 0 : HCCL_ERROR("[SetSpecificAlgType] specific config level0 not support null type.");
83 0 : return HCCL_E_PARA;
84 : }
85 0 : g_algEnvConfig.hcclAlgoConfig[optype] = algType;
86 0 : } else {
87 0 : HCCL_ERROR("[SetSpecificAlgType] specific config optype[%s] is invalid, please check",
88 : opStringName.c_str());
89 0 : return HCCL_E_PARA;
90 : }
91 0 : }
92 0 : g_algEnvConfig.hcclAlgoConfig[HcclCMDType::HCCL_CMD_ALLTOALLV] =
93 0 : g_algEnvConfig.hcclAlgoConfig[HcclCMDType::HCCL_CMD_ALLTOALL];
94 0 : g_algEnvConfig.hcclAlgoConfig[HcclCMDType::HCCL_CMD_ALLTOALLVC] =
95 0 : g_algEnvConfig.hcclAlgoConfig[HcclCMDType::HCCL_CMD_ALLTOALL];
96 0 : return HCCL_SUCCESS;
97 0 : }
98 :
99 92 : HcclResult ParserHcclAlgoLevel(const std::string &algoLevel, u32 &level, HcclAlgoType &algoType)
100 : {
101 92 : std::size_t found = algoLevel.find(":");
102 92 : if ((found == 0) || (found == (algoLevel.length() - 1))) {
103 0 : HCCL_ERROR("[Parser][HcclAlgoLevel] algo config is invalid.");
104 0 : return HCCL_E_PARA;
105 : }
106 :
107 92 : std::string orginalLevel = algoLevel.substr(0, found);
108 92 : std::string orginalAlgo = algoLevel.substr(found + 1);
109 :
110 : const std::map<std::string, u32> hcclAlgoLevelMap = {
111 : {"level0", HCCL_ALGO_LEVEL_0},
112 : {"level1", HCCL_ALGO_LEVEL_1},
113 : {"level2", HCCL_ALGO_LEVEL_2},
114 : {"level3", HCCL_ALGO_LEVEL_3}
115 552 : };
116 :
117 : const std::map<std::string, HcclAlgoType> hcclAlgoTypeMap = {
118 0 : {"null", HcclAlgoType::HCCL_ALGO_TYPE_NULL},
119 0 : {"ring", HcclAlgoType::HCCL_ALGO_TYPE_RING},
120 0 : {"pipeline", HcclAlgoType::HCCL_ALGO_TYPE_PIPELINE},
121 0 : {"fullmesh", HcclAlgoType::HCCL_ALGO_TYPE_FULLMESH},
122 0 : {"H-D_R", HcclAlgoType::HCCL_ALGO_TYPE_HDR},
123 0 : {"pairwise", HcclAlgoType::HCCL_ALGO_TYPE_PAIRWISE},
124 0 : {"NHR", HcclAlgoType::HCCL_ALGO_TYPE_NHR},
125 0 : {"NHR_V1", HcclAlgoType::HCCL_ALGO_TYPE_NHR_V1},
126 0 : {"AHC", HcclAlgoType::HCCL_ALGO_TYPE_AHC},
127 0 : {"AHC_BROKE", HcclAlgoType::HCCL_ALGO_TYPE_AHC_BROKE},
128 0 : {"NB", HcclAlgoType::HCCL_ALGO_TYPE_NB},
129 0 : {"NA", HcclAlgoType::HCCL_ALGO_TYPE_NA},
130 1288 : };
131 :
132 92 : auto iterAlgoLevel = hcclAlgoLevelMap.find(orginalLevel);
133 92 : if (iterAlgoLevel == hcclAlgoLevelMap.end()) {
134 1 : HCCL_ERROR("[Parser][HcclAlgoLevel] algo config is invalid, level %s is not supported.", orginalLevel.c_str());
135 1 : return HCCL_E_PARA;
136 : }
137 :
138 91 : auto iterAlgoType = hcclAlgoTypeMap.find(orginalAlgo);
139 91 : if (iterAlgoType == hcclAlgoTypeMap.end()) {
140 0 : HCCL_ERROR("[Parser][HcclAlgoLevel] algo config is invalid, algo %s is not supported.", orginalAlgo.c_str());
141 0 : return HCCL_E_PARA;
142 : }
143 :
144 91 : level = iterAlgoLevel->second;
145 91 : algoType = iterAlgoType->second;
146 :
147 91 : return HCCL_SUCCESS;
148 276 : }
149 :
150 43 : HcclResult ParseAlgoString(std::string opName, std::string &algoString, std::vector<HcclAlgoType> &algType)
151 : {
152 43 : algType = std::vector<HcclAlgoType>(HCCL_ALGO_LEVEL_NUM, HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT);
153 43 : std::vector<std::string> algoLevels;
154 43 : HcclResult ret = SplitHcclAlgoLevel(algoString, algoLevels);
155 43 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "\
156 : "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
157 : algoString.c_str()), ret);
158 134 : for (auto algoLevel : algoLevels) {
159 92 : u32 level = 0;
160 92 : HcclAlgoType algo = HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT;
161 92 : ret = ParserHcclAlgoLevel(algoLevel, level, algo);
162 92 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "\
163 : "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
164 : algoString.c_str()), ret);
165 : // 检查是否存在重复配置level
166 91 : if (algType[level] != HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT) {
167 0 : HCCL_ERROR("[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "\
168 : "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
169 : algoString.c_str());
170 0 : return HCCL_E_PARA;
171 : }
172 91 : algType[level] = algo;
173 92 : }
174 42 : auto level0Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_0]);
175 42 : auto level1Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_1]);
176 42 : auto level2Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_2]);
177 42 : auto level3Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_3]);
178 42 : HCCL_RUN_INFO("hccl algo op %s config: config level0:%s, level1:%s, level2:%s, level3:%s",
179 : opName.c_str(),
180 : level0Iter->second.c_str(), level1Iter->second.c_str(),
181 : level2Iter->second.c_str(), level3Iter->second.c_str());
182 42 : return HCCL_SUCCESS;
183 43 : }
184 :
185 42 : HcclResult SplitHcclOpType(const std::string &algoConfig, std::vector<std::string> &algos)
186 : {
187 42 : std::string remainAlgoConfig;
188 42 : std::size_t found = algoConfig.find("/");
189 42 : if ((found == 0) || (found == (algoConfig.length() - 1))) {
190 0 : HCCL_ERROR("[Split][SplitHcclOpType] algo config is invalid.");
191 0 : return HCCL_E_PARA;
192 42 : } else if (found != std::string::npos) {
193 0 : remainAlgoConfig = algoConfig.substr(found + 1);
194 : }
195 42 : algos.push_back(algoConfig.substr(0, found));
196 42 : if (!remainAlgoConfig.empty()) {
197 0 : CHK_RET(SplitHcclOpType(remainAlgoConfig, algos));
198 : }
199 42 : return HCCL_SUCCESS;
200 42 : }
201 :
202 : // 新的逐算法的配置和原有的统一配置只可使用一种,发现同时存在时报错
203 42 : HcclResult CheckAlgoConfigValid(
204 : std::vector<std::string> &algos,
205 : bool& anyCommonConfig,
206 : bool& anySpecificConfig)
207 : {
208 84 : for (std::string& algConfig : algos) {
209 42 : std::size_t found = algConfig.find("=");
210 42 : if ((found == 0) || (found == (algConfig.length() - 1))) {
211 0 : HCCL_ERROR("[Split][CheckAlgoConfigValid] algo config is invalid.");
212 0 : return HCCL_E_PARA;
213 42 : } else if (found != std::string::npos) {
214 0 : anySpecificConfig = true;
215 : } else {
216 42 : anyCommonConfig = true;
217 : }
218 : }
219 42 : if (anyCommonConfig && anySpecificConfig) {
220 0 : HCCL_ERROR("[CheckAlgoConfigValid]should not set both algo config way");
221 0 : return HCCL_E_PARA;
222 : }
223 42 : if (anyCommonConfig && algos.size() > 1) {
224 0 : HCCL_ERROR("[CheckAlgoConfigValid]should only set one common config");
225 0 : return HCCL_E_PARA;
226 : }
227 42 : return HCCL_SUCCESS;
228 : }
229 :
230 92 : HcclResult SplitHcclAlgoLevel(const std::string &algoConfig, std::vector<std::string> &algos)
231 : {
232 92 : std::string remainAlgoConfig;
233 92 : std::size_t found = algoConfig.find(";");
234 92 : if ((found == 0) || (found == (algoConfig.length() - 1))) {
235 0 : HCCL_ERROR("[Split][HcclAlgoLevel] algo config is invalid.");
236 0 : return HCCL_E_PARA;
237 92 : } else if (found != std::string::npos) {
238 49 : remainAlgoConfig = algoConfig.substr(found + 1);
239 : } else {
240 : // 最后一组配置,剩余的字符串为空
241 : }
242 92 : algos.push_back(algoConfig.substr(0, found));
243 :
244 92 : if (algos.size() > HCCL_ALGO_LEVEL_NUM) {
245 0 : HCCL_ERROR("[Split][HcclAlgoLevel] algo config is invalid. algo level is more than %u.", HCCL_ALGO_LEVEL_NUM);
246 0 : return HCCL_E_PARA;
247 : }
248 92 : if (!remainAlgoConfig.empty()) {
249 49 : CHK_RET(SplitHcclAlgoLevel(remainAlgoConfig, algos));
250 : }
251 :
252 92 : return HCCL_SUCCESS;
253 92 : }
254 :
255 3740 : s32 GetInternalExecTimeOut()
256 : {
257 3740 : double timeout = GetExternalInputHcclExecTimeOut();
258 : // 向上取整获取s32秒级超时时间
259 3741 : return static_cast<s32>(std::ceil(timeout));
260 : }
|