LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_reduce_scatter - reduce_scatter_recursive_hd.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 3.6 % 225 8
Test Date: 2026-08-04 10:52:23 Functions: 40.0 % 10 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_scatter_recursive_hd.h"
      13              : 
      14              : namespace hccl {
      15            5 : ReduceScatterRecursiveHalvingDoubling::ReduceScatterRecursiveHalvingDoubling(
      16            5 :     const HcclDispatcher dispatcher) : RecursiveHalvingDoublingBase(dispatcher)
      17              : {
      18            5 : }
      19              : 
      20           10 : ReduceScatterRecursiveHalvingDoubling::~ReduceScatterRecursiveHalvingDoubling()
      21              : {
      22           10 : }
      23              : 
      24            5 : HcclResult ReduceScatterRecursiveHalvingDoubling::Prepare(u64 reduceAttrBitMap, HcomCollOpInfo *opInfo)
      25              : {
      26              :     (void)opInfo;
      27            5 :     reduceAttr = reduceAttrBitMap;
      28            5 :     return HCCL_SUCCESS;
      29              : }
      30              : 
      31              : // reducescatter recursiveHD 入口函数
      32            0 : HcclResult ReduceScatterRecursiveHalvingDoubling::RunAsync(const u32 rank, const u32 rankSize,
      33              :     const std::vector<std::shared_ptr<Transport> > &links)
      34              : {
      35            0 :     CHK_SMART_PTR_NULL(dispatcher_);
      36            0 :     CHK_PTR_NULL(stream_.ptr());
      37            0 :     HCCL_INFO("run: rank[%u] totalrank[%u] inputMem[%p] outputMem[%p] count[%llu]", rank, rankSize,
      38              :               inputMem_.ptr(), outputMem_.ptr(), count_);
      39            0 :     if (!outputMem_ || !inputMem_) {
      40            0 :         HCCL_ERROR("[ReduceScatterRecursiveHalvingDoubling][RunAsync]rank[%u] run_async inputmem or outputmem is null",
      41              :             rank);
      42            0 :         return HCCL_E_PTR;
      43              :     }
      44              : 
      45            0 :     HcclResult ret = HCCL_SUCCESS;
      46              : 
      47            0 :     if (rankSize == 1) {
      48            0 :         if (inputMem_ != outputMem_) {
      49            0 :             ret = HcclD2DMemcpyAsync(dispatcher_, outputMem_, inputMem_, stream_);
      50              :         }
      51            0 :         return ret;
      52              :     }
      53              : 
      54              :     // 创建reducer & sender
      55            0 :     senderInfo_.reset(new (std::nothrow) Sender(dataType_, reductionOp_, reduceAttr));
      56            0 :     CHK_SMART_PTR_NULL(senderInfo_);
      57              : 
      58            0 :     reducerInfo_.reset(new (std::nothrow) Reducer(dataType_, reductionOp_, reduceAttr));
      59            0 :     CHK_SMART_PTR_NULL(reducerInfo_);
      60              : 
      61            0 :     bool bRetSize = (links.size() < rankSize);
      62            0 :     CHK_PRT_RET(bRetSize, HCCL_ERROR("[ReduceScatterRecursiveHalvingDoubling][RunAsync]rank[%u] linksize[%llu] is "\
      63              :         "error", rank, links.size()), HCCL_E_INTERNAL);
      64              : 
      65            0 :     ret = CalcPartOneSizeAndBlockSize(rankSize);
      66            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
      67              :         HCCL_ERROR("[ReduceScatterRecursiveHalvingDoubling][RunAsync]calculate part1size[%u] "\
      68              :         "and blocksize[%u] Failed! rankSize[%u]", part1Size_, blockSize_, rankSize), ret);
      69              : 
      70            0 :     HCCL_DEBUG("rank[%u] calculate par1size[%u] blocksize[%u] ranksize[%u]", rank, part1Size_, blockSize_, rankSize);
      71              : 
      72            0 :     CHK_RET(ReduceInPartOne(rank, links));
      73              : 
      74            0 :     CHK_RET(CalculateSlices(dataBytes_, rankSize));
      75              : 
      76            0 :     CHK_RET(ReduceScatterInBlock(rank, rankSize, links));
      77              : 
      78            0 :     CHK_RET(ScatterInPartOne(rank, rankSize, links));
      79              : 
      80            0 :     HCCL_INFO("ReduceScatterRecursiveHalvingDoubling finished: rank[%u]", rank);
      81            0 :     return HCCL_SUCCESS;
      82              : }
      83              : 
      84              : 
      85            0 : HcclResult ReduceScatterRecursiveHalvingDoubling::CalculateSlices(u64 dataBytes, const u32 rankSize) const
      86              : {
      87            0 :     CHK_PRT_RET((blockSize_ == 0), HCCL_ERROR("[Calculate][Slices]calculate_slices para error"), HCCL_E_INTERNAL);
      88              : 
      89            0 :     slices_.resize(blockSize_);
      90            0 :     u64 bytesPerSlice = dataBytes / rankSize; // input大小 / server数 = 服务器内rank数*count (4p mesh以4*count为粒度)
      91            0 :     u32 i = 0;
      92            0 :     u32 halfPart1Size = (part1Size_ / 2); // 除2计算一半part1的大小
      93              : 
      94              :     /* 先给属于part1的block rank分配slice。每个rank有两份数据 */
      95            0 :     while (i < halfPart1Size) {
      96            0 :         slices_[i].size = 2 * bytesPerSlice; // 乘2计算2倍数据大小
      97            0 :         slices_[i].offset = i * 2 * bytesPerSlice; // 乘2计算2倍数据大小
      98            0 :         i++;
      99              :     }
     100              : 
     101              :     /* 再给剩余的block rank分配slice。每个rank有一份数据 */
     102            0 :     while (i < blockSize_) {
     103            0 :         slices_[i].size = bytesPerSlice;
     104            0 :         slices_[i].offset = (i * bytesPerSlice) + (halfPart1Size * bytesPerSlice);
     105            0 :         i++;
     106              :     }
     107              : 
     108            0 :     return HCCL_SUCCESS;
     109              : }
     110              : 
     111            0 : HcclResult ReduceScatterRecursiveHalvingDoubling::ReduceInPartOne(u32 rank, const std::vector<LINK> &links)
     112              : {
     113            0 :     if (rank < part1Size_ && rank % 2 == 0) {  // 模2判断奇偶性,rank属于第一部分,并且为偶数rank
     114            0 :         u32 peerRank = rank + 1;
     115            0 :         HCCL_DEBUG("rank[%u] outputmem receives from peerrank[%u] inputmem, offset[%llu], size[%llu]", \
     116              :                    rank, peerRank, baseOffset_, scratchMem_.size());
     117            0 :         if (peerRank < links.size()) {
     118            0 :             CHK_SMART_PTR_NULL(links[peerRank]);
     119            0 :             HcclResult ret = links[peerRank]->TxAck(stream_);
     120            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     121              :                 HCCL_ERROR("[Reduce][InPartOneToEven]rank[%u] tx ack from peerank[%u] failed", rank, peerRank), ret);
     122            0 :             ret = links[peerRank]->RxAck(stream_);
     123            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     124              :                 HCCL_ERROR("[Reduce][InPartOneToEven]rank[%u] rx ack from peerank[%u] failed", rank, peerRank), ret);
     125              :             // 接收数据到本端的input
     126            0 :             HCCL_DEBUG("send mem[%p] size[%llu] to peerank[%u]", \
     127              :                 scratchMem_.ptr(), scratchMem_.size(), peerRank);
     128            0 :             ret = links[peerRank]->TxAsync(UserMemType::INPUT_MEM, baseOffset_, scratchMem_.ptr(), 0, stream_);
     129            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOneToEven]TxAsync: tx async size[%llu] "\
     130              :                 "failed", 0), ret);
     131            0 :             CHK_RET(reducerInfo_->run(dispatcher_, links[peerRank], baseOffset_,
     132              :                 inputMem_, inputMem_, scratchMem_, stream_));
     133            0 :             ret = links[peerRank]->RxWaitDone(stream_);
     134            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]RxWaitDone failed"), ret);
     135              :         }
     136            0 :     } else if (rank < part1Size_ && rank % 2 == 1) { //  向上一个rank的input发数据 2
     137            0 :         u32 peerRank = rank - 1;
     138            0 :         if (peerRank < links.size()) {
     139            0 :             CHK_SMART_PTR_NULL(links[peerRank]);
     140            0 :             HcclResult ret = links[peerRank]->TxAck(stream_);
     141            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     142              :                 HCCL_ERROR("[Reduce][InPartOneToEven]rank[%u] tx ack from peerank[%u] failed", rank, peerRank), ret);
     143            0 :             ret = links[peerRank]->RxAck(stream_);
     144            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     145              :                 HCCL_ERROR("[Reduce][InPartOneToEven]rank[%u] rx ack from peerank[%u] failed", rank, peerRank), ret);
     146              :             //  发送到对端的input
     147            0 :             HCCL_DEBUG("rank[%u] sends inputMem[%p] to peerrank[%u] offset[%llu], size[%llu]", \
     148              :                 rank, inputMem_.ptr(), peerRank, baseOffset_, inputMem_.size());
     149            0 :             ret = senderInfo_->run(links[peerRank], baseOffset_, inputMem_, stream_);
     150            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]tx sync to peerank[%u] failed",
     151              :                 peerRank), ret);
     152            0 :             ret = links[peerRank]->RxAsync(UserMemType::OUTPUT_MEM, baseOffset_, inputMem_.ptr(), 0, stream_);
     153            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     154              :                 HCCL_ERROR("[AlgTemplateBase][ExecuteTxSync]ExecuteTxSync: rx async size[%llu] failed", 0), ret);
     155            0 :             ret = links[peerRank]->DataReceivedAck(stream_);
     156            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     157              :                 HCCL_ERROR("[AlgTemplateBase][ExecuteTxSync]ExecuteTxSync: data received ack failed"), ret);
     158            0 :             ret = links[peerRank]->TxWaitDone(stream_);
     159            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]TxWaitDone failed"), ret);
     160              :         }
     161              :     }
     162              : 
     163            0 :     return HCCL_SUCCESS;
     164              : }
     165              : 
     166              : 
     167            0 : HcclResult ReduceScatterRecursiveHalvingDoubling::ReduceScatterInBlock(u32 rank, u32 rankSize,
     168              :     const std::vector<LINK> &links)
     169              : {
     170            0 :     u32 rankInBlock = 0;
     171            0 :     if (rank < part1Size_ && (rank % 2) == 1) { // rank号对2求余,rank为奇数
     172            0 :         return HCCL_SUCCESS;
     173            0 :     } else if (rank < part1Size_ && (rank % 2) == 0) { // rank对2求余,rank为偶数
     174            0 :         rankInBlock = rank / 2; // 直接除以2即为本rank的在block内的排序
     175              :     } else {
     176            0 :         rankInBlock = rank - part1Size_ / 2; // 通过rank减去part1除2的大小即不处于第一部分的block内rank号
     177              :     }
     178              : 
     179            0 :     std::unique_ptr<AlgTemplateBase> executor = AlgTemplateRegistry::Instance().GetAlgTemplate(
     180            0 :         TemplateType::TEMPLATE_REDUCESCATTER_HD, dispatcher_);
     181            0 :     CHK_SMART_PTR_NULL(executor);
     182            0 :     CHK_RET(executor->Prepare(inputMem_, inputMem_, scratchMem_, count_, dataType_, stream_,
     183              :         reductionOp_, root_, slices_, baseOffset_, blockSize_, reduceAttr,
     184              :         UserMemType::INPUT_MEM, UserMemType::OUTPUT_MEM));
     185              : 
     186            0 :     CHK_RET(executor->RegisterProfiler(profilerInput_.planeID, profilerInput_.stage, profilerInput_.step, stream_));
     187              : 
     188            0 :     std::vector<LINK> subLinks;
     189            0 :     CHK_RET(BuildSubLinks(links, subLinks, rankSize));
     190              : 
     191            0 :     CHK_PRT_RET(subLinks.size() == 0,
     192              :         HCCL_ERROR("[ReduceScatterRecursiveHalvingDoubling][ReduceScatterInBlock]rank[%u] "\
     193              :             "build sub links failed", rank), HCCL_E_PARA);
     194            0 :     CHK_RET(executor->RunAsync(rankInBlock, blockSize_, subLinks));
     195            0 :     return HCCL_SUCCESS;
     196            0 : }
     197              : 
     198            0 : HcclResult ReduceScatterRecursiveHalvingDoubling::ScatterInPartOne(u32 rank, u32 rankSize,
     199              :     const std::vector<LINK> &links)
     200              : {
     201            0 :     u32 bytesPerData = DataUnitSize(dataType_);
     202            0 :     u64 dataBytes = count_ * bytesPerData;
     203            0 :     u64 bytesPerSlice = dataBytes / rankSize;
     204              : 
     205            0 :     if (rank < part1Size_ && rank % 2 == 0) {  // 模2计算奇偶性,偶数rank把自己第二份数据给下一个奇数rank
     206            0 :         u32 peerRank = rank + 1;
     207            0 :         if (peerRank < links.size()) {
     208            0 :             CHK_SMART_PTR_NULL(links[peerRank]);
     209            0 :             HcclResult ret = links[peerRank]->TxAck(stream_);
     210            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     211              :                 HCCL_ERROR("[Scatter][InPartOneToEven]rank[%u] tx ack from peerank[%u] failed", rank, peerRank), ret);
     212            0 :             ret = links[peerRank]->RxAck(stream_);
     213            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     214              :                 HCCL_ERROR("[Scatter][InPartOneToEven]rank[%u] rx ack from peerank[%u] failed", rank,  peerRank), ret);
     215              :             //  发送到对端的input
     216            0 :             HCCL_DEBUG("rank[%u] sends inputmem[%p] to peerrank[%u] Offset[%llu], Size[%llu]", \
     217              :                 rank, inputMem_.ptr(), peerRank, baseOffset_, inputMem_.size());
     218              : 
     219            0 :             u64 offset = peerRank * bytesPerSlice; // 计算对端rank的slice偏移
     220            0 :             void *srcAddr = reinterpret_cast<s8 *>(inputMem_.ptr()) + offset;
     221            0 :             ret = ExecuteTxSync(links[peerRank], UserMemType::INPUT_MEM, offset + baseOffset_, srcAddr, bytesPerSlice,
     222            0 :                 stream_);
     223            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Scatter][InPartOne]tx sync to peerank[%u] failed",
     224              :                 peerRank), ret);
     225            0 :             ret = links[peerRank]->TxWaitDone(stream_);
     226            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]TxWaitDone failed"), ret);
     227              :         }
     228            0 :     } else if (rank < part1Size_ && rank % 2 == 1) { // 模2计算奇偶性,奇数rank接收偶数rank发过来下半份的数据
     229            0 :         u32 peerRank = rank - 1;
     230            0 :         if (peerRank < links.size()) {
     231            0 :             CHK_SMART_PTR_NULL(links[peerRank]);
     232            0 :             HcclResult ret = links[peerRank]->TxAck(stream_);
     233            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     234              :                 HCCL_ERROR("[Scatter][InPartOneToEven]rank[%u] tx ack from peerank[%u] failed", rank, peerRank), ret);
     235            0 :             ret = links[peerRank]->RxAck(stream_);
     236            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     237              :                 HCCL_ERROR("[Scatter][InPartOneToEven]rank[%u] rx ack from peerank[%u] failed", rank, peerRank), ret);
     238              :             //  接收数据到本端的 inputMem_
     239            0 :             HCCL_DEBUG("rx mem[%p] size[%llu] from peerank[%u]", inputMem_.ptr(), inputMem_.size(), peerRank);
     240              : 
     241            0 :             u64 offset = rank * bytesPerSlice; // 本rank slice偏移
     242            0 :             void *dstAddr = reinterpret_cast<s8 *>(inputMem_.ptr()) + offset;
     243            0 :             ret = ExecuteRxSync(links[peerRank], UserMemType::INPUT_MEM, offset + baseOffset_, dstAddr, bytesPerSlice,
     244            0 :                 stream_);
     245            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Scatter][InPartOne]rx sync from peerank[%u] failed",
     246              :                 peerRank), ret);
     247            0 :             ret = links[peerRank]->RxWaitDone(stream_);
     248            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Reduce][InPartOne]RxWaitDone failed"), ret);
     249              :         }
     250              :     }
     251              : 
     252            0 :     return HCCL_SUCCESS;
     253              : }
     254              : 
     255            0 : HcclResult ReduceScatterRecursiveHalvingDoubling::GetNslbAdjInfo(const u32 rank, const u32 rankSize,
     256              :                                                                  const std::vector<LINK> &links,
     257              :                                                                  AdjInfo& nslbAdjInfo)
     258              : {
     259            0 :     u32 nslbRound = 0;
     260            0 :     u32 base = 1;
     261            0 :     const u32 minExponent = 1;
     262            0 :     while ((base << nslbRound) <= rankSize) {
     263            0 :         nslbRound++;
     264              :     }
     265            0 :     if (nslbRound >= minExponent) {
     266            0 :         nslbRound = nslbRound - minExponent;
     267              :     }
     268            0 :     u32 nslbBlockSize = base << nslbRound;
     269              :     // 获取第一部分:rank数减block数乘2
     270            0 :     u32 nslbPart1Size = (rankSize - nslbBlockSize) * 2;
     271              :     // 2的次幂场景下处理流程
     272            0 :     if (nslbPart1Size == 0) {
     273            0 :         u32 stepNum = 0;
     274            0 :         while ((rankSize >> (stepNum + 1)) != 0) {
     275            0 :             stepNum++;
     276              :         }
     277            0 :         for (u32 step = 0; step < stepNum; step++) {
     278            0 :             u32 peerRankBitmask = 1 << (stepNum - step - 1);
     279            0 :             u32 peerRank = rank ^ peerRankBitmask;
     280            0 :             NslbDpAdjInfo adjInfoStep = {0};
     281            0 :             u32 remoteuserRank = links[peerRank]->GetRemoteRank();
     282            0 :             adjInfoStep.dstLocalRankId = remoteuserRank;
     283            0 :             adjInfoStep.phaseId = step + 1;
     284            0 :             adjInfoStep.rev = 0;
     285            0 :             nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     286              :         }
     287            0 :         nslbAdjInfo.dstRankNum = stepNum;
     288            0 :         return HCCL_SUCCESS;
     289              :     }
     290              :     // 非2的次幂场景下,被合并部分的奇数rank处理流程
     291            0 :     if (rank < nslbPart1Size && rank % NSLBDP_REDUCE_SCATTER_MOLD2 == 1) {
     292            0 :         u32 peerRank = rank - 1;
     293            0 :         if (peerRank < links.size()) {
     294            0 :             NslbDpAdjInfo adjInfoStep = {0};
     295            0 :             adjInfoStep.dstLocalRankId = links[peerRank]->GetRemoteRank();
     296            0 :             adjInfoStep.phaseId = 1;
     297            0 :             adjInfoStep.rev = 0;
     298            0 :             HCCL_INFO("AllGatherHDR-nslb: peerRank[%u]", peerRank);
     299            0 :             nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     300            0 :             nslbAdjInfo.dstRankNum = 1;
     301              :         }
     302            0 :         return HCCL_SUCCESS;
     303              :     }
     304              :     // 针对合并后映射成2的次幂场景处理
     305            0 :     u32 rankInBlock = 0;
     306            0 :     if (rank < nslbPart1Size && (rank % NSLBDP_REDUCE_SCATTER_MOLD2) == 0) {
     307            0 :         rankInBlock = rank / NSLBDP_REDUCE_SCATTER_MOLD2; // 直接除以2即为本rank的在block内的排序
     308              :     } else {
     309            0 :         rankInBlock = rank - nslbPart1Size / NSLBDP_REDUCE_SCATTER_MOLD2; // 通过rank减去part1除2的大小即不处于第一部分的block内rank号
     310              :     }
     311            0 :     std::vector<LINK> subLinks;
     312            0 :     std::vector<LINK>::const_iterator iter = links.begin();
     313            0 :     subLinks.resize(nslbBlockSize);
     314            0 :     for (u32 i = 0; i < rankSize; i++) {
     315            0 :         if (i < nslbPart1Size && (i % NSLBDP_REDUCE_SCATTER_MOLD2) == 1) {   // 模2余1代表当前rank在part1的奇数位置上,不参与block内的建链
     316            0 :             continue;
     317            0 :         } else if (i < nslbPart1Size && (i % NSLBDP_REDUCE_SCATTER_MOLD2) == 0) {  // 模2余0代表当前rank在part1的偶数位置上
     318            0 :             std::vector<LINK>::const_iterator niter = std::next(iter, i);
     319            0 :             if (niter != links.end()) {
     320            0 :                 subLinks[i / NSLBDP_REDUCE_SCATTER_MOLD2] = *niter;
     321              :             }
     322            0 :         } else {
     323            0 :             std::vector<LINK>::const_iterator niter = std::next(iter, i);
     324            0 :             if (niter != links.end()) {
     325            0 :                 subLinks[i - nslbPart1Size / NSLBDP_REDUCE_SCATTER_MOLD2] = *niter; 
     326              :             }
     327              :         }
     328              :     }
     329            0 :     u32 stepNum = 0;
     330            0 :     while ((rankSize >> (stepNum + 1)) != 0) {
     331            0 :         stepNum++;
     332              :     }
     333              :     // 映射完成后针对以新的通信域进行邻接表获取
     334            0 :     u32 begin = 1;
     335            0 :     for (u32 step = 0; step < stepNum; step++) {
     336            0 :         u32 peerRankBitmask = 1 << (stepNum - step - 1);
     337            0 :         u32 peerRank = rankInBlock ^ peerRankBitmask;
     338            0 :         if (subLinks[peerRank] == nullptr) {
     339            0 :             continue;
     340              :         }
     341            0 :         NslbDpAdjInfo adjInfoStep = {0};
     342            0 :         u32 remoteuserRank = subLinks[peerRank]->GetRemoteRank();
     343            0 :         adjInfoStep.dstLocalRankId = remoteuserRank;
     344            0 :         adjInfoStep.phaseId = step + begin + 1;
     345            0 :         adjInfoStep.rev = 0;
     346            0 :         nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     347              :     }
     348            0 :     nslbAdjInfo.dstRankNum = nslbAdjInfo.nsAdjInfo.size();
     349              : 
     350            0 :     if(nslbAdjInfo.nsAdjInfo.size() == 0) {
     351            0 :         return HCCL_SUCCESS;
     352              :     }
     353              :     // 上面处理完成后,紧接着处理合并部分的偶数rank同步到奇数rank增加phaseId
     354            0 :     if (rank < nslbPart1Size && rank % NSLBDP_REDUCE_SCATTER_MOLD2 == 0) {
     355            0 :         u32 peerRank = rank + 1;
     356            0 :         uint16_t phaseSize = nslbAdjInfo.nsAdjInfo.size();
     357            0 :         if (peerRank < links.size()) {
     358            0 :                 NslbDpAdjInfo adjInfoStep = {0};
     359            0 :                 adjInfoStep.dstLocalRankId = links[peerRank]->GetRemoteRank();
     360            0 :                 adjInfoStep.phaseId = nslbAdjInfo.nsAdjInfo[phaseSize - 1].phaseId + 1;
     361            0 :                 adjInfoStep.rev = 0;
     362            0 :                 HCCL_INFO("Scatter-nslb: peerRank[%u]", peerRank);
     363            0 :                 nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     364            0 :                 nslbAdjInfo.dstRankNum = nslbAdjInfo.nsAdjInfo.size();
     365              :         }
     366            0 :         return HCCL_SUCCESS;
     367              :     }
     368            0 :     return HCCL_SUCCESS;
     369            0 : }
     370              : REGISTER_TEMPLATE(TemplateType::TEMPLATE_REDUCESCATTER_RECURSIVE_HD, ReduceScatterRecursiveHalvingDoubling);
     371              : }  // namespace hccl
        

Generated by: LCOV version 2.0-1