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

Generated by: LCOV version 2.0-1