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 348766 : const std::vector<HcclAlgoType> GetExternalInputHcclAlgoConfig(HcclCMDType opType)
29 : {
30 348766 : std::lock_guard<std::mutex> lock(g_algEnvConfigMutex);
31 698258 : return g_algEnvConfig.hcclAlgoConfig[opType];
32 349133 : }
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(
88 : "[SetSpecificAlgType] specific config optype[%s] is invalid, please check", 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 552 : {"level3", HCCL_ALGO_LEVEL_3}};
115 :
116 : const std::map<std::string, HcclAlgoType> hcclAlgoTypeMap = {
117 0 : {"null", HcclAlgoType::HCCL_ALGO_TYPE_NULL},
118 0 : {"ring", HcclAlgoType::HCCL_ALGO_TYPE_RING},
119 0 : {"pipeline", HcclAlgoType::HCCL_ALGO_TYPE_PIPELINE},
120 0 : {"fullmesh", HcclAlgoType::HCCL_ALGO_TYPE_FULLMESH},
121 0 : {"H-D_R", HcclAlgoType::HCCL_ALGO_TYPE_HDR},
122 0 : {"pairwise", HcclAlgoType::HCCL_ALGO_TYPE_PAIRWISE},
123 0 : {"NHR", HcclAlgoType::HCCL_ALGO_TYPE_NHR},
124 0 : {"NHR_V1", HcclAlgoType::HCCL_ALGO_TYPE_NHR_V1},
125 0 : {"AHC", HcclAlgoType::HCCL_ALGO_TYPE_AHC},
126 0 : {"AHC_BROKE", HcclAlgoType::HCCL_ALGO_TYPE_AHC_BROKE},
127 0 : {"NB", HcclAlgoType::HCCL_ALGO_TYPE_NB},
128 0 : {"NA", HcclAlgoType::HCCL_ALGO_TYPE_NA},
129 1288 : };
130 :
131 92 : auto iterAlgoLevel = hcclAlgoLevelMap.find(orginalLevel);
132 92 : if (iterAlgoLevel == hcclAlgoLevelMap.end()) {
133 1 : HCCL_ERROR("[Parser][HcclAlgoLevel] algo config is invalid, level %s is not supported.", orginalLevel.c_str());
134 1 : return HCCL_E_PARA;
135 : }
136 :
137 91 : auto iterAlgoType = hcclAlgoTypeMap.find(orginalAlgo);
138 91 : if (iterAlgoType == hcclAlgoTypeMap.end()) {
139 0 : HCCL_ERROR("[Parser][HcclAlgoLevel] algo config is invalid, algo %s is not supported.", orginalAlgo.c_str());
140 0 : return HCCL_E_PARA;
141 : }
142 :
143 91 : level = iterAlgoLevel->second;
144 91 : algoType = iterAlgoType->second;
145 :
146 91 : return HCCL_SUCCESS;
147 276 : }
148 :
149 43 : HcclResult ParseAlgoString(std::string opName, std::string& algoString, std::vector<HcclAlgoType>& algType)
150 : {
151 43 : algType = std::vector<HcclAlgoType>(HCCL_ALGO_LEVEL_NUM, HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT);
152 43 : std::vector<std::string> algoLevels;
153 43 : HcclResult ret = SplitHcclAlgoLevel(algoString, algoLevels);
154 43 : CHK_PRT_RET(
155 : ret != HCCL_SUCCESS,
156 : HCCL_ERROR(
157 : "[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "
158 : "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
159 : algoString.c_str()),
160 : ret);
161 134 : for (auto algoLevel : algoLevels) {
162 92 : u32 level = 0;
163 92 : HcclAlgoType algo = HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT;
164 92 : ret = ParserHcclAlgoLevel(algoLevel, level, algo);
165 92 : CHK_PRT_RET(
166 : ret != HCCL_SUCCESS,
167 : HCCL_ERROR(
168 : "[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "
169 : "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
170 : algoString.c_str()),
171 : ret);
172 : // 检查是否存在重复配置level
173 91 : if (algType[level] != HcclAlgoType::HCCL_ALGO_TYPE_DEFAULT) {
174 0 : HCCL_ERROR(
175 : "[Set][HcclAlgoConfig]hccl algo config[%s] is invalid. "
176 : "expect: level0:NA;level1:<algo> or <op0>=level0:NA;level1:<algo0>/<op1>=level0:NA;level1:<algo1>",
177 : algoString.c_str());
178 0 : return HCCL_E_PARA;
179 : }
180 91 : algType[level] = algo;
181 92 : }
182 42 : auto level0Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_0]);
183 42 : auto level1Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_1]);
184 42 : auto level2Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_2]);
185 42 : auto level3Iter = HcclAlgoTypeMap.find(algType[HCCL_ALGO_LEVEL_3]);
186 42 : HCCL_RUN_INFO(
187 : "hccl algo op %s config: config level0:%s, level1:%s, level2:%s, level3:%s", opName.c_str(),
188 : level0Iter->second.c_str(), level1Iter->second.c_str(), level2Iter->second.c_str(), level3Iter->second.c_str());
189 42 : return HCCL_SUCCESS;
190 43 : }
191 :
192 42 : HcclResult SplitHcclOpType(const std::string& algoConfig, std::vector<std::string>& algos)
193 : {
194 42 : std::string remainAlgoConfig;
195 42 : std::size_t found = algoConfig.find("/");
196 42 : if ((found == 0) || (found == (algoConfig.length() - 1))) {
197 0 : HCCL_ERROR("[Split][SplitHcclOpType] algo config is invalid.");
198 0 : return HCCL_E_PARA;
199 42 : } else if (found != std::string::npos) {
200 0 : remainAlgoConfig = algoConfig.substr(found + 1);
201 : }
202 42 : algos.push_back(algoConfig.substr(0, found));
203 42 : if (!remainAlgoConfig.empty()) {
204 0 : CHK_RET(SplitHcclOpType(remainAlgoConfig, algos));
205 : }
206 42 : return HCCL_SUCCESS;
207 42 : }
208 :
209 : // 新的逐算法的配置和原有的统一配置只可使用一种,发现同时存在时报错
210 42 : HcclResult CheckAlgoConfigValid(std::vector<std::string>& algos, bool& anyCommonConfig, bool& anySpecificConfig)
211 : {
212 84 : for (std::string& algConfig : algos) {
213 42 : std::size_t found = algConfig.find("=");
214 42 : if ((found == 0) || (found == (algConfig.length() - 1))) {
215 0 : HCCL_ERROR("[Split][CheckAlgoConfigValid] algo config is invalid.");
216 0 : return HCCL_E_PARA;
217 42 : } else if (found != std::string::npos) {
218 0 : anySpecificConfig = true;
219 : } else {
220 42 : anyCommonConfig = true;
221 : }
222 : }
223 42 : if (anyCommonConfig && anySpecificConfig) {
224 0 : HCCL_ERROR("[CheckAlgoConfigValid]should not set both algo config way");
225 0 : return HCCL_E_PARA;
226 : }
227 42 : if (anyCommonConfig && algos.size() > 1) {
228 0 : HCCL_ERROR("[CheckAlgoConfigValid]should only set one common config");
229 0 : return HCCL_E_PARA;
230 : }
231 42 : return HCCL_SUCCESS;
232 : }
233 :
234 92 : HcclResult SplitHcclAlgoLevel(const std::string& algoConfig, std::vector<std::string>& algos)
235 : {
236 92 : std::string remainAlgoConfig;
237 92 : std::size_t found = algoConfig.find(";");
238 92 : if ((found == 0) || (found == (algoConfig.length() - 1))) {
239 0 : HCCL_ERROR("[Split][HcclAlgoLevel] algo config is invalid.");
240 0 : return HCCL_E_PARA;
241 92 : } else if (found != std::string::npos) {
242 49 : remainAlgoConfig = algoConfig.substr(found + 1);
243 : } else {
244 : // 最后一组配置,剩余的字符串为空
245 : }
246 92 : algos.push_back(algoConfig.substr(0, found));
247 :
248 92 : if (algos.size() > HCCL_ALGO_LEVEL_NUM) {
249 0 : HCCL_ERROR("[Split][HcclAlgoLevel] algo config is invalid. algo level is more than %u.", HCCL_ALGO_LEVEL_NUM);
250 0 : return HCCL_E_PARA;
251 : }
252 92 : if (!remainAlgoConfig.empty()) {
253 49 : CHK_RET(SplitHcclAlgoLevel(remainAlgoConfig, algos));
254 : }
255 :
256 92 : return HCCL_SUCCESS;
257 92 : }
258 :
259 3890 : s32 GetInternalExecTimeOut()
260 : {
261 3890 : double timeout = GetExternalInputHcclExecTimeOut();
262 : // 向上取整获取s32秒级超时时间
263 3893 : return static_cast<s32>(std::ceil(timeout));
264 : }
|