LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_reduce_scatter - reduce_scatter_nb.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 4.2 % 190 8
Test Date: 2026-08-04 10:52:23 Functions: 30.8 % 13 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 "reduce_scatter_nb.h"
      12              : #include "alg_template_register.h"
      13              : 
      14              : namespace hccl {
      15              : 
      16           10 : ReduceScatterNB::ReduceScatterNB(const HcclDispatcher dispatcher)
      17           10 :     :NBBase(dispatcher)
      18              : {
      19           10 : }
      20              : 
      21           11 : ReduceScatterNB::~ReduceScatterNB()
      22              : {
      23           11 : }
      24              : 
      25            1 : HcclResult ReduceScatterNB::Prepare(u64 reduceAttrBitMap, HcomCollOpInfo *opInfo)
      26              : {
      27              :     (void)opInfo;
      28            1 :     reduceAttr_ = reduceAttrBitMap;
      29            1 :     return HCCL_SUCCESS;
      30              : }
      31              : 
      32            0 : HcclResult ReduceScatterNB::RunAsync(const u32 rank, const u32 rankSize, const std::vector<LINK> &links)
      33              : {
      34              :     // 参数校验
      35            0 :     CHK_RET(SimpleCheck(rank, rankSize, links));
      36            0 :     HCCL_INFO("ReduceScatterNB run: rank[%u] ranksize[%u] inputMem[%p] outputMem[%p] count[%llu]", rank, rankSize,
      37              :         inputMem_.ptr(), outputMem_.ptr(), count_);
      38              : 
      39            0 :     if (rankSize == 1) {
      40            0 :         if (inputMem_ != outputMem_) {
      41            0 :             return HcclD2DMemcpyAsync(dispatcher_, outputMem_, inputMem_, stream_);
      42              :         }
      43            0 :         return HCCL_SUCCESS;
      44              :     }
      45              : 
      46            0 :     u32 unitSize = DataUnitSize(dataType_);
      47            0 :     CHK_PRT_RET(unitSize == 0, HCCL_ERROR("[ReduceScatterRing][RunAsync] rank[%u] unit data size is zero", rank),
      48              :         HCCL_E_INTERNAL);
      49              : 
      50            0 :     std::vector<Slice> outputSlices(slices_);
      51              : 
      52              :     // 处理和检查Slices
      53            0 :     if (slices_.size() == 0) {
      54            0 :         slices_.resize(rankSize);
      55            0 :         outputSlices.resize(rankSize);
      56              : 
      57              :         // 生成std::vector<Slice> slices_
      58            0 :         u64 sliceSize = count_ * unitSize;
      59            0 :         HCCL_DEBUG("[ReduceScatterNB][RunAsync]sliceSize is %llu", sliceSize);
      60              : 
      61            0 :         for (u32 i = 0; i < rankSize; i++) {
      62            0 :             slices_[i].size = sliceSize;
      63            0 :             slices_[i].offset = (i * sliceSize);
      64              : 
      65            0 :             outputSlices[i].size = sliceSize;
      66            0 :             outputSlices[i].offset = (inputMem_.size() > outputMem_.size()) ? 0 : (i * sliceSize);
      67            0 :             HCCL_DEBUG("rank[%u], slices[%u].offset=[%llu], slices[%u].size=[%llu] outputSlices[%u].offset=[%llu], \
      68              :                 outputSlices[%u].size=[%llu] count_[%llu] unitSize[%llu]",
      69              :                 rank, i, slices_[i].offset, i, slices_[i].size, i, outputSlices[i].offset, i, outputSlices[i].size,
      70              :                 count_, unitSize);
      71              :         }
      72              :     }
      73              : 
      74            0 :     CHK_RET(CheckSlices(slices_, rankSize));
      75              : 
      76              :     // 创建reducer & sender
      77            0 :     senderInfo_.reset(new (std::nothrow) Sender(dataType_, reductionOp_, reduceAttr_));
      78            0 :     CHK_SMART_PTR_NULL(senderInfo_);
      79              : 
      80            0 :     reducerInfo_.reset(new (std::nothrow) Reducer(dataType_, reductionOp_, reduceAttr_));
      81            0 :     CHK_SMART_PTR_NULL(reducerInfo_);
      82              : 
      83              :     // 运行reduce-scatter, NB 算法
      84            0 :     CHK_RET(RunReduceScatterNB(rank, rankSize, links, slices_, outputSlices));
      85              : 
      86            0 :     HCCL_INFO("ReduceScatterNB finished: rank[%u] end", rank);
      87            0 :     return HCCL_SUCCESS;
      88            0 : }
      89              : 
      90            0 : HcclResult ReduceScatterNB::SimpleCheck(const u32 rank, const u32 rankSize, const std::vector<LINK> &links)
      91              : {
      92              :     // 判断stream, dispatcher是否为空
      93            0 :     CHK_SMART_PTR_NULL(dispatcher_);
      94            0 :     CHK_PTR_NULL(stream_.ptr());
      95              : 
      96              :     // 检查memory
      97            0 :     CHK_PRT_RET(!outputMem_ || !inputMem_, HCCL_ERROR("[ReduceScatterNB]rank[%u] inputmem or outputmem is null", rank),
      98              :         HCCL_E_PTR);
      99              : 
     100              :     // 判断links数量是否正确
     101            0 :     CHK_PRT_RET(links.size() < rankSize,
     102              :         HCCL_ERROR("[ReduceScatterNB]rank[%u] link size[%llu] is less than "
     103              :         "rank size[%u]", rank, links.size(), rankSize), HCCL_E_INTERNAL);
     104            0 :     return HCCL_SUCCESS;
     105              : }
     106              : 
     107            0 : HcclResult ReduceScatterNB::CheckSlices(const std::vector<Slice> &checkSlices, const u32 rankSize)
     108              : {
     109            0 :     CHK_PRT_RET(checkSlices.size() % rankSize != 0,
     110              :         HCCL_ERROR("[ReduceScatterNB]slices.size[%u] should be divided by rankSize[%u]", checkSlices.size(), rankSize),
     111              :         HCCL_E_INTERNAL);
     112            0 :     return HCCL_SUCCESS;
     113              : }
     114              : 
     115            0 : HcclResult ReduceScatterNB::RunReduceScatterNB(const u32 rank, const u32 rankSize,
     116              :                                                const std::vector<LINK>  &links,
     117              :                                                const std::vector<Slice> &inputSlices,
     118              :                                                const std::vector<Slice> &outputSlices)
     119              : {
     120            0 :     bool bRetSize = (inputSlices.size() < rankSize);
     121            0 :     CHK_PRT_RET(bRetSize,
     122              :         HCCL_ERROR("[Run][ReduceScatter]rank[%u] inputslice size[%llu] is less than rank size[%u]",
     123              :             rank, inputSlices.size(), rankSize), HCCL_E_INTERNAL);
     124              : 
     125            0 :     bRetSize = (outputSlices.size() < rankSize);
     126            0 :     CHK_PRT_RET(bRetSize,
     127              :         HCCL_ERROR("[Run][ReduceScatter]rank[%u] outputslice size[%llu] is less than rank size[%u]",
     128              :             rank, outputSlices.size(), rankSize), HCCL_E_INTERNAL);
     129              : 
     130            0 :     HcclResult ret = HCCL_SUCCESS;
     131              : 
     132              :     // 计算通信步数:ceiling(log2(rankSize))
     133            0 :     u32 nSteps = CalcCeilLog2(rankSize);
     134            0 :     u32 sliceSize = inputSlices.size() / rankSize;
     135            0 :     HCCL_DEBUG("ReduceScatter debug-1: rank[%u] rankSize[%u] nSteps[%u] sliceSize[%u]", rank, rankSize, nSteps,
     136              :         sliceSize);
     137              :     // 逐步编排任务
     138            0 :     for (u32 step = 0; step < nSteps; step++) {
     139              :         // 计算通信对象
     140            0 :         u32 deltaRank = 1 << step;
     141            0 :         u32 recvFrom = (rankSize + rank - deltaRank) % rankSize;
     142            0 :         u32 sendTo = (rank + deltaRank) % rankSize;
     143              : 
     144              :         // 数据份数和数据编号增量
     145            0 :         u32 nSlices = (rankSize - 1 + (1 << step)) / (1 << (step + 1));
     146            0 :         u32 deltaSliceIndex = 1 << (step + 1);
     147            0 :         u32 txSliceIdx = (rank + (1 << step)) % rankSize;
     148            0 :         u32 rxSliceIdx = rank;
     149              : 
     150            0 :         LINK linkLeft = links[recvFrom];
     151            0 :         CHK_SMART_PTR_NULL(linkLeft);
     152              : 
     153            0 :         LINK linkRight = links[sendTo];
     154            0 :         CHK_SMART_PTR_NULL(linkRight);
     155              : 
     156              :         // 当前每个数据块发送一次ACK、reduce一次、同步一次
     157            0 :         HCCL_DEBUG("ReduceScatter debug-2: recvFrom[%u] sendTo[%u] step[%u] nSlices[%u] deltaSliceIndex[%u] "
     158              :             "rxSliceIdx[%u] txSliceIdx[%u]",
     159              :             recvFrom, sendTo, step, nSlices, deltaSliceIndex, rxSliceIdx, txSliceIdx);
     160              : 
     161            0 :         u32 txCount = 0;
     162            0 :         u32 txSliceIdxTmp = txSliceIdx;
     163            0 :         for (u32 i = 0; i < nSlices; i++) {
     164            0 :             for (u32 j = 0; j < sliceSize; j++) {
     165            0 :                 if (inputSlices[txSliceIdxTmp * sliceSize + j].size > 0) {
     166            0 :                     txCount++;
     167              :                 }
     168              :             }
     169            0 :             txSliceIdxTmp = (txSliceIdxTmp + deltaSliceIndex) % rankSize;
     170              :         }
     171              : 
     172            0 :         u32 rxCount = 0;
     173            0 :         u32 rxSliceIdxTmp = rxSliceIdx;
     174            0 :         for (u32 i = 0; i < nSlices; i++) {
     175            0 :             for (u32 j = 0; j < sliceSize; j++){
     176            0 :                 if (inputSlices[rxSliceIdxTmp * sliceSize + j].size > 0) {
     177            0 :                     rxCount++;
     178              :                 }
     179              :             }
     180            0 :             rxSliceIdxTmp = (rxSliceIdxTmp + deltaSliceIndex) % rankSize;
     181              :         }
     182            0 :         if (rxCount > 0) {
     183            0 :             CHK_RET(linkLeft->TxAck(stream_));
     184              :         }
     185            0 :         if (txCount > 0) {
     186            0 :             CHK_RET(linkRight->RxAck(stream_));
     187            0 :             RunSrcReducerNB(step, nSlices, sliceSize, txSliceIdx, deltaSliceIndex, linkRight, rank, rankSize,
     188              :                 inputSlices, outputSlices);
     189              :         }
     190            0 :         if (rxCount > 0) {
     191            0 :             RunDestReducerNB(step, nSteps, sliceSize, nSlices, rxSliceIdx, deltaSliceIndex, linkLeft, rank, rankSize,
     192              :                 inputSlices, outputSlices);
     193            0 :             ret = linkLeft->RxWaitDone(stream_);
     194            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     195              :                 HCCL_ERROR("[Run][ReduceScatterNB]rank[%u] step[%u] blocknum[%u] rx wait done failed", rank, step,
     196              :                 nSlices),
     197              :                 ret);
     198            0 :             ret = linkLeft->PostFinAck(stream_);
     199            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Run][ReduceScatter]PostFinAck failed"), ret);
     200              :         }
     201            0 :         if (txCount > 0) {
     202            0 :             ret = linkRight->TxWaitDone(stream_);
     203            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS,
     204              :                 HCCL_ERROR("[Run][ReduceScatterNB]rank[%u] step[%u] blocknum[%u] tx wait done failed", rank, step,
     205              :                 nSlices),
     206              :                 ret);
     207            0 :             ret = linkRight->WaitFinAck(stream_);
     208            0 :             CHK_PRT_RET(ret != HCCL_SUCCESS, HCCL_ERROR("[Run][ReduceScatter]WaitFinAck failed"), ret);
     209              :         }
     210            0 :         if (linkRight->IsSpInlineReduce() || linkLeft->IsSpInlineReduce()) {
     211              :             // SDMA场景同步
     212            0 :             CHK_RET(ExecuteBarrier(linkLeft, linkRight));
     213              :         }
     214            0 :     }
     215            0 :     return HCCL_SUCCESS;
     216              : }
     217              : 
     218            0 : HcclResult ReduceScatterNB::RunSrcReducerNB(const u32 step, const u32 nSlices, const u32 sliceSize,
     219              :                                             u32 txSliceIdx, const u32 deltaSliceIndex,
     220              :                                             const LINK linkRight, const u32 rank,
     221              :                                             const u32 rankSize, const std::vector<Slice> &inputSlices,
     222              :                                             const std::vector<Slice> &outputSlices)
     223              : {
     224            0 :     HcclResult ret = HCCL_SUCCESS;
     225              : 
     226            0 :     std::vector<Slice> txSlices;
     227            0 :     std::vector<Slice> txSlicestemp;
     228            0 :     for (u32 i = 0; i < nSlices; i++) {
     229            0 :         for (u32 j = 0; j < sliceSize; j++) {
     230            0 :             u32 txIndex = txSliceIdx * sliceSize + j;
     231            0 :             if (inputSlices[txIndex].size > 0) {
     232            0 :                 txSlices.push_back(inputSlices[txIndex]);
     233            0 :                 txSlicestemp.push_back(outputSlices[txIndex]);
     234              :             }
     235              :         }
     236            0 :         txSliceIdx = (txSliceIdx + deltaSliceIndex) % rankSize;
     237              :     }
     238              : 
     239            0 :     ret = RunSourceReducer(linkRight, txSlices, txSlicestemp);
     240            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
     241              :         HCCL_ERROR("[Run][ReduceScatterNB]rank[%u] step[%u] blocknum[%u] tx multi blocks failed",
     242              :         rank, step, nSlices), ret);
     243            0 :     return HCCL_SUCCESS;
     244            0 : }
     245              : 
     246            0 : HcclResult ReduceScatterNB::RunDestReducerNB(  const u32 step, const u32 nSteps, const u32 sliceSize,
     247              :                                                const u32 nSlices, u32 rxSliceIdx,
     248              :                                                const u32 deltaSliceIndex, const LINK linkLeft,
     249              :                                                const u32 rank, const u32 rankSize,
     250              :                                                const std::vector<Slice> &inputSlices,
     251              :                                                const std::vector<Slice> &outputSlices)
     252              : {
     253            0 :     HcclResult ret = HCCL_SUCCESS;
     254              : 
     255            0 :     if (step == (nSteps - 1)) {
     256            0 :         std::vector<ReducerMemoryInfo> rxReduceMems;
     257            0 :         for (u32 i = 0; i < nSlices; i++) {
     258            0 :             for (u32 j = 0; j < sliceSize; j++) {
     259            0 :                 u32 rxIndex = rxSliceIdx * sliceSize + j;
     260            0 :                 if (inputSlices[rxIndex].size > 0) {
     261            0 :                     DeviceMem dstMem = outputMem_.range(outputSlices[rxIndex].offset, outputSlices[rxIndex].size);
     262            0 :                     DeviceMem srcMem = inputMem_.range(inputSlices[rxIndex].offset, inputSlices[rxIndex].size);
     263              :                     DeviceMem scratchMem =
     264            0 :                         scratchMem_.range(outputSlices[rxIndex].offset, outputSlices[rxIndex].size);
     265            0 :                     HCCL_DEBUG("final reduce rxSliceIdx[%u] will reduce with inputMem_ offset[%llu] to ouput_mem_ "
     266              :                         "offset[%llu] size[%llu]",
     267              :                         rxIndex, inputSlices[rxIndex].offset, outputSlices[rxIndex].offset,
     268              :                         outputSlices[rxIndex].size);
     269              :  
     270            0 :                     rxReduceMems.emplace_back(
     271            0 :                         ReducerMemoryInfo{ baseOffset_ + inputSlices[rxIndex].offset, srcMem, dstMem, scratchMem });
     272            0 :                 }
     273              :             }
     274            0 :             rxSliceIdx = (rxSliceIdx + deltaSliceIndex) % rankSize;
     275              :         }
     276              : 
     277            0 :         ret = reducerInfo_->run(dispatcher_, linkLeft, rxReduceMems, stream_);
     278            0 :     } else {
     279            0 :         std::vector<Slice> rxSlices;
     280            0 :         std::vector<Slice> rxSlicestemp;
     281            0 :         for (u32 i = 0; i < nSlices; i++) {
     282            0 :             for (u32 j = 0; j < sliceSize; j++) {
     283            0 :                 u32 rxIndex = rxSliceIdx * sliceSize + j;
     284            0 :                 if (inputSlices[rxIndex].size > 0) {
     285            0 :                     rxSlices.push_back(inputSlices[rxIndex]);
     286            0 :                     rxSlicestemp.push_back(outputSlices[rxIndex]);
     287              :                 }
     288              :             }
     289            0 :             rxSliceIdx = (rxSliceIdx + deltaSliceIndex) % rankSize;
     290              :         }
     291              : 
     292            0 :         ret = RunDestReducer(linkLeft, rxSlices, rxSlicestemp);
     293            0 :     }
     294              : 
     295            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
     296              :         HCCL_ERROR("[Run][ReduceScatterNB]rank[%u] step[%u] blocknum[%u] rx multi blocks failed", rank, step, nSlices),
     297              :         ret);
     298            0 :     return HCCL_SUCCESS;
     299              : }
     300              : 
     301            0 : HcclResult ReduceScatterNB::RunDestReducer(const LINK &link, const std::vector<Slice> &rxSlices,
     302              :     const std::vector<Slice> &rxSlicestemp)
     303              : {
     304            0 :     std::vector<ReducerMemoryInfo> rxReduceMems;
     305              : 
     306            0 :     for (u64 i = 0; i < rxSlices.size(); i++) {
     307            0 :         DeviceMem dstMem = inputMem_.range(rxSlices[i].offset, rxSlices[i].size);
     308            0 :         DeviceMem srcMemTemp = scratchMem_.range(rxSlicestemp[i].offset, rxSlicestemp[i].size);
     309            0 :         HCCL_DEBUG("rcv offset[%llu], size[%llu] ,then reduce with "
     310              :             "offset[%llu] size[%llu] ",
     311              :             rxSlicestemp[i].offset, rxSlicestemp[i].size, rxSlices[i].offset, rxSlices[i].size);
     312            0 :         rxReduceMems.emplace_back(ReducerMemoryInfo{baseOffset_ + rxSlices[i].offset, dstMem, dstMem, srcMemTemp});
     313            0 :     }
     314            0 :     CHK_RET(reducerInfo_->run(dispatcher_, link, rxReduceMems, stream_));
     315            0 :     return HCCL_SUCCESS;
     316            0 : }
     317              : 
     318            0 : HcclResult ReduceScatterNB::RunSourceReducer(const LINK &link, const std::vector<Slice> &txSlices,
     319              :     const std::vector<Slice> &txSlicestemp)
     320              : {
     321            0 :     std::vector<SenderMemoryInfo> txMems;
     322              : 
     323            0 :     for (u64 i = 0; i < txSlices.size(); i++) {
     324            0 :         DeviceMem srcMem = inputMem_.range(txSlices[i].offset, txSlices[i].size);
     325            0 :         HCCL_DEBUG(" send inputmem range[%llu], size[%llu] tx dstmem offset[%llu]", txSlices[i].offset,
     326              :             txSlices[i].size, txSlicestemp[i].offset);
     327            0 :         txMems.emplace_back(SenderMemoryInfo{baseOffset_ + txSlicestemp[i].offset, srcMem});
     328            0 :     }
     329            0 :     CHK_RET(senderInfo_->run(link, txMems, stream_));
     330            0 :     return HCCL_SUCCESS;
     331            0 : }
     332            0 : HcclResult ReduceScatterNB::GetNslbAdjInfo(const u32 rank, const u32 rankSize,
     333              :                                        const std::vector<LINK> &links, AdjInfo& nslbAdjInfo)
     334              : {
     335            0 :     if (rankSize == 1) {
     336            0 :         return HCCL_SUCCESS;
     337              :     }
     338            0 :     if (links.size() < rankSize) {
     339            0 :         return HCCL_SUCCESS;
     340              :     }
     341            0 :     u32 nSteps  = 0;
     342            0 :     for(u32 temp = rankSize - 1; temp != 0; temp >>= 1, ++nSteps){}
     343              : 
     344            0 :     for (u32 step = 0; step < nSteps; step++) {
     345            0 :         u32 deltaRank = 1 << step;
     346            0 :         u32 sendTo =(rank + deltaRank) % rankSize;
     347            0 :         LINK linkRight = links[sendTo];
     348            0 :         CHK_SMART_PTR_NULL(linkRight);
     349              : 
     350            0 :         NslbDpAdjInfo adjInfoStep = {0};
     351            0 :         adjInfoStep.dstLocalRankId = linkRight->GetRemoteRank();
     352            0 :         adjInfoStep.phaseId = step + 1;
     353            0 :         adjInfoStep.rev = 0;
     354            0 :         nslbAdjInfo.nsAdjInfo.push_back(adjInfoStep);
     355            0 :     }
     356            0 :     nslbAdjInfo.dstRankNum = nSteps;
     357            0 :     return HCCL_SUCCESS;
     358              : }
     359              : REGISTER_TEMPLATE(TemplateType::TEMPLATE_REDUCESCATTER_NB, ReduceScatterNB);
     360              : }   // ~~ namespace hccl
        

Generated by: LCOV version 2.0-1