LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/base/alg_template/temp_broadcast - broadcast_nhr_oneshot.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 74.0 % 104 77
Test Date: 2026-08-18 17:47:01 Functions: 80.0 % 10 8

            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 "broadcast_nhr_oneshot.h"
      12              : #include <cmath>
      13              : #include "alg_template_register.h"
      14              : 
      15              : namespace hccl {
      16            3 : BroadcastNHROneshot::BroadcastNHROneshot(const HcclDispatcher dispatcher)
      17              :     : NHRBase(dispatcher),
      18            3 :       localBaseOffset_(0),
      19            3 :       isForAllReduce_(false)
      20            3 : {}
      21              : 
      22            3 : BroadcastNHROneshot::~BroadcastNHROneshot() {}
      23              : 
      24            3 : HcclResult BroadcastNHROneshot::RunAsync(const u32 rank, const u32 rankSize, const std::vector<LINK>& links)
      25              : {
      26              :     // 基本的检查
      27            3 :     CHK_RET(SimpleCheck(rank, rankSize, links));
      28            3 :     HCCL_INFO(
      29              :         "[BroadcastNHROneshot][RunAsync] rank[%u] ranksize[%u] inputMem[%p] outputMem[%p] count[%llu]", rank, rankSize,
      30              :         inputMem_.ptr(), outputMem_.ptr(), count_);
      31              : 
      32            3 :     u32 unitSize = DataUnitSize(dataType_);
      33            3 :     CHK_PRT_RET(unitSize == 0, HCCL_ERROR("[BroadcastNHROneshot][RunAsync] unitSize is zero"), HCCL_E_INTERNAL);
      34              : 
      35            3 :     if (!isForAllReduce_) {
      36            0 :         localBaseOffset_ = baseOffset_; // broadcast的本地偏移量和baseOffset_一致
      37              :     }
      38              : 
      39              :     // 双buffer下, 先将input拷贝到output的合适位置
      40            3 :     if (inputMem_ != outputMem_ && rank == root_) {
      41            3 :         u64 totalSize = count_ * SIZE_TABLE[dataType_];
      42            3 :         DeviceMem src = inputMem_.range(localBaseOffset_, totalSize);
      43            3 :         DeviceMem dst = outputMem_.range(localBaseOffset_, totalSize);
      44            3 :         CHK_RET(HcclD2DMemcpyAsync(dispatcher_, dst, src, stream_));
      45            3 :     }
      46              : 
      47              :     // 如果ranksize为1, 从input->output就结束
      48            3 :     if (rankSize == 1) {
      49            0 :         return HCCL_SUCCESS;
      50              :     }
      51              : 
      52              :     // 运行bcast, rst算法
      53            3 :     CHK_RET(RunBroadcastNHROneshot(rank, rankSize, links));
      54              : 
      55            3 :     HCCL_INFO("[BroadcastNHROneshot][RunAsync] finished: rank[%u] ranksize[%u]", rank, rankSize);
      56            3 :     return HCCL_SUCCESS;
      57              : }
      58              : 
      59            3 : HcclResult BroadcastNHROneshot::RunAsyncForAllReduce(const u32 rank, const u32 rankSize, const std::vector<LINK>& links)
      60              : {
      61            3 :     isForAllReduce_ = true;
      62            3 :     return RunAsync(rank, rankSize, links);
      63              : }
      64              : 
      65            3 : HcclResult BroadcastNHROneshot::SimpleCheck(const u32 rank, const u32 rankSize, const std::vector<LINK>& links)
      66              : {
      67              :     // 判断stream, dispatcher是否为空
      68            3 :     CHK_SMART_PTR_NULL(dispatcher_);
      69            3 :     CHK_PTR_NULL(stream_.ptr());
      70              : 
      71              :     // 检查memory
      72            3 :     CHK_PRT_RET(
      73              :         !outputMem_ || !inputMem_,
      74              :         HCCL_ERROR("[BroadcastNHROneshot][SimpleCheck] rank[%u] inputmem or outputmem is null", rank), HCCL_E_PTR);
      75              : 
      76              :     // 判断links数量是否正确
      77            3 :     CHK_PRT_RET(
      78              :         links.size() < rankSize,
      79              :         HCCL_ERROR(
      80              :             "[BroadcastNHROneshot][SimpleCheck] rank[%u] link size[%llu] is "
      81              :             "less than rank size[%u]",
      82              :             rank, links.size(), rankSize),
      83              :         HCCL_E_INTERNAL);
      84            3 :     return HCCL_SUCCESS;
      85              : }
      86              : 
      87            0 : HcclResult BroadcastNHROneshot::SdmaRx(
      88              :     LINK& linkLeft, LINK& linkRight, [[maybe_unused]] InterServerAlgoStep& stepInfo,
      89              :     [[maybe_unused]] const std::vector<LINK>& links)
      90              : {
      91            0 :     u64 totalSize = count_ * SIZE_TABLE[dataType_];
      92            0 :     DeviceMem srcMem = outputMem_.range(localBaseOffset_, totalSize);
      93              : 
      94            0 :     if (linkRight != nullptr) {
      95            0 :         CHK_RET(linkRight->TxAck(stream_));
      96              :     }
      97            0 :     if (linkLeft != nullptr) {
      98            0 :         CHK_RET(linkLeft->RxAck(stream_));
      99            0 :         void* srcMemPtr = nullptr;
     100            0 :         CHK_RET(linkLeft->GetRemoteMem(UserMemType::OUTPUT_MEM, &srcMemPtr));
     101            0 :         DeviceMem srcMemLeft(static_cast<s8*>(srcMemPtr) + baseOffset_, totalSize);
     102            0 :         CHK_RET(HcclD2DMemcpyAsync(
     103              :             dispatcher_, srcMem, srcMemLeft, stream_, linkLeft->GetRemoteRank(), // Memecpy
     104              :             linkLeft->GetLinkType()));
     105            0 :         CHK_RET(linkLeft->TxDataSignal(stream_));
     106            0 :     }
     107            0 :     if (linkRight != nullptr) {
     108            0 :         CHK_RET(linkRight->RxDataSignal(stream_));
     109              :     }
     110            0 :     return HCCL_SUCCESS;
     111            0 : }
     112              : 
     113            9 : HcclResult BroadcastNHROneshot::RdmaTxRx(
     114              :     LINK& linkLeft, LINK& linkRight, [[maybe_unused]] InterServerAlgoStep& stepInfo,
     115              :     [[maybe_unused]] const std::vector<LINK>& links)
     116              : {
     117            9 :     u64 totalSize = count_ * SIZE_TABLE[dataType_];
     118            9 :     DeviceMem srcMem = outputMem_.range(localBaseOffset_, totalSize);
     119              : 
     120            9 :     if (linkLeft != nullptr) {
     121            0 :         CHK_RET(linkLeft->TxAck(stream_));
     122              :     }
     123              : 
     124            9 :     if (linkRight != nullptr) {
     125            9 :         CHK_RET(linkRight->RxAck(stream_));
     126            9 :         CHK_RET(linkRight->TxAsync(UserMemType::OUTPUT_MEM, baseOffset_, srcMem.ptr(), srcMem.size(), stream_));
     127            9 :         CHK_RET(linkRight->WaitFinAck(stream_));
     128              :     }
     129              : 
     130            9 :     if (linkLeft != nullptr) {
     131            0 :         CHK_RET(linkLeft->RxAsync(UserMemType::OUTPUT_MEM, baseOffset_, srcMem.ptr(), srcMem.size(), stream_));
     132            0 :         CHK_RET(linkLeft->PostFinAck(stream_));
     133              :     }
     134            9 :     return HCCL_SUCCESS;
     135            9 : }
     136              : 
     137            3 : HcclResult BroadcastNHROneshot::RunBroadcastNHROneshot(u32 rank, u32 rankSize, const std::vector<LINK>& links)
     138              : {
     139              :     // 计算通信步数
     140            3 :     u32 nSteps = GetStepNumInterServer(rankSize);
     141            3 :     HCCL_DEBUG(
     142              :         "[BroadcastNHROneshot][RunBroadcastNHROneshot] rank[%u] rankSize[%u] nSteps[%u]", rank, rankSize, nSteps);
     143              : 
     144              :     // 逐步编排任务
     145           12 :     for (u32 step = 0; step < nSteps; step++) {
     146            9 :         InterServerAlgoStep stepInfo;
     147            9 :         GetStepInfo(step, nSteps, rank, rankSize, stepInfo);
     148              : 
     149            9 :         HCCL_DEBUG(
     150              :             "[BroadcastNHROneshot][RunBroadcastNHROneshot] recvFrom[%u] sendTo[%u] step[%u]", stepInfo.fromRank,
     151              :             stepInfo.toRank, step);
     152              : 
     153            9 :         LINK linkLeft;
     154            9 :         LINK linkRight;
     155            9 :         if (stepInfo.txSliceIdxs.size() > 0) {
     156            9 :             linkRight = links[stepInfo.toRank];
     157            9 :             CHK_SMART_PTR_NULL(linkRight);
     158              :         }
     159            9 :         if (stepInfo.rxSliceIdxs.size() > 0) {
     160            0 :             linkLeft = links[stepInfo.fromRank];
     161            0 :             CHK_SMART_PTR_NULL(linkLeft);
     162              :         }
     163              : 
     164           18 :         if ((linkRight != nullptr && linkRight->IsSpInlineReduce())
     165           18 :             || (linkLeft != nullptr && linkLeft->IsSpInlineReduce())) {
     166            0 :             CHK_RET(SdmaRx(linkLeft, linkRight, stepInfo, links));
     167              :         } else {
     168            9 :             CHK_RET(RdmaTxRx(linkLeft, linkRight, stepInfo, links));
     169              :         }
     170            9 :     }
     171            3 :     return HCCL_SUCCESS;
     172              : }
     173              : 
     174              : // NHR每步的算法描述原理函数
     175            9 : HcclResult BroadcastNHROneshot::GetStepInfo(u32 step, u32 nSteps, u32 rank, u32 rankSize, InterServerAlgoStep& stepInfo)
     176              : {
     177            9 :     stepInfo.txSliceIdxs.clear();
     178            9 :     stepInfo.rxSliceIdxs.clear();
     179            9 :     stepInfo.nSlices = 1;
     180            9 :     stepInfo.toRank = rankSize;
     181            9 :     stepInfo.fromRank = rankSize;
     182            9 :     stepInfo.step = step;
     183            9 :     stepInfo.myRank = rank;
     184              : 
     185            9 :     u32 nRanks = (rankSize - 1 + (1 << (nSteps - 1 - step))) / (1 << (nSteps - step)); // 本步需要进行收/发的rank数
     186              : 
     187            9 :     u32 deltaRoot = (rank + rankSize - root_) % rankSize;
     188              : 
     189            9 :     u32 deltaRankPair = 1 << (nSteps - 1 - step);
     190            9 :     u32 deltaRankGroup = 1 << (nSteps - step);
     191              : 
     192            9 :     if (deltaRoot / deltaRankGroup < nRanks) {
     193            9 :         if (deltaRoot % deltaRankGroup == 0) {
     194            9 :             stepInfo.toRank = (rank + deltaRankPair) % rankSize;
     195            9 :             stepInfo.txSliceIdxs.push_back(0);
     196              :         }
     197              : 
     198            9 :         if ((deltaRoot + deltaRankPair) % deltaRankGroup == 0) {
     199            0 :             stepInfo.fromRank = (rank + rankSize - deltaRankPair) % rankSize;
     200            0 :             stepInfo.rxSliceIdxs.push_back(0);
     201              :         }
     202              :     }
     203            9 :     return HCCL_SUCCESS;
     204              : }
     205              : 
     206              : REGISTER_TEMPLATE(TemplateType::TEMPLATE_BROADCAST_NHR_ONESHOT, BroadcastNHROneshot);
     207              : } // namespace hccl
        

Generated by: LCOV version 2.0-1