LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_all_reduce - all_reduce_graph_pipeline.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 178 0
Test Date: 2026-08-18 17:47:01 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 "alg_template_register.h"
      12              : #include "all_reduce_graph_pipeline.h"
      13              : 
      14              : constexpr u32 STEP_OFFSET_TWO = 2;
      15              : 
      16              : namespace hccl {
      17            0 : AllReduceGraphPipeline::AllReduceGraphPipeline(const HcclDispatcher dispatcher) : AlgTemplateBase(dispatcher) {}
      18              : 
      19            0 : AllReduceGraphPipeline::~AllReduceGraphPipeline() {}
      20              : 
      21            0 : HcclResult AllReduceGraphPipeline::Prepare(u64 reduceAttrBitMap, [[maybe_unused]] HcomCollOpInfo* opInfo)
      22              : {
      23            0 :     reduceAttr_ = reduceAttrBitMap;
      24            0 :     return HCCL_SUCCESS;
      25              : }
      26              : 
      27            0 : HcclResult AllReduceGraphPipeline::MainWaitSub()
      28              : {
      29            0 :     u32 subStreamNum = intraRankSize_ - 1;
      30            0 :     for (u32 signalIndex = 0; signalIndex < subStreamNum; signalIndex++) {
      31            0 :         CHK_RET(LocalNotify::Wait(stream_, dispatcher_, streamNotifyMain_[signalIndex], INVALID_VALUE_STAGE));
      32              :     }
      33            0 :     return HCCL_SUCCESS;
      34              : }
      35              : 
      36            0 : HcclResult AllReduceGraphPipeline::SubRecordMain()
      37              : {
      38            0 :     u32 subStreamNum = intraRankSize_ - 1;
      39            0 :     for (u32 streamIndex = 0; streamIndex < subStreamNum; streamIndex++) {
      40            0 :         CHK_RET(LocalNotify::Post(subStreams_[streamIndex], dispatcher_, streamNotifyMain_[streamIndex], -1));
      41              :     }
      42            0 :     return HCCL_SUCCESS;
      43              : }
      44              : 
      45            0 : HcclResult AllReduceGraphPipeline::MainRecordSub()
      46              : {
      47            0 :     u32 subStreamNum = intraRankSize_ - 1;
      48            0 :     for (u32 signalIndex = 0; signalIndex < subStreamNum; signalIndex++) {
      49            0 :         CHK_RET(LocalNotify::Post(stream_, dispatcher_, streamNotifySub_[signalIndex], -1));
      50              :     }
      51            0 :     return HCCL_SUCCESS;
      52              : }
      53              : 
      54            0 : HcclResult AllReduceGraphPipeline::SubWaitMain()
      55              : {
      56            0 :     u32 subStreamNum = intraRankSize_ - 1;
      57            0 :     for (u32 streamIndex = 0; streamIndex < subStreamNum; streamIndex++) {
      58            0 :         CHK_RET(LocalNotify::Wait(
      59              :             subStreams_[streamIndex], dispatcher_, streamNotifySub_[streamIndex], INVALID_VALUE_STAGE));
      60              :     }
      61            0 :     return HCCL_SUCCESS;
      62              : }
      63              : 
      64            0 : HcclResult AllReduceGraphPipeline::RunReduceScatterIntraServer(u32 step)
      65              : {
      66            0 :     for (u32 i = 1; i < intraRankSize_; i++) {
      67            0 :         u32 remIntraRankId = (intraRankId_ + i) % intraRankSize_;
      68            0 :         CHK_RET(intraLinks_[remIntraRankId]->TxAck(subStreams_[i - 1]));
      69            0 :         CHK_RET(intraLinks_[remIntraRankId]->RxAck(subStreams_[i - 1]));
      70            0 :         void* remoteMemPtr = nullptr;
      71            0 :         CHK_RET(intraLinks_[remIntraRankId]->GetRemoteMem(UserMemType::INPUT_MEM, &remoteMemPtr));
      72            0 :         u32 sliceId = ((interRankId_ + step + 1) % interRankSize_) * intraRankSize_ + remIntraRankId;
      73            0 :         u64 srcOffset = sliceId * memSliceSize_;
      74            0 :         u64 dataSize = memSliceSize_;
      75            0 :         u64 dataCount = sliceCount_;
      76            0 :         if (sliceId == (interRankSize_ * intraRankSize_ - 1)) {
      77            0 :             dataSize = lastSliceSize_;
      78            0 :             dataCount = lastSliceCount_;
      79              :         }
      80            0 :         DeviceMem src = DeviceMem::create(static_cast<u8*>(usrInMem_) + srcOffset, dataSize);
      81            0 :         DeviceMem dst = DeviceMem::create(static_cast<u8*>(remoteMemPtr) + srcOffset, dataSize);
      82              : 
      83            0 :         CHK_RET(HcclReduceAsync(
      84              :             dispatcher_, src.ptr(), dataCount, dataType_, reductionOp_, subStreams_[i - 1], dst.ptr(),
      85              :             intraLinks_[remIntraRankId]->GetRemoteRank(), intraLinks_[remIntraRankId]->GetLinkType(),
      86              :             INLINE_REDUCE_BIT));
      87              : 
      88            0 :         CHK_RET(intraLinks_[remIntraRankId]->TxDataSignal(subStreams_[i - 1]));
      89            0 :         CHK_RET(intraLinks_[remIntraRankId]->RxDataSignal(subStreams_[i - 1]));
      90            0 :     }
      91            0 :     return HCCL_SUCCESS;
      92              : }
      93              : 
      94            0 : HcclResult AllReduceGraphPipeline::RunAllGatherIntraServer(u32 step)
      95              : {
      96            0 :     for (u32 i = 1; i < intraRankSize_; i++) {
      97            0 :         u32 remIntraRankId = (intraRankId_ + i) % intraRankSize_;
      98            0 :         CHK_RET(intraLinks_[remIntraRankId]->TxAck(subStreams_[i - 1]));
      99            0 :         CHK_RET(intraLinks_[remIntraRankId]->RxAck(subStreams_[i - 1]));
     100            0 :         void* remoteMemPtr = nullptr;
     101            0 :         CHK_RET(intraLinks_[remIntraRankId]->GetRemoteMem(UserMemType::OUTPUT_MEM, &remoteMemPtr));
     102            0 :         u32 sliceId = ((interRankId_ + step) % interRankSize_) * intraRankSize_ + remIntraRankId;
     103            0 :         u64 dstOffset = sliceId * memSliceSize_;
     104            0 :         u64 dataSize = memSliceSize_;
     105            0 :         if (sliceId == (interRankSize_ * intraRankSize_ - 1)) {
     106            0 :             dataSize = lastSliceSize_;
     107              :         }
     108            0 :         DeviceMem src = DeviceMem::create(static_cast<u8*>(remoteMemPtr) + dstOffset, dataSize);
     109            0 :         DeviceMem dst = DeviceMem::create(static_cast<u8*>(usrOutMem_) + dstOffset, dataSize);
     110              : 
     111            0 :         CHK_RET(HcclD2DMemcpyAsync(
     112              :             dispatcher_, dst, src, subStreams_[i - 1], intraLinks_[remIntraRankId]->GetRemoteRank(),
     113              :             intraLinks_[remIntraRankId]->GetLinkType()));
     114              : 
     115            0 :         CHK_RET(intraLinks_[remIntraRankId]->TxDataSignal(subStreams_[i - 1]));
     116            0 :         CHK_RET(intraLinks_[remIntraRankId]->RxDataSignal(subStreams_[i - 1]));
     117            0 :     }
     118            0 :     return HCCL_SUCCESS;
     119              : }
     120              : 
     121              : HcclResult
     122            0 : AllReduceGraphPipeline::RunReduceScatterInterServer(u32 step, const LINK& prevInterLink, const LINK& nextInterLink)
     123              : {
     124            0 :     u32 txSliceId = ((interRankId_ + 1 + step) % interRankSize_) * intraRankSize_ + intraRankId_;
     125            0 :     u64 txSliceOffset = memSliceSize_ * txSliceId;
     126            0 :     u64 txDataSize = memSliceSize_;
     127            0 :     if (txSliceId == (interRankSize_ * intraRankSize_ - 1)) {
     128            0 :         txDataSize = lastSliceSize_;
     129              :     }
     130            0 :     DeviceMem srcMem = DeviceMem::create(static_cast<u8*>(usrInMem_) + txSliceOffset, txDataSize);
     131            0 :     CHK_RET(senderInfo_->run(nextInterLink, txSliceOffset, srcMem, stream_, UserMemType::INPUT_MEM));
     132            0 :     HCCL_DEBUG(
     133              :         "[AllReduceGraphPipeline][RunReduceScatterInterServer] local rank[%u], localOffset[%llu],"
     134              :         "tx with slice[%llu]",
     135              :         rankId_, txSliceOffset, txDataSize);
     136              : 
     137            0 :     u32 rxSliceId = ((interRankId_ + 2 + step) % interRankSize_) * intraRankSize_ + intraRankId_;
     138            0 :     u64 rxSliceOffset = memSliceSize_ * rxSliceId;
     139            0 :     u64 rxDataSize = memSliceSize_;
     140            0 :     if (rxSliceId == (interRankSize_ * intraRankSize_ - 1)) {
     141            0 :         rxDataSize = lastSliceSize_;
     142              :     }
     143            0 :     DeviceMem rxLocalMem = DeviceMem::create(static_cast<u8*>(usrInMem_) + rxSliceOffset, rxDataSize);
     144            0 :     CHK_RET(reducerInfo_->run(dispatcher_, prevInterLink, rxSliceOffset, rxLocalMem, rxLocalMem, rxLocalMem, stream_));
     145            0 :     return HCCL_SUCCESS;
     146            0 : }
     147              : 
     148              : HcclResult
     149            0 : AllReduceGraphPipeline::RunAllGatherInterServer(u32 step, const LINK& prevInterLink, const LINK& nextInterLink)
     150              : {
     151            0 :     u32 txSliceId = ((interRankId_ + step) % interRankSize_) * intraRankSize_ + intraRankId_;
     152            0 :     u64 txSliceOffset = memSliceSize_ * txSliceId;
     153            0 :     u64 txDataSize = memSliceSize_;
     154            0 :     if (txSliceId == (interRankSize_ * intraRankSize_ - 1)) {
     155            0 :         txDataSize = lastSliceSize_;
     156              :     }
     157            0 :     CHK_RET(nextInterLink->TxAsync(
     158              :         UserMemType::OUTPUT_MEM, txSliceOffset, static_cast<u8*>(usrOutMem_) + txSliceOffset, txDataSize, stream_));
     159            0 :     HCCL_DEBUG(
     160              :         "[AllReduceGraphPipeline][RunAllGatherInterServer] local rank[%u], localOffset[%llu],"
     161              :         "tx with slice[%llu]",
     162              :         rankId_, txSliceOffset, txDataSize);
     163              : 
     164            0 :     u32 rxSliceId = ((interRankId_ + step + 1) % interRankSize_) * intraRankSize_ + intraRankId_;
     165            0 :     u64 rxSliceOffset = memSliceSize_ * rxSliceId;
     166            0 :     u64 rxDataSize = memSliceSize_;
     167            0 :     if (rxSliceId == (interRankSize_ * intraRankSize_ - 1)) {
     168            0 :         rxDataSize = lastSliceSize_;
     169              :     }
     170            0 :     CHK_RET(prevInterLink->RxAsync(
     171              :         UserMemType::OUTPUT_MEM, rxSliceOffset, static_cast<u8*>(usrOutMem_) + rxSliceOffset, rxDataSize, stream_));
     172            0 :     return HCCL_SUCCESS;
     173              : }
     174              : 
     175            0 : HcclResult AllReduceGraphPipeline::RunAsync()
     176              : {
     177              :     // inter ring algo
     178            0 :     u32 prevInterRankId = (interRankId_ + 1) % interRankSize_;
     179            0 :     u32 nextInterRankId = (interRankId_ - 1 + interRankSize_) % interRankSize_;
     180            0 :     LINK prevInterLink = interLinks_[prevInterRankId];
     181            0 :     LINK nextInterLink = interLinks_[nextInterRankId];
     182              :     // 在user in执行reducescatter pipeline
     183            0 :     for (u32 step = 0; step < interRankSize_; step++) {
     184            0 :         if (step == 0) {
     185            0 :             CHK_RET(MainRecordSub());
     186            0 :             CHK_RET(SubWaitMain());
     187              :         }
     188              :         // server内做SDMA的reduce
     189            0 :         CHK_RET(RunReduceScatterIntraServer(step));
     190            0 :         CHK_RET(SubRecordMain());
     191            0 :         CHK_RET(MainWaitSub());
     192            0 :         if (step < interRankSize_ - 1) {
     193            0 :             CHK_RET(MainRecordSub());
     194            0 :             CHK_RET(SubWaitMain());
     195            0 :             CHK_RET(prevInterLink->TxAck(stream_));
     196            0 :             CHK_RET(nextInterLink->RxAck(stream_));
     197              :             // server间做RDMA的reduce,可与下一个step的SDMA并发执行
     198            0 :             CHK_RET(RunReduceScatterInterServer(step, prevInterLink, nextInterLink));
     199              :             // 确保step[n+2]的SDMA之前step[n]的RDMA已经完成,防止内存踩踏
     200            0 :             CHK_RET(prevInterLink->PostFinAck(stream_));
     201            0 :             CHK_RET(nextInterLink->WaitFinAck(stream_));
     202              :         }
     203              :     }
     204              : 
     205              :     // reducescatter通信结束,将数据从user in拷贝到user out
     206            0 :     u64 localOffsetByte = memSliceSize_ * rankId_;
     207            0 :     u64 dataSize = memSliceSize_;
     208            0 :     if (rankId_ == (interRankSize_ * intraRankSize_ - 1)) {
     209            0 :         dataSize = lastSliceSize_;
     210              :     }
     211            0 :     DeviceMem locSrc = DeviceMem::create(static_cast<u8*>(usrInMem_) + localOffsetByte, dataSize);
     212            0 :     DeviceMem locDst = DeviceMem::create(static_cast<u8*>(usrOutMem_) + localOffsetByte, dataSize);
     213            0 :     CHK_RET(HcclD2DMemcpyAsync(dispatcher_, locDst, locSrc, stream_));
     214              : 
     215              :     // 在user out执行allgather pipeline
     216            0 :     for (u32 step = 0; step < interRankSize_; step++) {
     217            0 :         CHK_RET(MainRecordSub());
     218            0 :         CHK_RET(SubWaitMain());
     219            0 :         if (step < interRankSize_ - 1) {
     220            0 :             CHK_RET(prevInterLink->TxAck(stream_));
     221            0 :             CHK_RET(nextInterLink->RxAck(stream_));
     222            0 :             CHK_RET(RunAllGatherInterServer(step, prevInterLink, nextInterLink));
     223            0 :             CHK_RET(prevInterLink->PostFinAck(stream_));
     224            0 :             CHK_RET(nextInterLink->WaitFinAck(stream_));
     225              :             // inter的最后一步需要barrier确保数据发完
     226            0 :             if (step == interRankSize_ - STEP_OFFSET_TWO) {
     227            0 :                 CHK_RET(ExecuteBarrier(prevInterLink, nextInterLink));
     228              :             }
     229              :         }
     230            0 :         HCCL_DEBUG("[AllReducePipeline][RunAsync]step %u runAllGatherInterServer success", step);
     231            0 :         CHK_RET(RunAllGatherIntraServer(step));
     232            0 :         CHK_RET(SubRecordMain());
     233            0 :         CHK_RET(MainWaitSub());
     234            0 :         HCCL_INFO("[AllReducePipeline][RunAsync]AllReducePipeline finished groupRankId[%u] ", rankId_);
     235              :     }
     236            0 :     return HCCL_SUCCESS;
     237            0 : }
     238              : 
     239            0 : HcclResult AllReduceGraphPipeline::Prepare(
     240              :     const HcomCollOpInfo* opInfo, [[maybe_unused]] DeviceMem& cclBufferA, [[maybe_unused]] DeviceMem& cclBufferB,
     241              :     const u64 count, const SubCommInfo& level1CommInfo, const SubCommInfo& level0CommInfo, Stream& mainStream,
     242              :     std::vector<Stream>& subStream, std::vector<std::shared_ptr<LocalNotify>>& notifyMain,
     243              :     std::vector<std::shared_ptr<LocalNotify>>& notifySub)
     244              : {
     245            0 :     unitSize_ = SIZE_TABLE[opInfo->dataType];
     246            0 :     sliceCount_ = count / (level0CommInfo.localRankSize * level1CommInfo.localRankSize);
     247            0 :     memSliceSize_ = sliceCount_ * unitSize_;
     248            0 :     lastSliceCount_ = count - sliceCount_ * (level0CommInfo.localRankSize * level1CommInfo.localRankSize - 1);
     249            0 :     lastSliceSize_ = lastSliceCount_ * unitSize_;
     250            0 :     HCCL_DEBUG("[%s] PrepareSliceDataWithAlignSize for data_slice_prepare", __func__);
     251              : 
     252            0 :     usrInMem_ = opInfo->inputAddr;
     253            0 :     usrOutMem_ = opInfo->outputAddr;
     254            0 :     reductionOp_ = opInfo->reduceOp;
     255            0 :     dataType_ = opInfo->dataType;
     256              : 
     257              :     // needed resource
     258              :     // stream: 1 * mainStream + (n -1) * subStream
     259              :     // interNotify, streamNotify
     260              : 
     261              :     // stream
     262              :     // mainStream负责locMemCpy、inter执行以及subStream同步控制
     263            0 :     stream_ = mainStream;
     264              :     // subStream负责:
     265              :     // streamId[0:intraRankSize-1]: intraRankSize-1个intra执行
     266            0 :     subStreams_ = subStream;
     267              : 
     268            0 :     intraRankSize_ = level0CommInfo.localRankSize;
     269            0 :     interRankSize_ = level1CommInfo.localRankSize;
     270            0 :     intraRankId_ = level0CommInfo.localRank;
     271            0 :     interRankId_ = level1CommInfo.localRank;
     272            0 :     rankId_ = intraRankId_ + interRankId_ * intraRankSize_;
     273              : 
     274              :     // streamNotify, size: n
     275            0 :     streamNotifyMain_ = notifyMain;
     276            0 :     if (streamNotifyMain_.size() < intraRankSize_ - 1) {
     277            0 :         HCCL_ERROR(
     278              :             "[AllReduceGraphPipeline][Prepare]rank[%u] streamNotifyMain_ size [%u] error, is smaller than,"
     279              :             "intraRankSize_[%u]",
     280              :             rankId_, streamNotifyMain_.size(), intraRankSize_);
     281            0 :         return HCCL_E_INTERNAL;
     282              :     }
     283            0 :     streamNotifySub_ = notifySub;
     284            0 :     if (streamNotifySub_.size() < intraRankSize_ - 1) {
     285            0 :         HCCL_ERROR(
     286              :             "[AllReduceGraphPipeline][Prepare]rank[%u] streamNotifySub_ size [%u] error, is smaller than,"
     287              :             "intraRankSize_[%u]",
     288              :             rankId_, streamNotifySub_.size(), intraRankSize_);
     289            0 :         return HCCL_E_INTERNAL;
     290              :     }
     291              : 
     292            0 :     intraLinks_ = level0CommInfo.links;
     293            0 :     interLinks_ = level1CommInfo.links;
     294              : 
     295            0 :     HCCL_INFO(
     296              :         "[AllReduceGraphPipeline][Prepare]streamNum[%u], streamNotifyMainNum[%u], streamNotifySubNum[%u]",
     297              :         subStreams_.size(), streamNotifyMain_.size(), streamNotifySub_.size());
     298            0 :     HCCL_INFO(
     299              :         "[AllReduceGraphPipeline][Prepare]interLinksNum[%u], intraLinksNum[%u]", interLinks_.size(),
     300              :         intraLinks_.size());
     301            0 :     senderInfo_.reset(new (std::nothrow) Sender(dataType_, reductionOp_, reduceAttr_));
     302            0 :     CHK_SMART_PTR_NULL(senderInfo_);
     303            0 :     reducerInfo_.reset(new (std::nothrow) Reducer(dataType_, reductionOp_, reduceAttr_));
     304            0 :     CHK_SMART_PTR_NULL(reducerInfo_);
     305            0 :     return HCCL_SUCCESS;
     306              : }
     307              : REGISTER_TEMPLATE(TemplateType::TEMPLATE_ALLREDUCE_GRAPH_PIPELINE, AllReduceGraphPipeline);
     308              : } // namespace hccl
        

Generated by: LCOV version 2.0-1