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 "bcast_recursive_halvingdoubling.h"
12 : #include <cmath>
13 : #include "alg_template_register.h"
14 :
15 : namespace hccl {
16 0 : BcastRecursiveHalvingDoubling::BcastRecursiveHalvingDoubling(const HcclDispatcher dispatcher)
17 : : RecursiveHalvingDoublingBase(dispatcher),
18 0 : hasData_(false)
19 0 : {}
20 :
21 0 : BcastRecursiveHalvingDoubling::~BcastRecursiveHalvingDoubling() {}
22 :
23 : // recursiveHD broadcast算法主入口
24 0 : HcclResult BcastRecursiveHalvingDoubling::RunAsync(
25 : const u32 rank, const u32 rankSize, const std::vector<std::shared_ptr<Transport>>& links)
26 : {
27 0 : CHK_SMART_PTR_NULL(dispatcher_);
28 0 : CHK_PTR_NULL(stream_.ptr());
29 0 : CHK_PRT_RET(
30 : !inputMem_, HCCL_ERROR("[BcastRecursiveHalvingDoubling][RunAsync]rank[%u] run_async inputmem is null", rank),
31 : HCCL_E_PTR);
32 :
33 0 : HCCL_INFO(
34 : "BcastRecursiveHalvingDoubling run: rank[%u] rootRank[%u] totalrank[%u]"
35 : " inputMem[%p] outputMem[%p] count[%llu]",
36 : rank, root_, rankSize, inputMem_.ptr(), outputMem_.ptr(), count_);
37 :
38 0 : if (rankSize == 1) {
39 0 : return HCCL_SUCCESS;
40 : }
41 :
42 0 : if (rank == root_) {
43 0 : hasData_ = true;
44 : }
45 :
46 0 : CHK_PRT_RET(
47 : links.size() < rankSize,
48 : HCCL_ERROR(
49 : "[BcastRecursiveHalvingDoubling][RunAsync]rank[%u] linksize[%llu] is less than rankSize[%u]", rank,
50 : links.size(), rankSize),
51 : HCCL_E_INTERNAL);
52 :
53 : // 计算recursive算法第一部分相关参数
54 0 : HcclResult ret = CalcPartOneSizeAndBlockSize(rankSize);
55 0 : CHK_PRT_RET(
56 : ret != HCCL_SUCCESS,
57 : HCCL_ERROR(
58 : "[BcastRecursiveHalvingDoubling][RunAsync]rank[%u] Calculate "
59 : "Par1Size[%u] And BlockSize[%u] Failed! rankSize[%u]",
60 : rank, part1Size_, blockSize_, rankSize),
61 : ret);
62 :
63 0 : HCCL_DEBUG("rank[%u] BroadcastInBlock... blockSize_[%u], part1Size_[%u]", rank, blockSize_, part1Size_);
64 :
65 : // 先进行block内部的bcast
66 0 : CHK_RET(BroadcastInBlock(rank, links));
67 :
68 0 : HCCL_DEBUG("rank[%u] BroadcastOutOfBlock", rank);
69 :
70 0 : if (rank < part1Size_ && (rank % 2 == 0)) { // 模2是否为0判断rank奇偶性
71 0 : CHK_RET(EvenNumberRankProcess(rank, links));
72 0 : } else if (rank < part1Size_ && (rank % 2 == 1)) { // 模2是否为1判断rank奇偶性
73 0 : CHK_RET(OddNumberRankProcess(rank, links));
74 : }
75 :
76 0 : HCCL_INFO("BcastRecursiveHalvingDoubling finished: rank[%u] finished", rank);
77 0 : return HCCL_SUCCESS;
78 : }
79 :
80 : HcclResult
81 0 : BcastRecursiveHalvingDoubling::ReceiveData(const u32 destRank, const std::vector<std::shared_ptr<Transport>>& links)
82 : {
83 0 : if (destRank < links.size()) {
84 0 : if (links[destRank] == nullptr) {
85 0 : HCCL_ERROR(
86 : "[Receive][Data]errNo[0x%016llx] links[destRank[%u]] ptr is NULL, return HCCL_E_PTR",
87 : HCCL_ERROR_CODE(HCCL_E_PTR), destRank);
88 0 : return HCCL_E_PTR;
89 : }
90 0 : HcclResult ret = links[destRank]->TxAck(stream_);
91 0 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Receive][Data]tx ack to dstrank[%u] failed", destRank), ret);
92 0 : ret = links[destRank]->RxAck(stream_);
93 0 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Receive][Data]rx ack to dstrank[%u] failed", destRank), ret);
94 :
95 0 : u64 dataBytes = count_ * DataUnitSize(dataType_);
96 0 : DeviceMem rcvMem = inputMem_.range(baseOffset_, dataBytes);
97 0 : HCCL_DEBUG(
98 : "rx async from dstrank[%u] with rcvMem[%p] inputmem's offset[%llu] size[%llu]", destRank, rcvMem.ptr(),
99 : baseOffset_, dataBytes);
100 :
101 0 : ret = ExecuteRxSync(links[destRank], UserMemType::INPUT_MEM, baseOffset_, rcvMem.ptr(), dataBytes, stream_);
102 0 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Receive][Data]rx sync from rank[%u] failed", destRank), ret);
103 0 : }
104 0 : return HCCL_SUCCESS;
105 : }
106 :
107 : HcclResult
108 0 : BcastRecursiveHalvingDoubling::SendData(const u32 destRank, const std::vector<std::shared_ptr<Transport>>& links)
109 : {
110 0 : if (destRank < links.size()) {
111 0 : if (links[destRank] == nullptr) {
112 0 : HCCL_ERROR(
113 : "[Send][Data]errNo[0x%016llx] links[destRank[%u]] ptr is NULL, return HCCL_E_PTR",
114 : HCCL_ERROR_CODE(HCCL_E_PTR), destRank);
115 0 : return HCCL_E_PTR;
116 : }
117 0 : HcclResult ret = links[destRank]->TxAck(stream_);
118 0 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Send][Data]tx ack from rank[%u] failed", destRank), ret);
119 0 : ret = links[destRank]->RxAck(stream_);
120 0 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Send][Data]rx ack from rank[%u] failed", destRank), ret);
121 :
122 0 : u64 dataBytes = count_ * DataUnitSize(dataType_);
123 0 : DeviceMem sendMem = inputMem_.range(baseOffset_, dataBytes);
124 0 : HCCL_DEBUG(
125 : "tx async to dstrank[%u] from sendMem[%p] inputmem's offset[%llu] size[%llu]", destRank, sendMem.ptr(),
126 : baseOffset_, dataBytes);
127 :
128 0 : ret = ExecuteTxSync(links[destRank], UserMemType::INPUT_MEM, baseOffset_, sendMem.ptr(), dataBytes, stream_);
129 0 : CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Send][Data]tx sync to rank[%u] failed", destRank), ret);
130 0 : }
131 0 : return HCCL_SUCCESS;
132 : }
133 :
134 0 : u32 BcastRecursiveHalvingDoubling::GetRankIndexReal(const u32 rankInBlock) const
135 : {
136 0 : u32 res = 0;
137 : /* 如果根节点在第一部分的偶数位置或其他部分 */
138 0 : if ((root_ < part1Size_ && (root_ % 2) == 0) || root_ >= part1Size_) { // 模2判断奇偶性
139 0 : if (rankInBlock < part1Size_ / 2) { // 除2计算block内part1的rank范围
140 0 : res = rankInBlock * 2; // 乘2计算block内part1的rank范围
141 0 : return res;
142 : } else {
143 0 : res = part1Size_ / 2 + rankInBlock; // 除2加rankInBlock计算真实的rank值
144 0 : return res;
145 : }
146 : } else {
147 0 : if (rankInBlock < part1Size_ / 2) { // 除2计算block内part1的rank范围
148 0 : res = rankInBlock * 2 + 1; // 乘2加1计算计算真实的rank值
149 0 : return res;
150 : } else {
151 0 : res = part1Size_ / 2 + rankInBlock; // 除2加rankInBlock计算真实的rank值
152 0 : return res;
153 : }
154 : }
155 : }
156 :
157 0 : u32 BcastRecursiveHalvingDoubling::GetRankIndexInBlock(const u32 rank) const
158 : {
159 : // root在第一部分,并且root是偶数rank,或者root在第二部分
160 0 : if ((root_ < part1Size_ && (root_ % 2) == 0) || root_ >= part1Size_) { // 模2判断奇偶性
161 : // rank在第一部分,并且本rank是偶数rank,除以2就为在block内的index
162 0 : if (rank < part1Size_ && rank % 2 == 0) { // 模2判断奇偶性
163 0 : return rank / 2; // 除2计算block内rank值
164 0 : } else if (rank < part1Size_ && rank % 2 == 1) { // 模2判断奇偶性,奇数的话不在block内
165 0 : return INVALID_VALUE_RANKID;
166 : } else {
167 0 : return rank - part1Size_ / 2; // 除2计算block内part1的rank范围
168 : }
169 : } else { // root在第一部分属于奇数rank
170 0 : if (rank < part1Size_ && rank % 2 == 0) { // 模2判断奇偶性,偶数rank不在block内
171 0 : return INVALID_VALUE_RANKID;
172 0 : } else if (rank < part1Size_ && rank % 2 == 1) { // 模2判断奇偶性,为奇计算block内rank号
173 0 : return (rank - 1) / 2; // 通过减1再除2得到block内rank号
174 : } else {
175 0 : return rank - part1Size_ / 2; // 除2计算block内part1的rank范围
176 : }
177 : }
178 : }
179 :
180 : HcclResult
181 0 : BcastRecursiveHalvingDoubling::BroadcastInBlock(const u32 rank, const std::vector<std::shared_ptr<Transport>>& links)
182 : {
183 0 : u32 rankInBlock = GetRankIndexInBlock(rank);
184 0 : if (rankInBlock == INVALID_VALUE_RANKID) { // 非block内的节点,不做操作
185 0 : return HCCL_SUCCESS;
186 : }
187 :
188 0 : u32 rootInBlock = GetRankIndexInBlock(root_);
189 0 : for (u32 i = 0; i < round_; i++) {
190 0 : u32 peerRankBitmask = 1 << (round_ - i - 1); // 进入此条件,round必然不小于1
191 0 : u32 peerRankInBlock = rankInBlock ^ peerRankBitmask;
192 0 : u32 andOprand = (1 << (round_ - i - 1)) - 1;
193 0 : u32 peerRankReal = GetRankIndexReal(peerRankInBlock);
194 :
195 0 : HcclResult ret = HCCL_SUCCESS;
196 : // 本rank在第round轮需要接收数据
197 0 : if (((rankInBlock & andOprand) == (rootInBlock & andOprand)) && (rank != root_) && !hasData_) {
198 0 : HCCL_DEBUG(
199 : "rank[%u] receive memsize[%llu] from rank[%u] in round[%u]", rank, DataUnitSize(dataType_) * count_,
200 : peerRankReal, i);
201 0 : ret = ReceiveData(peerRankReal, links);
202 0 : CHK_PRT_RET(
203 : ret != HCCL_SUCCESS,
204 : HCCL_ERROR(
205 : "[BcastRecursiveHalvingDoubling][BroadcastInBlock]rank[%u] "
206 : "Receive Data from rank[%u] failed.",
207 : rank, peerRankReal),
208 : ret);
209 0 : hasData_ = true;
210 0 : if (peerRankReal < links.size()) {
211 0 : ret = links[peerRankReal]->RxWaitDone(stream_);
212 0 : CHK_PRT_RET(
213 : ret != HCCL_SUCCESS,
214 : HCCL_ERROR("[BcastRecursiveHalvingDoubling][BroadcastInBlock]RxWaitDone failed"), ret);
215 : }
216 0 : continue;
217 : }
218 :
219 : // 需要向目的rank发送数据,前提是收到数据后(root 节点每轮都发)
220 0 : if (hasData_) {
221 0 : HCCL_DEBUG(
222 : "rank[%u] send mem[%llu] to rank[%u] in round:%u", rank, DataUnitSize(dataType_) * count_, peerRankReal,
223 : i);
224 0 : ret = SendData(peerRankReal, links);
225 0 : CHK_PRT_RET(
226 : ret != HCCL_SUCCESS,
227 : HCCL_ERROR(
228 : "[BcastRecursiveHalvingDoubling][BroadcastInBlock]rank[%u] Send "
229 : "Data to rank[%u] failed.",
230 : rank, peerRankReal),
231 : ret);
232 : }
233 0 : if (peerRankReal < links.size()) {
234 0 : ret = links[peerRankReal]->TxWaitDone(stream_);
235 0 : CHK_PRT_RET(
236 : ret != HCCL_SUCCESS, HCCL_ERROR("[BcastRecursiveHalvingDoubling][BroadcastInBlock]TxWaitDone failed"),
237 : ret);
238 : }
239 : }
240 0 : return HCCL_SUCCESS;
241 : }
242 :
243 0 : HcclResult BcastRecursiveHalvingDoubling::EvenNumberRankProcess(
244 : const u32 rank, const std::vector<std::shared_ptr<Transport>>& links)
245 : {
246 : HcclResult ret;
247 0 : if (root_ % 2 == 0 || root_ >= part1Size_) { // 模2是否为0判断rank_奇偶性
248 0 : HCCL_DEBUG(
249 : "rank[%u] stream[%p] send memsize[%llu] to rank[%u]", rank, stream_.ptr(), DataUnitSize(dataType_) * count_,
250 : rank + 1);
251 : // 该rank需要向第一部分的后续奇数rank发送数据
252 0 : ret = SendData(rank + 1, links);
253 0 : CHK_PRT_RET(
254 : ret != HCCL_SUCCESS,
255 : HCCL_ERROR(
256 : "[BcastRecursiveHalvingDoubling][RunAsync]rank[%u] stream[%p] Send data to "
257 : "Rank[%u] failed",
258 : rank, stream_.ptr(), rank + 1),
259 : ret);
260 0 : if (rank + 1 < links.size()) {
261 0 : ret = links[rank + 1]->TxWaitDone(stream_);
262 0 : CHK_PRT_RET(
263 : ret != HCCL_SUCCESS, HCCL_ERROR("[BcastRecursiveHalvingDoubling][RunAsync]TxWaitDone failed"), ret);
264 : }
265 : } else {
266 0 : HCCL_DEBUG(
267 : "rank[%u] stream[%p] receive memsize[%llu] from rank[%u]", rank, stream_.ptr(),
268 : DataUnitSize(dataType_) * count_, rank + 1);
269 :
270 : // root为奇数,本rank为偶数,需要从邻接的奇数rank接收数据
271 0 : ret = ReceiveData(rank + 1, links);
272 0 : CHK_PRT_RET(
273 : ret != HCCL_SUCCESS,
274 : HCCL_ERROR(
275 : "[BcastRecursiveHalvingDoubling][RunAsync]rank[%u] stream[%p] Receive data "
276 : "from Rank[%u] failed",
277 : rank, stream_.ptr(), rank + 1),
278 : ret);
279 0 : if (rank + 1 < links.size()) {
280 0 : ret = links[rank + 1]->RxWaitDone(stream_);
281 0 : CHK_PRT_RET(
282 : ret != HCCL_SUCCESS, HCCL_ERROR("[BcastRecursiveHalvingDoubling][RunAsync]RxWaitDone failed"), ret);
283 : }
284 : }
285 0 : return HCCL_SUCCESS;
286 : }
287 :
288 0 : HcclResult BcastRecursiveHalvingDoubling::OddNumberRankProcess(
289 : const u32 rank, const std::vector<std::shared_ptr<Transport>>& links)
290 : {
291 : HcclResult ret;
292 0 : if (root_ % 2 == 0 || root_ >= part1Size_) { // 模2是否为0判断rank_奇偶性
293 0 : HCCL_DEBUG(
294 : "rank[%u] stream[%p] receive memsize[%llu] from rank[%u]", rank, stream_.ptr(),
295 : DataUnitSize(dataType_) * count_, rank - 1);
296 :
297 : // root是偶数节点,rank从前面邻接的偶数节点接收数据
298 0 : ret = ReceiveData(rank - 1, links);
299 0 : CHK_PRT_RET(
300 : ret != HCCL_SUCCESS,
301 : HCCL_ERROR(
302 : "[BcastRecursiveHalvingDoubling][RunAsync]rank[%u] stream[%p] Receive data "
303 : "from Rank[%u] failed",
304 : rank, stream_.ptr(), rank - 1),
305 : ret);
306 0 : if (rank - 1 < links.size()) {
307 0 : ret = links[rank - 1]->RxWaitDone(stream_);
308 0 : CHK_PRT_RET(
309 : ret != HCCL_SUCCESS, HCCL_ERROR("[BcastRecursiveHalvingDoubling][RunAsync]RxWaitDone failed"), ret);
310 : }
311 : } else {
312 0 : HCCL_DEBUG(
313 : "rank[%u] stream[%p] send memsize[%llu] to rank[%u]", rank, stream_.ptr(), DataUnitSize(dataType_) * count_,
314 : rank - 1);
315 0 : ret = SendData(rank - 1, links);
316 0 : CHK_PRT_RET(
317 : ret != HCCL_SUCCESS,
318 : HCCL_ERROR(
319 : "[BcastRecursiveHalvingDoubling][RunAsync]rank[%u] stream[%p] Send data to "
320 : "Rank[%u] failed",
321 : rank, stream_.ptr(), rank - 1),
322 : ret);
323 0 : if (rank - 1 < links.size()) {
324 0 : ret = links[rank - 1]->TxWaitDone(stream_);
325 0 : CHK_PRT_RET(
326 : ret != HCCL_SUCCESS, HCCL_ERROR("[BcastRecursiveHalvingDoubling][RunAsync]TxWaitDone failed"), ret);
327 : }
328 : }
329 0 : return HCCL_SUCCESS;
330 : }
331 0 : HcclResult BcastRecursiveHalvingDoubling::GetNslbAdjInfo(
332 : const u32 rank, const u32 rankSize, const std::vector<LINK>& links, AdjInfo& nslbAdjInfo)
333 : {
334 0 : u32 nslbRound = 0;
335 0 : u32 base = 1;
336 0 : const u32 minExponent = 1;
337 0 : while ((base << nslbRound) <= rankSize) {
338 0 : nslbRound++;
339 : }
340 0 : if (nslbRound >= minExponent) {
341 0 : nslbRound = nslbRound - minExponent;
342 : }
343 0 : u32 nslbBlockSize = base << nslbRound;
344 : // 获取第一部分:rank数减block数乘2
345 0 : u32 nslbPart1Size = (rankSize - nslbBlockSize) * NSLBDP_BCAST_MOLD2;
346 :
347 0 : u32 rankInBlock = 0;
348 0 : if (rank < nslbPart1Size && (rank % NSLBDP_BCAST_MOLD2) == 0) {
349 0 : rankInBlock = rank / NSLBDP_BCAST_MOLD2; // 直接除以2即为本rank的在block内的排序
350 : } else {
351 : rankInBlock
352 0 : = rank - nslbPart1Size / NSLBDP_BCAST_MOLD2; // 通过rank减去part1除2的大小即不处于第一部分的block内rank号
353 : }
354 : // 2的次幂场景下处理流程
355 0 : if (nslbPart1Size == 0) {
356 0 : u32 stepNum = 0;
357 0 : while ((rankSize >> (stepNum + 1)) != 0) {
358 0 : stepNum++;
359 : }
360 0 : bool begin = false;
361 0 : if (rank == 0) {
362 0 : begin = true;
363 : }
364 0 : for (u32 step = 0; step < stepNum; step++) {
365 0 : u32 peerRankBitmask = 1 << (stepNum - step - 1); // 进入此条件,round必然不小于1
366 0 : u32 peerRankInBlock = rankInBlock ^ peerRankBitmask;
367 0 : u32 andOprand = (1 << (stepNum - step - 1)) - 1;
368 :
369 : // 本rank在第round轮需要接收数据
370 0 : if (((rankInBlock & andOprand) == 0) && (rank != 0) && !begin) {
371 0 : begin = true;
372 0 : continue;
373 : }
374 0 : if (begin) {
375 0 : NslbDpAdjInfo adjInfoStep = {};
376 0 : u32 remoteuserRank = links[peerRankInBlock]->GetRemoteRank();
377 0 : adjInfoStep.dstLocalRankId = remoteuserRank;
378 0 : adjInfoStep.phaseId = step + 1;
379 0 : adjInfoStep.rev = 0;
380 0 : nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
381 : }
382 : }
383 0 : nslbAdjInfo.dstRankNum = nslbAdjInfo.nsAdjInfo.size();
384 0 : return HCCL_SUCCESS;
385 : }
386 : // 非2的次幂场景下,被合并部分的奇数rank处理流程
387 0 : if (rank < nslbPart1Size && rank % NSLBDP_BCAST_MOLD2 == 1) {
388 0 : u32 peerRank = rank - 1;
389 0 : if (peerRank < links.size()) {
390 0 : NslbDpAdjInfo adjInfoStep = {};
391 0 : adjInfoStep.dstLocalRankId = links[peerRank]->GetRemoteRank();
392 0 : adjInfoStep.phaseId = 1;
393 0 : adjInfoStep.rev = 0;
394 0 : HCCL_INFO("AllGatherHDR-nslb: peerRank[%u]", peerRank);
395 0 : nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
396 0 : nslbAdjInfo.dstRankNum = 1;
397 : }
398 0 : return HCCL_SUCCESS;
399 : }
400 :
401 0 : std::vector<LINK> subLinks;
402 0 : std::vector<LINK>::const_iterator iter = links.begin();
403 0 : subLinks.resize(nslbBlockSize);
404 0 : for (u32 i = 0; i < rankSize; i++) {
405 0 : if (i < nslbPart1Size
406 0 : && (i % NSLBDP_BCAST_MOLD2) == 1) { // 模2余1代表当前rank在part1的奇数位置上,不参与block内的建链
407 0 : continue;
408 0 : } else if (i < nslbPart1Size && (i % NSLBDP_BCAST_MOLD2) == 0) { // 模2余0代表当前rank在part1的偶数位置上
409 0 : std::vector<LINK>::const_iterator niter = std::next(iter, i);
410 0 : if (niter != links.end()) {
411 0 : subLinks[i / NSLBDP_BCAST_MOLD2] = *niter;
412 : }
413 0 : } else {
414 0 : std::vector<LINK>::const_iterator niter = std::next(iter, i);
415 0 : if (niter != links.end()) {
416 0 : subLinks[i - nslbPart1Size / NSLBDP_BCAST_MOLD2] = *niter;
417 : }
418 : }
419 : }
420 0 : u32 stepNum = 0;
421 0 : while ((nslbBlockSize >> (stepNum + 1)) != 0) {
422 0 : stepNum++;
423 : }
424 : // 映射完成后针对以新的通信域进行邻接表获取
425 0 : u32 begin = 1;
426 0 : for (u32 step = 0; step < stepNum; step++) {
427 0 : u32 peerRankBitmask = 1 << (stepNum - step - 1);
428 0 : u32 peerRank = rankInBlock ^ peerRankBitmask;
429 0 : NslbDpAdjInfo adjInfoStep = {};
430 0 : if (subLinks[peerRank] == nullptr) {
431 0 : continue;
432 : }
433 0 : u32 remoteuserRank = subLinks[peerRank]->GetRemoteRank();
434 0 : adjInfoStep.dstLocalRankId = remoteuserRank;
435 0 : adjInfoStep.phaseId = step + begin + 1;
436 0 : adjInfoStep.rev = 0;
437 0 : nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
438 : }
439 0 : nslbAdjInfo.dstRankNum = nslbAdjInfo.nsAdjInfo.size();
440 0 : HCCL_DEBUG("[BcastRecursiveHalvingDoubling]dstRankNum is %u", nslbAdjInfo.dstRankNum);
441 :
442 0 : if (nslbAdjInfo.nsAdjInfo.size() == 0) {
443 0 : return HCCL_SUCCESS;
444 : }
445 : // 上面处理完成后,紧接着处理合并部分的偶数rank同步到奇数rank增加phaseId
446 0 : if (rank < nslbPart1Size && rank % NSLBDP_BCAST_MOLD2 == 0) {
447 0 : u32 peerRank = rank + 1;
448 0 : uint16_t phaseSize = nslbAdjInfo.nsAdjInfo.size();
449 0 : if (peerRank < links.size()) {
450 0 : NslbDpAdjInfo adjInfoStep = {};
451 0 : adjInfoStep.dstLocalRankId = links[peerRank]->GetRemoteRank();
452 0 : adjInfoStep.phaseId = nslbAdjInfo.nsAdjInfo[phaseSize - 1].phaseId + 1;
453 0 : adjInfoStep.rev = 0;
454 0 : HCCL_INFO("Scatter-nslb: peerRank[%u]", peerRank);
455 0 : nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
456 0 : nslbAdjInfo.dstRankNum = nslbAdjInfo.nsAdjInfo.size();
457 : }
458 0 : return HCCL_SUCCESS;
459 : }
460 0 : return HCCL_SUCCESS;
461 0 : }
462 : REGISTER_TEMPLATE(TemplateType::TEMPLATE_BROADCAST_RECURSIVE_HD, BcastRecursiveHalvingDoubling);
463 : } // namespace hccl
|