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 "broadcast_operator.h"
12 : #include "device_capacity.h"
13 : #include "coll_alg_op_registry.h"
14 :
15 : namespace hccl {
16 : constexpr u64 AIV_MAX_DATASIZE = 4ULL * 1024 * 1024 * 1024;
17 :
18 1 : BroadCastOperator::BroadCastOperator(AlgConfigurator* algConfigurator, CCLBufferManager &cclBufferManager,
19 1 : HcclDispatcher dispatcher, std::unique_ptr<TopoMatcher> &topoMatcher)
20 1 : : CollAlgOperator(algConfigurator, cclBufferManager, dispatcher, topoMatcher, HcclCMDType::HCCL_CMD_BROADCAST)
21 : {
22 : // 由于bcast暂不支持server间ring,需继续使用HD或NHR
23 1 : if (!(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NHR) &&
24 0 : !(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NHR_V1) &&
25 0 : !(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_WHOLE_RING) &&
26 0 : !(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NB)) {
27 0 : algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_HD;
28 0 : HCCL_WARNING("[BroadCastOperator][BroadCastOperator] do not support ring in AlgoLevel1 yet, reset algType=HD.");
29 : }
30 1 : }
31 2 : BroadCastOperator::~BroadCastOperator()
32 : {
33 2 : }
34 :
35 1 : HcclResult BroadCastOperator::SelectAlg(const std::string& tag, const OpParam& param, std::string& algName,
36 : std::string& newTag)
37 : {
38 : HcclResult ret;
39 1 : isAivMode_ = false;
40 1 : if (isDiffDeviceType_) {
41 0 : ret = SelectAlgforMix(param, algName);
42 1 : } else if (Is310P3Common(isHaveCpuRank_, deviceType_)) {
43 0 : ret = SelectAlgfor310P3(param, algName);
44 1 : } else if (Is310PDevice() && topoType_ == TopoType::TOPO_TYPE_2P_MESH) {
45 0 : ret = SelectAlgfor310P(param, algName);
46 1 : } else if (deviceType_ == DevType::DEV_TYPE_910) {
47 0 : ret = SelectAlgfor910A(param, algName);
48 1 : } else if (deviceType_ == DevType::DEV_TYPE_910B) {
49 0 : ret = SelectAlgfor910B(param, algName);
50 1 : } else if (deviceType_ == DevType::DEV_TYPE_910_93) {
51 1 : ret = SelectAlgfor91093(param, algName);
52 : } else {
53 0 : HCCL_ERROR("BroadCastOperator[SelectAlg] device type[%d] is out of range for selector.", deviceType_);
54 0 : return HCCL_E_NOT_SUPPORT;
55 : }
56 1 : CHK_PRT_RET(ret != HCCL_SUCCESS,
57 : HCCL_ERROR("[BroadCastSelector][SelectAlg]tag[%s], broadcast failed, return[%d]", tag.c_str(), ret), ret);
58 :
59 1 : if (GetWorkflowMode() != HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) {
60 1 : newTag = tag;
61 0 : } else if (isAivMode_ || (Is310P3Common(isHaveCpuRank_, deviceType_) &&
62 0 : (algType_.algoLevel1 != AlgTypeLevel1::ALG_LEVEL1_HD))) {
63 0 : newTag = tag + algName;
64 0 : } else if (algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_HD || algType_.algoLevel2 == AlgTypeLevel2::ALG_LEVEL2_HD) {
65 0 : newTag = tag + algName;
66 0 : std::string appendTag = "";
67 0 : u32 serverNumPerSuperPod = superPodNum_ == 0 ? moduleNum_ : moduleNum_ / superPodNum_;
68 0 : if (algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_HD) {
69 0 : u32 part1Size = FACTOR_TWO * (serverNumPerSuperPod - (1 << static_cast<u32>(log2(serverNumPerSuperPod))));
70 0 : u32 rootId = param.root / deviceNumPerAggregation_ % serverNumPerSuperPod;
71 0 : appendTag += "L1_" + std::to_string((rootId >= part1Size) || ((rootId % FACTOR_TWO) == 0));
72 : }
73 0 : if (algType_.algoLevel2 == AlgTypeLevel2::ALG_LEVEL2_HD) {
74 0 : u32 part1Size = FACTOR_TWO * (superPodNum_ - (1 << static_cast<u32>(log2(superPodNum_))));
75 0 : u32 rootId = param.root / deviceNumPerAggregation_ / serverNumPerSuperPod;
76 0 : appendTag += (appendTag.empty() ? "L2_" : "_L2_") + std::to_string((rootId >= part1Size) || ((rootId % FACTOR_TWO) == 0));
77 : }
78 0 : HCCL_DEBUG("[BroadCastOperator][SelectAlg]tag is [%s]", tag);
79 0 : newTag = newTag + '_' + appendTag;
80 0 : if (GetExternalInputHcclEnableEntryLog() && param.opBaseAtraceInfo != nullptr) {
81 0 : CHK_RET(param.opBaseAtraceInfo->SavealgtypeTraceInfo(appendTag, param.tag));
82 : }
83 0 : } else {
84 0 : AlgTypeLevel1 algType1 = algType_.algoLevel1;
85 0 : auto level1Iter = HCCL_ALGO_LEVEL1_NAME_MAP.find(algType1);
86 0 : CHK_PRT_RET(level1Iter == HCCL_ALGO_LEVEL1_NAME_MAP.end(), HCCL_ERROR("level1: algType1[%u] is invalid.",
87 : algType1), HCCL_E_INTERNAL);
88 0 : newTag = tag + level1Iter->second + algName;
89 : }
90 1 : HCCL_DEBUG("[%s] SelectAlg for newTag", __func__);
91 1 : newTag += (param.aicpuUnfoldMode ? "_device" : "_host");
92 1 : return ret;
93 : }
94 :
95 0 : HcclResult BroadCastOperator::SelectAlgforMix(const OpParam& param, std::string& algName)
96 : {
97 : (void) param;
98 0 : if (gcdDeviceNumPerAggregation_ > 1) {
99 0 : algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_NHR;
100 0 : HCCL_WARNING("[BroadCastOperator][SelectAlgforMix] only support NHR in AlgoLevel1 yet, "\
101 : "default is algType=NHR.");
102 0 : algName = "BroadCastMixExecutor";
103 : } else {
104 0 : algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_RING;
105 0 : HCCL_WARNING("[BroadCastOperator][SelectAlgforMix] only support ring in AlgoComm yet, "\
106 : "default is algType=ring.");
107 0 : algName = "BroadCastComm";
108 : }
109 :
110 0 : HCCL_INFO("[SelectAlgforMix] broadcast SelectAlgforMix is algName [%s]", algName.c_str());
111 0 : return HCCL_SUCCESS;
112 : }
113 :
114 0 : HcclResult BroadCastOperator::SelectAlgfor310P3(const OpParam& param, std::string& algName)
115 : {
116 : (void) param;
117 0 : algName = "BroadCastCommFor310P";
118 0 : HCCL_INFO("[SelectAlgfor310P3] broadcast SelectAlgfor310P3 is algName [%s]", algName.c_str());
119 0 : return HCCL_SUCCESS;
120 : }
121 :
122 0 : HcclResult BroadCastOperator::SelectAlgfor310P(const OpParam& param, std::string& algName)
123 : {
124 0 : algName = "BroadcastPlusBroadcast";
125 0 : HCCL_INFO("[SelectAlgfor310P] broadcast SelectAlgfor310P is algName [%s]", algName.c_str());
126 0 : return HCCL_SUCCESS;
127 : }
128 :
129 0 : HcclResult BroadCastOperator::SelectAlgfor910A(const OpParam& param, std::string& algName)
130 : {
131 : (void) param;
132 0 : bool isMeshTopo = topoType_ == TopoType::TOPO_TYPE_4P_MESH || topoType_ == TopoType::TOPO_TYPE_2P_MESH;
133 0 : bool isRingTopo = topoType_ == TopoType::TOPO_TYPE_NP_SINGLE_RING || topoType_ == TopoType::TOPO_TYPE_8P_RING;
134 :
135 0 : if (isMeshTopo) {
136 0 : algName = "BroadCastMeshExecutor";
137 0 : } else if (topoType_ == TopoType::TOPO_TYPE_4P_RING) {
138 0 : algName = "BroadCast4pRingExecutor";
139 0 : } else if (isRingTopo) {
140 0 : algName = "BroadCastRingExecutor";
141 : } else {
142 0 : algName = "BroadCastComm";
143 : }
144 0 : HCCL_INFO("[SelectAlgfor910A] broadcast SelectAlgfor910A is algName [%s]", algName.c_str());
145 0 : return HCCL_SUCCESS;
146 : }
147 :
148 0 : HcclResult BroadCastOperator::SelectAlgfor910B(const OpParam& param, std::string& algName)
149 : {
150 0 : bool isMeshTopo = topoType_ == TopoType::TOPO_TYPE_NP_MESH || topoType_ == TopoType::TOPO_TYPE_4P_MESH ||
151 0 : topoType_ == TopoType::TOPO_TYPE_2P_MESH || topoType_ == TopoType::TOPO_TYPE_1P_MESH;
152 0 : bool isRingTopo = topoType_ == TopoType::TOPO_TYPE_NP_SINGLE_RING || topoType_ == TopoType::TOPO_TYPE_8P_RING;
153 0 : bool isOpbase = (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE);
154 :
155 : // 暂只支持单算子模式
156 0 : const u64 commInputSize = cclBufferManager_.GetInCCLbufferSize();
157 0 : const u64 commOutputSize = cclBufferManager_.GetOutCCLbufferSize();
158 0 : u64 dataSize = param.DataDes.count * SIZE_TABLE[param.DataDes.dataType];
159 0 : bool isCCLBufferGE16M = commInputSize >= HCCL_MID_COUNT_16_MB && commOutputSize >= HCCL_MID_COUNT_16_MB;
160 0 : isAivMode_ = topoMatcher_->GetAivModeConfig() && isSingleMeshAggregation_ && isOpbase && isCCLBufferGE16M &&
161 0 : IsSupportAIVCopy(param.DataDes.dataType) && dataSize <= AIV_MAX_DATASIZE;
162 0 : if (isAivMode_) {
163 0 : algName = "BroadcastMeshAivExecutor";
164 0 : } else if (isMeshTopo) {
165 0 : algName = "BroadCastMeshExecutor";
166 0 : } else if (topoType_ == TopoType::TOPO_TYPE_4P_RING) {
167 0 : algName = "BroadCast4pRingExecutor";
168 0 : } else if (isRingTopo) {
169 0 : algName = "BroadCastRingExecutor";
170 : } else {
171 0 : algName = "BroadCastComm";
172 : }
173 0 : HCCL_INFO("[SelectAlgfor910B] broadcast SelectAlgfor910B is algName [%s]", algName.c_str());
174 0 : return HCCL_SUCCESS;
175 : }
176 :
177 1 : HcclResult BroadCastOperator::SelectAlgfor91093(const OpParam& param, std::string& algName)
178 : {
179 : // level 1重定向为NHR, 因scatter && broadcast只支持nhr/nb
180 1 : if (!(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NHR) &&
181 0 : !(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NB)) {
182 0 : algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_NHR;
183 0 : HCCL_WARNING("[BroadCastOperator][BroadCastOperator] do not support ring in AlgoLevel1 yet, reset algType=NHR.");
184 : }
185 :
186 1 : u32 unitSize = SIZE_TABLE[param.DataDes.dataType];
187 1 : u64 dataSize = param.DataDes.count * unitSize; // 单位:字节
188 1 : if (dataSize >= cclBufferManager_.GetInCCLbufferSize()) {
189 1 : HCCL_WARNING("The current inCCLbufferSize is [%llu] bytes, change the HCCL_BUFFSIZE environment variable "\
190 : "to be greater than the current data volume[%llu] bytes to improve the performance of the 91093 environment.",
191 : cclBufferManager_.GetInCCLbufferSize(), dataSize);
192 : }
193 :
194 1 : const u64 commInputSize = cclBufferManager_.GetInCCLbufferSize();
195 1 : const u64 commOutputSize = cclBufferManager_.GetOutCCLbufferSize();
196 1 : bool isCCLBufferGE16M = commInputSize >= HCCL_MID_COUNT_16_MB && commOutputSize >= HCCL_MID_COUNT_16_MB;
197 1 : bool isOpbase = (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE);
198 :
199 1 : bool isOnlyAiv = topoMatcher_->GetIsOnlyAivConfig();
200 1 : bool hasEnoughCCLBuffer = isSingleMeshAggregation_ && isOpbase && isCCLBufferGE16M && dataSize <= AIV_MAX_DATASIZE;
201 1 : bool hasSmallDataOrOnlyAiv = !isOpbase && (isOnlyAiv || dataSize <= HCCL_MID_COUNT_16_MB);
202 1 : bool isSatisfyDataSize = (userRankSize_ <= DEVICE_EIGHT && dataSize <= HCCL_SMALL_COUNT_512_KB ) ||
203 0 : (userRankSize_ > DEVICE_EIGHT && dataSize <= HCCL_SMALL_COUNT_1_MB);
204 :
205 1 : bool isAivSingleNode = serverNum_ == 1 && (hasEnoughCCLBuffer || hasSmallDataOrOnlyAiv);
206 0 : bool isAivCrossNode = (superPodNum_ == 1) && (serverNum_ > 1) && !GetExternalInputInterHccsDisable()
207 1 : && ((isOpbase && isCCLBufferGE16M && isSatisfyDataSize) || hasSmallDataOrOnlyAiv);
208 :
209 1 : isAivMode_ = topoMatcher_->GetAivModeConfig()
210 1 : && IsSupportAIVCopy(param.DataDes.dataType)
211 2 : && (isAivSingleNode || isAivCrossNode);
212 :
213 1 : bool smallCountOptimSingleServer =
214 2 : (serverNum_ == 1) &&
215 1 : ((workflowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) ||
216 1 : (workflowMode_ != HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE && !param.aicpuUnfoldMode)) &&
217 2 : (deviceNumPerAggregation_ > HCCL_DEVICE_NUM_TWO) &&
218 0 : (param.DataDes.count * SIZE_TABLE[param.DataDes.dataType] <= HCCL_SMALL_COUNT_512_KB * userRankSize_);
219 1 : bool smallCountOptimMultiServer =
220 1 : (deviceNumPerAggregation_ > HCCL_DEVICE_NUM_TWO) && (serverNum_ != 1) && (superPodNum_ == 1) &&
221 0 : (param.DataDes.count * SIZE_TABLE[param.DataDes.dataType] <= HCCL_SMALL_COUNT_1_MB * deviceNumPerAggregation_);
222 1 : bool is2Pod2ServerTopo = (superPodNum_ == 2 && serverNum_ == 2);// 针对 A3背靠背机型
223 1 : bool smallCountOptimMultiPod = (superPodNum_ > 1 || (GetExternalInputInterHccsDisable() && serverNum_ > 1)) && !is2Pod2ServerTopo &&
224 2 : (param.DataDes.count * unitSize <= HCCL_SMALL_COUNT_16_KB * deviceNumPerAggregation_) && !retryEnable_; // 涉及ROCE平面
225 0 : bool isBack2BackFor91093 = is2Pod2ServerTopo && (workflowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) &&
226 1 : (param.DataDes.count * unitSize <= HCCL_SMALL_COUNT_16_KB * deviceNumPerAggregation_) && !retryEnable_;
227 1 : if (isAivMode_) {
228 1 : if(isAivSingleNode) {
229 1 : algName = "BroadcastMeshAivExecutor";
230 : } else {
231 0 : algName = "BroadcastMeshAivFor91093Executor";
232 : }
233 0 : } else if (multiModuleDiffDeviceNumMode_ || multiSuperPodDiffServerNumMode_) {
234 0 : algName = "BroadCastComm";
235 0 : } else if (smallCountOptimMultiServer || smallCountOptimMultiPod) {
236 0 : algName = "BroadCastComm";
237 0 : algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_NHR;
238 0 : } else if (isBack2BackFor91093) {
239 0 : algName = "BroadcastMidCountFor91093Executor";
240 0 : } else if (smallCountOptimSingleServer) {
241 0 : algName = "BroadCastSmallCountExecutor";
242 0 : } else if (param.supportZeroCopy &&
243 0 : (topoType_ == TopoType::TOPO_TYPE_NP_DOUBLE_RING || param.DataDes.count * unitSize > HCCL_MID_COUNT_16_MB * serverNum_)) {
244 0 : algName = "BroadCastRingZerocopyExecutor";
245 0 : } else if (topoType_ == TopoType::TOPO_TYPE_NP_SINGLE_RING || topoType_ == TopoType::TOPO_TYPE_NP_DOUBLE_RING) {
246 0 : algName = "BroadCastRingFor91093Executor";
247 : } else {
248 0 : algName = "BroadCastComm";
249 : }
250 1 : HCCL_INFO("[SelectAlgfor91093] broadcast SelectAlgfor91093 is algName [%s]", algName.c_str());
251 1 : return HCCL_SUCCESS;
252 : }
253 :
254 : REGISTER_OP(HcclCMDType::HCCL_CMD_BROADCAST, Broadcast, BroadCastOperator);
255 : } // namespace hccl
|