LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_all_reduce - all_reduce_recursive_hd.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 2.6 % 265 7
Test Date: 2026-08-18 17:47:01 Functions: 28.6 % 14 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 "all_reduce_recursive_hd.h"
      13              : 
      14              : namespace hccl {
      15            1 : AllReduceRecursiveHalvingDoubling::AllReduceRecursiveHalvingDoubling(const HcclDispatcher dispatcher)
      16            1 :     : RecursiveHalvingDoublingBase(dispatcher)
      17            1 : {}
      18              : 
      19            2 : AllReduceRecursiveHalvingDoubling::~AllReduceRecursiveHalvingDoubling() {}
      20              : 
      21            1 : HcclResult AllReduceRecursiveHalvingDoubling::Prepare(u64 reduceAttrBitMap, [[maybe_unused]] HcomCollOpInfo* opInfo)
      22              : {
      23            1 :     reduceAttr = reduceAttrBitMap;
      24            1 :     return HCCL_SUCCESS;
      25              : }
      26              : 
      27              : // 算法的主入口
      28              : HcclResult
      29            0 : AllReduceRecursiveHalvingDoubling::RunAsync(const u32 rank, const u32 rankSize, const std::vector<LINK>& links)
      30              : {
      31            0 :     CHK_RET(PrepareRunAsync(rank, rankSize, links));
      32            0 :     CHK_PRT_RET(
      33              :         rankSize == 1,
      34              :         HCCL_INFO(
      35              :             "[AllReduceRecursiveHalvingDoubling][RunAsync]"
      36              :             "rankSize[%u], do nothing.",
      37              :             rankSize),
      38              :         HCCL_SUCCESS);
      39              : 
      40            0 :     CHK_RET(ReduceInPartOne(rank, links));
      41              : 
      42            0 :     CHK_RET(ReduceScatterInBlock(rank, rankSize, links));
      43              : 
      44            0 :     CHK_RET(AllGatherInBlock(rank, rankSize, links));
      45              : 
      46            0 :     CHK_RET(GatherInPartOne(rank, links));
      47              : 
      48            0 :     HCCL_INFO("AllReduceRecursiveHalvingDoubling finished: rank[%u] finished", rank);
      49            0 :     return HCCL_SUCCESS;
      50              : }
      51              : 
      52            0 : HcclResult AllReduceRecursiveHalvingDoubling::RunAsyncStaged(
      53              :     const u32 rank, const u32 rankSize, const std::vector<LINK>& links, RunStage stage)
      54              : {
      55            0 :     CHK_PRT_RET(
      56              :         rankSize == 1 && stage != RunStage::RUN_PREPARE,
      57              :         HCCL_INFO(
      58              :             "[AllReduceRecursiveHalvingDoubling][RunAsyncStaged] rankSize[%u], stage[%d], do nothing.", rankSize,
      59              :             stage),
      60              :         HCCL_SUCCESS);
      61            0 :     switch (stage) {
      62            0 :         case RunStage::RUN_PREPARE:
      63            0 :             CHK_RET(PrepareRunAsync(rank, rankSize, links));
      64            0 :             break;
      65            0 :         case RunStage::RUN_REDUCE_SCATTER:
      66              :             // 先执行reducescater
      67            0 :             CHK_RET(ReduceInPartOne(rank, links));
      68            0 :             CHK_RET(ReduceScatterInBlock(rank, rankSize, links));
      69            0 :             break;
      70            0 :         case RunStage::RUN_ALLGATHER:
      71              :             // 再执行allgather
      72            0 :             CHK_RET(AllGatherInBlock(rank, rankSize, links));
      73            0 :             CHK_RET(GatherInPartOne(rank, links));
      74            0 :             break;
      75            0 :         default:
      76            0 :             HCCL_ERROR("[AllReduceRecursiveHalvingDoubling][RunAsyncStaged]stage[%d]is not support", stage);
      77            0 :             return HCCL_E_NOT_SUPPORT;
      78              :     }
      79            0 :     HCCL_INFO(
      80              :         "AllReduceRecursiveHalvingDoubling RunAsyncStaged stage[%d] finished: rank[%u] ranksize[%u]", stage, rank,
      81              :         rankSize);
      82            0 :     return HCCL_SUCCESS;
      83              : }
      84              : 
      85              : HcclResult
      86            0 : AllReduceRecursiveHalvingDoubling::PrepareRunAsync(const u32 rank, const u32 rankSize, const std::vector<LINK>& links)
      87              : {
      88            0 :     CHK_SMART_PTR_NULL(dispatcher_);
      89            0 :     CHK_PTR_NULL(stream_.ptr());
      90            0 :     if (!outputMem_ || !inputMem_) {
      91            0 :         HCCL_ERROR(
      92              :             "[AllReduceRecursiveHalvingDoubling][RunAsync]rank[%u] run_async inputmem or outputmem is null", rank);
      93            0 :         return HCCL_E_PTR;
      94              :     }
      95            0 :     HCCL_INFO(
      96              :         "AllReduceRecursiveHalvingDoubling run: rank[%u] totalrank[%u] inputMem[%p] outputMem[%p] count[%llu]", rank,
      97              :         rankSize, inputMem_.ptr(), outputMem_.ptr(), count_);
      98              : 
      99            0 :     HcclResult ret = HCCL_SUCCESS;
     100              : 
     101            0 :     if (rankSize == 1) {
     102            0 :         if (inputMem_ != outputMem_) {
     103            0 :             ret = HcclD2DMemcpyAsync(dispatcher_, outputMem_, inputMem_, stream_);
     104              :         }
     105            0 :         return ret;
     106              :     }
     107              : 
     108              :     // 创建reducer & sender
     109            0 :     senderInfo_.reset(new (std::nothrow) Sender(dataType_, reductionOp_, reduceAttr));
     110            0 :     CHK_SMART_PTR_NULL(senderInfo_);
     111              : 
     112            0 :     reducerInfo_.reset(new (std::nothrow) Reducer(dataType_, reductionOp_, reduceAttr));
     113            0 :     CHK_SMART_PTR_NULL(reducerInfo_);
     114              : 
     115            0 :     bool bRetSize = (links.size() < rankSize);
     116            0 :     CHK_PRT_RET(
     117              :         bRetSize,
     118              :         HCCL_ERROR(
     119              :             "[AllReduceRecursiveHalvingDoubling][RunAsync]rank[%u] linksize[%llu] is "
     120              :             "error",
     121              :             rank, links.size()),
     122              :         HCCL_E_INTERNAL);
     123              : 
     124            0 :     CHK_RET(CalcPartOneSizeAndBlockSize(rankSize));
     125              : 
     126            0 :     u32 bytesPerData = SIZE_TABLE[dataType_];
     127            0 :     u64 dataBytes = count_ * bytesPerData;
     128            0 :     CHK_RET(CalculateSlices(dataBytes));
     129            0 :     HCCL_INFO("AllReduceRecursiveHalvingDoubling PrepareRunAsync finished: rank[%u] finished", rank);
     130            0 :     return HCCL_SUCCESS;
     131              : }
     132              : 
     133            0 : HcclResult AllReduceRecursiveHalvingDoubling::ReduceInPartOne(u32 rank, const std::vector<LINK>& links)
     134              : {
     135              :     // 本rank属于第一部分,并且是2的整数倍
     136            0 :     if (rank < part1Size_ && rank % 2 == 0) { // 1.从下一个rank接收数据到output,2. reduce到本rank的input
     137            0 :         u32 peerRank = rank + 1;
     138            0 :         HCCL_DEBUG(
     139              :             "rank[%u] outputMem receives from PeerRank[%u] inputMem, Offset[%llu], Size[%llu]", rank, peerRank,
     140              :             baseOffset_, outputMem_.size());
     141              : 
     142            0 :         if (peerRank < links.size()) {
     143            0 :             const LINK& link = links[peerRank];
     144            0 :             CHK_SMART_PTR_NULL(link);
     145              : 
     146            0 :             HcclResult ret = link->TxAck(stream_);
     147            0 :             CHK_PRT_RET(
     148              :                 ret != HCCL_SUCCESS,
     149              :                 HCCL_ERROR("[Reduce][InPartOneToEven]rank[%u] tx ack from peerank[%u] failed", rank, peerRank), ret);
     150            0 :             ret = link->RxAck(stream_);
     151            0 :             CHK_PRT_RET(
     152              :                 ret != HCCL_SUCCESS,
     153              :                 HCCL_ERROR("[Reduce][InPartOneToEven]rank[%u] rx ack from peerank[%u] failed", rank, peerRank), ret);
     154              :             //  接收数据到本端的 output
     155            0 :             HCCL_DEBUG("send mem[%p] size[%llu] to peerank[%u]", outputMem_.ptr(), outputMem_.size(), peerRank);
     156            0 :             ret = link->TxAsync(UserMemType::INPUT_MEM, baseOffset_, outputMem_.ptr(), 0, stream_);
     157            0 :             CHK_PRT_RET(
     158              :                 ret != HCCL_SUCCESS,
     159              :                 HCCL_ERROR(
     160              :                     "[Reduce][InPartOneToEven]TxAsync: tx async size[%llu] "
     161              :                     "failed",
     162              :                     0),
     163              :                 ret);
     164            0 :             CHK_RET(reducerInfo_->run(dispatcher_, link, baseOffset_, inputMem_, inputMem_, outputMem_, stream_));
     165            0 :             ret = link->RxWaitDone(stream_);
     166            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]RxWaitDone failed"), ret);
     167              :         }
     168            0 :     } else if (rank < part1Size_ && rank % 2 == 1) { //  向上一个rank的output发数据 2
     169            0 :         u32 peerRank = rank - 1;
     170              : 
     171            0 :         if (peerRank < links.size()) {
     172            0 :             const LINK& link = links[peerRank];
     173            0 :             CHK_SMART_PTR_NULL(link);
     174            0 :             HcclResult ret = link->TxAck(stream_);
     175            0 :             CHK_PRT_RET(
     176              :                 ret != HCCL_SUCCESS,
     177              :                 HCCL_ERROR("[Reduce][InPartOneToEven]rank[%u] tx ack from peerank[%u] failed", rank, peerRank), ret);
     178            0 :             ret = link->RxAck(stream_);
     179            0 :             CHK_PRT_RET(
     180              :                 ret != HCCL_SUCCESS,
     181              :                 HCCL_ERROR("[Reduce][InPartOneToEven]rank[%u] rx ack from peerank[%u] failed", rank, peerRank), ret);
     182              :             //  发送到对端的output
     183            0 :             HCCL_DEBUG(
     184              :                 "rank[%u] sends inputMem[%p] to PeerRank[%u] Offset[%llu], Size[%llu]", rank, inputMem_.ptr(), peerRank,
     185              :                 baseOffset_, inputMem_.size());
     186            0 :             ret = senderInfo_->run(link, baseOffset_, inputMem_, stream_);
     187            0 :             CHK_PRT_RET(
     188              :                 ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]tx sync to peerank[%u] failed", peerRank), ret);
     189            0 :             ret = link->RxAsync(UserMemType::OUTPUT_MEM, baseOffset_, inputMem_.ptr(), 0, stream_);
     190            0 :             CHK_PRT_RET(
     191              :                 ret != HCCL_SUCCESS,
     192              :                 HCCL_ERROR("[AlgTemplateBase][ExecuteTxSync]ExecuteTxSync: rx async size[%llu] failed", 0), ret);
     193            0 :             ret = link->DataReceivedAck(stream_);
     194            0 :             CHK_PRT_RET(
     195              :                 ret != HCCL_SUCCESS,
     196              :                 HCCL_ERROR("[AlgTemplateBase][ExecuteTxSync]ExecuteTxSync: data received ack failed"), ret);
     197            0 :             ret = link->TxWaitDone(stream_);
     198            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]TxWaitDone failed"), ret);
     199              :         }
     200              :     }
     201              : 
     202            0 :     return HCCL_SUCCESS;
     203              : }
     204              : 
     205              : HcclResult
     206            0 : AllReduceRecursiveHalvingDoubling::ReduceScatterInBlock(u32 rank, u32 rankSize, const std::vector<LINK>& links)
     207              : {
     208            0 :     u32 rankInBlock = 0;
     209            0 :     if (rank < part1Size_ && (rank % 2) == 1) { // 模2判断奇偶性,本rank处于第一部分,并且为奇数rank
     210            0 :         return HCCL_SUCCESS;
     211            0 :     } else if (rank < part1Size_ && (rank % 2) == 0) { // 模2判断奇偶性,本rank 处于第一部分,并且为偶数rank
     212            0 :         rankInBlock = rank / 2;                        // 除2计算block内的rank值
     213              :     } else {                                           // 本rank不属于第一部分
     214            0 :         rankInBlock = rank - part1Size_ / 2;           // 除2计算block内的part1的范围
     215              :     }
     216              :     // 直接调用block的reducscatterhd算法
     217              :     std::unique_ptr<AlgTemplateBase> tempAlg
     218            0 :         = AlgTemplateRegistry::Instance().GetAlgTemplate(TemplateType::TEMPLATE_REDUCESCATTER_HD, dispatcher_);
     219            0 :     CHK_SMART_PTR_NULL(tempAlg);
     220            0 :     CHK_RET(tempAlg->Prepare(
     221              :         inputMem_, outputMem_, outputMem_, count_, dataType_, stream_, reductionOp_, root_, slices_, baseOffset_,
     222              :         blockSize_, reduceAttr, UserMemType::INPUT_MEM, UserMemType::OUTPUT_MEM));
     223              : 
     224            0 :     CHK_RET(tempAlg->RegisterProfiler(profilerInput_.planeID, profilerInput_.stage, profilerInput_.step, stream_));
     225              : 
     226              :     // 重新建立reducscatterscatter需要的链接
     227            0 :     std::vector<LINK> subLinks;
     228            0 :     CHK_RET(BuildSubLinks(links, subLinks, rankSize));
     229              : 
     230            0 :     CHK_PRT_RET(
     231              :         subLinks.size() == 0,
     232              :         HCCL_ERROR(
     233              :             "[AllReduceRecursiveHalvingDoubling][ReduceScatterInBlock]rank[%u] BuildSubLinks "
     234              :             "failed",
     235              :             rank),
     236              :         HCCL_E_PARA);
     237            0 :     CHK_RET(tempAlg->RunAsync(rankInBlock, blockSize_, subLinks));
     238            0 :     return HCCL_SUCCESS;
     239            0 : }
     240              : 
     241            0 : HcclResult AllReduceRecursiveHalvingDoubling::AllGatherInBlock(u32 rank, u32 rankSize, const std::vector<LINK>& links)
     242              : {
     243            0 :     u32 rankInBlock = 0;
     244            0 :     if (rank < part1Size_ && (rank % 2) == 1) { // 模2判断奇偶性,本rank 处于第一部分,并且为奇数rank
     245            0 :         return HCCL_SUCCESS;
     246            0 :     } else if (rank < part1Size_ && (rank % 2) == 0) { // 模2判断奇偶性,本rank 处于第一部分,并且为偶数rank
     247            0 :         rankInBlock = rank / 2;                        // 在block内的rank为实际rank除以2
     248              :     } else {
     249            0 :         rankInBlock = rank - part1Size_ / 2; // 除2计算block内的part1的范围
     250              :     }
     251              :     // 直接调用block的allgatherhd算法
     252            0 :     std::unique_ptr<AlgTemplateBase> tempAlg = AlgTemplateRegistry::Instance().GetAlgTemplate(
     253            0 :         TemplateType::TEMPLATE_ALL_GATHER_HALVING_DOUBLING, dispatcher_);
     254            0 :     CHK_SMART_PTR_NULL(tempAlg);
     255            0 :     CHK_RET(tempAlg->Prepare(blockSize_, UserMemType::OUTPUT_MEM, UserMemType::OUTPUT_MEM));
     256            0 :     CHK_RET(tempAlg->Prepare(
     257              :         outputMem_, outputMem_, count_, dataType_, stream_, reductionOp_, root_, slices_, baseOffset_));
     258              : 
     259            0 :     CHK_RET(tempAlg->RegisterProfiler(profilerInput_.planeID, profilerInput_.stage, profilerInput_.step, stream_));
     260              : 
     261              :     // 重新建立allgather需要的链接
     262            0 :     std::vector<LINK> subLinks;
     263            0 :     CHK_RET(BuildSubLinks(links, subLinks, rankSize));
     264              : 
     265            0 :     CHK_PRT_RET(
     266              :         subLinks.size() == 0,
     267              :         HCCL_ERROR(
     268              :             "[AllReduceRecursiveHalvingDoubling][AllGatherInBlock]rank[%u] build sub "
     269              :             "links failed",
     270              :             rank),
     271              :         HCCL_E_PARA);
     272              : 
     273            0 :     CHK_RET(tempAlg->RunAsync(rankInBlock, blockSize_, subLinks));
     274            0 :     return HCCL_SUCCESS;
     275            0 : }
     276              : 
     277            0 : HcclResult AllReduceRecursiveHalvingDoubling::GatherInPartOne(u32 rank, const std::vector<LINK>& links)
     278              : {
     279            0 :     if (rank < part1Size_ && rank % 2 == 0) { // 模2判断奇偶性,本rank 处于第一部分,并且为偶数rank
     280            0 :         u32 peerRank = rank + 1;
     281              :         //  发送到对端的output
     282            0 :         if (peerRank < links.size()) {
     283            0 :             CHK_SMART_PTR_NULL(links[peerRank]);
     284            0 :             HcclResult ret = links[peerRank]->TxAck(stream_);
     285            0 :             CHK_PRT_RET(
     286              :                 ret != HCCL_SUCCESS,
     287              :                 HCCL_ERROR("[Gather][InPartOneToEven]rank[%u] tx ack from peerank[%u] failed", rank, peerRank), ret);
     288            0 :             ret = links[peerRank]->RxAck(stream_);
     289            0 :             CHK_PRT_RET(
     290              :                 ret != HCCL_SUCCESS,
     291              :                 HCCL_ERROR("[Gather][InPartOneToEven]rank[%u] rx ack from peerank[%u] failed", rank, peerRank), ret);
     292            0 :             HCCL_DEBUG(
     293              :                 "rank[%u] outputMem[%p] sends to peerrank[%u] outputmem, offset[%llu], size[%llu]", rank,
     294              :                 outputMem_.ptr(), peerRank, baseOffset_, outputMem_.size());
     295            0 :             ret = ExecuteTxSync(
     296            0 :                 links[peerRank], UserMemType::OUTPUT_MEM, baseOffset_, outputMem_.ptr(), outputMem_.size(), stream_);
     297            0 :             CHK_PRT_RET(
     298              :                 ret != HCCL_SUCCESS,
     299              :                 HCCL_ERROR(
     300              :                     "[AllReduceRecursiveHalvingDoubling][GatherInPartOne]rank[%u] tx "
     301              :                     "sync to PeerRank[%u] failed",
     302              :                     rank, peerRank),
     303              :                 ret);
     304            0 :             ret = links[peerRank]->TxWaitDone(stream_);
     305            0 :             CHK_PRT_RET(
     306              :                 ret != HCCL_SUCCESS,
     307              :                 HCCL_ERROR("[AllReduceRecursiveHalvingDoubling][GatherInPartOne]TxWaitDone failed"), ret);
     308              :         }
     309            0 :     } else if (rank < part1Size_ && rank % 2 == 1) { // 模2判断奇偶性,本rank 处于第一部分,并且为奇数rank
     310            0 :         u32 peerRank = rank - 1;
     311            0 :         if (peerRank < links.size()) {
     312            0 :             CHK_SMART_PTR_NULL(links[peerRank]);
     313            0 :             HcclResult ret = links[peerRank]->TxAck(stream_);
     314            0 :             CHK_PRT_RET(
     315              :                 ret != HCCL_SUCCESS,
     316              :                 HCCL_ERROR("[Gather][InPartOneToEven]rank[%u] tx ack from peerank[%u] failed", rank, peerRank), ret);
     317            0 :             ret = links[peerRank]->RxAck(stream_);
     318            0 :             CHK_PRT_RET(
     319              :                 ret != HCCL_SUCCESS,
     320              :                 HCCL_ERROR("[Gather][InPartOneToEven]rank[%u] rx ack from peerank[%u] failed", rank, peerRank), ret);
     321              :             // 等待对端可以接收数据
     322            0 :             HCCL_DEBUG(
     323              :                 "rank[%u] outputMem[%p] receive from PeerRank[%u] outputMem, Offset[%llu], "
     324              :                 "Size[%llu]",
     325              :                 rank, outputMem_.ptr(), peerRank, baseOffset_, outputMem_.size());
     326            0 :             ret = ExecuteRxSync(
     327            0 :                 links[peerRank], UserMemType::OUTPUT_MEM, baseOffset_, outputMem_.ptr(), outputMem_.size(), stream_);
     328            0 :             CHK_PRT_RET(
     329              :                 ret != HCCL_SUCCESS,
     330              :                 HCCL_ERROR(
     331              :                     "[AllReduceRecursiveHalvingDoubling][GatherInPartOne]rank[%u] rx "
     332              :                     "sync from PeerRank[%u] failed",
     333              :                     rank, peerRank),
     334              :                 ret);
     335            0 :             ret = links[peerRank]->RxWaitDone(stream_);
     336            0 :             CHK_PRT_RET(
     337              :                 ret != HCCL_SUCCESS,
     338              :                 HCCL_ERROR("[AllReduceRecursiveHalvingDoubling][GatherInPartOne]RxWaitDone failed"), ret);
     339              :         }
     340              :     }
     341              : 
     342            0 :     return HCCL_SUCCESS;
     343              : }
     344              : 
     345            0 : HcclResult AllReduceRecursiveHalvingDoubling::GetCommonNslbAdjInfo(
     346              :     const u32 rank, const u32 rankSize, const std::vector<LINK>& links, AdjInfo& nslbAdjInfo)
     347              : {
     348            0 :     u32 stepNum = 0;
     349            0 :     while ((rankSize >> (stepNum + 1)) != 0) {
     350            0 :         stepNum++;
     351              :     }
     352              :     // 执行reducscatter流程
     353            0 :     for (u32 step = 0; step < stepNum; step++) {
     354            0 :         u32 peerRankBitmask = 1 << (stepNum - step - 1);
     355            0 :         u32 peerRank = rank ^ peerRankBitmask;
     356            0 :         NslbDpAdjInfo adjInfoStep = {};
     357            0 :         u32 remoteuserRank = links[peerRank]->GetRemoteRank();
     358            0 :         adjInfoStep.dstLocalRankId = remoteuserRank;
     359            0 :         adjInfoStep.phaseId = step + 1;
     360            0 :         adjInfoStep.rev = 0;
     361            0 :         nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     362              :     }
     363            0 :     u32 begin = stepNum;
     364              :     // 后续执行allgather流程
     365            0 :     for (u32 step = 0; step < stepNum; step++) {
     366            0 :         u32 peerRankBitmask = (1 << step);
     367            0 :         u32 peerRank = rank ^ peerRankBitmask;
     368            0 :         NslbDpAdjInfo adjInfoStep = {};
     369            0 :         u32 remoteuserRank = links[peerRank]->GetRemoteRank();
     370            0 :         adjInfoStep.dstLocalRankId = remoteuserRank;
     371            0 :         adjInfoStep.phaseId = step + begin + 1;
     372            0 :         adjInfoStep.rev = 0;
     373            0 :         nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     374              :     }
     375            0 :     nslbAdjInfo.dstRankNum = nslbAdjInfo.nsAdjInfo.size();
     376            0 :     return HCCL_SUCCESS;
     377              : }
     378            0 : HcclResult AllReduceRecursiveHalvingDoubling::GetOddNslbAdjInfo(
     379              :     const u32 rank, const u32 rankSize, const std::vector<LINK>& links, AdjInfo& nslbAdjInfo)
     380              : {
     381              :     (void)rankSize;
     382            0 :     u32 peerRank = rank - 1;
     383            0 :     if (peerRank < links.size()) {
     384            0 :         NslbDpAdjInfo adjInfoStep = {};
     385            0 :         adjInfoStep.dstLocalRankId = links[peerRank]->GetRemoteRank();
     386            0 :         adjInfoStep.phaseId = 1;
     387            0 :         adjInfoStep.rev = 0;
     388            0 :         HCCL_INFO("AllGatherHDR-nslb: peerRank[%u]", peerRank);
     389            0 :         nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     390            0 :         nslbAdjInfo.dstRankNum = 1;
     391              :     }
     392            0 :     return HCCL_SUCCESS;
     393              : }
     394            0 : HcclResult AllReduceRecursiveHalvingDoubling::GetNslbAdjInfo(
     395              :     const u32 rank, const u32 rankSize, const std::vector<LINK>& links, AdjInfo& nslbAdjInfo)
     396              : {
     397            0 :     u32 nslbRound = 0;
     398            0 :     u32 base = 1;
     399            0 :     const u32 minExponent = 1;
     400            0 :     while ((base << nslbRound) <= rankSize) {
     401            0 :         nslbRound++;
     402              :     }
     403            0 :     if (nslbRound >= minExponent) {
     404            0 :         nslbRound = nslbRound - minExponent;
     405              :     }
     406            0 :     u32 nslbBlockSize = base << nslbRound;
     407              :     // 获取第一部分:rank数减block数乘2
     408            0 :     u32 nslbPart1Size = (rankSize - nslbBlockSize) * NSLBDP_ALL_REDUCE_MOLD2;
     409              :     // 2的次幂场景下处理流程
     410            0 :     if (nslbPart1Size == 0) {
     411            0 :         GetCommonNslbAdjInfo(rank, rankSize, links, nslbAdjInfo);
     412            0 :         return HCCL_SUCCESS;
     413              :     }
     414              :     // 非2的次幂场景下,被合并部分的奇数rank处理流程
     415            0 :     if (rank < nslbPart1Size && rank % NSLBDP_ALL_REDUCE_MOLD2 == 1) {
     416            0 :         GetOddNslbAdjInfo(rank, rankSize, links, nslbAdjInfo);
     417            0 :         return HCCL_SUCCESS;
     418              :     }
     419              :     // 针对合并后映射成2的次幂场景处理
     420            0 :     u32 rankInBlock = 0;
     421            0 :     if (rank < nslbPart1Size && (rank % NSLBDP_ALL_REDUCE_MOLD2) == 0) {
     422            0 :         rankInBlock = rank / NSLBDP_ALL_REDUCE_MOLD2; // 直接除以2即为本rank的在block内的排序
     423              :     } else {
     424              :         rankInBlock
     425            0 :             = rank
     426            0 :               - nslbPart1Size / NSLBDP_ALL_REDUCE_MOLD2; // 通过rank减去part1除2的大小即不处于第一部分的block内rank号
     427              :     }
     428            0 :     std::vector<LINK> subLinks;
     429            0 :     std::vector<LINK>::const_iterator iter = links.begin();
     430            0 :     subLinks.resize(nslbBlockSize);
     431            0 :     for (u32 i = 0; i < rankSize; i++) {
     432            0 :         if (i < nslbPart1Size
     433            0 :             && (i % NSLBDP_ALL_REDUCE_MOLD2) == 1) { // 模2余1代表当前rank在part1的奇数位置上,不参与block内的建链
     434            0 :             continue;
     435            0 :         } else if (i < nslbPart1Size && (i % NSLBDP_ALL_REDUCE_MOLD2) == 0) { // 模2余0代表当前rank在part1的偶数位置上
     436            0 :             std::vector<LINK>::const_iterator niter = std::next(iter, i);
     437            0 :             if (niter != links.end()) {
     438            0 :                 subLinks[i / NSLBDP_ALL_REDUCE_MOLD2] = *niter;
     439              :             }
     440            0 :         } else {
     441            0 :             std::vector<LINK>::const_iterator niter = std::next(iter, i);
     442            0 :             if (niter != links.end()) {
     443            0 :                 subLinks[i - nslbPart1Size / NSLBDP_ALL_REDUCE_MOLD2] = *niter;
     444              :             }
     445              :         }
     446              :     }
     447            0 :     u32 stepNum = 0;
     448            0 :     while ((rankSize >> (stepNum + 1)) != 0) {
     449            0 :         stepNum++;
     450              :     }
     451              :     // 映射完成后针对以新的通信域进行邻接表获取
     452            0 :     u32 begin = 1;
     453            0 :     for (u32 step = 0; step < stepNum; step++) {
     454            0 :         u32 peerRankBitmask = 1 << (stepNum - step - 1);
     455            0 :         u32 peerRank = rankInBlock ^ peerRankBitmask;
     456            0 :         if (subLinks[peerRank] == nullptr) {
     457            0 :             continue;
     458              :         }
     459            0 :         NslbDpAdjInfo adjInfoStep = {};
     460            0 :         u32 remoteuserRank = subLinks[peerRank]->GetRemoteRank();
     461            0 :         adjInfoStep.dstLocalRankId = remoteuserRank;
     462            0 :         adjInfoStep.phaseId = step + 1 + begin;
     463            0 :         adjInfoStep.rev = 0;
     464            0 :         nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     465              :     }
     466            0 :     nslbAdjInfo.dstRankNum = stepNum;
     467              : 
     468            0 :     if (nslbAdjInfo.nsAdjInfo.size() == 0) {
     469            0 :         return HCCL_SUCCESS;
     470              :     }
     471              :     // 上面处理完成后,紧接着处理合并部分的偶数rank同步到奇数rank增加phaseId
     472            0 :     if (rank < nslbPart1Size && rank % NSLBDP_ALL_REDUCE_MOLD2 == 0) {
     473            0 :         u32 peerRank = rank + 1;
     474            0 :         uint16_t phaseSize = nslbAdjInfo.nsAdjInfo.size();
     475            0 :         if (peerRank < links.size()) {
     476            0 :             NslbDpAdjInfo adjInfoStep = {};
     477            0 :             adjInfoStep.dstLocalRankId = links[peerRank]->GetRemoteRank();
     478            0 :             adjInfoStep.phaseId = nslbAdjInfo.nsAdjInfo[phaseSize - 1].phaseId + 1;
     479            0 :             adjInfoStep.rev = 0;
     480            0 :             HCCL_INFO("Scatter-nslb: peerRank[%u]", peerRank);
     481            0 :             nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     482            0 :             nslbAdjInfo.dstRankNum = nslbAdjInfo.nsAdjInfo.size();
     483              :         }
     484            0 :         return HCCL_SUCCESS;
     485              :     }
     486            0 :     return HCCL_SUCCESS;
     487            0 : }
     488              : REGISTER_TEMPLATE(TemplateType::TEMPLATE_ALL_REDUCE_RECURSIVE_HALVING_DOUBLING, AllReduceRecursiveHalvingDoubling);
     489              : } // namespace hccl
        

Generated by: LCOV version 2.0-1