LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_reduce_scatter - reduce_scatter_plant_local_reduce.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 232 0
Test Date: 2026-08-18 17:47:01 Functions: 0.0 % 18 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 <cmath>
      12              : #include "alg_template_register.h"
      13              : #include "reduce_scatter_plant_local_reduce.h"
      14              : 
      15              : namespace hccl {
      16              : constexpr u32 DEVICE_EIGHT = 8;
      17              : constexpr u32 FACTOR_NUM_TWO = 2;
      18            0 : ReduceScatterPlantLocalReduce::ReduceScatterPlantLocalReduce(const HcclDispatcher dispatcher)
      19            0 :     : AlgTemplateBase(dispatcher)
      20            0 : {}
      21              : 
      22            0 : ReduceScatterPlantLocalReduce::~ReduceScatterPlantLocalReduce() {}
      23              : 
      24            0 : HcclResult ReduceScatterPlantLocalReduce::Prepare(
      25              :     void* inputMemPtr, DeviceMem& cclInMem, DeviceMem& outputMem, const Stream& stream, std::vector<Stream>& subStreams,
      26              :     std::vector<std::shared_ptr<LocalNotify>>& meshSignal, std::vector<std::shared_ptr<LocalNotify>>& meshSignalAux,
      27              :     GroupSlicesInfo& grouSlicesInfo, const HcclReduceOp reductionOp, u32 all2allOffset, const HcclDataType dataType,
      28              :     bool isNeedSpaceBorrow, bool reverseMemUsage, bool isA3CrossNode)
      29              : {
      30            0 :     inputMemPtr_ = inputMemPtr; // UserInPtr,All2All使用
      31            0 :     inputMem_ = cclInMem;       // 空拷贝 & 存放最后一块数据(Allreduce非整除场景)
      32            0 :     outputMem_ = outputMem;     // 单算子CclOut 图模式Scrach/UserOut,LocalReduce使用
      33            0 :     stream_ = stream;
      34            0 :     subStreams_ = subStreams;
      35            0 :     meshSignalPtr_ = &meshSignal;
      36            0 :     meshSignalAuxPtr_ = &meshSignalAux;
      37            0 :     groupSlicesInfo_ = std::move(grouSlicesInfo);
      38            0 :     reductionOp_ = reductionOp;
      39            0 :     all2allOffset_ = all2allOffset;
      40            0 :     dataType_ = dataType;
      41            0 :     isNeedSpaceBorrow_ = isNeedSpaceBorrow;
      42            0 :     isA3CrossNode_ = isA3CrossNode;
      43            0 :     if (reverseMemUsage) {
      44              :         // 交换两块buffer的用途,in buffer作为输出buffer
      45            0 :         HCCL_INFO("[%s] reverse memory usage.", __func__);
      46            0 :         std::swap(scratchMemType_, outputMemType_);
      47            0 :         std::swap(inputMem_, outputMem_);
      48              :     }
      49            0 :     return HCCL_SUCCESS;
      50              : }
      51              : 
      52            0 : HcclResult ReduceScatterPlantLocalReduce::MainRecordSub(Stream& mainStream, u32 firstSubStreamIndex, u32 totalTask)
      53              : {
      54            0 :     for (u32 streamIndex = firstSubStreamIndex; streamIndex < totalTask; streamIndex++) {
      55            0 :         CHK_RET(LocalNotify::Post(mainStream, dispatcher_, (*meshSignalAuxPtr_)[streamIndex], profilerInput_.stage));
      56              :     }
      57            0 :     return HCCL_SUCCESS;
      58              : }
      59              : 
      60            0 : HcclResult ReduceScatterPlantLocalReduce::SubWaitMain(u32 firstSubStreamIndex, u32 totalTask)
      61              : {
      62            0 :     for (u32 streamIndex = firstSubStreamIndex; streamIndex < totalTask; streamIndex++) {
      63            0 :         CHK_RET(LocalNotify::Wait(
      64              :             subStreams_[streamIndex], dispatcher_, (*meshSignalAuxPtr_)[streamIndex], profilerInput_.stage));
      65              :     }
      66            0 :     return HCCL_SUCCESS;
      67              : }
      68              : 
      69            0 : HcclResult ReduceScatterPlantLocalReduce::MainWaitSub(Stream& mainStream, u32 firstSubStreamIndex, u32 totalTask)
      70              : {
      71            0 :     for (u32 streamIndex = firstSubStreamIndex; streamIndex < totalTask; streamIndex++) {
      72            0 :         CHK_RET(LocalNotify::Wait(mainStream, dispatcher_, (*meshSignalPtr_)[streamIndex], profilerInput_.stage));
      73              :     }
      74            0 :     return HCCL_SUCCESS;
      75              : }
      76              : 
      77            0 : HcclResult ReduceScatterPlantLocalReduce::SubRecordMain(u32 firstSubStreamIndex, u32 totalTask)
      78              : {
      79            0 :     for (u32 streamIndex = firstSubStreamIndex; streamIndex < totalTask; streamIndex++) {
      80            0 :         CHK_RET(LocalNotify::Post(
      81              :             subStreams_[streamIndex], dispatcher_, (*meshSignalPtr_)[streamIndex], profilerInput_.stage));
      82              :     }
      83            0 :     return HCCL_SUCCESS;
      84              : }
      85              : 
      86            0 : HcclResult ReduceScatterPlantLocalReduce::MainRecordLocalReduceWait(u32 lRMainStreamIndex)
      87              : {
      88            0 :     CHK_RET(LocalNotify::Post(stream_, dispatcher_, (*meshSignalAuxPtr_)[lRMainStreamIndex], profilerInput_.stage));
      89            0 :     CHK_RET(LocalNotify::Wait(
      90              :         subStreams_[lRMainStreamIndex], dispatcher_, (*meshSignalAuxPtr_)[lRMainStreamIndex], profilerInput_.stage));
      91            0 :     return HCCL_SUCCESS;
      92              : }
      93              : 
      94            0 : u32 ReduceScatterPlantLocalReduce::CalcOutputIndex(const u32 round)
      95              : {
      96            0 :     return (all2allOffset_ + round + localRank_) % rankSize_;
      97              : }
      98              : 
      99            0 : bool ReduceScatterPlantLocalReduce::isLastGroup(const u32 groupId) { return groupId == groupSlicesInfo_.size() - 1; }
     100              : 
     101            0 : bool ReduceScatterPlantLocalReduce::isLastRank(const u32 rankId) { return rankId == rankSize_ - 1; }
     102              : 
     103            0 : bool ReduceScatterPlantLocalReduce::isLastBlockData(const u32 outputIndex) { return outputIndex == rankSize_ - 1; }
     104              : 
     105            0 : HcclResult ReduceScatterPlantLocalReduce::RunAsync(const u32 rank, const u32 rankSize, const std::vector<LINK>& links)
     106              : {
     107            0 :     HCCL_INFO(
     108              :         "ReduceScatterPlantLocalReduce run: rank[%u] ranksize[%u] inputMem[%p] outputMem[%p].", rank, rankSize,
     109              :         inputMem_.ptr(), outputMem_.ptr());
     110            0 :     CHK_SMART_PTR_NULL(dispatcher_);
     111            0 :     CHK_PTR_NULL(stream_.ptr());
     112            0 :     CHK_PRT_RET(
     113              :         links.size() < rankSize,
     114              :         HCCL_ERROR("[%s]rank[%u] linksize[%llu] is less than rankSize[%u]", __func__, rank, links.size(), rankSize),
     115              :         HCCL_E_INTERNAL);
     116              : 
     117            0 :     rankSize_ = rankSize;
     118            0 :     localRank_ = rank;
     119              : 
     120              :     // All2All主流(主流)通知LocalReduce主流开始准备执行,
     121              :     // All2All需要rankSize条流,其中主流完成LocalCopy&第一个A2A任务,因此主从同步需要rankSize-2个任务。lRMainStreamId_需要-2
     122            0 :     all2allSubStreamNum_ = isA3CrossNode_ ? std::min(rankSize, DEVICE_EIGHT) - 1 : rankSize - 2;
     123            0 :     lRMainStreamId_ = all2allSubStreamNum_;
     124              : 
     125            0 :     CHK_RET(AlgTemplateBase::ExecEmptyTask(inputMem_, outputMem_, stream_, dispatcher_));
     126            0 :     CHK_RET(MainRecordLocalReduceWait(lRMainStreamId_));
     127              :     // 额外一次LocalReduce主流通知All2All主流准备好接受信息(通知第一次执行完的All2AllWait)
     128            0 :     CHK_RET(LocalNotify::Post(
     129              :         subStreams_[lRMainStreamId_], dispatcher_, (*meshSignalPtr_)[lRMainStreamId_], profilerInput_.stage));
     130              : 
     131            0 :     HcclResult ret = HCCL_SUCCESS;
     132            0 :     for (u32 groupId = 0; groupId < groupSlicesInfo_.size(); groupId++) {
     133            0 :         const MemBlockInfo& memBlockInfo = groupSlicesInfo_[groupId];
     134            0 :         if (isA3CrossNode_) {
     135            0 :             ret = RunGroupAlltoAll(links, groupId, memBlockInfo);
     136              :         } else {
     137            0 :             ret = RunAlltoAll(links, groupId, memBlockInfo);
     138              :         }
     139            0 :         CHK_PRT_RET(
     140              :             ret != HCCL_SUCCESS,
     141              :             HCCL_ERROR(
     142              :                 "[%s]RunAlltoAll or RunGroupAlltoAll failed, localRank[%u], groupId[%u]", __func__, localRank_,
     143              :                 groupId),
     144              :             ret);
     145              : 
     146            0 :         CHK_RET(LocalNotify::Wait(stream_, dispatcher_, (*meshSignalPtr_)[lRMainStreamId_], profilerInput_.stage));
     147            0 :         CHK_RET(AlgTemplateBase::ExecEmptyTask(inputMem_, outputMem_, stream_, dispatcher_));
     148            0 :         CHK_RET(MainRecordLocalReduceWait(lRMainStreamId_));
     149            0 :         CHK_RET(AlgTemplateBase::ExecEmptyTask(inputMem_, outputMem_, subStreams_[lRMainStreamId_], dispatcher_));
     150              : 
     151            0 :         ret = RunLocalReduce(groupId, memBlockInfo);
     152            0 :         CHK_PRT_RET(
     153              :             ret != HCCL_SUCCESS,
     154              :             HCCL_ERROR("[%s]LocalReduce failed, localRank[%u], groupId[%u]", __func__, localRank_, groupId), ret);
     155              : 
     156              :         // LocalReduce主流通知All2All主流执行完成,可以下发下一次LocalReduce操作
     157            0 :         CHK_RET(LocalNotify::Post(
     158              :             subStreams_[lRMainStreamId_], dispatcher_, (*meshSignalPtr_)[lRMainStreamId_], profilerInput_.stage));
     159              :     }
     160              : 
     161              :     // All2All主流等待最后一次LocalReduce执行完成
     162            0 :     CHK_RET(LocalNotify::Wait(stream_, dispatcher_, (*meshSignalPtr_)[lRMainStreamId_], profilerInput_.stage));
     163            0 :     CHK_RET(AlgTemplateBase::ExecEmptyTask(inputMem_, outputMem_, stream_, dispatcher_));
     164            0 :     HCCL_INFO("ReduceScatterPlantLocalReduce finished: localRank[%u] ranksize[%u]", localRank_, rankSize_);
     165            0 :     return HCCL_SUCCESS;
     166              : }
     167              : 
     168            0 : HcclResult ReduceScatterPlantLocalReduce::LocalCopy(u32 groupId, const MemBlockInfo& memBlockInfo)
     169              : {
     170            0 :     u64 sliceSize = memBlockInfo.size[localRank_];
     171            0 :     if (sliceSize == 0) {
     172            0 :         return HCCL_SUCCESS;
     173              :     }
     174              : 
     175              :     DeviceMem src
     176            0 :         = DeviceMem::create(static_cast<u8*>(inputMemPtr_) + memBlockInfo.userInputOffsets[localRank_], sliceSize);
     177              : 
     178              :     // 当非最后一组最后一卡且outputIndex是最后一块时,Copy至CclIn/UserIn预留位
     179            0 :     DeviceMem dst;
     180            0 :     u32 outputIndex = CalcOutputIndex(localRank_);
     181            0 :     if (isNeedSpaceBorrow_ && isLastBlockData(outputIndex) && !(isLastRank(localRank_) && isLastGroup(groupId))) {
     182            0 :         dst = inputMem_.range(memBlockInfo.outputOffsets[localRank_], sliceSize);
     183              :     } else {
     184            0 :         dst = outputMem_.range(memBlockInfo.outputOffsets[outputIndex], sliceSize);
     185              :     }
     186            0 :     CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dst, src, stream_));
     187            0 :     return HCCL_SUCCESS;
     188            0 : }
     189              : 
     190            0 : HcclResult ReduceScatterPlantLocalReduce::RunAlltoAll(
     191              :     const std::vector<LINK>& links, u32 groupId, const MemBlockInfo& memBlockInfo)
     192              : {
     193              :     // 本卡优先拷贝同号位数据
     194            0 :     CHK_RET(LocalCopy(groupId, memBlockInfo));
     195              :     // 主流通知从流可以开始接受数据
     196            0 :     u32 all2allfirstSubStreamId = 0;
     197            0 :     CHK_RET(MainRecordSub(stream_, all2allfirstSubStreamId, all2allSubStreamNum_));
     198            0 :     CHK_RET(SubWaitMain(all2allfirstSubStreamId, all2allSubStreamNum_));
     199              : 
     200              :     // 开始数据拷贝
     201            0 :     u32 streamIndex = 0;
     202            0 :     for (u32 round = 0; round < rankSize_; round++) {
     203            0 :         if (round == localRank_) {
     204            0 :             continue;
     205              :         }
     206            0 :         Stream& subStream = (streamIndex == 0) ? stream_ : subStreams_[streamIndex - 1];
     207            0 :         CHK_SMART_PTR_NULL(links[round]);
     208            0 :         CHK_RET(links[round]->TxAck(subStream));
     209            0 :         CHK_RET(links[round]->RxAck(subStream));
     210            0 :         streamIndex++;
     211              :     }
     212              : 
     213            0 :     CHK_RET(SubRecordMain(all2allfirstSubStreamId, all2allSubStreamNum_));
     214            0 :     CHK_RET(MainWaitSub(stream_, all2allfirstSubStreamId, all2allSubStreamNum_));
     215            0 :     CHK_RET(AlgTemplateBase::ExecEmptyTask(inputMem_, outputMem_, subStreams_[lRMainStreamId_], dispatcher_));
     216              : 
     217            0 :     CHK_RET(MainRecordSub(stream_, all2allfirstSubStreamId, all2allSubStreamNum_));
     218            0 :     CHK_RET(SubWaitMain(all2allfirstSubStreamId, all2allSubStreamNum_));
     219            0 :     streamIndex = 0;
     220            0 :     for (u32 round = 0; round < rankSize_; round++) {
     221            0 :         if (round == localRank_) {
     222            0 :             continue;
     223              :         }
     224            0 :         Stream& subStream = (streamIndex == 0) ? stream_ : subStreams_[streamIndex - 1];
     225            0 :         CHK_SMART_PTR_NULL(links[round]);
     226              : 
     227            0 :         u64 sliceSize = memBlockInfo.size[round];
     228            0 :         if (sliceSize != 0) {
     229            0 :             u64 userMemInOffset = memBlockInfo.userInputOffsets[round];
     230            0 :             DeviceMem src = DeviceMem::create(static_cast<u8*>(inputMemPtr_) + userMemInOffset, sliceSize);
     231            0 :             u32 outputIndex = CalcOutputIndex(round);
     232            0 :             u64 dstOffset = 0;
     233            0 :             void* remMemPtr = nullptr;
     234            0 :             if (isNeedSpaceBorrow_ && isLastBlockData(outputIndex) && !(isLastRank(round) && isLastGroup(groupId))) {
     235            0 :                 CHK_RET(links[round]->GetRemoteMem(scratchMemType_, &remMemPtr));
     236            0 :                 dstOffset = memBlockInfo.outputOffsets[round];
     237              :             } else {
     238            0 :                 CHK_RET(links[round]->GetRemoteMem(outputMemType_, &remMemPtr));
     239            0 :                 dstOffset = memBlockInfo.outputOffsets[outputIndex];
     240              :             }
     241            0 :             DeviceMem dst = DeviceMem::create(static_cast<u8*>(remMemPtr) + dstOffset, sliceSize);
     242            0 :             CHK_RET(HcclD2DMemcpyAsync(
     243              :                 dispatcher_, dst, src, subStream, links[round]->GetRemoteRank(), links[round]->GetLinkType()));
     244            0 :         }
     245            0 :         CHK_RET(links[round]->TxDataSignal(subStream));
     246            0 :         CHK_RET(links[round]->RxDataSignal(subStream));
     247            0 :         streamIndex++;
     248              :     }
     249              : 
     250              :     // 从流通知主流完成拷贝
     251            0 :     CHK_RET(SubRecordMain(all2allfirstSubStreamId, all2allSubStreamNum_));
     252            0 :     CHK_RET(MainWaitSub(stream_, all2allfirstSubStreamId, all2allSubStreamNum_));
     253            0 :     return HCCL_SUCCESS;
     254              : }
     255              : 
     256            0 : HcclResult ReduceScatterPlantLocalReduce::RunGroupAlltoAll(
     257              :     const std::vector<LINK>& links, u32 groupId, const MemBlockInfo& memBlockInfo)
     258              : {
     259            0 :     constexpr u32 numInGroup = DEVICE_EIGHT;
     260            0 :     u32 numOfGroups = (rankSize_ + numInGroup - 1) / numInGroup;
     261              : 
     262              :     // 本卡优先拷贝同号位数据
     263            0 :     CHK_RET(LocalCopy(groupId, memBlockInfo));
     264              : 
     265            0 :     for (u32 idGroup = 0; idGroup < numOfGroups; ++idGroup) {
     266              :         // 主流通知从流可以开始接受数据
     267            0 :         u32 all2allfirstSubStreamId = 0;
     268            0 :         CHK_RET(MainRecordSub(stream_, all2allfirstSubStreamId, all2allSubStreamNum_));
     269            0 :         CHK_RET(SubWaitMain(all2allfirstSubStreamId, all2allSubStreamNum_));
     270              : 
     271              :         // 开始数据拷贝
     272            0 :         u32 streamIndex = 0;
     273            0 :         for (u32 cnt = 0, round = idGroup * numInGroup; round < rankSize_ && cnt < numInGroup; ++round, ++cnt) {
     274            0 :             if (round == 0) {
     275            0 :                 continue;
     276              :             }
     277            0 :             u32 sendRank = (localRank_ + round) % rankSize_;
     278            0 :             u32 recvRank = (rankSize_ + localRank_ - round) % rankSize_;
     279            0 :             Stream& subStream = (streamIndex == 0) ? stream_ : subStreams_[streamIndex - 1];
     280            0 :             CHK_SMART_PTR_NULL(links[sendRank]);
     281            0 :             CHK_SMART_PTR_NULL(links[recvRank]);
     282            0 :             CHK_RET(links[recvRank]->TxAck(subStream));
     283            0 :             CHK_RET(links[sendRank]->RxAck(subStream));
     284            0 :             streamIndex++;
     285              :         }
     286              : 
     287            0 :         CHK_RET(SubRecordMain(all2allfirstSubStreamId, all2allSubStreamNum_));
     288            0 :         CHK_RET(MainWaitSub(stream_, all2allfirstSubStreamId, all2allSubStreamNum_));
     289            0 :         CHK_RET(AlgTemplateBase::ExecEmptyTask(inputMem_, outputMem_, subStreams_[lRMainStreamId_], dispatcher_));
     290              : 
     291            0 :         CHK_RET(MainRecordSub(stream_, all2allfirstSubStreamId, all2allSubStreamNum_));
     292            0 :         CHK_RET(SubWaitMain(all2allfirstSubStreamId, all2allSubStreamNum_));
     293            0 :         streamIndex = 0;
     294            0 :         for (u32 cnt = 0, round = idGroup * numInGroup; round < rankSize_ && cnt < numInGroup; ++round, ++cnt) {
     295            0 :             if (round == 0) {
     296            0 :                 continue;
     297              :             }
     298            0 :             u32 sendRank = (localRank_ + round) % rankSize_;
     299            0 :             u32 recvRank = (rankSize_ + localRank_ - round) % rankSize_;
     300            0 :             Stream& subStream = (streamIndex == 0) ? stream_ : subStreams_[streamIndex - 1];
     301            0 :             CHK_SMART_PTR_NULL(links[sendRank]);
     302            0 :             CHK_SMART_PTR_NULL(links[recvRank]);
     303              : 
     304            0 :             u64 sliceSize = memBlockInfo.size[sendRank];
     305            0 :             if (sliceSize != 0) {
     306            0 :                 u64 userMemInOffset = memBlockInfo.userInputOffsets[sendRank];
     307            0 :                 DeviceMem src = DeviceMem::create(static_cast<u8*>(inputMemPtr_) + userMemInOffset, sliceSize);
     308            0 :                 u32 outputIndex = CalcOutputIndex(sendRank);
     309            0 :                 u64 dstOffset = 0;
     310            0 :                 void* remMemPtr = nullptr;
     311            0 :                 if (isNeedSpaceBorrow_ && isLastBlockData(outputIndex)
     312            0 :                     && !(isLastRank(sendRank) && isLastGroup(groupId))) {
     313            0 :                     CHK_RET(links[sendRank]->GetRemoteMem(scratchMemType_, &remMemPtr));
     314            0 :                     dstOffset = memBlockInfo.outputOffsets[sendRank];
     315              :                 } else {
     316            0 :                     CHK_RET(links[sendRank]->GetRemoteMem(outputMemType_, &remMemPtr));
     317            0 :                     dstOffset = memBlockInfo.outputOffsets[outputIndex];
     318              :                 }
     319            0 :                 DeviceMem dst = DeviceMem::create(static_cast<u8*>(remMemPtr) + dstOffset, sliceSize);
     320            0 :                 CHK_RET(HcclD2DMemcpyAsync(
     321              :                     dispatcher_, dst, src, subStream, links[sendRank]->GetRemoteRank(),
     322              :                     links[sendRank]->GetLinkType()));
     323            0 :             }
     324            0 :             CHK_RET(links[sendRank]->TxDataSignal(subStream));
     325            0 :             CHK_RET(links[recvRank]->RxDataSignal(subStream));
     326            0 :             streamIndex++;
     327              :         }
     328              : 
     329              :         // 从流通知主流完成拷贝
     330            0 :         CHK_RET(SubRecordMain(all2allfirstSubStreamId, all2allSubStreamNum_));
     331            0 :         CHK_RET(MainWaitSub(stream_, all2allfirstSubStreamId, all2allSubStreamNum_));
     332              :     }
     333              : 
     334            0 :     return HCCL_SUCCESS;
     335              : }
     336              : 
     337            0 : HcclResult ReduceScatterPlantLocalReduce::RunLocalReduce(u32 groupId, const MemBlockInfo& memBlockInfo)
     338              : {
     339            0 :     u32 reduceStep = static_cast<u32>(std::ceil(log2(rankSize_)));
     340            0 :     u64 srcOffset = memBlockInfo.inputOffsets[localRank_];
     341            0 :     u64 sliceSize = memBlockInfo.size[localRank_];
     342            0 :     u32 dataUnitSize = DataUnitSize(dataType_);
     343            0 :     if (dataUnitSize == 0) {
     344            0 :         HCCL_ERROR(
     345              :             "[ReduceScatterPlantLocalReduce][RunLocalReduce]data type[%s] out of range[%d, %d]",
     346              :             GetDataTypeEnumStr(dataType_).c_str(), HCCL_DATA_TYPE_INT8, static_cast<int>(HCCL_DATA_TYPE_RESERVED) - 1);
     347            0 :         return HCCL_E_INTERNAL;
     348              :     }
     349            0 :     u64 count = sliceSize / dataUnitSize;
     350              : 
     351            0 :     for (u32 round = 0; round < reduceStep; round++) {
     352            0 :         u32 tailIndex = std::min(rankSize_, static_cast<u32>(1 << static_cast<int>(reduceStep - round))) - 1;
     353            0 :         u32 headIndex = static_cast<u32>(1 << static_cast<int>((reduceStep - round - 1)));
     354            0 :         u32 reduceSubStreamNum = std::min(tailIndex - headIndex, DEVICE_EIGHT / FACTOR_NUM_TWO - 1);
     355              :         // LR主流通知从流可以开始接受数据
     356            0 :         for (u32 offset = 0; offset < reduceSubStreamNum; offset++) {
     357            0 :             u32 streamId = lRMainStreamId_ + offset + 1;
     358              :             // 只有reduce任务 > 1时才需要主从流同步: LR主流通知从流, 从流Wait LR主流
     359            0 :             CHK_RET(LocalNotify::Post(
     360              :                 subStreams_[lRMainStreamId_], dispatcher_, (*meshSignalAuxPtr_)[streamId], profilerInput_.stage));
     361            0 :             CHK_RET(LocalNotify::Wait(
     362              :                 subStreams_[streamId], dispatcher_, (*meshSignalAuxPtr_)[streamId], profilerInput_.stage));
     363              :         }
     364              : 
     365              :         // LocalReduce操作
     366            0 :         for (u32 offset = 0; offset <= tailIndex - headIndex; offset++) {
     367            0 :             u32 inputIndex = CalcOutputIndex(headIndex + offset); // reduce的源数据offset
     368            0 :             u32 outputIndex = CalcOutputIndex(offset);            // reduce的目标offset
     369            0 :             u32 streamOffset = offset % (reduceSubStreamNum + 1);
     370            0 :             Stream& subStream = subStreams_[lRMainStreamId_ + streamOffset];
     371            0 :             if (sliceSize == 0) {
     372            0 :                 continue;
     373              :             }
     374              :             void* srcPtr;
     375              :             void* dstPtr;
     376            0 :             if (isNeedSpaceBorrow_ && !(isLastRank(localRank_) && isLastGroup(groupId))
     377            0 :                 && isLastBlockData(inputIndex)) {
     378            0 :                 srcPtr = static_cast<u8*>(inputMem_.ptr()) + srcOffset;
     379              :             } else {
     380            0 :                 srcPtr = static_cast<u8*>(outputMem_.ptr()) + memBlockInfo.outputOffsets[inputIndex];
     381              :             }
     382              : 
     383            0 :             if (isNeedSpaceBorrow_ && !(isLastRank(localRank_) && isLastGroup(groupId))
     384            0 :                 && isLastBlockData(outputIndex)) {
     385            0 :                 dstPtr = static_cast<u8*>(inputMem_.ptr()) + srcOffset;
     386              :             } else {
     387            0 :                 dstPtr = static_cast<u8*>(outputMem_.ptr()) + memBlockInfo.outputOffsets[outputIndex];
     388              :             }
     389              : 
     390            0 :             CHK_RET(HcclReduceAsync(
     391              :                 dispatcher_, srcPtr, count, dataType_, reductionOp_, subStream, dstPtr, INVALID_VALUE_RANKID,
     392              :                 LinkType::LINK_ONCHIP, INLINE_REDUCE_BIT));
     393              :         }
     394              : 
     395              :         // 从流通知LR主流可以开始下一轮
     396            0 :         for (u32 offset = 0; offset < reduceSubStreamNum; offset++) {
     397            0 :             u32 streamId = lRMainStreamId_ + offset + 1;
     398              :             // 只有reduce任务 > 1时才需要主从流同步: LR主流通知从流, 从流Wait LR主流
     399            0 :             CHK_RET(LocalNotify::Post(
     400              :                 subStreams_[streamId], dispatcher_, (*meshSignalPtr_)[streamId], profilerInput_.stage));
     401            0 :             CHK_RET(LocalNotify::Wait(
     402              :                 subStreams_[lRMainStreamId_], dispatcher_, (*meshSignalPtr_)[streamId], profilerInput_.stage));
     403              :         }
     404              : 
     405            0 :         CHK_RET(AlgTemplateBase::ExecEmptyTask(inputMem_, outputMem_, subStreams_[lRMainStreamId_], dispatcher_));
     406              :     }
     407              : 
     408            0 :     return HCCL_SUCCESS;
     409              : }
     410              : REGISTER_TEMPLATE(TemplateType::TEMPLATE_REDUCESCATTER_PLANT_LOCAL_REDUCE, ReduceScatterPlantLocalReduce);
     411              : } // namespace hccl
        

Generated by: LCOV version 2.0-1