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