LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_reduce - reduce_recursive_hd.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 2.7 % 261 7
Test Date: 2026-08-18 17:47:01 Functions: 36.4 % 11 4

            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 "alg_template_register.h"
      12              : #include "reduce_recursive_hd.h"
      13              : 
      14              : namespace hccl {
      15            1 : ReduceRecursiveHalvingDoubling::ReduceRecursiveHalvingDoubling(const HcclDispatcher dispatcher)
      16            1 :     : RecursiveHalvingDoublingBase(dispatcher)
      17            1 : {}
      18              : 
      19            2 : ReduceRecursiveHalvingDoubling::~ReduceRecursiveHalvingDoubling() {}
      20              : 
      21            1 : HcclResult ReduceRecursiveHalvingDoubling::Prepare(u64 reduceAttrBitMap, [[maybe_unused]] HcomCollOpInfo* opInfo)
      22              : {
      23            1 :     reduceAttr = reduceAttrBitMap;
      24            1 :     return HCCL_SUCCESS;
      25              : }
      26              : 
      27              : // 算法的主入口
      28            0 : HcclResult ReduceRecursiveHalvingDoubling::RunAsync(
      29              :     const u32 rank, const u32 rankSize, const std::vector<std::shared_ptr<Transport>>& links)
      30              : {
      31            0 :     CHK_SMART_PTR_NULL(dispatcher_);
      32            0 :     CHK_PTR_NULL(stream_.ptr());
      33            0 :     if (!outputMem_ || !inputMem_) {
      34            0 :         HCCL_ERROR("[ReduceRecursiveHalvingDoubling][RunAsync]rank[%u] run_async inputmem or outputmem is null", rank);
      35            0 :         return HCCL_E_PTR;
      36              :     }
      37            0 :     HCCL_INFO(
      38              :         "ReduceRecursiveHalvingDoubling run: rank[%u] root[%u] totalrank[%u] inputMem[%p] outputMem[%p]"
      39              :         "count[%llu]",
      40              :         rank, root_, rankSize, inputMem_.ptr(), outputMem_.ptr(), count_);
      41              : 
      42            0 :     HcclResult ret = HCCL_SUCCESS;
      43              : 
      44            0 :     if (rankSize == 1) {
      45            0 :         if (inputMem_ != outputMem_) {
      46            0 :             ret = HcclD2DMemcpyAsync(dispatcher_, outputMem_, inputMem_, stream_);
      47              :         }
      48            0 :         return ret;
      49              :     }
      50              : 
      51            0 :     senderInfo_.reset(new (std::nothrow) Sender(dataType_, reductionOp_, reduceAttr));
      52            0 :     CHK_SMART_PTR_NULL(senderInfo_);
      53              : 
      54            0 :     reducerInfo_.reset(new (std::nothrow) Reducer(dataType_, reductionOp_, reduceAttr));
      55            0 :     CHK_SMART_PTR_NULL(reducerInfo_);
      56              : 
      57            0 :     bool bRetSize = (links.size() < rankSize);
      58            0 :     CHK_PRT_RET(
      59              :         bRetSize,
      60              :         HCCL_ERROR("[ReduceRecursiveHalvingDoubling][RunAsync]rank[%u] linksize[%llu] is error", rank, links.size()),
      61              :         HCCL_E_INTERNAL);
      62              : 
      63            0 :     CHK_RET(CalcPartOneSizeAndBlockSize(rankSize));
      64              : 
      65            0 :     u32 bytesPerData = DataUnitSize(dataType_);
      66            0 :     u64 dataBytes = count_ * bytesPerData;
      67            0 :     CHK_RET(CalculateSlices(dataBytes));
      68              : 
      69              :     // 结果完成需要放在input
      70            0 :     CHK_RET(ReduceInPartOne(rank, links));
      71              : 
      72              :     // 此步骤完成后,结果放在ouput中
      73            0 :     CHK_RET(ReduceScatterInBlock(rank, rankSize, links));
      74              : 
      75              :     // 使用output进行gather
      76            0 :     CHK_RET(GatherInBlock(rank, rankSize, links));
      77              : 
      78            0 :     HCCL_INFO("ReduceRecursiveHalvingDoubling rank[%u] finished", rank);
      79            0 :     return HCCL_SUCCESS;
      80              : }
      81              : 
      82            0 : HcclResult ReduceRecursiveHalvingDoubling::ReduceInPartOne(u32 rank, const std::vector<LINK>& links)
      83              : {
      84            0 :     HCCL_INFO("rank[%u] part1Size_[%u] root[%u]", rank, part1Size_, root_);
      85              : 
      86            0 :     if (rank >= part1Size_) { // rank在第二部分,不参与ReduceInPartOne
      87            0 :         HCCL_INFO("rank[%u] not in part1, don't need reduce", rank);
      88            0 :         return HCCL_SUCCESS;
      89              :     }
      90              :     // root在第二部分,需要选取第一部分偶数rank接收,以0作为判断标准,否则在第一部分,与root奇偶性相同rank接收
      91            0 :     u32 rootFlag = (root_ >= part1Size_) ? 0 : root_;
      92              : 
      93            0 :     if (rank % 2 == rootFlag % 2) { // 1.从下一个rank接收数据到output,2. reduce到本rank的input
      94            0 :         u32 peerRank = (rank % 2) == 0 ? (rank + 1) : (rank - 1);
      95            0 :         HCCL_INFO(
      96              :             "rank[%u] outputMem receives from PeerRank[%u] inputMem, Offset[%llu], Size[%llu]", rank, peerRank,
      97              :             baseOffset_, outputMem_.size());
      98              : 
      99            0 :         if (peerRank < links.size()) {
     100            0 :             CHK_SMART_PTR_NULL(links[peerRank]);
     101              : 
     102            0 :             HcclResult ret = links[peerRank]->TxAck(stream_);
     103            0 :             CHK_PRT_RET(
     104              :                 ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]tx ack to peerrank[%u] failed", peerRank), ret);
     105            0 :             ret = links[peerRank]->RxAck(stream_);
     106            0 :             CHK_PRT_RET(
     107              :                 ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]rx ack from peerank[%u] failed", peerRank), ret);
     108              : 
     109              :             //  接收数据到本端的 output
     110            0 :             HCCL_DEBUG("send mem[%p] size[%llu] to peerank[%u]", outputMem_.ptr(), outputMem_.size(), peerRank);
     111            0 :             ret = links[peerRank]->TxAsync(UserMemType::INPUT_MEM, baseOffset_, outputMem_.ptr(), 0, stream_);
     112            0 :             CHK_PRT_RET(
     113              :                 ret != HCCL_SUCCESS,
     114              :                 HCCL_ERROR(
     115              :                     "[Reduce][InPartOneToEven]TxAsync: tx async size[%llu] "
     116              :                     "failed",
     117              :                     0),
     118              :                 ret);
     119            0 :             CHK_RET(reducerInfo_->run(
     120              :                 dispatcher_, links[peerRank], baseOffset_, outputMem_, inputMem_, outputMem_, stream_));
     121            0 :             ret = links[peerRank]->RxWaitDone(stream_);
     122            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]RxWaitDone failed"), ret);
     123              :         }
     124            0 :     } else if ((rank % 2) != (rootFlag % 2)) { //  向上一个rank的output发数据 2
     125            0 :         u32 peerRank = (rank % 2 == 0) ? (rank + 1) : (rank - 1);
     126              : 
     127            0 :         if (peerRank < links.size()) {
     128            0 :             CHK_SMART_PTR_NULL(links[peerRank]);
     129            0 :             HcclResult ret = links[peerRank]->TxAck(stream_);
     130            0 :             CHK_PRT_RET(
     131              :                 ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]tx ack to peerrank[%u] failed", peerRank), ret);
     132            0 :             ret = links[peerRank]->RxAck(stream_);
     133            0 :             CHK_PRT_RET(
     134              :                 ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]rx ack from peerank[%u] failed", peerRank), ret);
     135              :             //  发送到对端的output
     136            0 :             HCCL_DEBUG(
     137              :                 "rank[%u] sends inputMem[%p] to PeerRank[%u] Offset[%llu], Size[%llu]", rank, inputMem_.ptr(), peerRank,
     138              :                 baseOffset_, inputMem_.size());
     139            0 :             ret = senderInfo_->run(links[peerRank], baseOffset_, inputMem_, stream_);
     140            0 :             CHK_PRT_RET(
     141              :                 ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]tx sync to peerank[%u] failed", peerRank), ret);
     142            0 :             ret = links[peerRank]->RxAsync(UserMemType::OUTPUT_MEM, baseOffset_, inputMem_.ptr(), 0, stream_);
     143            0 :             CHK_PRT_RET(
     144              :                 ret != HCCL_SUCCESS,
     145              :                 HCCL_ERROR("[AlgTemplateBase][ExecuteTxSync]ExecuteTxSync: rx async size[%llu] failed", 0), ret);
     146            0 :             ret = links[peerRank]->DataReceivedAck(stream_);
     147            0 :             CHK_PRT_RET(
     148              :                 ret != HCCL_SUCCESS,
     149              :                 HCCL_ERROR("[AlgTemplateBase][ExecuteTxSync]ExecuteTxSync: data received ack failed"), ret);
     150            0 :             ret = links[peerRank]->TxWaitDone(stream_);
     151            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]TxWaitDone failed"), ret);
     152              :         }
     153              :     }
     154            0 :     return HCCL_SUCCESS;
     155              : }
     156              : 
     157            0 : HcclResult ReduceRecursiveHalvingDoubling::ReduceScatterInBlock(u32 rank, u32 rankSize, const std::vector<LINK>& links)
     158              : {
     159            0 :     u32 rankInBlock = 0;
     160              : 
     161            0 :     u32 rootFlag = (root_ >= part1Size_) ? 0 : root_;
     162            0 :     HCCL_DEBUG(
     163              :         "[ReduceRecursiveHalvingDoubling][ReduceScatterInBlock]rootFlag is %u, rankInBlock is %u", rootFlag,
     164              :         rankInBlock);
     165              :     // 需要根据root判断,让root节点必然参加reducescatter,在第一部分的rank若与root奇偶性不同,直接返回
     166            0 :     if (rank < part1Size_ && (rank % 2) != (rootFlag % 2)) { // 模2判断奇偶性,本rank处于第一部分,奇偶性与root不同
     167            0 :         return HCCL_SUCCESS;
     168            0 :     } else if (rank < part1Size_) { // 模2判断奇偶性,本rank 处于第一部分,奇偶性与root相同
     169            0 :         rankInBlock = rank / 2;     // 除2计算block内的rank值
     170              :     } else {                        // 本rank不属于第一部分
     171            0 :         rankInBlock = rank - part1Size_ / 2; // 除2计算block内的part1的范围
     172              :     }
     173              :     // 直接调用block的reducscatterhd算法
     174              :     std::unique_ptr<AlgTemplateBase> executor
     175            0 :         = AlgTemplateRegistry::Instance().GetAlgTemplate(TemplateType::TEMPLATE_REDUCESCATTER_HD, dispatcher_);
     176            0 :     CHK_SMART_PTR_NULL(executor);
     177            0 :     CHK_RET(executor->Prepare(
     178              :         inputMem_, outputMem_, outputMem_, count_, dataType_, stream_, reductionOp_, -1, slices_, baseOffset_,
     179              :         blockSize_, reduceAttr, UserMemType::INPUT_MEM, UserMemType::OUTPUT_MEM));
     180              : 
     181            0 :     CHK_RET(executor->RegisterProfiler(profilerInput_.planeID, profilerInput_.stage, profilerInput_.step, stream_));
     182              : 
     183              :     // 重新建立reducscatterscatter需要的链接
     184            0 :     std::vector<LINK> subLinks;
     185            0 :     CHK_RET(BuildRootSubLinks(links, subLinks, rankSize));
     186              : 
     187            0 :     CHK_PRT_RET(
     188              :         subLinks.size() == 0,
     189              :         HCCL_ERROR(
     190              :             "[ReduceRecursiveHalvingDoubling][ReduceScatterInBlock]rank[%u] "
     191              :             "BuildSubLinks failed",
     192              :             rank),
     193              :         HCCL_E_PARA);
     194              : 
     195            0 :     CHK_RET(executor->RunAsync(rankInBlock, blockSize_, subLinks));
     196              : 
     197            0 :     return HCCL_SUCCESS;
     198            0 : }
     199              : 
     200            0 : HcclResult ReduceRecursiveHalvingDoubling::CalculateStepSlices(
     201              :     const std::vector<Slice>& inputSlices, u32 stepNum, u32 rank, SliceType type, std::vector<Slice>& sliceOut)
     202              : {
     203            0 :     std::vector<Slice> slice(stepNum);
     204              : 
     205            0 :     for (u32 step = 0; step < stepNum; step++) {
     206              :         // all-gather操作, halving_bitmask从低往高循环, size倍增
     207            0 :         u32 halvingBitmask = (1 << step);
     208            0 :         u32 peerRank = rank ^ halvingBitmask;
     209              : 
     210              :         // 计算tx_slice/rx_slice
     211            0 :         u32 sliceId = (type == SliceType::SLICE_TYPE_RX) ? (peerRank & (~(halvingBitmask - 1))) :
     212            0 :                                                            (rank & (~(halvingBitmask - 1)));
     213              : 
     214            0 :         slice[step].offset = inputSlices[sliceId].offset;
     215            0 :         CHK_RET(Sum(inputSlices, sliceId, halvingBitmask, slice[step].size));
     216              : 
     217            0 :         HCCL_DEBUG(
     218              :             "Slice Info: rank[%u], slices[%u].offset=%llu, slices[%u].size=%llu", rank, step, slice[step].offset, step,
     219              :             slice[step].size);
     220              :     }
     221              : 
     222            0 :     sliceOut = std::move(slice);
     223            0 :     return HCCL_SUCCESS;
     224            0 : }
     225            0 : HcclResult ReduceRecursiveHalvingDoubling::BuildRootSubLinks(
     226              :     const std::vector<LINK>& links, std::vector<LINK>& subLinks, u32 rankSize) const
     227              : {
     228            0 :     std::vector<LINK>::const_iterator iter = links.begin();
     229            0 :     subLinks.resize(blockSize_);
     230            0 :     u32 rootFlag = (root_ >= part1Size_) ? 0 : root_;
     231            0 :     for (u32 i = 0; i < rankSize; i++) {
     232            0 :         if (i < part1Size_
     233            0 :             && (i % 2)
     234            0 :                    != rootFlag % 2) { // 模2与root模2比较代表当前rank在part1的内且与root奇偶性不同,不参与block内的建链
     235            0 :             continue;
     236            0 :         } else if (i < part1Size_) {
     237            0 :             std::vector<LINK>::const_iterator niter = std::next(iter, i);
     238            0 :             if (niter != links.end()) {
     239            0 :                 subLinks[i / 2] = *niter; // 除2计算出在block内的rank号
     240              :             }
     241              :         } else {
     242            0 :             std::vector<LINK>::const_iterator niter = std::next(iter, i);
     243            0 :             if (niter != links.end()) {
     244            0 :                 subLinks[i - part1Size_ / 2] = *niter; // rank在part2中,用原始rank减part1除2,计算出在block内的rank号
     245              :             }
     246              :         }
     247              :     }
     248              : 
     249            0 :     return HCCL_SUCCESS;
     250              : }
     251              : // 结果在output中,直接使用oupt进行数据收发
     252            0 : HcclResult ReduceRecursiveHalvingDoubling::GatherInBlock(u32 rank, u32 rankSize, const std::vector<LINK>& links)
     253              : {
     254            0 :     u32 rankInBlock = 0;
     255              : 
     256            0 :     u32 rootFlag = (root_ >= part1Size_) ? 0 : root_;
     257            0 :     if (rank < part1Size_
     258            0 :         && (rank % 2) != (rootFlag % 2)) { // 模2判断奇偶性,本rank 处于第一部分,并且和root rank奇偶不同
     259            0 :         return HCCL_SUCCESS;
     260            0 :     } else if (rank < part1Size_) { // 模2判断奇偶性,本rank 处于第一部分,并且奇偶性和root相同
     261            0 :         rankInBlock = rank / 2;     // 在block内的rank为实际rank除以2
     262              :     } else {
     263            0 :         rankInBlock = rank - part1Size_ / 2; // 除2计算block内的part1的范围
     264              :     }
     265            0 :     u32 rootInBlock = (root_ > part1Size_) ? (root_ - part1Size_ / 2) : (root_ / 2);
     266              :     // 重新建立gather需要的链接
     267            0 :     std::vector<LINK> subLinks;
     268              : 
     269            0 :     CHK_RET(BuildRootSubLinks(links, subLinks, rankSize));
     270              : 
     271            0 :     CHK_PRT_RET(
     272              :         subLinks.size() == 0, HCCL_ERROR("[Gather][InBlock]rank[%u] build sub links failed", rank), HCCL_E_PARA);
     273              : 
     274            0 :     CHK_RET(CalculateStepSlices(slices_, round_, rankInBlock, SliceType::SLICE_TYPE_TX, txSlices_));
     275              : 
     276            0 :     CHK_RET(CalculateStepSlices(slices_, round_, rankInBlock, SliceType::SLICE_TYPE_RX, rxSlices_));
     277              : 
     278            0 :     for (u32 step = 0; step < round_; step++) {
     279            0 :         u32 peerRankBitmask = (1 << step);
     280            0 :         u32 opBitmask = peerRankBitmask - 1; // 判断本轮是否进行收发
     281              :         // 断rank是否和root在同一轮次接收发送的block内,第一轮为total,第二轮为1/2,第三轮为1/4....
     282            0 :         if ((step != 0) && ((rankInBlock & opBitmask) != (rootInBlock & opBitmask))) {
     283            0 :             return HCCL_SUCCESS; // rank在本轮同root不在一个操作块内,不操作,直接返回
     284              :         }
     285            0 :         u32 peerRank = rankInBlock ^ peerRankBitmask;
     286            0 :         CHK_SMART_PTR_NULL(subLinks[peerRank]);
     287              :         // 再次判断是否和root在同一1/2,1/4,用来判断数据是收还是发
     288            0 :         if ((rankInBlock & peerRankBitmask) == (rootInBlock & peerRankBitmask)) {
     289            0 :             DeviceMem rxMem = outputMem_.range(rxSlices_[step].offset, rxSlices_[step].size);
     290            0 :             HcclResult ret = subLinks[peerRank]->TxAck(stream_);
     291            0 :             CHK_PRT_RET(
     292              :                 ret != HCCL_SUCCESS,
     293              :                 HCCL_ERROR("[Gather][InBlock]rank[%u] tx ack from peerank[%u] failed", rank, peerRank), ret);
     294            0 :             ret = subLinks[peerRank]->RxAck(stream_);
     295            0 :             CHK_PRT_RET(
     296              :                 ret != HCCL_SUCCESS,
     297              :                 HCCL_ERROR("[Gather][InBlock]rank[%u] rx ack from peerank[%u] failed", rank, peerRank), ret);
     298              : 
     299              :             // 等待对端可以接收数据
     300            0 :             HCCL_DEBUG(
     301              :                 "rank[%u] outputMem[%p] receive from PeerRank[%u] outputMem, Offset[%llu], "
     302              :                 "Size[%llu]",
     303              :                 rank, outputMem_.ptr(), peerRank, baseOffset_ + rxSlices_[step].offset, rxSlices_[step].size);
     304              : 
     305            0 :             ret = ExecuteRxSync(
     306            0 :                 subLinks[peerRank], UserMemType::OUTPUT_MEM, baseOffset_ + rxSlices_[step].offset, rxMem.ptr(),
     307            0 :                 rxSlices_[step].size, stream_);
     308            0 :             CHK_PRT_RET(
     309              :                 ret != HCCL_SUCCESS,
     310              :                 HCCL_ERROR("[Gather][InBlock]rank[%u] rx sync from PeerRank[%u] failed", rank, peerRank), ret);
     311            0 :             ret = subLinks[peerRank]->RxWaitDone(stream_);
     312            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]RxWaitDone failed"), ret);
     313            0 :         } else {
     314            0 :             DeviceMem txMem = outputMem_.range(txSlices_[step].offset, txSlices_[step].size);
     315            0 :             HcclResult ret = subLinks[peerRank]->TxAck(stream_);
     316            0 :             CHK_PRT_RET(
     317              :                 ret != HCCL_SUCCESS,
     318              :                 HCCL_ERROR("[Gather][InBlock]rank[%u] tx ack from peerank[%u] failed", rank, peerRank), ret);
     319            0 :             ret = subLinks[peerRank]->RxAck(stream_);
     320            0 :             CHK_PRT_RET(
     321              :                 ret != HCCL_SUCCESS,
     322              :                 HCCL_ERROR("[Gather][InBlock]rank[%u] rx ack from peerank[%u] failed", rank, peerRank), ret);
     323            0 :             HCCL_DEBUG(
     324              :                 "rank[%u] outputMem[%p] sends to peerrank[%u] outputmem, offset[%llu], "
     325              :                 "size[%llu]",
     326              :                 rank, outputMem_.ptr(), peerRank, baseOffset_ + txSlices_[step].offset, txSlices_[step].size);
     327            0 :             ret = ExecuteTxSync(
     328            0 :                 subLinks[peerRank], UserMemType::OUTPUT_MEM, baseOffset_ + txSlices_[step].offset, txMem.ptr(),
     329            0 :                 txSlices_[step].size, stream_);
     330            0 :             CHK_PRT_RET(
     331              :                 ret != HCCL_SUCCESS,
     332              :                 HCCL_ERROR("[Gather][InBlock]rank[%u] tx sync to PeerRank[%u] failed", rank, peerRank), ret);
     333            0 :             ret = subLinks[peerRank]->TxWaitDone(stream_);
     334            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]TxWaitDone failed"), ret);
     335            0 :         }
     336              :     }
     337              : 
     338            0 :     return HCCL_SUCCESS;
     339            0 : }
     340            0 : HcclResult ReduceRecursiveHalvingDoubling::GetNslbAdjInfo(
     341              :     const u32 rank, const u32 rankSize, const std::vector<LINK>& links, AdjInfo& nslbAdjInfo)
     342              : {
     343            0 :     u32 nslbRound = 0;
     344            0 :     u32 base = 1;
     345            0 :     const u32 minExponent = 1;
     346            0 :     while ((base << nslbRound) <= rankSize) {
     347            0 :         nslbRound++;
     348              :     }
     349            0 :     if (nslbRound >= minExponent) {
     350            0 :         nslbRound = nslbRound - minExponent;
     351              :     }
     352            0 :     u32 nslbBlockSize = base << nslbRound;
     353              :     // 获取第一部分:rank数减block数乘2
     354            0 :     u32 nslbPart1Size = (rankSize - nslbBlockSize) * NSLBDP_REDUCE_MOLD2;
     355              :     // 2的次幂场景下处理流程
     356            0 :     if (nslbPart1Size == 0) {
     357            0 :         u32 stepNum = 0;
     358            0 :         while ((rankSize >> (stepNum + 1)) != 0) {
     359            0 :             stepNum++;
     360              :         }
     361            0 :         HCCL_DEBUG("[ReduceRecursiveHalvingDoubling]GetNslbAdjInfo start");
     362            0 :         for (u32 step = 0; step < stepNum; step++) {
     363            0 :             u32 peerRankBitmask = 1 << (stepNum - step - 1);
     364            0 :             u32 peerRank = rank ^ peerRankBitmask;
     365            0 :             NslbDpAdjInfo adjInfoStep = {};
     366            0 :             u32 remoteuserRank = links[peerRank]->GetRemoteRank();
     367            0 :             HCCL_DEBUG("[ReduceRecursiveHalvingDoubling]now step %u, remoteuserRank is %u", step, remoteuserRank);
     368            0 :             adjInfoStep.dstLocalRankId = remoteuserRank;
     369            0 :             adjInfoStep.phaseId = step + 1;
     370            0 :             adjInfoStep.rev = 0;
     371            0 :             nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     372              :         }
     373            0 :         nslbAdjInfo.dstRankNum = stepNum;
     374            0 :         return HCCL_SUCCESS;
     375              :     }
     376              :     // 非2的次幂场景下,被合并部分的奇数rank处理流程
     377            0 :     if (rank < nslbPart1Size && rank % NSLBDP_REDUCE_MOLD2 == 1) {
     378            0 :         u32 peerRank = rank - 1;
     379            0 :         if (peerRank < links.size()) {
     380            0 :             NslbDpAdjInfo adjInfoStep = {};
     381            0 :             adjInfoStep.dstLocalRankId = links[peerRank]->GetRemoteRank();
     382            0 :             adjInfoStep.phaseId = 1;
     383            0 :             adjInfoStep.rev = 0;
     384            0 :             HCCL_INFO("AllGatherHDR-nslb: peerRank[%u]", peerRank);
     385            0 :             nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     386            0 :             nslbAdjInfo.dstRankNum = 1;
     387              :         }
     388            0 :         return HCCL_SUCCESS;
     389              :     }
     390              :     // 针对合并后映射成2的次幂场景处理
     391            0 :     u32 rankInBlock = 0;
     392            0 :     if (rank < nslbPart1Size && (rank % NSLBDP_REDUCE_MOLD2) == 0) {
     393            0 :         rankInBlock = rank / NSLBDP_REDUCE_MOLD2; // 直接除以2即为本rank的在block内的排序
     394              :     } else {
     395              :         rankInBlock
     396            0 :             = rank - nslbPart1Size / NSLBDP_REDUCE_MOLD2; // 通过rank减去part1除2的大小即不处于第一部分的block内rank号
     397              :     }
     398            0 :     std::vector<LINK> subLinks;
     399            0 :     std::vector<LINK>::const_iterator iter = links.begin();
     400            0 :     subLinks.resize(nslbBlockSize);
     401            0 :     for (u32 i = 0; i < rankSize; i++) {
     402            0 :         if (i < nslbPart1Size
     403            0 :             && (i % NSLBDP_REDUCE_MOLD2) == 1) { // 模2余1代表当前rank在part1的奇数位置上,不参与block内的建链
     404            0 :             continue;
     405            0 :         } else if (i < nslbPart1Size && (i % NSLBDP_REDUCE_MOLD2) == 0) { // 模2余0代表当前rank在part1的偶数位置上
     406            0 :             std::vector<LINK>::const_iterator niter = std::next(iter, i);
     407            0 :             if (niter != links.end()) {
     408            0 :                 subLinks[i / NSLBDP_REDUCE_MOLD2] = *niter;
     409              :             }
     410            0 :         } else {
     411            0 :             std::vector<LINK>::const_iterator niter = std::next(iter, i);
     412            0 :             if (niter != links.end()) {
     413            0 :                 subLinks[i - nslbPart1Size / NSLBDP_REDUCE_MOLD2] = *niter;
     414              :             }
     415              :         }
     416              :     }
     417            0 :     u32 stepNum = 0;
     418            0 :     while ((rankSize >> (stepNum + 1)) != 0) {
     419            0 :         stepNum++;
     420              :     }
     421              :     // 映射完成后针对以新的通信域进行邻接表获取
     422            0 :     for (u32 step = 0; step < stepNum; step++) {
     423            0 :         u32 peerRankBitmask = 1 << (stepNum - step - 1);
     424            0 :         u32 peerRank = rankInBlock ^ peerRankBitmask;
     425            0 :         if (subLinks[peerRank] == nullptr) {
     426            0 :             continue;
     427              :         }
     428            0 :         NslbDpAdjInfo adjInfoStep = {};
     429            0 :         u32 remoteuserRank = subLinks[peerRank]->GetRemoteRank();
     430            0 :         adjInfoStep.dstLocalRankId = remoteuserRank;
     431            0 :         adjInfoStep.phaseId = step + 1;
     432            0 :         adjInfoStep.rev = 0;
     433            0 :         nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     434              :     }
     435            0 :     nslbAdjInfo.dstRankNum = stepNum;
     436              : 
     437            0 :     if (nslbAdjInfo.nsAdjInfo.size() == 0) {
     438            0 :         return HCCL_SUCCESS;
     439              :     }
     440              :     // 上面处理完成后,紧接着处理合并部分的偶数rank同步到奇数rank增加phaseId
     441            0 :     if (rank < nslbPart1Size && rank % NSLBDP_REDUCE_MOLD2 == 0) {
     442            0 :         u32 peerRank = rank + 1;
     443            0 :         uint16_t phaseSize = nslbAdjInfo.nsAdjInfo.size();
     444            0 :         if (peerRank < links.size()) {
     445            0 :             NslbDpAdjInfo adjInfoStep = {};
     446            0 :             adjInfoStep.dstLocalRankId = links[peerRank]->GetRemoteRank();
     447            0 :             adjInfoStep.phaseId = nslbAdjInfo.nsAdjInfo[phaseSize - 1].phaseId + 1;
     448            0 :             adjInfoStep.rev = 0;
     449            0 :             HCCL_INFO("Scatter-nslb: peerRank[%u]", peerRank);
     450            0 :             nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     451            0 :             nslbAdjInfo.dstRankNum = nslbAdjInfo.nsAdjInfo.size();
     452              :         }
     453            0 :         return HCCL_SUCCESS;
     454              :     }
     455            0 :     return HCCL_SUCCESS;
     456            0 : }
     457              : REGISTER_TEMPLATE(TemplateType::TEMPLATE_REDUCE_RECURSIVE_HALVING_DOUBLING, ReduceRecursiveHalvingDoubling);
     458              : } // namespace hccl
        

Generated by: LCOV version 2.0-1