LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/impl/operator - broadcast_operator.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 32.0 % 175 56
Test Date: 2026-08-18 17:47:01 Functions: 50.0 % 10 5

            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_operator.h"
      12              : #include "device_capacity.h"
      13              : #include "coll_alg_op_registry.h"
      14              : 
      15              : namespace hccl {
      16              : constexpr u64 AIV_MAX_DATASIZE = 4ULL * 1024 * 1024 * 1024;
      17              : 
      18            1 : BroadCastOperator::BroadCastOperator(
      19              :     AlgConfigurator* algConfigurator, CCLBufferManager& cclBufferManager, HcclDispatcher dispatcher,
      20            1 :     std::unique_ptr<TopoMatcher>& topoMatcher)
      21            1 :     : CollAlgOperator(algConfigurator, cclBufferManager, dispatcher, topoMatcher, HcclCMDType::HCCL_CMD_BROADCAST)
      22              : {
      23              :     // 由于bcast暂不支持server间ring,需继续使用HD或NHR
      24            1 :     if (!(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NHR)
      25            0 :         && !(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NHR_V1)
      26            0 :         && !(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_WHOLE_RING)
      27            0 :         && !(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NB)) {
      28            0 :         algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_HD;
      29            0 :         HCCL_WARNING("[BroadCastOperator][BroadCastOperator] do not support ring in AlgoLevel1 yet, reset algType=HD.");
      30              :     }
      31            1 : }
      32            2 : BroadCastOperator::~BroadCastOperator() {}
      33              : 
      34              : HcclResult
      35            1 : BroadCastOperator::SelectAlg(const std::string& tag, const OpParam& param, std::string& algName, std::string& newTag)
      36              : {
      37              :     HcclResult ret;
      38            1 :     isAivMode_ = false;
      39            1 :     if (isDiffDeviceType_) {
      40            0 :         ret = SelectAlgforMix(param, algName);
      41            1 :     } else if (Is310P3Common(isHaveCpuRank_, deviceType_)) {
      42            0 :         ret = SelectAlgfor310P3(param, algName);
      43            1 :     } else if (Is310PDevice() && topoType_ == TopoType::TOPO_TYPE_2P_MESH) {
      44            0 :         ret = SelectAlgfor310P(param, algName);
      45            1 :     } else if (deviceType_ == DevType::DEV_TYPE_910) {
      46            0 :         ret = SelectAlgfor910A(param, algName);
      47            1 :     } else if (deviceType_ == DevType::DEV_TYPE_910B) {
      48            0 :         ret = SelectAlgfor910B(param, algName);
      49            1 :     } else if (deviceType_ == DevType::DEV_TYPE_910_93) {
      50            1 :         ret = SelectAlgfor91093(param, algName);
      51              :     } else {
      52            0 :         HCCL_ERROR("BroadCastOperator[SelectAlg] device type[%d] is out of range for selector.", deviceType_);
      53            0 :         return HCCL_E_NOT_SUPPORT;
      54              :     }
      55            1 :     CHK_PRT_RET(
      56              :         ret != HCCL_SUCCESS,
      57              :         HCCL_ERROR("[BroadCastSelector][SelectAlg]tag[%s], broadcast failed, return[%d]", tag.c_str(), ret), ret);
      58              : 
      59            1 :     if (GetWorkflowMode() != HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE) {
      60            1 :         newTag = tag;
      61            0 :     } else if (
      62            0 :         isAivMode_
      63            0 :         || (Is310P3Common(isHaveCpuRank_, deviceType_) && (algType_.algoLevel1 != AlgTypeLevel1::ALG_LEVEL1_HD))) {
      64            0 :         newTag = tag + algName;
      65            0 :     } else if (
      66            0 :         algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_HD || algType_.algoLevel2 == AlgTypeLevel2::ALG_LEVEL2_HD) {
      67            0 :         newTag = tag + algName;
      68            0 :         std::string appendTag = "";
      69            0 :         u32 serverNumPerSuperPod = superPodNum_ == 0 ? moduleNum_ : moduleNum_ / superPodNum_;
      70            0 :         if (algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_HD) {
      71            0 :             u32 part1Size = FACTOR_TWO * (serverNumPerSuperPod - (1 << static_cast<u32>(log2(serverNumPerSuperPod))));
      72            0 :             u32 rootId = param.root / deviceNumPerAggregation_ % serverNumPerSuperPod;
      73            0 :             appendTag += "L1_" + std::to_string((rootId >= part1Size) || ((rootId % FACTOR_TWO) == 0));
      74              :         }
      75            0 :         if (algType_.algoLevel2 == AlgTypeLevel2::ALG_LEVEL2_HD) {
      76            0 :             u32 part1Size = FACTOR_TWO * (superPodNum_ - (1 << static_cast<u32>(log2(superPodNum_))));
      77            0 :             u32 rootId = param.root / deviceNumPerAggregation_ / serverNumPerSuperPod;
      78            0 :             appendTag += (appendTag.empty() ? "L2_" : "_L2_")
      79            0 :                          + std::to_string((rootId >= part1Size) || ((rootId % FACTOR_TWO) == 0));
      80              :         }
      81            0 :         HCCL_DEBUG("[BroadCastOperator][SelectAlg]tag is [%s]", tag.c_str());
      82            0 :         newTag = newTag + '_' + appendTag;
      83            0 :         if (GetExternalInputHcclEnableEntryLog() && param.opBaseAtraceInfo != nullptr) {
      84            0 :             CHK_RET(param.opBaseAtraceInfo->SavealgtypeTraceInfo(appendTag, param.tag));
      85              :         }
      86            0 :     } else {
      87            0 :         AlgTypeLevel1 algType1 = algType_.algoLevel1;
      88            0 :         auto level1Iter = HCCL_ALGO_LEVEL1_NAME_MAP.find(algType1);
      89            0 :         CHK_PRT_RET(
      90              :             level1Iter == HCCL_ALGO_LEVEL1_NAME_MAP.end(), HCCL_ERROR("level1: algType1[%u] is invalid.", algType1),
      91              :             HCCL_E_INTERNAL);
      92            0 :         newTag = tag + level1Iter->second + algName;
      93              :     }
      94            1 :     HCCL_DEBUG("[%s] SelectAlg for newTag", __func__);
      95            1 :     newTag += (param.aicpuUnfoldMode ? "_device" : "_host");
      96            1 :     return ret;
      97              : }
      98              : 
      99            0 : HcclResult BroadCastOperator::SelectAlgforMix(const OpParam& param, std::string& algName)
     100              : {
     101              :     (void)param;
     102            0 :     if (gcdDeviceNumPerAggregation_ > 1) {
     103            0 :         algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_NHR;
     104            0 :         HCCL_WARNING("[BroadCastOperator][SelectAlgforMix] only support NHR in AlgoLevel1 yet, "
     105              :                      "default is algType=NHR.");
     106            0 :         algName = "BroadCastMixExecutor";
     107              :     } else {
     108            0 :         algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_RING;
     109            0 :         HCCL_WARNING("[BroadCastOperator][SelectAlgforMix] only support ring in AlgoComm yet, "
     110              :                      "default is algType=ring.");
     111            0 :         algName = "BroadCastComm";
     112              :     }
     113              : 
     114            0 :     HCCL_INFO("[SelectAlgforMix] broadcast SelectAlgforMix is algName [%s]", algName.c_str());
     115            0 :     return HCCL_SUCCESS;
     116              : }
     117              : 
     118            0 : HcclResult BroadCastOperator::SelectAlgfor310P3(const OpParam& param, std::string& algName)
     119              : {
     120              :     (void)param;
     121            0 :     algName = "BroadCastCommFor310P";
     122            0 :     HCCL_INFO("[SelectAlgfor310P3] broadcast SelectAlgfor310P3 is algName [%s]", algName.c_str());
     123            0 :     return HCCL_SUCCESS;
     124              : }
     125              : 
     126            0 : HcclResult BroadCastOperator::SelectAlgfor310P([[maybe_unused]] const OpParam& param, std::string& algName)
     127              : {
     128            0 :     algName = "BroadcastPlusBroadcast";
     129            0 :     HCCL_INFO("[SelectAlgfor310P] broadcast SelectAlgfor310P is algName [%s]", algName.c_str());
     130            0 :     return HCCL_SUCCESS;
     131              : }
     132              : 
     133            0 : HcclResult BroadCastOperator::SelectAlgfor910A(const OpParam& param, std::string& algName)
     134              : {
     135              :     (void)param;
     136            0 :     bool isMeshTopo = topoType_ == TopoType::TOPO_TYPE_4P_MESH || topoType_ == TopoType::TOPO_TYPE_2P_MESH;
     137            0 :     bool isRingTopo = topoType_ == TopoType::TOPO_TYPE_NP_SINGLE_RING || topoType_ == TopoType::TOPO_TYPE_8P_RING;
     138              : 
     139            0 :     if (isMeshTopo) {
     140            0 :         algName = "BroadCastMeshExecutor";
     141            0 :     } else if (topoType_ == TopoType::TOPO_TYPE_4P_RING) {
     142            0 :         algName = "BroadCast4pRingExecutor";
     143            0 :     } else if (isRingTopo) {
     144            0 :         algName = "BroadCastRingExecutor";
     145              :     } else {
     146            0 :         algName = "BroadCastComm";
     147              :     }
     148            0 :     HCCL_INFO("[SelectAlgfor910A] broadcast SelectAlgfor910A is algName [%s]", algName.c_str());
     149            0 :     return HCCL_SUCCESS;
     150              : }
     151              : 
     152            0 : HcclResult BroadCastOperator::SelectAlgfor910B(const OpParam& param, std::string& algName)
     153              : {
     154            0 :     bool isMeshTopo = topoType_ == TopoType::TOPO_TYPE_NP_MESH || topoType_ == TopoType::TOPO_TYPE_4P_MESH
     155            0 :                       || topoType_ == TopoType::TOPO_TYPE_2P_MESH || topoType_ == TopoType::TOPO_TYPE_1P_MESH;
     156            0 :     bool isRingTopo = topoType_ == TopoType::TOPO_TYPE_NP_SINGLE_RING || topoType_ == TopoType::TOPO_TYPE_8P_RING;
     157            0 :     bool isOpbase = (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE);
     158              : 
     159              :     // 暂只支持单算子模式
     160            0 :     const u64 commInputSize = cclBufferManager_.GetInCCLbufferSize();
     161            0 :     const u64 commOutputSize = cclBufferManager_.GetOutCCLbufferSize();
     162            0 :     u64 dataSize = param.DataDes.count * SIZE_TABLE[param.DataDes.dataType];
     163            0 :     bool isCCLBufferGE16M = commInputSize >= HCCL_MID_COUNT_16_MB && commOutputSize >= HCCL_MID_COUNT_16_MB;
     164            0 :     isAivMode_ = topoMatcher_->GetAivModeConfig() && isSingleMeshAggregation_ && isOpbase && isCCLBufferGE16M
     165            0 :                  && IsSupportAIVCopy(param.DataDes.dataType) && dataSize <= AIV_MAX_DATASIZE;
     166            0 :     if (isAivMode_) {
     167            0 :         algName = "BroadcastMeshAivExecutor";
     168            0 :     } else if (isMeshTopo) {
     169            0 :         algName = "BroadCastMeshExecutor";
     170            0 :     } else if (topoType_ == TopoType::TOPO_TYPE_4P_RING) {
     171            0 :         algName = "BroadCast4pRingExecutor";
     172            0 :     } else if (isRingTopo) {
     173            0 :         algName = "BroadCastRingExecutor";
     174              :     } else {
     175            0 :         algName = "BroadCastComm";
     176              :     }
     177            0 :     HCCL_INFO("[SelectAlgfor910B] broadcast SelectAlgfor910B is algName [%s]", algName.c_str());
     178            0 :     return HCCL_SUCCESS;
     179              : }
     180              : 
     181            1 : HcclResult BroadCastOperator::SelectAlgfor91093(const OpParam& param, std::string& algName)
     182              : {
     183              :     // level 1重定向为NHR, 因scatter && broadcast只支持nhr/nb
     184            1 :     if (!(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NHR)
     185            0 :         && !(algType_.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_NB)) {
     186            0 :         algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_NHR;
     187            0 :         HCCL_WARNING(
     188              :             "[BroadCastOperator][BroadCastOperator] do not support ring in AlgoLevel1 yet, reset algType=NHR.");
     189              :     }
     190              : 
     191            1 :     u32 unitSize = SIZE_TABLE[param.DataDes.dataType];
     192            1 :     u64 dataSize = param.DataDes.count * unitSize; // 单位:字节
     193            1 :     if (dataSize >= cclBufferManager_.GetInCCLbufferSize()) {
     194            1 :         HCCL_WARNING(
     195              :             "The current inCCLbufferSize is [%llu] bytes, change the HCCL_BUFFSIZE environment variable "
     196              :             "to be greater than the current data volume[%llu] bytes to improve the performance of the 91093 "
     197              :             "environment.",
     198              :             cclBufferManager_.GetInCCLbufferSize(), dataSize);
     199              :     }
     200              : 
     201            1 :     const u64 commInputSize = cclBufferManager_.GetInCCLbufferSize();
     202            1 :     const u64 commOutputSize = cclBufferManager_.GetOutCCLbufferSize();
     203            1 :     bool isCCLBufferGE16M = commInputSize >= HCCL_MID_COUNT_16_MB && commOutputSize >= HCCL_MID_COUNT_16_MB;
     204            1 :     bool isOpbase = (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE);
     205              : 
     206            1 :     bool isOnlyAiv = topoMatcher_->GetIsOnlyAivConfig();
     207            1 :     bool hasEnoughCCLBuffer = isSingleMeshAggregation_ && isOpbase && isCCLBufferGE16M && dataSize <= AIV_MAX_DATASIZE;
     208            1 :     bool hasSmallDataOrOnlyAiv = !isOpbase && (isOnlyAiv || dataSize <= HCCL_MID_COUNT_16_MB);
     209            1 :     bool isSatisfyDataSize = (userRankSize_ <= DEVICE_EIGHT && dataSize <= HCCL_SMALL_COUNT_512_KB)
     210            2 :                              || (userRankSize_ > DEVICE_EIGHT && dataSize <= HCCL_SMALL_COUNT_1_MB);
     211              : 
     212            1 :     bool isAivSingleNode = serverNum_ == 1 && (hasEnoughCCLBuffer || hasSmallDataOrOnlyAiv);
     213            0 :     bool isAivCrossNode = (superPodNum_ == 1) && (serverNum_ > 1) && !GetExternalInputInterHccsDisable()
     214            1 :                           && ((isOpbase && isCCLBufferGE16M && isSatisfyDataSize) || hasSmallDataOrOnlyAiv);
     215              : 
     216            2 :     isAivMode_ = topoMatcher_->GetAivModeConfig() && IsSupportAIVCopy(param.DataDes.dataType)
     217            2 :                  && (isAivSingleNode || isAivCrossNode);
     218              : 
     219            1 :     bool smallCountOptimSingleServer
     220            1 :         = (serverNum_ == 1)
     221            1 :           && ((workflowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE)
     222            1 :               || (workflowMode_ != HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE && !param.aicpuUnfoldMode))
     223            1 :           && (deviceNumPerAggregation_ > HCCL_DEVICE_NUM_TWO)
     224            2 :           && (param.DataDes.count * SIZE_TABLE[param.DataDes.dataType] <= HCCL_SMALL_COUNT_512_KB * userRankSize_);
     225            0 :     bool smallCountOptimMultiServer = (deviceNumPerAggregation_ > HCCL_DEVICE_NUM_TWO) && (serverNum_ != 1)
     226            0 :                                       && (superPodNum_ == 1)
     227            1 :                                       && (param.DataDes.count * SIZE_TABLE[param.DataDes.dataType]
     228            0 :                                           <= HCCL_SMALL_COUNT_1_MB * deviceNumPerAggregation_);
     229            1 :     bool is2Pod2ServerTopo = (superPodNum_ == 2 && serverNum_ == 2); // 针对 A3背靠背机型
     230              :     bool smallCountOptimMultiPod
     231            1 :         = (superPodNum_ > 1 || (GetExternalInputInterHccsDisable() && serverNum_ > 1)) && !is2Pod2ServerTopo
     232            0 :           && (param.DataDes.count * unitSize <= HCCL_SMALL_COUNT_16_KB * deviceNumPerAggregation_)
     233            2 :           && !retryEnable_; // 涉及ROCE平面
     234            0 :     bool isBack2BackFor91093 = is2Pod2ServerTopo && (workflowMode_ == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE)
     235            0 :                                && (param.DataDes.count * unitSize <= HCCL_SMALL_COUNT_16_KB * deviceNumPerAggregation_)
     236            1 :                                && !retryEnable_;
     237            1 :     if (isAivMode_) {
     238            1 :         if (isAivSingleNode) {
     239            1 :             algName = "BroadcastMeshAivExecutor";
     240              :         } else {
     241            0 :             algName = "BroadcastMeshAivFor91093Executor";
     242              :         }
     243            0 :     } else if (multiModuleDiffDeviceNumMode_ || multiSuperPodDiffServerNumMode_) {
     244            0 :         algName = "BroadCastComm";
     245            0 :     } else if (smallCountOptimMultiServer || smallCountOptimMultiPod) {
     246            0 :         algName = "BroadCastComm";
     247            0 :         algType_.algoLevel1 = AlgTypeLevel1::ALG_LEVEL1_NHR;
     248            0 :     } else if (isBack2BackFor91093) {
     249            0 :         algName = "BroadcastMidCountFor91093Executor";
     250            0 :     } else if (smallCountOptimSingleServer) {
     251            0 :         algName = "BroadCastSmallCountExecutor";
     252            0 :     } else if (
     253            0 :         param.supportZeroCopy
     254            0 :         && (topoType_ == TopoType::TOPO_TYPE_NP_DOUBLE_RING
     255            0 :             || param.DataDes.count * unitSize > HCCL_MID_COUNT_16_MB * serverNum_)) {
     256            0 :         algName = "BroadCastRingZerocopyExecutor";
     257            0 :     } else if (topoType_ == TopoType::TOPO_TYPE_NP_SINGLE_RING || topoType_ == TopoType::TOPO_TYPE_NP_DOUBLE_RING) {
     258            0 :         algName = "BroadCastRingFor91093Executor";
     259              :     } else {
     260            0 :         algName = "BroadCastComm";
     261              :     }
     262            1 :     HCCL_INFO("[SelectAlgfor91093] broadcast SelectAlgfor91093 is algName [%s]", algName.c_str());
     263            1 :     return HCCL_SUCCESS;
     264              : }
     265              : 
     266              : REGISTER_OP(HcclCMDType::HCCL_CMD_BROADCAST, Broadcast, BroadCastOperator);
     267              : } // namespace hccl
        

Generated by: LCOV version 2.0-1