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 <cmath>
12 : #include <algorithm>
13 : #include "device_capacity.h"
14 : #include "coll_executor_base.h"
15 : #include "coll_alg_exec_registry.h"
16 : #include "coll_alg_operator.h"
17 :
18 : namespace hccl {
19 : using namespace std;
20 : constexpr float GB2B = 1024 * 1024 * 1024;
21 : constexpr float SECOND2MICROSECOND = 1000000;
22 : constexpr float RHD_FACTOR_TWO = 2.0;
23 : constexpr float RHD_FACTOR_ONE = 1.0;
24 : constexpr float DOUBLE_SUB_HCCLCMD = 2.0; // The hcclCMD can be considered as combination of two hcclCMDs.
25 : constexpr float COPY_TIME_IN_RHD = 1.0;
26 : constexpr double NHR_FACTOR_TWO = 2.0;
27 : constexpr double NHR_FACTOR_THREE = 3.0;
28 : constexpr double NHR_FACTOR_FOUR = 4.0;
29 : constexpr double NHR_SUB_TWO = 2.0;
30 : constexpr float LATENCY = 60; // 静态时延 60 us;
31 : constexpr u64 PIPELINE_MIN_SIZE = 32 * 1024; // 当数据量大于等于32KB时,reduce_scatter和all_gather使能pipeline模式
32 : constexpr u64 PIPELINE_ALLREDUCE_MIN_SIZE = 1024 * 1024; // 当数据量大于等于1MB时,allreduce使能pipeline模式
33 : constexpr u64 PIPELINE_MIN_SIZE_NO_LITE = 2 * 1024 * 1024; // 如不支持RDMALite,当数据量大于等于2MB时,使能pipeline模式
34 : constexpr u64 HCCL_FFTS_CAPACITY = 65535; // FFTS+子图最大容量
35 : constexpr u32 AHC_MIN_SUBGROUP_SPLIT_DIVISOR = 2;
36 : constexpr u32 AHC_LEVEL0_GROUP_SIZE_THRESHOLD = 3;
37 : constexpr u32 SERVER_COUNT_THRESHOLD_FOR_MULTI_DETER_PIPELINE = 2;
38 : constexpr u32 MIN_STRICT_RANK_NUM = 3;
39 :
40 84 : CollAlgOperator::CollAlgOperator(
41 : AlgConfigurator* algConfigurator, CCLBufferManager& cclBufferManager, HcclDispatcher dispatcher,
42 84 : std::unique_ptr<TopoMatcher>& topoMatcher, HcclCMDType opType)
43 83 : : algConfigurator_(algConfigurator),
44 83 : cclBufferManager_(cclBufferManager),
45 86 : dispatcher_(dispatcher),
46 86 : topoMatcher_(topoMatcher),
47 588 : workflowMode_(GetWorkflowMode())
48 : {
49 86 : SetTopoAttr(algConfigurator_);
50 86 : SetAlgoAttr(algConfigurator_);
51 94 : algConfigurator->GetAlgTypeDirect(algType_, opType);
52 84 : algConfigurator->GetAlgoLevel1DefaultSwitch(isAlgoLevel1Default_, opType);
53 84 : algConfigurator->GetTopoType(topoType_);
54 84 : }
55 :
56 0 : HcclResult CollAlgOperator::SelectAlg(
57 : [[maybe_unused]] const std::string& tag, [[maybe_unused]] const OpParam& param,
58 : [[maybe_unused]] std::string& algName, [[maybe_unused]] std::string& newTag)
59 : {
60 0 : return HCCL_SUCCESS;
61 : }
62 :
63 35 : HcclResult CollAlgOperator::SelectAlg(
64 : const std::string& tag, const OpParam& param, std::string& algName, std::string& newTag,
65 : [[maybe_unused]] const ResourceLimit& limit)
66 : {
67 35 : return SelectAlg(tag, param, algName, newTag);
68 : }
69 :
70 1 : HcclResult CollAlgOperator::GetAivExecParam(
71 : std::string& algName, const OpParam& param, AlgResourceResponse& algRes, AivSuperKernelArgs& args)
72 : {
73 1 : if (executor_.get() == nullptr) {
74 0 : executor_ = CollAlgExecRegistry::Instance().GetAlgExec(algName, dispatcher_, topoMatcher_);
75 0 : CHK_PRT_RET(
76 : executor_.get() == nullptr,
77 : HCCL_ERROR("[CollAlgOperator][GetAivExecParam]Fail to find executor for algName[%s]", algName.c_str()),
78 : HCCL_E_PARA);
79 : }
80 1 : return executor_->GetAivExecParam(param, algRes, args);
81 : }
82 :
83 : HcclResult
84 1 : CollAlgOperator::CalNumBlocks(std::string& algName, const OpParam& param, u32& numBlocks, int32_t aivCoreLimit)
85 : {
86 1 : if (executor_.get() == nullptr) {
87 0 : executor_ = CollAlgExecRegistry::Instance().GetAlgExec(algName, dispatcher_, topoMatcher_);
88 0 : CHK_PRT_RET(
89 : executor_.get() == nullptr,
90 : HCCL_ERROR("[CollAlgOperator][CalNumBlocks]Fail to find executor for algName[%s]", algName.c_str()),
91 : HCCL_E_PARA);
92 0 : CHK_RET(SetExecutorAttr(param));
93 : }
94 :
95 1 : if (aivCoreLimit != 0) {
96 1 : CHK_RET(executor_->SetNumBlocks(aivCoreLimit));
97 : }
98 :
99 1 : if (param.opType == HcclCMDType::HCCL_CMD_ALLTOALL) {
100 0 : return executor_->CalNumBlocks(
101 0 : numBlocks, userRankSize_, param.All2AllDataDes.sendCount * SIZE_TABLE[param.All2AllDataDes.sendType],
102 0 : param.opType);
103 1 : } else if (
104 1 : param.opType == HcclCMDType::HCCL_CMD_ALLREDUCE || param.opType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER
105 0 : || param.opType == HcclCMDType::HCCL_CMD_ALLGATHER || param.opType == HcclCMDType::HCCL_CMD_BROADCAST) {
106 1 : return executor_->CalNumBlocks(
107 1 : numBlocks, userRankSize_, param.DataDes.count * SIZE_TABLE[param.DataDes.dataType], param.opType);
108 : } else {
109 0 : return executor_->CalNumBlocks(numBlocks, userRankSize_);
110 : }
111 : return HCCL_SUCCESS;
112 : }
113 :
114 0 : HcclResult CollAlgOperator::GetOpExpansionStr(const OpParam& param, const AlgDesc& algDesc, std::string& opExpansionStr)
115 : {
116 0 : if (algDesc.isAivMode) {
117 0 : opExpansionStr = "AIV";
118 0 : } else if (param.aicpuUnfoldMode) {
119 0 : opExpansionStr = "AI_CPU";
120 0 : } else if (static_cast<bool>(topoMatcher_->GetExternalInputHcclEnableFfts())) {
121 0 : opExpansionStr = "HOST";
122 : } else {
123 0 : opExpansionStr = "HOST_TS";
124 : }
125 0 : return HCCL_SUCCESS;
126 : }
127 :
128 73 : HcclResult CollAlgOperator::SelectAlg(
129 : const std::string& tag, const OpParam& param, const ResourceLimit& limit, std::string& algName, AlgDesc& algDesc,
130 : std::string& newTag)
131 : {
132 73 : bool isOnlyAiv = topoMatcher_->GetIsOnlyAivConfig();
133 75 : bool supportOnlyAiv
134 65 : = (param.opType == HcclCMDType::HCCL_CMD_ALLGATHER || param.opType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER
135 30 : || param.opType == HcclCMDType::HCCL_CMD_ALLTOALLV || param.opType == HcclCMDType::HCCL_CMD_ALLTOALLVC
136 140 : || param.opType == HcclCMDType::HCCL_CMD_ALLTOALL || param.opType == HcclCMDType::HCCL_CMD_ALLREDUCE);
137 75 : CHK_PRT_RET(
138 : isOnlyAiv && !supportOnlyAiv,
139 : HCCL_ERROR(
140 : "[CollAlgOperator][SelectAlg] opType[%s] currently do not support aivonly",
141 : GetCMDTypeEnumStr(param.opType).c_str()),
142 : HCCL_E_NOT_SUPPORT);
143 75 : CHK_PRT_RET(
144 : isOnlyAiv && userRankSize_ == 1 && supportOnlyAiv,
145 : HCCL_ERROR("[CollAlgOperator][SelectAlg] aivonly not support, please ensure rankNum is greater than one"),
146 : HCCL_E_NOT_SUPPORT);
147 :
148 : // 兼容老接口
149 75 : if (limit.ifLimit) {
150 75 : CHK_RET(SelectAlg(tag, param, algName, newTag, limit));
151 : } else {
152 0 : CHK_RET(SelectAlg(tag, param, algName, newTag));
153 : }
154 :
155 : // 非AIV算法提前返回, 采用兜底Executor
156 76 : if (algName.empty()) {
157 0 : executor_ = CollAlgExecRegistry::Instance().GetAlgExec("SendExecutor", dispatcher_, topoMatcher_);
158 0 : CHK_PRT_RET(
159 : executor_.get() == nullptr,
160 : HCCL_ERROR("[CollAlgOperator][SelectAlg]Fail to find executor for algName[DefaultExecutor]"), HCCL_E_PARA);
161 : } else {
162 : // 校验控核
163 75 : if (limit.ifLimit && deviceType_ == DevType::DEV_TYPE_910_93 && topoMatcher_->GetAivModeConfig()) {
164 0 : CHK_RET(SelectAlgFor91093WithCoreLimit(param, limit, algName));
165 : }
166 :
167 : // 从对应executor获取算法描述
168 76 : if (executor_.get() == nullptr) {
169 75 : executor_ = CollAlgExecRegistry::Instance().GetAlgExec(algName, dispatcher_, topoMatcher_);
170 78 : CHK_PRT_RET(
171 : executor_.get() == nullptr,
172 : HCCL_ERROR("[CollAlgOperator][SelectAlg]Fail to find executor for algName[%s]", algName.c_str()),
173 : HCCL_E_PARA);
174 77 : CHK_RET(SetExecutorAttr(param));
175 : }
176 : }
177 :
178 75 : bool isLastSelect = algDesc.isLastSelect;
179 75 : algDesc = executor_->GetAlgDesc();
180 : // 打印维测日志
181 73 : if (UNLIKELY(GetDebugConfig() & HCCL_ALG) && isLastSelect) {
182 : // 获取展开模式,转换成字符串
183 0 : std::string opExpansionStr;
184 0 : CHK_RET(GetOpExpansionStr(param, algDesc, opExpansionStr));
185 : // 尝试获取确定性属性(如果Executor有声明自己是否为确定性)
186 0 : std::string appendStr = "";
187 0 : if (algDesc.deterministic >= 0) {
188 0 : appendStr += "deterministic[" + std::to_string(algDesc.deterministic) + "]";
189 : }
190 : // 打印关键维测内容
191 0 : bool isOpBase = GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE;
192 0 : HCCL_CONFIG_INFO(
193 : HCCL_ALG,
194 : "[%s] newTag[%s] algName[%s] userRank[%u] topoType[%d] algType[%s] "
195 : "userRankSize[%u] level0Size[%u] moduleNum_[%u] level2Size[%u] ",
196 : __func__, newTag.c_str(), algName.c_str(), userRank_, topoType_, AlgTypeToStr(algDesc.algType).c_str(),
197 : userRankSize_, deviceNumPerAggregation_, moduleNum_, superPodNum_);
198 0 : HCCL_CONFIG_INFO(
199 : HCCL_ALG,
200 : "[%s] newTag[%s] "
201 : "opExpansionMode[%s] isZeroCopy[%u] retryEnable[%u] isOpBase[%u] isCapture[%u] aivCoreLimit[%u] %s.",
202 : __func__, newTag.c_str(), opExpansionStr.c_str(), algDesc.isZeroCopy, retryEnable_, isOpBase,
203 : param.isCapture, limit.aivCoreLimit, appendStr.c_str());
204 0 : }
205 76 : return HCCL_SUCCESS;
206 : }
207 :
208 : HcclResult
209 0 : CollAlgOperator::SelectAlgFor91093WithCoreLimit(const OpParam& param, const ResourceLimit& limit, std::string& algName)
210 : {
211 0 : if (executor_.get() == nullptr) {
212 0 : executor_ = CollAlgExecRegistry::Instance().GetAlgExec(algName, dispatcher_, topoMatcher_);
213 0 : CHK_PRT_RET(
214 : executor_.get() == nullptr,
215 : HCCL_ERROR(
216 : "[CollAlgOperator][SelectAlgFor91093WithCoreLimit]Fail to find executor for algName[%s]",
217 : algName.c_str()),
218 : HCCL_E_PARA);
219 0 : CHK_RET(SetExecutorAttr(param));
220 : }
221 :
222 0 : CHK_RET(SetNumBlocks(limit.aivCoreLimit));
223 :
224 0 : std::string reSelName;
225 0 : switch (param.opType) {
226 0 : case HcclCMDType::HCCL_CMD_ALLREDUCE:
227 0 : reSelName = "AllReduceMeshAivFor91093Executor";
228 0 : break;
229 0 : case HcclCMDType::HCCL_CMD_ALLGATHER:
230 0 : reSelName = "AllGatherMeshAivFor91093Executor";
231 0 : break;
232 0 : case HcclCMDType::HCCL_CMD_REDUCE_SCATTER:
233 0 : reSelName = "ReduceScatterMeshAivFor91093Executor";
234 0 : break;
235 0 : case HcclCMDType::HCCL_CMD_ALLTOALLV:
236 : case HcclCMDType::HCCL_CMD_ALLTOALL:
237 : case HcclCMDType::HCCL_CMD_ALLTOALLVC:
238 0 : reSelName = "AlltoAllMeshAivFor91093Executor";
239 0 : break;
240 0 : default:
241 0 : break;
242 : }
243 :
244 : u32 numBlocks;
245 0 : HcclResult ret = CalNumBlocks(algName, param, numBlocks);
246 0 : if (ret != HCCL_SUCCESS) {
247 0 : CHK_PRT_RET(
248 : reSelName.empty() || reSelName == algName,
249 : HCCL_ERROR(
250 : "[CollAlgOperator][SelectAlgFor91093WithCoreLimit]Fail to check CalNumBlocks for algName[%s]",
251 : algName.c_str()),
252 : HCCL_E_PARA);
253 :
254 0 : algName = reSelName;
255 0 : executor_ = nullptr;
256 0 : HCCL_INFO("[CollAlgOperator][SelectAlgFor91093WithCoreLimit]Re select to algName[%s]", reSelName.c_str());
257 : }
258 :
259 0 : return HCCL_SUCCESS;
260 0 : }
261 :
262 : HcclResult
263 75 : CollAlgOperator::CalcResRequest(const std::string& algName, const OpParam& param, AlgResourceRequest& resourceRequest)
264 : {
265 75 : if (executor_.get() == nullptr) {
266 0 : executor_ = CollAlgExecRegistry::Instance().GetAlgExec(algName, dispatcher_, topoMatcher_);
267 0 : CHK_PRT_RET(
268 : executor_.get() == nullptr,
269 : HCCL_ERROR("[CollAlgOperator][CalcResRequest]Fail to find executor for algName[%s]", algName.c_str()),
270 : HCCL_E_PARA);
271 0 : CHK_RET(SetExecutorAttr(param));
272 : }
273 76 : return executor_->CalcResRequest(param, resourceRequest);
274 : }
275 :
276 24 : HcclResult CollAlgOperator::Orchestrate(const std::string& algName, OpParam& param, AlgResourceResponse& algResource)
277 : {
278 24 : HCCL_INFO("[CollAlgOperator][Orchestrate]algName[%s]", algName.c_str());
279 24 : if (executor_.get() == nullptr) {
280 0 : executor_ = CollAlgExecRegistry::Instance().GetAlgExec(algName, dispatcher_, topoMatcher_);
281 0 : CHK_PRT_RET(
282 : executor_.get() == nullptr,
283 : HCCL_ERROR("[CollAlgOperator][Orchestrate]Fail to find executor for algName[%s]", algName.c_str()),
284 : HCCL_E_PARA);
285 0 : CHK_RET(SetExecutorAttr(param));
286 : }
287 24 : executor_->SetAivClearEnable(aivClearEnable_);
288 24 : executor_->SetAlgOpContext(algOpContext_);
289 24 : executor_->SetOpCounter(opCounter_);
290 24 : return executor_->Orchestrate(param, algResource);
291 : }
292 :
293 0 : HcclResult CollAlgOperator::GetAdjInfo(
294 : const std::string& algName, OpParam& param, AlgResourceResponse& algResource, AdjInfo& nslbAdjInfo)
295 : {
296 0 : if (executor_.get() == nullptr) {
297 0 : executor_ = CollAlgExecRegistry::Instance().GetAlgExec(algName, dispatcher_, topoMatcher_);
298 0 : CHK_PRT_RET(
299 : executor_.get() == nullptr,
300 : HCCL_ERROR("[CollAlgOperator][Orchestrate]Fail to find executor for algName[%s]", algName.c_str()),
301 : HCCL_E_PARA);
302 0 : CHK_RET(SetExecutorAttr(param));
303 : }
304 :
305 0 : return executor_->GetAdjInfo(algResource, nslbAdjInfo);
306 : }
307 :
308 25 : HcclResult CollAlgOperator::PrepareCommInfoToDevice(const std::string& algName, AlgResourceResponse& algResource)
309 : {
310 25 : if (executor_.get() == nullptr) {
311 0 : executor_ = CollAlgExecRegistry::Instance().GetAlgExec(algName, dispatcher_, topoMatcher_);
312 0 : CHK_PRT_RET(
313 : executor_.get() == nullptr,
314 : HCCL_ERROR(
315 : "[CollAlgOperator][PrepareCommInfoToDevice]Fail to find executor for algName[%s]", algName.c_str()),
316 : HCCL_E_PARA);
317 : }
318 25 : return executor_->PrepareCommInfoToDevice(algResource);
319 : }
320 :
321 0 : HcclResult CollAlgOperator::CalcIncreLinkRequest(
322 : const std::string& algName, const OpParam& param, std::set<u32>& ranksHasLinked,
323 : AlgResourceRequest& resourceRequest, bool& needIncreLink)
324 : {
325 0 : if (executor_.get() == nullptr) {
326 0 : executor_ = CollAlgExecRegistry::Instance().GetAlgExec(algName, dispatcher_, topoMatcher_);
327 0 : CHK_PRT_RET(
328 : executor_.get() == nullptr,
329 : HCCL_ERROR("[CollAlgOperator][CalcIncreLinkRequest]Fail to find executor for algName[%s]", algName.c_str()),
330 : HCCL_E_PARA);
331 : }
332 0 : return executor_->CalcIncreLinkRequest(param, ranksHasLinked, resourceRequest, needIncreLink);
333 : }
334 :
335 83 : void CollAlgOperator::SetTopoAttr(AlgConfigurator* algConfigurator)
336 : {
337 83 : const HcclTopoAttr& topoAttr = algConfigurator->GetTopoAttr();
338 84 : serverNum_ = topoAttr.serverNum;
339 84 : moduleNum_ = topoAttr.moduleNum;
340 84 : superPodNum_ = topoAttr.superPodNum;
341 84 : deviceNumPerServer_ = topoAttr.deviceNumPerServer;
342 84 : deviceNumPerAggregation_ = topoAttr.deviceNumPerAggregation;
343 84 : multiModuleDiffDeviceNumMode_ = topoAttr.multiModuleDiffDeviceNumMode;
344 84 : multiSuperPodDiffServerNumMode_ = topoAttr.multiSuperPodDiffServerNumMode;
345 84 : multiSuperPodDiffDeviceNumMode_ = topoAttr.multiSuperPodDiffDeviceNumMode;
346 84 : isDiffDeviceType_ = topoAttr.isDiffDeviceType;
347 84 : gcdDeviceNumPerAggregation_ = topoAttr.gcdDeviceNumPerAggregation;
348 :
349 84 : meshAggregationRankSize_ = topoAttr.meshAggregationRankSize;
350 84 : isDiffDeviceModule_ = topoAttr.isDiffDeviceModule;
351 84 : isSingleMeshAggregation_ = topoAttr.isSingleMeshAggregation;
352 84 : isAllRankSamePlane_ = topoAttr.isAllRankSamePlane;
353 84 : is310PDuoCard_ = topoAttr.is310PDuoCard;
354 84 : isCommon310P3DUO_ = topoAttr.isCommon310P3DUO;
355 84 : hccsPortNum_ = topoAttr.hccsPortNum;
356 :
357 84 : userRank_ = topoAttr.userRank;
358 84 : realUserRank_ = topoAttr.realUserRank;
359 84 : userRankSize_ = topoAttr.userRankSize;
360 :
361 84 : devicePhyId_ = topoAttr.devicePhyId;
362 84 : deviceLogicId_ = topoAttr.deviceLogicId;
363 84 : deviceType_ = topoAttr.deviceType;
364 :
365 84 : nicList_ = topoAttr.nicList;
366 83 : pairLinkCounter_ = topoAttr.pairLinkCounter;
367 86 : isSupportRdmaLite_ = topoAttr.isSupportRdmaLite;
368 86 : isSupportHccsAndSio_ = topoAttr.isSupportHccsAndSio;
369 86 : useSuperPodMode_ = topoAttr.useSuperPodMode;
370 86 : isARSDoubleRing_ = topoAttr.isARSDoubleRing;
371 86 : return;
372 : }
373 :
374 86 : void CollAlgOperator::SetAlgoAttr(AlgConfigurator* algConfigurator)
375 : {
376 86 : const HcclAlgoAttr& algoAttr = algConfigurator->GetAlgoAttr();
377 86 : isHaveCpuRank_ = algoAttr.isHaveCpuRank;
378 86 : inlineReduceSwitchOn_ = algoAttr.inlineReduceSwitchOn;
379 86 : identifier_ = algoAttr.identifier;
380 94 : return;
381 : }
382 :
383 72 : HcclResult CollAlgOperator::SetExecutorAttr(const OpParam& param)
384 : {
385 72 : CHK_RET(executor_->SetAlgType(algType_));
386 69 : CHK_RET(executor_->SetCCLInBuffer(cclBufferManager_.GetInCCLbufferSize()));
387 :
388 72 : if (param.opType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER) {
389 36 : bool isSupportSDMAReduce = false;
390 36 : if (GetWorkflowMode() != HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) {
391 : isSupportSDMAReduce
392 14 : = IsSupportSDMAReduce(param.inputPtr, param.outputPtr, param.DataDes.dataType, param.reduceType);
393 : } else {
394 21 : isSupportSDMAReduce = IsSupportSDMAReduce(
395 22 : cclBufferManager_.GetInCCLbuffer().ptr(), cclBufferManager_.GetOutCCLbuffer().ptr(),
396 22 : param.DataDes.dataType, param.reduceType);
397 : }
398 34 : CHK_RET(executor_->SetIsSupportSDMAReduce(isSupportSDMAReduce));
399 : }
400 70 : return HCCL_SUCCESS;
401 : }
402 :
403 0 : std::string CollAlgOperator::GenerateNewTagByAlgTypeLevel1(std::string tag, std::string algTypeLevel1Tag) const
404 : {
405 0 : if (algTypeLevel1Tag == "") {
406 0 : return tag;
407 : } else {
408 0 : return tag + "_" + algTypeLevel1Tag;
409 : }
410 : }
411 :
412 0 : HcclResult CollAlgOperator::AppendTag(const AlgTypeLevel1& algTypeLevel1, std::string& tag)
413 : {
414 0 : switch (algTypeLevel1) {
415 0 : case AlgTypeLevel1::ALG_LEVEL1_RING:
416 0 : tag = "ALG_LEVEL1_RING";
417 0 : break;
418 0 : case AlgTypeLevel1::ALG_LEVEL1_HD:
419 0 : tag = "ALG_LEVEL1_HD";
420 0 : break;
421 0 : case AlgTypeLevel1::ALG_LEVEL1_NHR:
422 0 : tag = "ALG_LEVEL1_NHR";
423 0 : break;
424 0 : case AlgTypeLevel1::ALG_LEVEL1_PIPELINE:
425 0 : tag = "ALG_LEVEL1_PIPELINE";
426 0 : break;
427 0 : default:
428 0 : HCCL_WARNING("[CollAlgOperator][AppendTag] The algTypeLevel1 %d is not supported.", algTypeLevel1);
429 0 : break;
430 : }
431 0 : return HCCL_SUCCESS;
432 : }
433 :
434 20 : HcclResult CollAlgOperator::AutoSelectAlgTypeLevel1(
435 : HcclCMDType hcclCMDType, u64 countSize, u64 cclBufferSize, std::string& algTypeLevel1Tag, bool isInlineReduce,
436 : bool isRdmaReduce, bool isAivMode)
437 : {
438 20 : if (isSingleMeshAggregation_) {
439 20 : HCCL_INFO(
440 : "[AutoSelectAlgTypeLevel1] there are %u server(%u module) in level1, no need to choose algo.", serverNum_,
441 : moduleNum_);
442 20 : return HCCL_SUCCESS;
443 : }
444 :
445 : // auto algo selection process
446 0 : if (isAlgoLevel1Default_) {
447 : // parse algType_ and get algTypeLevel1 and algTypeLevel0
448 0 : auto originalAlgTypeLevel0 = algType_.algoLevel0;
449 : // set algTypeLevel1
450 : AlgTypeLevel1 algTypeLevel1;
451 0 : CHK_RET(GetDefaultAlgoLevel1V2(
452 : hcclCMDType, countSize, cclBufferSize, algTypeLevel1, isInlineReduce, isRdmaReduce, isAivMode));
453 0 : auto iter = HCCL_ALGO_LEVEL1_NAME_MAP.find(algTypeLevel1);
454 0 : CHK_PRT_RET(
455 : iter == HCCL_ALGO_LEVEL1_NAME_MAP.end(),
456 : HCCL_ERROR("[AutoSelectAlgTypeLevel1] level1: algType[%u] is invalid.", algTypeLevel1), HCCL_E_INTERNAL);
457 0 : HCCL_INFO(
458 : "[AutoSelectAlgTypeLevel1] there are %u server(%u module) in level1, using %s algo", serverNum_, moduleNum_,
459 : iter->second.c_str());
460 0 : algType_.algoLevel0 = originalAlgTypeLevel0;
461 0 : algType_.algoLevel1 = algTypeLevel1;
462 : // tag 增加所选的算法
463 0 : AppendTag(algTypeLevel1, algTypeLevel1Tag);
464 : }
465 0 : return HCCL_SUCCESS;
466 : }
467 :
468 0 : HcclResult CollAlgOperator::SelectAlgoForComm(
469 : HcclCMDType hcclCMDType, float delay, u64 curSize, float bandWidth, AlgTypeLevel1& algType)
470 : {
471 : // 从map中查找对应的计算函数
472 0 : auto it = selectFuncMap_.find(hcclCMDType);
473 0 : if (it == selectFuncMap_.end()) {
474 0 : HCCL_ERROR("[Get][AlgTypeLevel1] The hcclCMDType %d is not supported.", hcclCMDType);
475 0 : return HCCL_E_NOT_SUPPORT;
476 : }
477 0 : return (it->second)(delay, curSize, bandWidth, algType);
478 : }
479 :
480 : // 保守估计Pipeline算法所需context数量
481 0 : u32 CollAlgOperator::CalcContextNumForPipeline(HcclCMDType hcclCMDType)
482 : {
483 : bool isDeterPipeline
484 0 : = topoMatcher_->GetDeterministicConfig() == DETERMINISTIC_ENABLE
485 0 : && (hcclCMDType == HcclCMDType::HCCL_CMD_ALLREDUCE || hcclCMDType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER);
486 0 : const u32 stepNum = moduleNum_; // 通信步数
487 0 : const u32 hccsContextNumPerStep = 5 * (deviceNumPerAggregation_ - 1); // SDMA跨片每步所需context数
488 0 : const u32 roceContextNumPerStep = 7; // RDMA每步所需context数
489 0 : const u32 copyContextNumPerStep = 1; // SDMA片内每步所需context数
490 0 : const u32 localReduceNumPerStep = isDeterPipeline ? (deviceNumPerAggregation_ - 1) : 0;
491 0 : const u32 contextNumPerStep
492 0 : = hccsContextNumPerStep + roceContextNumPerStep + copyContextNumPerStep + localReduceNumPerStep; // 小计
493 0 : const u32 barrierContextNum = 4; // 通信结束时barrier操作所需context数
494 :
495 0 : switch (hcclCMDType) {
496 0 : case HcclCMDType::HCCL_CMD_ALLREDUCE: // fall-through
497 : case HcclCMDType::HCCL_CMD_REDUCE_SCATTER: // fall-through
498 : case HcclCMDType::HCCL_CMD_ALLGATHER:
499 : case HcclCMDType::HCCL_CMD_ALLGATHER_V: {
500 0 : const u32 copyContextNum = 1; // 通信首尾所需context数量
501 0 : u32 contextNum = stepNum * contextNumPerStep + barrierContextNum + copyContextNum;
502 0 : if (hcclCMDType == HcclCMDType::HCCL_CMD_ALLREDUCE) {
503 0 : contextNum += contextNum;
504 : }
505 0 : if (isDeterPipeline) {
506 0 : contextNum += stepNum - 1; // 最后的local reduce
507 : }
508 0 : return contextNum;
509 : }
510 0 : case HcclCMDType::HCCL_CMD_ALLTOALLV: // fall-through
511 : case HcclCMDType::HCCL_CMD_ALLTOALLVC: // fall-through
512 : case HcclCMDType::HCCL_CMD_ALLTOALL: {
513 0 : const u32 copyContextNum = 1 + moduleNum_; // 通信首尾所需context数量
514 0 : return stepNum * contextNumPerStep + barrierContextNum + copyContextNum;
515 : }
516 0 : default:
517 0 : return 0;
518 : }
519 : }
520 :
521 0 : HcclResult CollAlgOperator::GetDefaultAlgoLevel1V2(
522 : HcclCMDType hcclCMDType, u64 curSize, u64 cclBufferSize, AlgTypeLevel1& algType, bool isInlineReduce,
523 : bool isRdmaReduce, bool isAivMode)
524 : {
525 : // pipeline mode is deployed,where there is multi-sever multi-device(insever) now,
526 : // since RDMA is not reduced by normal serial orchestration of tasks.
527 : // So pipeline mode is more dominant than normal serial orchestration now.
528 0 : auto originalAlgTypeLevel0 = algType_.algoLevel0;
529 : bool disdeterniminsticWithInlineReduce
530 0 : = isInlineReduce && isRdmaReduce && topoMatcher_->GetDeterministicConfig() == DETERMINISTIC_DISABLE;
531 : bool deterniminsticWithInlineReduce
532 0 : = isInlineReduce && isRdmaReduce && topoMatcher_->GetDeterministicConfig() == DETERMINISTIC_ENABLE;
533 :
534 : // 对于不支持Rdma Lite的场景,下发性能较差,RS和AG需要一个很大的数据量(AR的一半)才能掩盖下发时间
535 0 : u64 pipelineMinSize = (isSupportRdmaLite_) ? (PIPELINE_MIN_SIZE) : (PIPELINE_MIN_SIZE_NO_LITE);
536 0 : if (((hcclCMDType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER && disdeterniminsticWithInlineReduce)
537 0 : || hcclCMDType == HcclCMDType::HCCL_CMD_ALLGATHER || hcclCMDType == HcclCMDType::HCCL_CMD_ALLGATHER_V)
538 0 : && deviceNumPerAggregation_ != 1 && curSize >= pipelineMinSize && IsAlgTypeLevel0Mesh(originalAlgTypeLevel0)
539 0 : && CalcContextNumForPipeline(hcclCMDType) <= HCCL_FFTS_CAPACITY) {
540 0 : algType = AlgTypeLevel1::ALG_LEVEL1_PIPELINE;
541 0 : return HCCL_SUCCESS;
542 : }
543 0 : if (hcclCMDType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER && deterniminsticWithInlineReduce
544 0 : && deviceNumPerAggregation_ > 1 && curSize >= pipelineMinSize && IsAlgTypeLevel0Mesh(originalAlgTypeLevel0)
545 0 : && CalcContextNumForPipeline(hcclCMDType) <= HCCL_FFTS_CAPACITY && moduleNum_ > 1
546 0 : && curSize >= HCCL_SMALL_COUNT_256_KB) {
547 0 : algType = AlgTypeLevel1::ALG_LEVEL1_PIPELINE;
548 0 : return HCCL_SUCCESS;
549 : }
550 :
551 : // 对于不支持Rdma Lite的场景,下发性能较差,AllReduce需要一个较大的数据量才能掩盖下发时间
552 0 : pipelineMinSize = (isSupportRdmaLite_) ? (PIPELINE_ALLREDUCE_MIN_SIZE) : (PIPELINE_MIN_SIZE_NO_LITE);
553 0 : if (hcclCMDType == HcclCMDType::HCCL_CMD_ALLREDUCE) {
554 : // 计算每个slice的大小
555 0 : u64 allreduceCurSize = 0;
556 0 : allreduceCurSize = curSize / (moduleNum_ * deviceNumPerAggregation_);
557 0 : if (disdeterniminsticWithInlineReduce && deviceNumPerAggregation_ != 1 && allreduceCurSize >= pipelineMinSize
558 0 : && !isAivMode && IsAlgTypeLevel0Mesh(originalAlgTypeLevel0)
559 0 : && CalcContextNumForPipeline(hcclCMDType) <= HCCL_FFTS_CAPACITY) {
560 0 : algType = AlgTypeLevel1::ALG_LEVEL1_PIPELINE;
561 0 : return HCCL_SUCCESS;
562 : }
563 0 : if (deterniminsticWithInlineReduce && deviceNumPerAggregation_ > 1 && allreduceCurSize >= HCCL_SMALL_COUNT_1_MB
564 0 : && !isAivMode && IsAlgTypeLevel0Mesh(originalAlgTypeLevel0)
565 0 : && CalcContextNumForPipeline(hcclCMDType) <= HCCL_FFTS_CAPACITY) {
566 0 : algType = AlgTypeLevel1::ALG_LEVEL1_PIPELINE;
567 0 : return HCCL_SUCCESS;
568 : }
569 : }
570 0 : u64 dataSizePerLoop = curSize > cclBufferSize ? cclBufferSize : curSize;
571 0 : float delay = LATENCY; // 静态时延 60 us;
572 : float bandWidth;
573 0 : CHK_RET(GetBandWidthPerNPU(1, userRankSize_, deviceNumPerAggregation_, bandWidth)); // 单位:GB/s
574 0 : bandWidth = bandWidth * GB2B; // 单位:B/s
575 0 : CHK_RET(SelectAlgoForComm(hcclCMDType, delay, dataSizePerLoop, bandWidth, algType));
576 0 : return HCCL_SUCCESS;
577 : }
578 :
579 : HcclResult
580 0 : CollAlgOperator::SelectAlgoTypeForReduceScatter(float delay, u64 recvCurSize, float bandWidth, AlgTypeLevel1& algType)
581 : {
582 0 : auto steps = moduleNum_ - 1;
583 : // theoretical time cost of Ring
584 0 : double ringCost
585 0 : = static_cast<double>(steps) * delay
586 0 : + static_cast<double>(steps) / moduleNum_ * recvCurSize * userRankSize_ / bandWidth * SECOND2MICROSECOND;
587 :
588 : // theoretical time cost of NHR
589 0 : double nhrCost = ceil(log2(moduleNum_)) * delay
590 0 : + static_cast<double>(moduleNum_ - 1) / moduleNum_ * recvCurSize * userRankSize_ / bandWidth
591 0 : * SECOND2MICROSECOND;
592 :
593 : // compare costs between NHR and Ring, if same cost, Ring > NHR > HD
594 0 : algType = (nhrCost < ringCost) ? AlgTypeLevel1::ALG_LEVEL1_NHR : AlgTypeLevel1::ALG_LEVEL1_RING;
595 0 : double interMinCost = min(nhrCost, ringCost);
596 :
597 : // theoretical time cost of HD/RHD
598 0 : double hdCost = 0.0;
599 0 : if ((moduleNum_ & (moduleNum_ - 1)) == 0) {
600 : // theoretical time cost of HD
601 : hdCost
602 0 : = log2(moduleNum_) * delay
603 0 : + static_cast<double>(steps) / moduleNum_ * recvCurSize * userRankSize_ / bandWidth * SECOND2MICROSECOND;
604 : } else {
605 : // theoretical time cost of Recursive HD,
606 : // the (RHD_FACTOR_TWO * moduleNum_ - RHD_FACTOR_ONE) / moduleNum_ is equal to 1 + (moduleNum_ -1) / moduleNum_
607 0 : hdCost = ceil(log2(moduleNum_)) * delay
608 0 : + static_cast<double>(RHD_FACTOR_TWO * moduleNum_ - RHD_FACTOR_ONE) / moduleNum_ * recvCurSize
609 0 : * userRankSize_ / bandWidth * SECOND2MICROSECOND;
610 : }
611 :
612 : // compare cost among NHR, HD and Ring
613 0 : algType = (hdCost < interMinCost) ? AlgTypeLevel1::ALG_LEVEL1_HD : algType;
614 0 : return HCCL_SUCCESS;
615 : }
616 :
617 : HcclResult
618 0 : CollAlgOperator::SelectAlgoTypeForAllGather(float delay, u64 sendCurSize, float bandWidth, AlgTypeLevel1& algType) const
619 : {
620 0 : auto steps = moduleNum_ - 1;
621 : // theoretical time cost of Ring
622 0 : double ringCost
623 0 : = static_cast<double>(steps) * delay
624 0 : + static_cast<double>(steps) / moduleNum_ * sendCurSize * userRankSize_ / bandWidth * SECOND2MICROSECOND;
625 :
626 : // theoretical time cost of NHR
627 0 : double nhrCost = ceil(log2(moduleNum_)) * delay
628 0 : + static_cast<double>(moduleNum_ - 1) / moduleNum_ * sendCurSize * userRankSize_ / bandWidth
629 0 : * SECOND2MICROSECOND;
630 :
631 : // compare costs between NHR and Ring, if same cost, Ring > NHR > HD
632 0 : algType = (nhrCost < ringCost) ? AlgTypeLevel1::ALG_LEVEL1_NHR : AlgTypeLevel1::ALG_LEVEL1_RING;
633 0 : double interMinCost = min(nhrCost, ringCost);
634 :
635 : // theoretical time cost of HD/RHD
636 0 : double hdCost = 0.0;
637 0 : if ((moduleNum_ & (moduleNum_ - 1)) == 0) {
638 : // theoretical time cost of HD
639 : hdCost
640 0 : = log2(moduleNum_) * delay
641 0 : + static_cast<double>(steps) / moduleNum_ * sendCurSize * userRankSize_ / bandWidth * SECOND2MICROSECOND;
642 : } else {
643 : // theoretical time cost of Recursive HD
644 : // the (RHD_FACTOR_TWO * moduleNum_ - RHD_FACTOR_ONE) / moduleNum_ is equal to 1 + (moduleNum_ -1) / moduleNum_
645 0 : hdCost = ceil(log2(moduleNum_)) * delay
646 0 : + static_cast<double>(RHD_FACTOR_TWO * moduleNum_ - RHD_FACTOR_ONE) / moduleNum_ * sendCurSize
647 0 : * userRankSize_ / bandWidth * SECOND2MICROSECOND;
648 : }
649 :
650 : // compare cost among NHR, HD and Ring
651 0 : algType = (hdCost < interMinCost) ? AlgTypeLevel1::ALG_LEVEL1_HD : algType;
652 0 : return HCCL_SUCCESS;
653 : }
654 :
655 0 : HcclResult CollAlgOperator::SelectAlgoTypeForAllGatherV(
656 : float delay, u64 sendCurSize, float bandWidth, AlgTypeLevel1& algType) const
657 : {
658 0 : auto steps = moduleNum_ - 1;
659 : // theoretical time cost of Ring
660 0 : double ringCost
661 0 : = static_cast<double>(steps) * delay
662 0 : + static_cast<double>(steps) / moduleNum_ * sendCurSize * userRankSize_ / bandWidth * SECOND2MICROSECOND;
663 :
664 0 : HCCL_DEBUG("[%s] CollAlgOperator for SelectAlgoTypeForAllGatherV", __func__);
665 : // theoretical time cost of NHR
666 0 : double nhrCost = ceil(log2(moduleNum_)) * delay
667 0 : + static_cast<double>(moduleNum_ - 1) / moduleNum_ * sendCurSize * userRankSize_ / bandWidth
668 0 : * SECOND2MICROSECOND;
669 :
670 : // compare costs between NHR and Ring, if same cost, Ring > NHR > HD
671 0 : algType = (nhrCost < ringCost) ? AlgTypeLevel1::ALG_LEVEL1_NHR : AlgTypeLevel1::ALG_LEVEL1_RING;
672 :
673 0 : return HCCL_SUCCESS;
674 : }
675 :
676 : HcclResult
677 0 : CollAlgOperator::SelectAlgoTypeForGather(float delay, u64 sendCurSize, float bandWidth, AlgTypeLevel1& algType) const
678 : {
679 0 : auto steps = moduleNum_ - 1;
680 : // theoretical time cost of Ring
681 0 : double ringCost
682 0 : = static_cast<double>(steps) * delay
683 0 : + static_cast<double>(steps) / moduleNum_ * sendCurSize * userRankSize_ / bandWidth * SECOND2MICROSECOND;
684 0 : double hdCost = 0.0;
685 0 : if ((moduleNum_ & (moduleNum_ - 1)) == 0) {
686 : // theoretical time cost of HD
687 : hdCost
688 0 : = log2(moduleNum_) * delay
689 0 : + static_cast<double>(steps) / moduleNum_ * sendCurSize * userRankSize_ / bandWidth * SECOND2MICROSECOND;
690 : } else {
691 : // theoretical time cost of Recursive HD
692 : // the (RHD_FACTOR_TWO * moduleNum_ - RHD_FACTOR_ONE) / moduleNum_ is equal to 1 + (moduleNum_ -1) / moduleNum_
693 0 : hdCost = ceil(log2(moduleNum_)) * delay
694 0 : + static_cast<double>(RHD_FACTOR_TWO * moduleNum_ - RHD_FACTOR_ONE) / moduleNum_ * sendCurSize
695 0 : * userRankSize_ / bandWidth * SECOND2MICROSECOND;
696 : }
697 0 : algType = (hdCost < ringCost) ? AlgTypeLevel1::ALG_LEVEL1_HD : AlgTypeLevel1::ALG_LEVEL1_RING;
698 0 : return HCCL_SUCCESS;
699 : }
700 :
701 : HcclResult
702 0 : CollAlgOperator::SelectAlgoTypeForAllReduce(float delay, u64 curSize, float bandWidth, AlgTypeLevel1& algType) const
703 : {
704 0 : auto steps = moduleNum_ - 1;
705 : // theoretical time cost of Ring
706 0 : double ringCost = DOUBLE_SUB_HCCLCMD * static_cast<double>(steps) * delay
707 0 : + DOUBLE_SUB_HCCLCMD * static_cast<double>(steps) / moduleNum_ * curSize
708 0 : / deviceNumPerAggregation_ / bandWidth * SECOND2MICROSECOND;
709 :
710 : // theoretical time cost of NHR
711 0 : double nhrCost = NHR_FACTOR_TWO * ceil(log2(moduleNum_)) * delay
712 0 : + NHR_FACTOR_TWO * static_cast<double>(moduleNum_ - 1) / moduleNum_ * curSize
713 0 : / deviceNumPerAggregation_ / bandWidth * SECOND2MICROSECOND;
714 :
715 : // compare costs between NHR and Ring, if same cost, Ring > NHR > HD
716 0 : algType = (nhrCost < ringCost) ? AlgTypeLevel1::ALG_LEVEL1_NHR : AlgTypeLevel1::ALG_LEVEL1_RING;
717 0 : double interMinCost = min(nhrCost, ringCost);
718 :
719 : // theoretical time cost of HD/RHD
720 0 : double hdCost = 0.0;
721 0 : if ((moduleNum_ & (moduleNum_ - 1)) == 0) {
722 : // theoretical time cost of HD
723 0 : hdCost = DOUBLE_SUB_HCCLCMD * log2(moduleNum_) * delay
724 0 : + DOUBLE_SUB_HCCLCMD * static_cast<double>(steps) / moduleNum_ * curSize / deviceNumPerAggregation_
725 0 : / bandWidth * SECOND2MICROSECOND;
726 : } else {
727 : // theoretical time cost of Recursive HD
728 : // the (RHD_FACTOR_TWO * moduleNum_ - RHD_FACTOR_ONE) / moduleNum_ is equal to 1 + (moduleNum_ -1) / moduleNum_
729 0 : hdCost = DOUBLE_SUB_HCCLCMD * ceil(log2(moduleNum_)) * delay
730 0 : + DOUBLE_SUB_HCCLCMD * static_cast<double>(RHD_FACTOR_TWO * moduleNum_ - RHD_FACTOR_ONE) / moduleNum_
731 0 : * curSize / deviceNumPerAggregation_ / bandWidth * SECOND2MICROSECOND;
732 : }
733 :
734 : // compare cost among NHR, HD and Ring
735 0 : algType = (hdCost < interMinCost) ? AlgTypeLevel1::ALG_LEVEL1_HD : algType;
736 0 : return HCCL_SUCCESS;
737 : }
738 :
739 : HcclResult
740 0 : CollAlgOperator::SelectAlgoTypeForBroadcast(float delay, u64 curSize, float bandWidth, AlgTypeLevel1& algType) const
741 : {
742 0 : auto steps = moduleNum_ - 1;
743 : // theoretical time cost of Ring
744 0 : double ringCost = DOUBLE_SUB_HCCLCMD * static_cast<double>(steps) * delay
745 0 : + DOUBLE_SUB_HCCLCMD * static_cast<double>(steps) / moduleNum_ * curSize
746 0 : / deviceNumPerAggregation_ / bandWidth * SECOND2MICROSECOND;
747 0 : double hdCost = 0.0;
748 0 : if ((moduleNum_ & (moduleNum_ - 1)) == 0) {
749 : // theoretical time cost of HD
750 0 : hdCost = DOUBLE_SUB_HCCLCMD * log2(moduleNum_) * delay
751 0 : + DOUBLE_SUB_HCCLCMD * static_cast<double>(steps) / moduleNum_ * curSize / deviceNumPerAggregation_
752 0 : / bandWidth * SECOND2MICROSECOND;
753 : } else {
754 : // theoretical time cost of Recursive HD
755 : // rhd-broadcast = scatter + allgather + copy
756 0 : hdCost = (COPY_TIME_IN_RHD + DOUBLE_SUB_HCCLCMD * floor(log2(moduleNum_))) * delay
757 0 : + (COPY_TIME_IN_RHD + DOUBLE_SUB_HCCLCMD * static_cast<double>(steps) / moduleNum_) * curSize
758 0 : / deviceNumPerAggregation_ / bandWidth * SECOND2MICROSECOND;
759 : }
760 0 : algType = (hdCost < ringCost) ? AlgTypeLevel1::ALG_LEVEL1_HD : AlgTypeLevel1::ALG_LEVEL1_RING;
761 0 : return HCCL_SUCCESS;
762 : }
763 :
764 : HcclResult
765 0 : CollAlgOperator::SelectAlgoTypeForReduce(float delay, u64 curSize, float bandWidth, AlgTypeLevel1& algType) const
766 : {
767 0 : HCCL_DEBUG("[CollAlgOperator]SelectAlgoTypeForReduce start");
768 0 : auto steps = moduleNum_ - 1;
769 : // theoretical time cost of Ring
770 0 : double ringCost = DOUBLE_SUB_HCCLCMD * static_cast<double>(steps) * delay
771 0 : + DOUBLE_SUB_HCCLCMD * static_cast<double>(steps) / moduleNum_ * curSize
772 0 : / deviceNumPerAggregation_ / bandWidth * SECOND2MICROSECOND;
773 0 : double hdCost = 0.0;
774 0 : if ((moduleNum_ & (moduleNum_ - 1)) == 0) {
775 : // theoretical time cost of HD
776 0 : hdCost = DOUBLE_SUB_HCCLCMD * log2(moduleNum_) * delay
777 0 : + DOUBLE_SUB_HCCLCMD * static_cast<double>(steps) / moduleNum_ * curSize / deviceNumPerAggregation_
778 0 : / bandWidth * SECOND2MICROSECOND;
779 : } else {
780 : // theoretical time cost of Recursive HD
781 : // rhd-broadcast = reducescatter + gather + copy
782 0 : hdCost = (COPY_TIME_IN_RHD + DOUBLE_SUB_HCCLCMD * floor(log2(moduleNum_))) * delay
783 0 : + (COPY_TIME_IN_RHD + DOUBLE_SUB_HCCLCMD * static_cast<double>(steps) / moduleNum_) * curSize
784 0 : / deviceNumPerAggregation_ / bandWidth * SECOND2MICROSECOND;
785 : }
786 0 : algType = (hdCost < ringCost) ? AlgTypeLevel1::ALG_LEVEL1_HD : AlgTypeLevel1::ALG_LEVEL1_RING;
787 0 : return HCCL_SUCCESS;
788 : }
789 :
790 24 : AlgType CollAlgOperator::GetAlgType() { return algType_; }
791 :
792 2 : bool CollAlgOperator::Is2U2PInfer()
793 : {
794 : return (
795 0 : (deviceNumPerAggregation_ == HCCL_DEVICE_NUM_TWO) && (serverNum_ == 1)
796 0 : && (deviceType_ == DevType::DEV_TYPE_910B) && (meshAggregationRankSize_ == HCCL_DEVICE_NUM_TWO)
797 2 : && (pairLinkCounter_[static_cast<u32>(LinkTypeInServer::HCCS_TYPE)] == 0));
798 : }
799 :
800 31 : bool CollAlgOperator::Is910BSingleMesh()
801 : {
802 1 : bool isMeshTopo = topoType_ == TopoType::TOPO_TYPE_NP_MESH || topoType_ == TopoType::TOPO_TYPE_4P_MESH
803 32 : || topoType_ == TopoType::TOPO_TYPE_2P_MESH || topoType_ == TopoType::TOPO_TYPE_1P_MESH;
804 :
805 : bool isSingleMesh
806 31 : = (deviceType_ == DevType::DEV_TYPE_910B) && (isMeshTopo || Is2U2PInfer()) && (userRankSize_ != 1);
807 31 : return isSingleMesh;
808 : }
809 :
810 1 : bool CollAlgOperator::NeedCreateSingleMeshPlane(const bool isInlineReduce)
811 : {
812 : // 910B 图模式非确定计算,inlineReduce使能,MESH拓扑场景下,创建一个mesh平面
813 1 : bool meshSinglePlane = Is910BSingleMesh() && topoMatcher_->GetDeterministicConfig() == DETERMINISTIC_DISABLE
814 1 : && isInlineReduce && (GetWorkflowMode() != HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE);
815 :
816 1 : return meshSinglePlane;
817 : }
818 :
819 30 : bool CollAlgOperator::SingleMeshInlineReduce(void* inputPtr, void* outputPtr, HcclDataType dataType, HcclReduceOp op)
820 : {
821 30 : bool isInlineReduce = IsSupportSDMAReduce(inputPtr, outputPtr, dataType, op);
822 29 : bool singleMeshInlineReduce = Is910BSingleMesh() && isInlineReduce && isSingleMeshAggregation_;
823 28 : return singleMeshInlineReduce;
824 : }
825 :
826 4 : bool CollAlgOperator::IsMultiMeshInlineReduce(void* inputPtr, void* outputPtr, HcclDataType dataType, HcclReduceOp op)
827 : {
828 0 : bool isMeshTopo = topoType_ == TopoType::TOPO_TYPE_NP_MESH || topoType_ == TopoType::TOPO_TYPE_4P_MESH
829 4 : || topoType_ == TopoType::TOPO_TYPE_2P_MESH || topoType_ == TopoType::TOPO_TYPE_1P_MESH;
830 :
831 4 : bool isInlineReduce = IsSupportSDMAReduce(inputPtr, outputPtr, dataType, op);
832 2 : bool isRdmaReduce = IsSupportRDMAReduce(dataType, op);
833 2 : bool multiMeshInlineReduce = (deviceType_ == DevType::DEV_TYPE_910B) && isMeshTopo && isInlineReduce && isRdmaReduce
834 4 : && (!isSingleMeshAggregation_);
835 2 : return multiMeshInlineReduce;
836 : }
837 :
838 0 : void CollAlgOperator::SetLegacyHcclImpl(std::unique_ptr<hcclImpl>& impl)
839 : {
840 0 : hcclImpl_ = impl.get();
841 0 : return;
842 : }
843 :
844 8 : HcclResult CollAlgOperator::SetRetryEnable(bool retryEnable)
845 : {
846 8 : retryEnable_ = retryEnable;
847 8 : return HCCL_SUCCESS;
848 : }
849 :
850 7 : HcclResult CollAlgOperator::SetAivClearEnable(bool aivClearEnable)
851 : {
852 7 : aivClearEnable_ = aivClearEnable;
853 7 : return HCCL_SUCCESS;
854 : }
855 :
856 0 : HcclResult CollAlgOperator::SetAlgOpContext(AlgOpContext algOpContext)
857 : {
858 0 : algOpContext_ = algOpContext;
859 0 : return HCCL_SUCCESS;
860 : }
861 :
862 29 : bool CollAlgOperator::SupportRetryWithInplaceCheck(
863 : const HcclCMDType& opType, OpParam& param, std::string& algName, u8& isInplaceStatus,
864 : InplaceSupportRetryStatus& inPlaceSupportRetryStatus)
865 : {
866 : // 不支持inplace的通信算子重执行
867 29 : if (IsHcclOpInplace(opType, param, userRank_, userRankSize_, isInplaceStatus)) {
868 13 : void* commInputPtr = nullptr;
869 13 : u64 commInputSize = 0;
870 21 : CHK_RET(cclBufferManager_.GetInCCLbuffer(commInputPtr, commInputSize));
871 13 : if (!FitRetryConditionforInPlaceOp(
872 13 : opType, param, algName, commInputSize, userRankSize_, retryEnable_, inPlaceSupportRetryStatus)) {
873 8 : HCCL_DEBUG(
874 : "[CollAlgOperator][OpRetry][AICPU]hccl aicpu can not retry, opType[%s], inputPtr[%p], "
875 : "outputPtr[%p].",
876 : GetCMDTypeEnumStr(opType).c_str(), param.inputPtr, param.outputPtr);
877 8 : return false;
878 : }
879 : }
880 : // true 存在两种情况:
881 : // 1. 非inplace场景
882 : // 2. 是inplace但同时符合retry条件的场景
883 21 : return true;
884 : }
885 :
886 21 : HcclResult CollAlgOperator::GetNumBlocks(u32& numBlocks)
887 : {
888 21 : CHK_SMART_PTR_NULL(executor_);
889 21 : return executor_->GetNumBlocks(numBlocks);
890 : }
891 :
892 5 : HcclResult CollAlgOperator::SetNumBlocks(const u32& numBlocks)
893 : {
894 5 : CHK_SMART_PTR_NULL(executor_);
895 5 : return executor_->SetNumBlocks(numBlocks);
896 : }
897 :
898 2 : HcclResult CollAlgOperator::GetCache(HcclCacheInfo& cacheInfo)
899 : {
900 2 : CHK_SMART_PTR_NULL(executor_);
901 2 : return executor_->GetCache(cacheInfo);
902 : }
903 :
904 24 : HcclResult CollAlgOperator::SetOpCounter(const OpCounterInfo& opCounter)
905 : {
906 24 : opCounter_ = opCounter;
907 24 : return HCCL_SUCCESS;
908 : }
909 :
910 0 : HcclResult CollAlgOperator::SetRmaInfo(void* rmaInfo)
911 : {
912 0 : CHK_SMART_PTR_NULL(executor_);
913 0 : CHK_PTR_NULL(rmaInfo);
914 0 : return executor_->SetRmaInfo(rmaInfo);
915 : }
916 :
917 9 : HcclResult CollAlgOperator::SelectAlgforAHC(u64 dataSize, AHCOpType ahcOpType)
918 : {
919 9 : if (multiModuleDiffDeviceNumMode_) {
920 0 : return HCCL_SUCCESS;
921 : }
922 :
923 9 : bool isAHCWholeConfig
924 9 : = (algType_.algoLevel0 == AlgTypeLevel0::ALG_LEVEL0_RESERVED
925 9 : && (algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_AHC
926 0 : || algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_AHC_BROKE));
927 :
928 9 : CommPlane ahcSubGroupLevel = COMM_LEVEL1_AHC;
929 9 : if (isAHCWholeConfig) {
930 0 : if (deviceType_ != DevType::DEV_TYPE_910_93) {
931 0 : ahcSubGroupLevel = COMM_COMBINE;
932 : } else {
933 0 : ahcSubGroupLevel = COMM_COMBINE_ORDER;
934 : }
935 9 : } else if (deviceType_ != DevType::DEV_TYPE_910_93) {
936 0 : HCCL_DEBUG("[AHCAlgSelect] hccl algorithm: 910B not support level1 ahc, return ERROR.");
937 0 : return HCCL_E_PARA;
938 : }
939 :
940 9 : HCCL_INFO(
941 : "[SelectAlgforAHC] ahcOpType[%u] isAHCWholeConfig[%u] AHClevel[%u] algType_[%u] deviceType_[%u]", ahcOpType,
942 : isAHCWholeConfig, ahcSubGroupLevel, algType_.algoLevel1, deviceType_);
943 :
944 : AlgTypeLevel1 algTypeLevel1;
945 :
946 9 : std::vector<std::vector<std::vector<u32>>> globalSubGroups;
947 9 : std::map<AHCConcOpType, TemplateType> ahcAlgOption;
948 9 : CHK_RET(topoMatcher_->GetGlobalSubGroups(ahcSubGroupLevel, globalSubGroups));
949 9 : topoMatcher_->GetAHCAlgOption(ahcAlgOption);
950 :
951 9 : AHCAlgSelectParam ahcAlgSelectParam;
952 9 : ahcAlgSelectParam.opType = ahcOpType;
953 9 : ahcAlgSelectParam.dataSize = dataSize;
954 :
955 : // AHC 封装算法选择逻辑
956 9 : CHK_RET(AHCAlgSelect(algTypeLevel1, globalSubGroups, ahcAlgOption, ahcAlgSelectParam));
957 :
958 9 : topoMatcher_->SetAHCAlgOption(ahcAlgOption);
959 :
960 9 : auto iter = HCCL_ALGO_LEVEL1_NAME_MAP.find(algTypeLevel1);
961 9 : CHK_PRT_RET(
962 : iter == HCCL_ALGO_LEVEL1_NAME_MAP.end(),
963 : HCCL_ERROR("[AHCAlgSelect] level1: algType_[%u] is invalid.", algTypeLevel1), HCCL_E_INTERNAL);
964 :
965 : // 支持 AHC 自适应调节为 BROKE 类型
966 9 : if (algType_.algoLevel1 != algTypeLevel1 && algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_AHC) {
967 8 : algType_.algoLevel1 = algTypeLevel1;
968 : }
969 :
970 9 : HCCL_INFO(
971 : "[AHCAlgSelect] hccl algorithm: there are %u server(%u module) in level1, using %s algo", serverNum_,
972 : moduleNum_, iter->second.c_str());
973 :
974 9 : return HCCL_SUCCESS;
975 9 : }
976 :
977 9 : HcclResult CollAlgOperator::AHCAlgSelect(
978 : AlgTypeLevel1& algType, std::vector<std::vector<std::vector<u32>>>& globalSubGroups,
979 : std::map<AHCConcOpType, TemplateType>& ahcAlgOption, AHCAlgSelectParam& ahcAlgSelectParam)
980 : {
981 : // globalSubGroups 参数检查
982 9 : CHK_RET(CommAHCBaseInfo::CheckGlobalGroups(globalSubGroups));
983 :
984 9 : bool isAHCType = false;
985 9 : u32 minSubGroupSize = globalSubGroups[0][0].size();
986 9 : u32 maxSubGroupSize = globalSubGroups[0][0].size();
987 45 : for (u32 i = 1; i < globalSubGroups[0].size(); ++i) {
988 36 : if (globalSubGroups[0][i].size() < minSubGroupSize) {
989 0 : minSubGroupSize = globalSubGroups[0][i].size();
990 : }
991 36 : if (globalSubGroups[0][i].size() > maxSubGroupSize) {
992 0 : maxSubGroupSize = globalSubGroups[0][i].size();
993 : }
994 : }
995 54 : for (u32 i = 0; i < globalSubGroups[0].size(); ++i) {
996 45 : if (globalSubGroups[0][i].size() != minSubGroupSize) {
997 0 : isAHCType = true;
998 0 : break;
999 : }
1000 : }
1001 :
1002 : // 多平面 reduce scatter 和 all gather 算子,强制写死成BROKE类型
1003 9 : if (deviceNumPerServer_ != 1 && ahcAlgSelectParam.opType != AHCOpType::AHC_OP_TYPE_ALLREDUCE) {
1004 0 : isAHCType = false;
1005 : }
1006 :
1007 : // add AHC Conc Type logic here, modify init Type depend on the input para
1008 9 : CHK_RET(AHCAlgOptionSelect(algType, globalSubGroups, ahcAlgOption, ahcAlgSelectParam));
1009 :
1010 9 : if (ahcAlgSelectParam.enableAlgAutoSelect == false) { // 关闭算法自适应功能时,默认设置AHC算法
1011 0 : algType = AlgTypeLevel1::ALG_LEVEL1_AHC;
1012 0 : return HCCL_SUCCESS;
1013 : }
1014 :
1015 9 : if (isAHCType) {
1016 0 : algType = AlgTypeLevel1::ALG_LEVEL1_AHC; // 设置为 AHC 类型
1017 : } else {
1018 9 : algType = AlgTypeLevel1::ALG_LEVEL1_AHC_BROKE; // 设置为 BROKE 类型
1019 : }
1020 :
1021 9 : HCCL_DEBUG(
1022 : "[AHCAlgSelect] end minSubGroupSize = %u maxSubGroupSize = %u isAHCType = %u", minSubGroupSize, maxSubGroupSize,
1023 : isAHCType);
1024 :
1025 9 : return HCCL_SUCCESS;
1026 : }
1027 :
1028 11 : HcclResult CollAlgOperator::AHCAlgOptionSelect(
1029 : const AlgTypeLevel1& algType, std::vector<std::vector<std::vector<u32>>>& globalSubGroups,
1030 : std::map<AHCConcOpType, TemplateType>& ahcAlgOption, const AHCAlgSelectParam& ahcAlgSelectParam) const
1031 : {
1032 : (void)algType;
1033 : (void)ahcAlgSelectParam;
1034 11 : AHCConcOpType ahcConcOpType;
1035 : // 一层组间拼接时,分组数大于设定阈值则修改默认算法为NHR
1036 11 : if (globalSubGroups[0].size() <= AHC_LEVEL0_GROUP_SIZE_THRESHOLD) {
1037 4 : HCCL_DEBUG("[AHCAlgSelect] conc inter select type RING ");
1038 4 : ahcConcOpType = {AHCLevel::AHC_LEVEL_0, ConcType::CONC_INTER, AHCOpType::AHC_OP_TYPE_REDUCE_SCATTER};
1039 4 : ahcAlgOption[ahcConcOpType] = TemplateType::TEMPLATE_REDUCESCATTER_RING;
1040 :
1041 4 : ahcConcOpType = {AHCLevel::AHC_LEVEL_0, ConcType::CONC_INTER, AHCOpType::AHC_OP_TYPE_ALLREDUCE};
1042 4 : ahcAlgOption[ahcConcOpType] = TemplateType::TEMPLATE_ALL_REDUCE_RING;
1043 :
1044 4 : ahcConcOpType = {AHCLevel::AHC_LEVEL_0, ConcType::CONC_INTER, AHCOpType::AHC_OP_TYPE_ALLGATHER};
1045 4 : ahcAlgOption[ahcConcOpType] = TemplateType::TEMPLATE_ALL_GATHER_RING;
1046 : } else {
1047 7 : HCCL_DEBUG("[AHCAlgSelect] conc inter select type NHR ");
1048 7 : ahcConcOpType = {AHCLevel::AHC_LEVEL_0, ConcType::CONC_INTER, AHCOpType::AHC_OP_TYPE_REDUCE_SCATTER};
1049 7 : ahcAlgOption[ahcConcOpType] = TemplateType::TEMPLATE_REDUCESCATTER_NHR;
1050 :
1051 7 : ahcConcOpType = {AHCLevel::AHC_LEVEL_0, ConcType::CONC_INTER, AHCOpType::AHC_OP_TYPE_ALLREDUCE};
1052 7 : ahcAlgOption[ahcConcOpType] = TemplateType::TEMPLATE_ALL_REDUCE_NHR;
1053 :
1054 7 : ahcConcOpType = {AHCLevel::AHC_LEVEL_0, ConcType::CONC_INTER, AHCOpType::AHC_OP_TYPE_ALLGATHER};
1055 7 : ahcAlgOption[ahcConcOpType] = TemplateType::TEMPLATE_ALL_GATHER_NHR;
1056 : }
1057 11 : return HCCL_SUCCESS;
1058 : }
1059 :
1060 0 : u32 CollAlgOperator::CalcOptimalIntraRingsize(u64 count, HcclDataType dataType, HcclCMDType opType)
1061 : {
1062 0 : if (!topoMatcher_->GetARSFlag())
1063 0 : return 0;
1064 :
1065 0 : u32 level0RankSize = topoMatcher_->GetCommPlaneRanks(COMM_LEVEL0)[0].size();
1066 0 : u32 rankSizeInSuperPod = topoMatcher_->GetCommPlaneRanks(COMM_ARS)[0].size();
1067 0 : u32 perDataSize = 0;
1068 0 : CHK_RET(SalGetDataTypeSize(dataType, perDataSize));
1069 : // 不支持 ARS 或环内卡数不是 2 的倍数
1070 0 : u32 level0RingSize = 1;
1071 0 : if (!isARSDoubleRing_ || (level0RankSize % FACTOR_TWO != 0)) {
1072 0 : HCCL_INFO(
1073 : "not Support ARS doubleRing, level0RingSize:[%u], level0RankSize[%u].", level0RingSize, level0RankSize);
1074 0 : return level0RingSize;
1075 : }
1076 : // --- 1. 带宽 & 基本参数 ---
1077 : float bwHCCS, bwHBM, bwSIO;
1078 0 : constexpr u32 level0 = 0;
1079 0 : constexpr u32 level2 = 2;
1080 0 : constexpr u32 level3 = 3;
1081 0 : CHK_RET(GetBandWidthPerNPU(level0, userRankSize_, deviceNumPerAggregation_, bwHCCS));
1082 0 : CHK_RET(GetBandWidthPerNPU(level2, userRankSize_, deviceNumPerAggregation_, bwHBM));
1083 0 : CHK_RET(GetBandWidthPerNPU(level3, userRankSize_, deviceNumPerAggregation_, bwSIO));
1084 0 : float latency = BASE_COMM_LATENCY / MULTIPLIER_MS2US; // ms
1085 : // --- 2. 数据总量 (GB) ---
1086 0 : float baseSizeGB = static_cast<double>(count) * perDataSize / GB2B;
1087 0 : float totalSize = baseSizeGB;
1088 0 : HCCL_INFO(
1089 : "CalcOptimalIntraRingsize: count[%u], totalSize:[%lf]GB, perDataSize[%u].", count, totalSize, perDataSize);
1090 0 : if (opType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER || opType == HcclCMDType::HCCL_CMD_ALLGATHER) {
1091 0 : totalSize *= rankSizeInSuperPod;
1092 : }
1093 : // --- 3. 枚举可能的环大小 ---
1094 0 : std::vector<u32> factors;
1095 0 : for (u32 i = 1; i <= rankSizeInSuperPod / i; ++i) {
1096 0 : if (rankSizeInSuperPod % i == 0) {
1097 0 : if (i != rankSizeInSuperPod / i) {
1098 0 : factors.push_back(rankSizeInSuperPod / i);
1099 : }
1100 0 : factors.push_back(i);
1101 : }
1102 : }
1103 0 : std::sort(factors.begin(), factors.end());
1104 : // --- 4. 计算最优带宽 ---
1105 0 : double maxBwARS = 0.0;
1106 0 : for (u32 N1 : factors) {
1107 : // 传输时延 (ms)
1108 : double latencyIntra;
1109 0 : if (N1 == FACTOR_TWO) {
1110 0 : latencyIntra = totalSize * MULTIPLIER_S2MS / FACTOR_TWO / bwSIO;
1111 0 : } else if ((N1 % FACTOR_TWO == 0) && (N1 > FACTOR_TWO)) {
1112 0 : latencyIntra = (N1 - 1) * totalSize * MULTIPLIER_S2MS / N1 / bwHCCS / FACTOR_TWO;
1113 : } else {
1114 0 : latencyIntra = (N1 - 1) * totalSize * MULTIPLIER_S2MS / N1 / bwHCCS;
1115 : }
1116 0 : u32 N2 = rankSizeInSuperPod / N1;
1117 : // 静态时延 (ms)
1118 0 : double interStep = (algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_RING) ? (N2 - 1) : log2(N2);
1119 0 : double latencyStep = (interStep + (N1 - 1)) * latency;
1120 0 : double latencyInter = (N2 - 1) * totalSize * MULTIPLIER_S2MS / N1 / N2 / bwHCCS;
1121 : // HBM 拷贝时延 (ms)
1122 0 : double latencyCopy = totalSize * MULTIPLIER_S2MS / bwHBM;
1123 0 : u8 mul = (HcclCMDType::HCCL_CMD_ALLREDUCE == opType) ? FACTOR_TWO : 1;
1124 0 : double timeCost = mul * (latencyStep + latencyIntra + latencyInter) + latencyCopy;
1125 0 : double bwARS = totalSize / timeCost; // GB/ms
1126 0 : if (bwARS > maxBwARS) {
1127 0 : level0RingSize = N1;
1128 0 : maxBwARS = bwARS;
1129 : }
1130 : }
1131 0 : HCCL_INFO("level0RingSize:[%u], level0RankSize[%u], totalSize:[%lf]GB", level0RingSize, level0RankSize, totalSize);
1132 0 : return level0RingSize;
1133 0 : }
1134 :
1135 20 : bool CollAlgOperator::IsNeedStrictMode(const OpParam& param)
1136 : {
1137 : bool isStrictMode
1138 20 : = (topoMatcher_->GetDeterministicConfig() == DETERMINISTIC_STRICT)
1139 0 : && (param.DataDes.dataType == HCCL_DATA_TYPE_FP16 || param.DataDes.dataType == HCCL_DATA_TYPE_FP32
1140 0 : || param.DataDes.dataType == HCCL_DATA_TYPE_BFP16 || param.DataDes.dataType == HCCL_DATA_TYPE_FP64)
1141 0 : && (param.reduceType == HCCL_REDUCE_SUM || param.reduceType == HCCL_REDUCE_PROD)
1142 20 : && userRankSize_ >= MIN_STRICT_RANK_NUM;
1143 :
1144 20 : return isStrictMode;
1145 : }
1146 :
1147 0 : bool CollAlgOperator::CheckStrictCondition(const OpParam& param) const
1148 : {
1149 0 : CHK_PRT_RET(
1150 : multiModuleDiffDeviceNumMode_ || multiSuperPodDiffDeviceNumMode_ || multiSuperPodDiffServerNumMode_,
1151 : HCCL_ERROR("[CollAlgOperator][CheckStrictCondition] DETERMINISTIC_STRICT mode not support asymmetrical topo."),
1152 : false);
1153 :
1154 0 : CHK_PRT_RET(
1155 : param.reduceType == HCCL_REDUCE_PROD,
1156 : HCCL_ERROR("[CollAlgOperator][CheckStrictCondition] DETERMINISTIC_STRICT mode not support PROD."), false);
1157 :
1158 0 : CHK_PRT_RET(
1159 : param.DataDes.dataType == HCCL_DATA_TYPE_FP64,
1160 : HCCL_ERROR("[CollAlgOperator][CheckStrictCondition] DETERMINISTIC_STRICT mode not support FP64."), false);
1161 :
1162 0 : CHK_PRT_RET(
1163 : GetExternalInputInterHccsDisable(),
1164 : HCCL_ERROR("[CollAlgOperator][CheckStrictCondition] DETERMINISTIC_STRICT mode not support HCCS disable."),
1165 : false);
1166 :
1167 0 : return true;
1168 : }
1169 :
1170 : } // namespace hccl
|