Line data Source code
1 : /**
2 : * Copyright (c) 2026 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 "coll_broadcast_midcount_for_910_93_executor.h"
12 :
13 : namespace hccl {
14 0 : CollBroadcastMidCountFor91093Executor::CollBroadcastMidCountFor91093Executor(const HcclDispatcher dispatcher,
15 0 : std::unique_ptr<TopoMatcher> &topoMatcher)
16 0 : : CollBroadcastExecutor(dispatcher, topoMatcher)
17 : {
18 0 : desc_.level1SupportedAlgos = {
19 : AlgTypeLevel1::ALG_LEVEL1_NHR,
20 0 : };
21 0 : desc_.level2SupportedAlgos = {
22 : AlgTypeLevel2::ALG_LEVEL2_NHR,
23 0 : };
24 0 : }
25 0 : HcclResult CollBroadcastMidCountFor91093Executor::CalcStreamNum(u32& streamNum)
26 : {
27 0 : streamNum = 0;
28 0 : HCCL_INFO("[CollBroadcastCommExecutor][CalcStreamNum]tag[%s] streamNum_ is [%u]", tag_.c_str(), streamNum);
29 0 : return HCCL_SUCCESS;
30 : }
31 :
32 0 : HcclResult CollBroadcastMidCountFor91093Executor::CalcCommInfo(std::vector<LevelNSubCommTransport>& opTransport)
33 : {
34 0 : TransportMemType inputType = TransportMemType::RESERVED;
35 0 : TransportMemType outputType = TransportMemType::RESERVED;
36 0 : CHK_RET(CalcTransportMemType(inputType, outputType));
37 0 : CHK_RET(CalcLevel1CommInfo(inputType, outputType, opTransport));
38 0 : CHK_RET(CalcLevel2CommInfo(inputType, outputType, opTransport));
39 0 : return HCCL_SUCCESS;
40 : }
41 :
42 0 : HcclResult CollBroadcastMidCountFor91093Executor::CalcTransportMemType(TransportMemType &inputType,
43 : TransportMemType &outputType) const
44 : {
45 0 : if (workflowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) {
46 0 : inputType = TransportMemType::CCL_INPUT;
47 0 : outputType = TransportMemType::CCL_OUTPUT;
48 : } else {
49 0 : HCCL_ERROR("BroadcastMidCountFor91093Executor do not support offload mode");
50 0 : return HCCL_E_UNAVAIL;
51 : }
52 0 : HCCL_INFO("[CollBroadcastMidCountFor91093Executor][CalcTransportMemType] tag[%s] inputType[%d], outputType[%d]",
53 : tag_.c_str(), inputType, outputType);
54 0 : return HCCL_SUCCESS;
55 : }
56 :
57 0 : HcclResult CollBroadcastMidCountFor91093Executor::CalcLevel1CommInfo(TransportMemType inputType,
58 : TransportMemType outputType,
59 : std::vector<LevelNSubCommTransport>& opTransport)
60 : {
61 0 : CommParaInfo commParaCombineL1(COMM_COMBINE_L1, CommType::COMM_TAG_NONUNIFORM_HIERARCHICAL_RING);
62 0 : CHK_RET(CalcCommPlaneInfo(tag_, commParaCombineL1, opTransport[COMM_COMBINE_L1], inputType, outputType));
63 0 : return HCCL_SUCCESS;
64 0 : }
65 :
66 0 : HcclResult CollBroadcastMidCountFor91093Executor::CalcLevel2CommInfo(TransportMemType inputType, TransportMemType outputType,
67 : std::vector<LevelNSubCommTransport>& opTransport)
68 : {
69 0 : CommParaInfo commParaLevel2(COMM_LEVEL2, CommType::COMM_TAG_NONUNIFORM_HIERARCHICAL_RING);
70 0 : CHK_RET(CalcCommPlaneInfo(tag_, commParaLevel2, opTransport[COMM_LEVEL2], inputType, outputType));
71 0 : return HCCL_SUCCESS;
72 0 : }
73 :
74 0 : u64 CollBroadcastMidCountFor91093Executor::CalcLoopMaxCount(const u64 cclBuffSize, const u32 unitSize)
75 : {
76 0 : u64 maxCountPerLoop = cclBuffSize / HCCL_MIN_SLICE_ALIGN_910_93 * HCCL_MIN_SLICE_ALIGN_910_93 / unitSize ;
77 0 : if (maxCountPerLoop == 0) {
78 0 : HCCL_ERROR("[CollBroadcastMidCountFor91093Executor][CalcLoopMaxCount] cclbuffer size is too small");
79 : }
80 0 : return maxCountPerLoop;
81 : }
82 :
83 0 : HcclResult CollBroadcastMidCountFor91093Executor::RunLevel2ByNHR(const OpParam ¶m, ExecMem &execMem,
84 : SubCommInfo &level1CommInfo, SubCommInfo &level2CommInfo) const
85 : {
86 0 : HCCL_CONFIG_INFO(HCCL_ALG, "[MidCountBroadcast][RunLevel2ByNHR] userRank[%u] starts.", topoAttr_.userRank);
87 :
88 0 : u32 unitSize = 0;
89 0 : const HcclDataType dataType = param.GetDataType();
90 0 : CHK_RET(SalGetDataTypeSize(dataType, unitSize));
91 :
92 0 : std::unique_ptr<AlgTemplateBase> tempAlg = AlgTemplateRegistry::Instance().GetAlgTemplate(
93 0 : TemplateType::TEMPLATE_BROADCAST_NHR_ONESHOT, dispatcher_);
94 0 : HCCL_CONFIG_INFO(HCCL_ALG, "[%s] Run TEMPLATE_BROADCAST_NHR_ONESHOT in COMM_LEVEL2", __func__);
95 0 : CHK_SMART_PTR_NULL(tempAlg);
96 :
97 : // 获取root
98 0 : u32 rootRank = param.root / level1CommInfo.localRankSize;
99 0 : CHK_RET(tempAlg->Prepare(execMem.inputMem, execMem.inputMem, execMem.inputMem, execMem.count,
100 : param.DataDes.dataType, param.stream, HCCL_REDUCE_RESERVED, rootRank));
101 :
102 0 : CHK_RET(RunTemplate(tempAlg, level2CommInfo));
103 :
104 0 : HCCL_INFO("MidCountBroadcast run success in level2");
105 0 : return HCCL_SUCCESS;
106 0 : }
107 :
108 0 : HcclResult CollBroadcastMidCountFor91093Executor::RunLevel1ByNHR(const OpParam ¶m, ExecMem &execMem,
109 : SubCommInfo &level1CommInfo, SubCommInfo &level2CommInfo)
110 : {
111 0 : HCCL_CONFIG_INFO(HCCL_ALG, "[MidCountBroadcast][RunLevel1ByNHR] userRank[%u] starts.", topoAttr_.userRank);
112 0 : u32 unitSize = 0;
113 0 : const HcclDataType dataType = param.GetDataType();
114 0 : CHK_RET(SalGetDataTypeSize(dataType, unitSize));
115 :
116 0 : std::unique_ptr<AlgTemplateBase> tempAlg = AlgTemplateRegistry::Instance().GetAlgTemplate(
117 0 : TemplateType::TEMPLATE_BROADCAST_NHR_ONESHOT, dispatcher_);
118 0 : HCCL_CONFIG_INFO(HCCL_ALG, "[%s] Run TEMPLATE_BROADCAST_NHR_ONESHOT in COMM_COMBINE_L1", __func__);
119 0 : CHK_SMART_PTR_NULL(tempAlg);
120 :
121 : // 获取root
122 0 : u32 rootRank = 0;
123 0 : CHK_RET(GetRankByUserRank(COMM_COMBINE_L1, COMM_INDEX_0, param.root, rootRank));
124 0 : CHK_RET(tempAlg->Prepare(execMem.inputMem, execMem.inputMem, execMem.inputMem, execMem.count,
125 : param.DataDes.dataType, param.stream, HCCL_REDUCE_RESERVED, rootRank));
126 :
127 0 : CHK_RET(RunTemplate(tempAlg, level1CommInfo));
128 :
129 0 : HCCL_INFO("MidCountBroadcast run success in level1");
130 0 : return HCCL_SUCCESS;
131 0 : }
132 :
133 0 : HcclResult CollBroadcastMidCountFor91093Executor::KernelRun(const OpParam ¶m, ExecMem &execMem)
134 : {
135 0 : HCCL_CONFIG_INFO(HCCL_ALG, "[%s] The MidCountFor91093Executor starts", __func__);
136 :
137 0 : SubCommInfo level1CommInfo;
138 0 : SubCommInfo level2CommInfo;
139 0 : CHK_RET(CheckCommSize(COMM_COMBINE_L1, COMM_INDEX_0 + 1));
140 0 : CHK_RET(CheckCommSize(COMM_LEVEL2, COMM_INDEX_0 + 1));
141 0 : level1CommInfo = GetSubCommInfo(COMM_COMBINE_L1, COMM_INDEX_0);
142 0 : level2CommInfo = GetSubCommInfo(COMM_LEVEL2, COMM_INDEX_0);
143 :
144 0 : u32 unitSize = 0;
145 0 : const HcclDataType dataType = param.GetDataType();
146 0 : CHK_RET(SalGetDataTypeSize(dataType, unitSize));
147 :
148 0 : u32 rootSideIndex = param.root / level1CommInfo.localRankSize;
149 0 : u32 rankSideIndex = topoAttr_.userRank / level1CommInfo.localRankSize;
150 0 : if (rootSideIndex == rankSideIndex) {
151 0 : CHK_RET(RunLevel1ByNHR(param, execMem, level1CommInfo, level2CommInfo));
152 : }
153 0 : CHK_RET(RunLevel2ByNHR(param, execMem, level1CommInfo, level2CommInfo));
154 :
155 0 : HCCL_INFO("MidCountBroadcast run success.");
156 0 : return HCCL_SUCCESS;
157 0 : }
158 :
159 0 : HcclResult CollBroadcastMidCountFor91093Executor::RunLoopInner(OpParam ¶m, ExecMem &execMem)
160 : {
161 0 : u32 unitSize = SIZE_TABLE[param.DataDes.dataType];
162 0 : u64 totalSize = unitSize * param.DataDes.count;
163 0 : bool isRootRank = param.root == topoAttr_.realUserRank ? true : false;
164 0 : u64 curSize = execMem.count * unitSize; // 单位:字节
165 0 : auto inCCLbufferSize = execMem.inputMem.size();
166 :
167 0 : HCCL_DEBUG("[CollBroadcastMidCountFor91093Executor][RunLoopInner]inputMem[%p], outputMem[%p]" \
168 : "intputPtr[%p], curCount[%llu], curSize[%llu]",
169 : execMem.inputMem.ptr(), execMem.outputMem.ptr(), execMem.inputPtr, execMem.count, curSize);
170 0 : CHK_PRT_RET((execMem.count == 0),
171 : HCCL_ERROR("[CollBroadcastMidCountFor91093Executor][RunLoop]In OP_BASE curCount is zero."), HCCL_E_PARA);
172 :
173 0 : bool hugeData = (inCCLbufferSize / topoAttr_.deviceNumPerAggregation > RDMA_SEND_MAX_SIZE) ||
174 : (curSize > SDMA_SEND_MAX_SIZE);
175 0 : bool isSmallData = IsBroadcastSmallData(curSize, totalSize);
176 0 : u64 sliceNum = 0;
177 0 : CHK_RET(GetSliceNum(curSize, isSmallData, sliceNum));
178 0 : CopyPattern copy = DMAReduceFlag_? CopyPattern::ZCOPY : CopyPattern::BCOPY;
179 0 : auto meta = HcclOpMetaInfo::GetOneForBroadcast(isRootRank, param.root, hugeData, isSmallData, sliceNum, copy);
180 0 : CHK_RET(InitTask(dispatcher_, param.stream, meta.isEnableCache, meta.GetCacheKey()));
181 :
182 : // 执行
183 : HcclResult ret;
184 : // 如果使用in CCL buffer,需要将user buffer in中的结果拷贝到CCL buffer in
185 0 : DeviceMem inCommMem = execMem.inputMem.range(0, curSize);
186 0 : DeviceMem inMem(execMem.inputPtr, curSize);
187 0 : if (topoAttr_.userRank == param.root) {
188 0 : CHK_RET(HcclD2DMemcpyAsync(dispatcher_, inCommMem, inMem, param.stream));
189 : }
190 :
191 0 : ret = KernelRun(param, execMem);
192 0 : if (topoAttr_.realUserRank != param.root) {
193 0 : CHK_RET(HcclD2DMemcpyAsync(dispatcher_, inMem, inCommMem, param.stream));
194 : }
195 :
196 0 : CHK_PRT_RET(ret != HCCL_SUCCESS,
197 : HCCL_ERROR("[CollBroadcastMidCountFor91093Executor][RunLoop]errNo[0x%016llx]kernel run error, tag[%s], " \
198 : "inputMem ptr[%p], count[%llu], dataType[%d]",
199 : HCCL_ERROR_CODE(ret), param.tag.c_str(), execMem.inputMem.ptr(),
200 : execMem.count, param.DataDes.dataType), ret);
201 :
202 0 : CHK_RET(LaunchTaskExtend(dispatcher_, param.stream, algResResp_->slaveStreams));
203 0 : return ret;
204 0 : }
205 :
206 0 : HcclResult CollBroadcastMidCountFor91093Executor::Orchestrate(OpParam& param, AlgResourceResponse& algRes)
207 : {
208 0 : tag_ = param.tag;
209 0 : algResResp_ = &algRes;
210 : /* ------------执行算法-------------- */
211 0 : HcclUs startut = TIME_NOW();
212 :
213 : // 图模式和单卡场景下不需要Loop
214 0 : ExecMem execMem;
215 0 : execMem.count = param.DataDes.count;
216 0 : execMem.inputPtr = param.inputPtr;
217 0 : execMem.outputPtr = param.inputPtr;
218 0 : HCCL_INFO("Orchestrate UserRank[%u], devicePhyId[%u], inputPtr[%p], outputPtr[%p], root[%u]",
219 : topoAttr_.userRank, topoAttr_.devicePhyId, param.inputPtr, param.outputPtr, param.root);
220 :
221 0 : u32 unitSize = SIZE_TABLE[param.DataDes.dataType];
222 0 : u8 *curInputPtr = static_cast<u8 *>(param.inputPtr);
223 0 : CHK_PTR_NULL(curInputPtr);
224 0 : u64 maxCountPerLoop = CalcLoopMaxCount(algRes.cclInputMem.size(), unitSize);
225 0 : HCCL_DEBUG("[CollBroadcastMidCountFor91093Executor][RunLoop]tag[%s], userRankSize is [%u], maxCountPerLoop is [%llu].",
226 : param.tag.c_str(), topoAttr_.userRankSize, maxCountPerLoop);
227 :
228 0 : u64 totalCount = param.DataDes.count;
229 0 : for (u64 countLeft = totalCount, curCount = 0, inputOffset = 0;
230 0 : countLeft > 0; countLeft -= curCount) {
231 0 : curInputPtr += inputOffset;
232 : // 判断剩余数据量对应的output size是否大于中转output size
233 0 : curCount = (countLeft > maxCountPerLoop) ? maxCountPerLoop : countLeft;
234 0 : u64 curSize = curCount * unitSize; // 单位:字节
235 :
236 0 : ExecMem execMem;
237 0 : execMem.count = curCount;
238 0 : execMem.inputMem = algRes.cclOutputMem;
239 0 : execMem.outputMem = algRes.cclOutputMem;// ccl buffer 均只使用out buffer
240 0 : execMem.inputPtr = curInputPtr;
241 0 : HCCL_DEBUG("[CollBroadcastMidCountFor91093Executor] RunLoop tag[%s], inputOffset[%llu], " \
242 : "curInputPtr[%p], sendCount[%llu], sendSize[%llu], dataType[%s], realUserRank[%u]",
243 : param.tag.c_str(), inputOffset, curInputPtr, curCount, curSize,
244 : GetDataTypeEnumStr(param.DataDes.dataType).c_str(), topoAttr_.realUserRank);
245 :
246 0 : CHK_RET(RunLoopInner(param, execMem));
247 :
248 0 : inputOffset = curSize;
249 0 : }
250 :
251 0 : HCCL_INFO("tag[%s], Broadcast executor orchestrate success, take time [%lld]us.",
252 : param.tag.c_str(), DURATION_US(TIME_NOW() - startut));
253 0 : return HCCL_SUCCESS;
254 0 : }
255 :
256 : REGISTER_EXEC("BroadcastMidCountFor91093Executor", BroadcastMidCountFor91093, CollBroadcastMidCountFor91093Executor);
257 : } // namespace hccl
|