LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_reduce_scatter - reduce_scatter_slim_ring.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 148 0
Test Date: 2026-08-04 10:52:23 Functions: 0.0 % 14 0

            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_slim_ring.h"
      12              : #include "alg_template_register.h"
      13              : 
      14              : namespace hccl {
      15            0 : ReduceScatterSlimRing::ReduceScatterSlimRing(const HcclDispatcher dispatcher)
      16            0 :     : AlgTemplateBase(dispatcher)
      17              : {
      18            0 : }
      19              : 
      20            0 : ReduceScatterSlimRing::~ReduceScatterSlimRing()
      21              : {
      22            0 : }
      23              : 
      24            0 : HcclResult ReduceScatterSlimRing::Prepare(u64 reduceAttrBitMap, HcomCollOpInfo *opInfo)
      25              : {
      26              :     (void)opInfo;
      27            0 :     reduceAttr_ = reduceAttrBitMap;
      28            0 :     return HCCL_SUCCESS;
      29              : }
      30              : 
      31            0 : HcclResult ReduceScatterSlimRing::RunVectorSourceReducer(const LINK &link, const std::vector<Slice> &txSlices,
      32              :                                                      const std::vector<Slice> &txSlicetemp)
      33              : {
      34              :     /* 1、对外reduce_scatter,output的大小为每块数据*rank_size。只能发送到对端地址偏移为0开始。
      35              :       2、allreduce中使用reduce_scatter,output与Input大小相等,接收和发送偏移相等都为slice.offset */
      36            0 :     std::vector<SenderMemoryInfo> txMems;
      37            0 :     for (u32 i = 0; i < txSlices.size(); i++) {
      38            0 :         DeviceMem srcMem = inputMem_.range(txSlices[i].offset, txSlices[i].size);
      39            0 :         HCCL_DEBUG("send inputmem range[%llu], size[%llu] tx dstmem offset[%llu]", txSlices[i].offset,
      40              :             txSlices[i].size, txSlicetemp[i].offset);
      41            0 :         txMems.emplace_back(SenderMemoryInfo{baseOffset_ + txSlicetemp[i].offset, srcMem});
      42            0 :     }
      43            0 :     CHK_RET(senderInfo_->run(link, txMems, notifyIdx_, stream_));
      44              : 
      45            0 :     return HCCL_SUCCESS;
      46            0 : }
      47              : 
      48            0 : HcclResult ReduceScatterSlimRing::RunVectorDestRducer(const LINK &link, const std::vector<Slice> &rxSlices,
      49              :                                                   const std::vector<Slice> &rxSlicetemp)
      50              : {
      51            0 :     std::vector<ReducerMemoryInfo> rxReduceMems;
      52            0 :     for (u32 i = 0; i < rxSlices.size(); i++) {
      53            0 :         DeviceMem dstMem = inputMem_.range(rxSlices[i].offset, rxSlices[i].size);
      54            0 :         DeviceMem srcMemTemp = scratchMem_.range(rxSlicetemp[i].offset, rxSlicetemp[i].size);
      55            0 :         HCCL_DEBUG("rcv offset[%llu], size[%llu] ,then reduce with "
      56              :             "offset[%llu] size[%llu] ",
      57              :             rxSlicetemp[i].offset, rxSlicetemp[i].size, rxSlices[i].offset, rxSlices[i].size);
      58            0 :         rxReduceMems.emplace_back(ReducerMemoryInfo{baseOffset_ + rxSlices[i].offset, dstMem, dstMem, srcMemTemp});
      59            0 :     }
      60            0 :     CHK_RET(reducerInfo_->run(dispatcher_, link, rxReduceMems, notifyIdx_, stream_));
      61              : 
      62            0 :     return HCCL_SUCCESS;
      63            0 : }
      64              : 
      65            0 : HcclResult ReduceScatterSlimRing::RunVectorFinRducer(const u32 rank,
      66              :                                                     const LINK &link, 
      67              :                                                     const u32 sliceSize,
      68              :                                                     const std::vector<Slice> &inputSlices,
      69              :                                                     const std::vector<Slice> &outputSlices)
      70              : {
      71            0 :     std::vector<ReducerMemoryInfo> rxReduceMems;
      72            0 :     for (u32 i = 0; i < sliceSize; i++) {
      73              :         DeviceMem dstMem =
      74            0 :             outputMem_.range(outputSlices[rank * sliceSize + i].offset, outputSlices[rank * sliceSize + i].size);
      75              :         // reduce目的操作
      76              :         DeviceMem srcMem =
      77            0 :             inputMem_.range(inputSlices[rank * sliceSize + i].offset, inputSlices[rank * sliceSize + i].size);
      78              :         DeviceMem scratchMem = 
      79            0 :             scratchMem_.range(outputSlices[rank * sliceSize + i].offset, outputSlices[rank * sliceSize + i].size);
      80            0 :         rxReduceMems.emplace_back(ReducerMemoryInfo{baseOffset_ + inputSlices[rank * sliceSize + i].offset,
      81              :             srcMem, dstMem, scratchMem});
      82            0 :     }
      83            0 :     CHK_RET(reducerInfo_->run(dispatcher_, link, rxReduceMems, notifyIdx_, stream_));
      84              : 
      85            0 :     notifyIdx_++;
      86              : 
      87            0 :     return HCCL_SUCCESS;
      88            0 : }
      89              : 
      90            0 : HcclResult ReduceScatterSlimRing::RunSourceReducer(const LINK &link, const Slice &txSlice, const Slice &txSlicetemp)
      91              : {
      92              :     /* 1、对外reduce_scatter,output的大小为每块数据*rank_size。只能发送到对端地址偏移为0开始。
      93              :       2、allreduce中使用reduce_scatter,output与Input大小相等,接收和发送偏移相等都为slice.offset */
      94            0 :     DeviceMem srcMem = inputMem_.range(txSlice.offset, txSlice.size);
      95            0 :     HCCL_DEBUG(" send inputmem range[%llu], size[%llu] tx dstmem offset[%llu]", txSlice.offset, txSlice.size,
      96              :         txSlicetemp.offset);
      97            0 :     CHK_RET(senderInfo_->run(link, baseOffset_ + txSlicetemp.offset, srcMem, stream_));
      98              : 
      99            0 :     return HCCL_SUCCESS;
     100            0 : }
     101              : 
     102            0 : HcclResult ReduceScatterSlimRing::RunDestRducer(const LINK &link, const Slice &rxSlice, const Slice &rxSlicetemp)
     103              : {
     104            0 :     DeviceMem dstMem = inputMem_.range(rxSlice.offset, rxSlice.size);
     105            0 :     DeviceMem srcMemTemp = scratchMem_.range(rxSlicetemp.offset, rxSlicetemp.size);
     106            0 :     HCCL_DEBUG("rcv offset[%llu], size[%llu] ,then reduce with "
     107              :         "offset[%llu] size[%llu] ",
     108              :         rxSlicetemp.offset, rxSlicetemp.size, rxSlice.offset, rxSlice.size);
     109            0 :     CHK_RET(reducerInfo_->run(dispatcher_, link, baseOffset_ + rxSlice.offset, dstMem, dstMem, srcMemTemp, stream_));
     110              : 
     111            0 :     return HCCL_SUCCESS;
     112            0 : }
     113              : 
     114            0 : HcclResult ReduceScatterSlimRing::InitSlice(std::vector<Slice>& outputSlices, u32 rank, u32 rankSize, u32 unitSize){
     115            0 :     if (slices_.size() == 0) {
     116            0 :         slices_.resize(rankSize);
     117            0 :         outputSlices.resize(rankSize);
     118            0 :         u64 sliceSize = count_ * unitSize;
     119            0 :         for (u32 i = 0; i < rankSize; i++) {
     120            0 :             slices_[i].size = sliceSize;
     121            0 :             slices_[i].offset = (i * sliceSize);
     122            0 :             outputSlices[i].size = sliceSize;
     123            0 :             outputSlices[i].offset = (inputMem_.size() > outputMem_.size()) ? 0 : (i * sliceSize);
     124            0 :             HCCL_DEBUG("rank[%u], slices[%u].offset=[%llu], slices[%u].size=[%llu] outputSlices[%u].offset=[%llu], \
     125              :                 outputSlices[%u].size=[%llu] ", rank, i, slices_[i].offset, i, slices_[i].size, i, \
     126              :                        outputSlices[i].offset, i, outputSlices[i].size);
     127              :         }
     128              :     }
     129            0 :     return HCCL_SUCCESS;
     130              : }
     131              : 
     132              : 
     133            0 : HcclResult ReduceScatterSlimRing::RunAsync(const u32 rank, const u32 rankSize, const std::vector<LINK> &links)
     134              : {
     135              :     // 判断stream, dispatcher是否为空
     136            0 :     CHK_SMART_PTR_NULL(dispatcher_);
     137            0 :     CHK_PTR_NULL(stream_.ptr());
     138            0 :     if (!outputMem_ || !inputMem_) {
     139            0 :         HCCL_ERROR("[ReduceScatterSlimRing][RunAsync]rank[%u] run_async inputmem or outputmem is null", rank);
     140            0 :         return HCCL_E_PTR;
     141              :     }
     142            0 :     HCCL_INFO("ReduceScatterRing run: rank[%u] ranksize[%u] inputMem[%p] outputMem[%p] count[%llu]",
     143              :         rank, rankSize, inputMem_.ptr(), outputMem_.ptr(), count_);
     144              : 
     145              :     // 判断rank_size == 1
     146            0 :     if (rankSize == 1) {
     147            0 :         if (inputMem_ != outputMem_) {
     148            0 :             return HcclD2DMemcpyAsync(dispatcher_, outputMem_, inputMem_, stream_);
     149              :         }
     150            0 :         return HCCL_SUCCESS;
     151              :     }
     152              : 
     153              :     // 创建reducer & sender
     154            0 :     senderInfo_.reset(new (std::nothrow) Sender(dataType_, reductionOp_, reduceAttr_));
     155            0 :     CHK_SMART_PTR_NULL(senderInfo_);
     156              : 
     157            0 :     reducerInfo_.reset(new (std::nothrow) Reducer(dataType_, reductionOp_, reduceAttr_));
     158            0 :     CHK_SMART_PTR_NULL(reducerInfo_);
     159              : 
     160            0 :     if (links.size() < rankSize) {
     161            0 :         HCCL_ERROR("[ReduceScatterSlimRing][RunAsync]rank[%u] link size[%llu] is less than rank size[%u]",
     162              :             rank, links.size(), rankSize);
     163            0 :         return HCCL_E_INTERNAL;
     164              :     }
     165              : 
     166            0 :     u32 ringPrevRank = (rank + rankSize - 1) % rankSize;
     167            0 :     linkLeft_ = links[ringPrevRank];
     168            0 :     CHK_SMART_PTR_NULL(linkLeft_);
     169              : 
     170            0 :     u32 ringNextRank = (rank + 1) % rankSize;
     171            0 :     linkRight_ = links[ringNextRank];
     172            0 :     CHK_SMART_PTR_NULL(linkRight_);
     173              : 
     174            0 :     u32 unitSize = DataUnitSize(dataType_);
     175            0 :     if (unitSize == 0) {
     176            0 :         HCCL_ERROR("[ReduceScatterSlimRing][RunAsync]rank[%u] unit data size is zero", rank);
     177            0 :         return HCCL_E_INTERNAL;
     178              :     }
     179              : 
     180            0 :     std::vector<Slice> outputSlices(slices_);
     181            0 :     InitSlice(outputSlices, rank, rankSize, unitSize);
     182              :     // 运行reduce-scatter, ring算法
     183              :     // 单环场景下 nicRankList_ 长度默认为 8。
     184              :     // 多环场景下 nicRankList_ 长度为网口数量。此时若 rankSize != nicRankList_ 则为网口裁剪场景
     185            0 :     if (rankSize != HCCL_NIC_MAX_NUM || nicRankList_.size() == HCCL_NIC_MAX_NUM) {
     186              :         // 非网口裁剪场景:
     187            0 :         CHK_RET(RunReduceScatter(rank, rankSize, slices_, outputSlices));
     188              :     } 
     189              : 
     190            0 :     if (barrierSwitchOn_) {
     191              :         // 执行barrier,保证数据收发完成
     192            0 :         CHK_RET(ExecuteBarrier(linkRight_, linkLeft_, notifyIdx_));
     193            0 :         notifyIdx_++;
     194              :     }
     195              : 
     196            0 :     HCCL_INFO("ReduceScatterRing finished: rank[%u]", rank);
     197            0 :     return HCCL_SUCCESS;
     198            0 : }
     199              : 
     200            0 : HcclResult ReduceScatterSlimRing::RunReduceScatter(const u32 rank, const u32 rankSize,
     201              :                                                const std::vector<Slice> &inputSlices,
     202              :                                                const std::vector<Slice> &outputSlices)
     203              : {
     204            0 :     bool bRetSize = (inputSlices.size() < rankSize);
     205            0 :     CHK_PRT_RET(bRetSize,
     206              :         HCCL_ERROR("[Run][ReduceScatter]rank[%u] inputslice size[%llu] is less than rank size[%u]",
     207              :             rank, inputSlices.size(), rankSize), HCCL_E_INTERNAL);
     208              : 
     209            0 :     bRetSize = (outputSlices.size() < rankSize);
     210            0 :     CHK_PRT_RET(bRetSize,
     211              :         HCCL_ERROR("[Run][ReduceScatter]rank[%u] outputslice size[%llu] is less than rank size[%u]",
     212              :             rank, outputSlices.size(), rankSize), HCCL_E_INTERNAL);
     213              : 
     214            0 :     HcclResult ret = HCCL_SUCCESS;
     215              : 
     216            0 :     u32 sliceSize = inputSlices.size() / rankSize;
     217              : 
     218              :     // 获取rx_slice, 首先向本rank前2个rank处发ack消息
     219            0 :     u32 rxSliceIndex = (rank + rankSize - 2) % rankSize;
     220              : 
     221              :     // reduce源操作, 获取tx_slice,从本rank前一rank开始接收ack
     222            0 :     u32 txSliceIndex = (rank + rankSize - 1) % rankSize;
     223              : 
     224            0 :     std::vector<Slice> txInputSegsSlice;
     225            0 :     std::vector<Slice> txOutputSegsSlice;
     226            0 :     for (u32 j = 0; j < sliceSize; j++) {
     227            0 :         txInputSegsSlice.push_back(inputSlices[txSliceIndex * sliceSize + j]);
     228            0 :         txOutputSegsSlice.push_back(outputSlices[txSliceIndex * sliceSize + j]);
     229              :     }
     230            0 :     ret = RunVectorSourceReducer(linkRight_, txInputSegsSlice, txOutputSegsSlice); // NotifyRecord
     231            0 :     CHK_PRT_RET(ret != HCCL_SUCCESS,
     232              :         HCCL_ERROR("[Run][ReduceScatter]rank[%u] txSliceIndex[%u] Reducer src run failed", rank, txSliceIndex), ret);
     233              : 
     234              :     // 本rank既当reduce源, 也当reduce操作的目的
     235            0 :     for (u32 i = 0; i < (rankSize - 2); i++) { // 中间rank_size - 2次传输
     236              :         // reduce目的操作
     237            0 :         std::vector<Slice> rxInputSegsSlice;
     238            0 :         std::vector<Slice> rxOutputSegsSlice;
     239            0 :         for (u32 j = 0; j < sliceSize; j++) {
     240            0 :             rxInputSegsSlice.push_back(inputSlices[rxSliceIndex * sliceSize + j]);
     241            0 :             rxOutputSegsSlice.push_back(outputSlices[rxSliceIndex * sliceSize + j]);
     242              :         }
     243            0 :         ret = RunVectorDestRducer(linkLeft_, rxInputSegsSlice, rxOutputSegsSlice);
     244              : 
     245            0 :         CHK_PRT_RET(ret != HCCL_SUCCESS,
     246              :             HCCL_ERROR("[Run][ReduceScatter]rank[%u] round[%u] rxSlice[%u] Reducer dst run failed", rank, i,
     247              :             rxSliceIndex),
     248              :             ret);
     249              : 
     250            0 :         notifyIdx_++;
     251              : 
     252              :         // 获取rx_slice
     253            0 :         rxSliceIndex = (rxSliceIndex + rankSize - 1) % rankSize;
     254              : 
     255              :         // reduce源操作, 获取tx_slice
     256            0 :         txSliceIndex = (txSliceIndex + rankSize - 1) % rankSize;
     257              : 
     258            0 :         std::vector<Slice> txInputSlice;
     259            0 :         std::vector<Slice> txOutputSlice;
     260            0 :         for (u32 j = 0; j < sliceSize; j++) {
     261            0 :             txInputSlice.push_back(inputSlices[txSliceIndex * sliceSize + j]);
     262            0 :             txOutputSlice.push_back(outputSlices[txSliceIndex * sliceSize + j]);
     263              :         }
     264            0 :         ret = RunVectorSourceReducer(linkRight_, txInputSlice, txOutputSlice);
     265            0 :         CHK_PRT_RET(ret != HCCL_SUCCESS,
     266              :             HCCL_ERROR("[Run][ReduceScatter]rank[%u] round[%u] Reducer src run failed", rank, i), ret);
     267            0 :     }
     268              : 
     269              :     /* * 末尾传输, 本rank只当reduce目的, 根据单buffer还是双buffer来决定如何搬移
     270              :         当前简化处理, 只考虑单buffer的场景, 双buffer则在run_async中多拷贝一次 */
     271            0 :     RunVectorFinRducer(rank, linkLeft_, sliceSize, inputSlices, outputSlices);
     272              : 
     273            0 :     return HCCL_SUCCESS;
     274            0 : }
     275              : 
     276            0 : HcclResult ReduceScatterSlimRing::SetNotifyIdx(u32 notifyIdx)
     277              : {
     278            0 :     notifyIdx_ = notifyIdx;
     279            0 :     return HCCL_SUCCESS;
     280              : }
     281              : 
     282            0 : HcclResult ReduceScatterSlimRing::GetNotifyIdx(u32 &notifyIdx)
     283              : {
     284            0 :     notifyIdx = notifyIdx_;
     285            0 :     return HCCL_SUCCESS;
     286              : }
     287              : 
     288              : REGISTER_TEMPLATE(TemplateType::TEMPLATE_REDUCESCATTER_SLIM_RING, ReduceScatterSlimRing);
     289              : }  // namespace hccl
        

Generated by: LCOV version 2.0-1