LCOV - code coverage report
Current view: top level - legacy/ascend950/service/collective/alg/coll_alg_factory/alg_ccu_context/broadcast - ccu_context_broadcast_nhr1d_mem2mem.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 220 0
Test Date: 2026-07-28 12:11:00 Functions: 0.0 % 13 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 "ccu_context_broadcast_nhr1d_mem2mem.h"
      12              : 
      13              : namespace Hccl {
      14              : 
      15              : constexpr uint16_t TOKEN_XN_ID      = 2;
      16              : constexpr uint16_t OUTPUT_XN_ID     = 1;
      17              : constexpr uint16_t RANK_NUM_PER_CKE = 16; // 本rank给远端置位时应当写的CKE,16个对端一个CKE
      18              : constexpr uint16_t CKE_IDX_0        = 0;    // 后同步
      19              : constexpr uint16_t CKE_IDX_1        = 1;    // 前同步addr
      20              : constexpr uint16_t CKE_IDX_2        = 2;    // 前同步token
      21              : constexpr uint16_t CKE_IDX_3        = 3;    // NHR step同步信号0,用于RS前同步,AG后同步
      22              : constexpr uint16_t CKE_IDX_4        = 4;    // NHR step同步信号1,用于RS后同步
      23              : constexpr uint16_t FST_AXIS_ID      = 0;
      24              : constexpr uint16_t SEC_AXIS_ID      = 1;
      25              : 
      26            0 : CcuContextBroadcastNHRMem2Mem1D::CcuContextBroadcastNHRMem2Mem1D(const CcuCtxArg &arg, const std::vector<CcuTransport *> &transports,
      27            0 :                                                    const CcuTransportGroup &group)
      28            0 :     : CcuContextAlgBase(arg, transports, group)
      29              : {
      30            0 :     const CcuCtxArgBroadcastNHRMem2Mem1D *ctxArg = dynamic_cast<const CcuCtxArgBroadcastNHRMem2Mem1D *>(&arg);
      31            0 :     rankId_                               = ctxArg->rankId_;
      32            0 :     axisId_                               = ctxArg->axisId_;
      33            0 :     axisSize_                             = ctxArg->axisSize_;
      34            0 :     dimSize_                              = ctxArg->dimSize_[0];
      35            0 :     localAxisSignalName_                  = "CcuContextBroadcastNHR1DDieSync_" + std::to_string(axisId_);
      36            0 :     anotherAxisSignalName_                = "CcuContextBroadcastNHR1DDieSync_" + std::to_string(1 - axisId_);
      37            0 :     stepInfoVector_                       = ctxArg->stepInfoVector_;
      38            0 :     indexMap_                             = ctxArg->indexMap_;
      39            0 :     localSize_                            = indexMap_.size();
      40            0 :     myRankIdx_                            = indexMap_.size();
      41            0 :     dataType_                             = ctxArg->op_.dataType;
      42            0 :     signalNum_ = (dimSize_ + RANK_NUM_PER_CKE - 1) / RANK_NUM_PER_CKE; // 每个CKE有16个bit
      43            0 :     HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] CtxArg: rankId_[%u], axisId_[%u], axisSize_[%u], dimSize_[%u], localSize_[%u], "
      44              :               "signalNum_[%u], dataType[%s]",
      45              :               rankId_, axisId_, axisSize_, dimSize_, localSize_, signalNum_, dataType_.Describe().c_str());
      46            0 : }
      47              : 
      48            0 : void CcuContextBroadcastNHRMem2Mem1D::InitResources()
      49              : {
      50            0 :     die0Size_           = CreateVariable();
      51            0 :     die1Size_           = CreateVariable();
      52            0 :     die0SliceSize_      = CreateVariable();
      53            0 :     die1SliceSize_      = CreateVariable();
      54            0 :     die0LastSliceSize_  = CreateVariable();
      55            0 :     die1LastSliceSize_  = CreateVariable();
      56            0 :     localAxisSignal_    = CreateMaskSignal();
      57            0 :     localSignal_        = CreateMaskSignal();
      58              : 
      59            0 :     if (axisSize_ > 1) {
      60            0 :         anotherAxisSignal_  = CreateMaskSignal();
      61              : 
      62            0 :         ExportMaskSignal(localAxisSignal_, localAxisSignalName_);
      63            0 :         anotherAxisSignal_ = ImportMaskSignal(anotherAxisSignalName_);
      64              :     }
      65              : 
      66            0 :     input_ = CreateVariable();
      67            0 :     for (uint32_t transportIdx = 0; transportIdx < localSize_; transportIdx++) {
      68            0 :         HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] MyRank[%u], TransportId[%u]", rankId_, transportIdx);
      69            0 :         CHK_PRT_RET(transports[transportIdx] == nullptr,
      70              :                     HCCL_ERROR("[CcuContextBroadcastNHRMem2Mem1D] Algorithm transport ptr is null"), );
      71            0 :         output_.push_back(
      72            0 :             CreateVariable((*transports[transportIdx]), OUTPUT_XN_ID)); // 获取transport中id=1的Var来传递output
      73            0 :         token_.push_back(CreateVariable((*transports[transportIdx]), TOKEN_XN_ID));
      74              :     }
      75            0 :     output_.push_back(CreateVariable());
      76            0 :     token_.push_back(CreateVariable());
      77              : 
      78            0 :     srcMem_ = CreateMemory();
      79            0 :     dstMem_ = CreateMemory();
      80              : 
      81            0 :     CcuRep::Variable tmpSliceOffset   = CreateVariable();
      82            0 :     tmpSliceOffset                    = 0;
      83              : 
      84            0 :     for (u64 i = 0; i < dimSize_; i++) {
      85            0 :         sliceOffset_.push_back(CreateVariable());
      86            0 :         sliceOffset_[i] = tmpSliceOffset;
      87            0 :         tmpSliceOffset += axisId_ == 0? die0SliceSize_: die1SliceSize_;
      88              :     }
      89              : 
      90            0 :     HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] InitResources finished");
      91            0 : }
      92              : 
      93            0 : void CcuContextBroadcastNHRMem2Mem1D::LoadArgs()
      94              : {
      95            0 :     Load(input_);
      96            0 :     Load(output_[myRankIdx_]);
      97            0 :     Load(token_[myRankIdx_]);
      98            0 :     Load(die0Size_);
      99            0 :     Load(die1Size_);
     100            0 :     Load(die0SliceSize_);
     101            0 :     Load(die1SliceSize_);
     102            0 :     Load(die0LastSliceSize_);
     103            0 :     Load(die1LastSliceSize_);
     104            0 :     HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] LoadArgs run finished");
     105            0 : }
     106              : 
     107            0 : void CcuContextBroadcastNHRMem2Mem1D::AxisSync(uint32_t signalIndex)
     108              : {
     109            0 :     const uint32_t DIE_NUM = 2;
     110            0 :     if (signalIndex > 1) {
     111            0 :         THROW<InvalidParamsException>(
     112            0 :             StringFormat("[CcuContextBroadcastNHRMem2Mem1D] Unexpected SignalInex[%u]", signalIndex));
     113              :     }
     114            0 :     LocalCtxPost(anotherAxisSignal_, 1 << (axisId_ + signalIndex * DIE_NUM));
     115            0 :     LocalWait(localAxisSignal_, 1 << (1 - axisId_ + signalIndex * DIE_NUM));
     116            0 :     HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] AxisSync run finished");
     117            0 :     return;
     118              : }
     119              : 
     120            0 : void CcuContextBroadcastNHRMem2Mem1D::PreSync()
     121              : {
     122            0 :     HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] PreSync start");
     123            0 :     uint16_t selfSignalId = rankId_ / RANK_NUM_PER_CKE;
     124            0 :     uint16_t selfBit      = 1 << (rankId_ % RANK_NUM_PER_CKE);
     125            0 :     for (auto t : transports) {
     126            0 :         WriteVariableWithSignal(*t, output_[localSize_], OUTPUT_XN_ID, selfSignalId + signalNum_ * CKE_IDX_1, selfBit);
     127            0 :         WriteVariableWithSignal(*t, token_[localSize_], TOKEN_XN_ID, selfSignalId + signalNum_ * CKE_IDX_2, selfBit);
     128              :     }
     129            0 :     std::vector<uint16_t> waitBitVector(signalNum_, 0);
     130            0 :     for (auto &pair : indexMap_) {
     131            0 :         uint16_t pairSignalId       = pair.first / RANK_NUM_PER_CKE;
     132            0 :         uint16_t pairBit            = 1 << (pair.first % RANK_NUM_PER_CKE);
     133            0 :         waitBitVector[pairSignalId] = waitBitVector[pairSignalId] | pairBit;
     134              :     }
     135            0 :     for (uint16_t sId = 0; sId < waitBitVector.size(); sId++) {
     136            0 :         GroupWait(*transportGroup, sId + signalNum_ * CKE_IDX_1, waitBitVector[sId]);
     137            0 :         GroupWait(*transportGroup, sId + signalNum_ * CKE_IDX_2, waitBitVector[sId]);
     138              :     }
     139            0 :     HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] PreSync end");
     140            0 : }
     141              : 
     142            0 : void CcuContextBroadcastNHRMem2Mem1D::PostSync()
     143              : {
     144            0 :     uint16_t selfSignalId = rankId_ / RANK_NUM_PER_CKE;
     145            0 :     uint16_t selfBit      = 1 << (rankId_ % RANK_NUM_PER_CKE);
     146            0 :     for (auto &t : transports) {
     147            0 :         RemotePost(*t, selfSignalId + signalNum_ * CKE_IDX_0, selfBit);
     148              :     }
     149            0 :     std::vector<uint16_t> waitBitVector(signalNum_, 0);
     150            0 :     for (auto &pair : indexMap_) {
     151            0 :         uint16_t pairSignalId       = pair.first / RANK_NUM_PER_CKE;
     152            0 :         uint16_t pairBit            = 1 << (pair.first % RANK_NUM_PER_CKE);
     153            0 :         waitBitVector[pairSignalId] = waitBitVector[pairSignalId] | pairBit;
     154              :     }
     155            0 :     for (uint32_t sId = 0; sId < signalNum_; sId++) {
     156            0 :         GroupWait(*transportGroup, sId + signalNum_ * CKE_IDX_0, waitBitVector[sId]);
     157              :     }
     158            0 :     HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] PostSync run finished");
     159            0 : }
     160              : 
     161            0 : void CcuContextBroadcastNHRMem2Mem1D::DoScatterNHR()
     162              : {
     163            0 :     const uint32_t NHR_NUM = 2;
     164            0 :     for (u64 i = 0; i < stepInfoVector_.size() / NHR_NUM; i++) {
     165            0 :         const NHRStepInfo &nhrStepInfo = stepInfoVector_[i];
     166            0 :         DoScatterNHRSingleStep(nhrStepInfo);
     167              :     }
     168            0 : }
     169              : 
     170            0 : void CcuContextBroadcastNHRMem2Mem1D::DoScatterNHRSingleStep(const NHRStepInfo &nhrStepInfo)
     171              : {
     172            0 :     const std::vector<u32> &sendSliceIdxList  = nhrStepInfo.txSliceIdxs;
     173            0 :     const std::vector<u32> &recvSliceIdxList  = nhrStepInfo.rxSliceIdxs;
     174              :     // 只需要发
     175            0 :     if(sendSliceIdxList.size() != 0){
     176            0 :         u32& toRankIdx = indexMap_[nhrStepInfo.toRank];
     177            0 :         u32  sendSliceIdx = 0;
     178            0 :         CcuTransport           *sendTransport = transports[toRankIdx];
     179            0 :         srcMem_.token                         = token_[myRankIdx_];
     180            0 :         dstMem_.token                         = token_[toRankIdx];
     181              : 
     182            0 :         uint16_t selfSignalId = rankId_ / RANK_NUM_PER_CKE;
     183            0 :         uint16_t selfBit      = 1 << (rankId_ % RANK_NUM_PER_CKE);
     184              : 
     185            0 :         for (u32 i = 0; i < sendSliceIdxList.size(); i++) {
     186            0 :         sendSliceIdx = sendSliceIdxList[i];
     187              : 
     188            0 :             if (i != 0) {
     189            0 :                 if (i % RANK_NUM_PER_CKE == 0) {
     190            0 :                 LocalWait(localSignal_, (1 << RANK_NUM_PER_CKE) - 1);
     191              :                 }
     192              :             }
     193              : 
     194            0 :             if (nhrStepInfo.step == 0) {
     195              :             // 只有第0步的源数据从input中取
     196            0 :                 HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] nhrStepInfo 0.");
     197            0 :                 srcMem_.addr = input_;
     198            0 :                 srcMem_.addr += sliceOffset_[sendSliceIdx];
     199              :             } else {
     200            0 :                 srcMem_.addr = output_[myRankIdx_];
     201            0 :                 srcMem_.addr += sliceOffset_[sendSliceIdx];
     202              :             }
     203              : 
     204            0 :             dstMem_.addr = output_[toRankIdx];
     205            0 :             dstMem_.addr += sliceOffset_[sendSliceIdx];
     206              : 
     207            0 :             DoSendRecvSlice(nhrStepInfo.toRank, srcMem_, dstMem_, sendSliceIdx, i % RANK_NUM_PER_CKE);
     208              :         }
     209              : 
     210            0 :         LocalWait(localSignal_, (1 << (sendSliceIdxList.size() % RANK_NUM_PER_CKE)) - 1);
     211              : 
     212              :         // 通知toRank数据写入完毕
     213            0 :         RemotePost(*sendTransport, selfSignalId + signalNum_ * CKE_IDX_4, selfBit, true);
     214              :     }
     215              : 
     216              :     //只需要收
     217            0 :     if(recvSliceIdxList.size() != 0){
     218            0 :         u32& fromRankIdx = indexMap_[nhrStepInfo.fromRank];
     219            0 :         CcuTransport           *recvTransport = transports[fromRankIdx];
     220              : 
     221            0 :         uint16_t recvSignalId = nhrStepInfo.fromRank / RANK_NUM_PER_CKE;
     222            0 :         uint16_t recvBit      = 1 << (nhrStepInfo.fromRank % RANK_NUM_PER_CKE);
     223            0 :         RemoteWait(*recvTransport, recvSignalId + signalNum_ * CKE_IDX_4, recvBit);
     224              :     }
     225            0 : }
     226              : 
     227            0 : void CcuContextBroadcastNHRMem2Mem1D::DoSendRecvSlice(const u32 &toRank, CcuRep::Memory &src, CcuRep::Memory &dst,
     228              :                                                      const u32 &sendSliceIdx, u32 signalIndex)
     229              : {
     230            0 :     CcuTransport *sendTransport = transports[indexMap_[toRank]];
     231              :     bool          islastSlice;
     232              : 
     233              :     // 添加 die1 偏移
     234            0 :     if (axisId_ == 1) {
     235            0 :         src.addr += die0Size_;
     236            0 :         dst.addr += die0Size_;
     237              :     }
     238              : 
     239            0 :     islastSlice = (sendSliceIdx + 1 == dimSize_);
     240            0 :     const CcuRep::Variable &sliceSize = axisId_ == 0? (islastSlice? die0LastSliceSize_ : die0SliceSize_)
     241              :                                                     : (islastSlice? die1LastSliceSize_ : die1SliceSize_);
     242              : 
     243            0 :     CCU_IF(sliceSize == 0)
     244              :     {
     245            0 :         LocalPost(localSignal_, 1 << signalIndex);
     246            0 :     }
     247              : 
     248            0 :     CCU_IF(sliceSize != 0)
     249              :     {
     250            0 :         Write(*sendTransport, dst, src, sliceSize, localSignal_, 1 << signalIndex);
     251            0 :     }
     252            0 : }
     253              : 
     254            0 : void CcuContextBroadcastNHRMem2Mem1D::DoAllGatherNHR()
     255              : {
     256            0 :     const uint32_t NHR_NUM = 2;
     257            0 :     for (u64 i = stepInfoVector_.size() / NHR_NUM; i < stepInfoVector_.size(); i++) {
     258            0 :         const NHRStepInfo &nhrStepInfo = stepInfoVector_[i];
     259            0 :         DoAllGatherNHRSingleStep(nhrStepInfo);
     260              :     }
     261            0 : }
     262              : 
     263            0 : void CcuContextBroadcastNHRMem2Mem1D::DoAllGatherNHRSingleStep(const NHRStepInfo &nhrStepInfo)
     264              : {
     265            0 :     u32& toRankIdx = indexMap_[nhrStepInfo.toRank];
     266            0 :     u32& fromRankIdx = indexMap_[nhrStepInfo.fromRank];
     267            0 :     u32  sendSliceIdx = 0;
     268            0 :     CcuTransport           *sendTransport = transports[toRankIdx];
     269            0 :     CcuTransport           *recvTransport = transports[fromRankIdx];
     270            0 :     const std::vector<u32> &sendSliceIdxList  = nhrStepInfo.txSliceIdxs;
     271            0 :     dstMem_.token                         = token_[toRankIdx];
     272            0 :     srcMem_.token                         = token_[myRankIdx_];
     273              : 
     274            0 :     uint16_t selfSignalId = rankId_ / RANK_NUM_PER_CKE;
     275            0 :     uint16_t selfBit      = 1 << (rankId_ % RANK_NUM_PER_CKE);
     276              : 
     277            0 :     for (u32 i = 0; i < sendSliceIdxList.size(); i++) {
     278            0 :         sendSliceIdx = sendSliceIdxList[i];
     279              : 
     280            0 :         if (i != 0) {
     281            0 :             if (i % RANK_NUM_PER_CKE == 0) {
     282            0 :                 LocalWait(localSignal_, (1 << RANK_NUM_PER_CKE) - 1);
     283              :             }
     284              :         }
     285              : 
     286            0 :         srcMem_.addr = output_[myRankIdx_];
     287            0 :         srcMem_.addr += sliceOffset_[sendSliceIdx];
     288              : 
     289            0 :         dstMem_.addr = output_[toRankIdx];
     290            0 :         dstMem_.addr += sliceOffset_[sendSliceIdx];
     291            0 :         DoSendRecvSlice(nhrStepInfo.toRank, srcMem_, dstMem_, sendSliceIdx, i % RANK_NUM_PER_CKE);
     292              :     }
     293              : 
     294            0 :     LocalWait(localSignal_, (1 << (sendSliceIdxList.size() % RANK_NUM_PER_CKE)) - 1);
     295              : 
     296            0 :     if (nhrStepInfo.step + 1 != stepInfoVector_.size()) {   // 最后一步不需要同步
     297              :         // 通知toRank,写入完毕
     298            0 :         RemotePost(*sendTransport, selfSignalId + signalNum_ * CKE_IDX_3, selfBit, true);
     299              :         // 等待fromRank通知写入完毕
     300            0 :         uint16_t recvSignalId = nhrStepInfo.fromRank / RANK_NUM_PER_CKE;
     301            0 :         uint16_t recvBit      = 1 << (nhrStepInfo.fromRank % RANK_NUM_PER_CKE);
     302            0 :         RemoteWait(*recvTransport, recvSignalId + signalNum_ * CKE_IDX_3, recvBit);
     303              :     }
     304              : 
     305            0 :     HCCL_DEBUG("[DoAllGatherNHRSingleStep] rank %u step %u, toRank=%u, fromRank=%u, nSlice=%lu",
     306              :                 rankId_, nhrStepInfo.step, nhrStepInfo.toRank, nhrStepInfo.fromRank, sendSliceIdxList.size());
     307            0 : }
     308              : 
     309            0 : void CcuContextBroadcastNHRMem2Mem1D::Algorithm()
     310              : {
     311            0 :     HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] BroadcastNHR1D run");
     312              : 
     313            0 :     InitResources();
     314            0 :     LoadArgs();
     315            0 :     if (axisSize_ > 1) {
     316            0 :         AxisSync(FST_AXIS_ID);
     317              :     }
     318            0 :     PreSync();
     319            0 :     DoScatterNHR();
     320            0 :     DoAllGatherNHR();
     321            0 :     PostSync();
     322            0 :     if (axisSize_ > 1) {
     323            0 :         AxisSync(SEC_AXIS_ID);
     324              :     }
     325              : 
     326            0 :     HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] BroadcastNHR1D end");
     327            0 :     return;
     328              : }
     329              : 
     330            0 : std::vector<uint64_t> CcuContextBroadcastNHRMem2Mem1D::GeneArgs(const CcuTaskArg &arg)
     331              : {
     332            0 :     const CcuTaskArgBroadcastNHRMem2Mem1D *taskArg = dynamic_cast<const CcuTaskArgBroadcastNHRMem2Mem1D *>(&arg);
     333            0 :     if (taskArg == nullptr) {
     334            0 :         THROW<NullPtrException>(StringFormat("CcuContextBroadcastNHRMem2Mem1D::taskArg ptr is null"));
     335              :     }
     336              :     // input&output&buffer地址
     337            0 :     uint64_t inputAddr          = taskArg->inputAddr_;
     338            0 :     uint64_t outputAddr         = taskArg->outputAddr_;
     339            0 :     uint64_t token              = taskArg->token_;
     340            0 :     uint64_t die0Size           = taskArg->die0Size_;
     341            0 :     uint64_t die1Size           = taskArg->die1Size_;
     342            0 :     uint64_t die0SliceSize      = taskArg->die0SliceSize_;
     343            0 :     uint64_t die1SliceSize      = taskArg->die1SliceSize_;
     344            0 :     uint64_t die0LastSliceSize  = taskArg->die0LastSliceSize_;
     345            0 :     uint64_t die1LastSliceSize  = taskArg->die1LastSliceSize_;
     346              : 
     347            0 :     HCCL_INFO("[CcuContextBroadcastNHRMem2Mem1D] TaskArgs: inputAddr[%llu], outputAddr[%llu], "
     348              :               "die0Size[%llu], die1Size[%llu], die0SliceSize[%llu], die1SliceSize[%llu],"
     349              :               "die0LastSliceSize[%llu], die1LastSliceSize[%llu]",
     350              :               inputAddr, outputAddr, die0Size, die1Size, die0SliceSize, die1SliceSize,
     351              :               die0LastSliceSize, die1LastSliceSize);
     352              : 
     353              :     return {inputAddr,          outputAddr,
     354              :             token,              die0Size,           die1Size,
     355              :             die0SliceSize,      die1SliceSize,      die0LastSliceSize,
     356            0 :             die1LastSliceSize};
     357              : }
     358              : 
     359              : } // namespace Hccl
        

Generated by: LCOV version 2.0-1