LCOV - code coverage report
Current view: top level - legacy/ascend910/algorithm/impl - coll_alg_utils.cc (source / functions) Coverage Total Hit
Test: coverage.info Lines: 92.3 % 273 252
Test Date: 2026-07-28 12:11:00 Functions: 100.0 % 27 27

            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 "stream_utils.h"
      13              : #include "coll_alg_utils.h"
      14              : 
      15              : namespace hccl {
      16              : 
      17            4 : bool IsAlgTypeLevel0Mesh(const AlgTypeLevel0 &originalAlgTypeLevel0)
      18              : {
      19            4 :     return originalAlgTypeLevel0 == AlgTypeLevel0::ALG_LEVEL0_NP_MESH ||
      20            0 :            originalAlgTypeLevel0 == AlgTypeLevel0::ALG_LEVEL0_4P_MESH ||
      21            4 :            originalAlgTypeLevel0 == AlgTypeLevel0::ALG_LEVEL0_2P_MESH ||
      22            4 :            originalAlgTypeLevel0 == AlgTypeLevel0::ALG_LEVEL0_1P_MESH;
      23              : }
      24              : 
      25            2 : bool IsAlltoAllvcSatisfyBufferSize(const OpParam& param, u32 userRankSize, u64 cclbufferSize) {
      26            6 :     for (u32 i = 0; i < userRankSize; i++) {
      27            4 :         u64 maxSendLength = 0;
      28            4 :         u64 maxRecvLength = 0;
      29              :         // 计算每个rank需使用的中转内存大小是否满足cclbuffer大小
      30           12 :         for (u32 j = 0; j < userRankSize; j++) {
      31            8 :             u64 curSendCounts =
      32            8 :                 *(static_cast<const u64 *>(param.All2AllDataDes.sendCountMatrix) + i * userRankSize + j);
      33            8 :             u64 curSendLength = curSendCounts * SIZE_TABLE[param.All2AllDataDes.sendType];
      34              : 
      35            8 :             u64 curRecvCounts =
      36            8 :                 *(static_cast<const u64 *>(param.All2AllDataDes.sendCountMatrix) + i + userRankSize * j);
      37            8 :             u64 curRecvLength = curRecvCounts * SIZE_TABLE[param.All2AllDataDes.recvType];
      38              : 
      39            8 :             maxSendLength += curSendLength;
      40            8 :             maxRecvLength += curRecvLength;
      41              :         }
      42            4 :         if ((maxSendLength <= cclbufferSize) || (maxRecvLength <= cclbufferSize)) {
      43            0 :             return false;
      44              :         }
      45              :     }
      46            2 :     return true;
      47              : }
      48              : 
      49           39 : bool IsSupportUnifiedMarch(const OpParam& param, const TopoType& topoType, u32 serverNum, u32 superPodNum)
      50              : {
      51           39 :     bool isGraphMode = (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OPS_KERNEL_INFO_LIB);
      52           39 :     bool isDoubleRing = topoType == TopoType::TOPO_TYPE_NP_DOUBLE_RING;
      53           39 :     bool isSingleServer = (serverNum == 1) && (superPodNum == 1);
      54           39 :     return (param.aicpuUnfoldMode) && isDoubleRing && isGraphMode && isSingleServer;
      55              : }
      56              : 
      57           10 : bool IsSupportDirectFullmeshForAlltoallv(const OpParam& param, DevType deviceType, bool useSuperPodMode, u32 serverNum,
      58              :     bool isSingleMeshAggregation, u32 userRankSize, u64 cclbufferSize)
      59              : {
      60           10 :     bool isOpbase = (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE);
      61           10 :     bool baseInfo = (deviceType == DevType::DEV_TYPE_910_93 || (deviceType == DevType::DEV_TYPE_910B && isOpbase));
      62           10 :     bool isHCCS = false;
      63           10 :     bool isSatisfyBuffer = true;
      64           10 :     if (deviceType == DevType::DEV_TYPE_910_93) {
      65            0 :         isHCCS = (serverNum > 1) ?
      66            0 :             (!GetExternalInputInterHccsDisable() && useSuperPodMode) : true;
      67           10 :     } else if (deviceType == DevType::DEV_TYPE_910B) {
      68           10 :         if (param.opType == HcclCMDType::HCCL_CMD_ALLTOALLV) {
      69              :             // alltoallv算子单机和多机(小于8机64卡)acl graph场景都走directfullmesh算法,且不支持卡数不一致场景
      70            8 :             aclmdlRI rtModel = nullptr;
      71            8 :             bool isCapture = false;
      72            8 :             if (isOpbase) { // acl graph模式下获取capture信息,图模式需要规避
      73            8 :                 HcclResult retCapture = GetStreamCaptureInfo(param.stream.ptr(), rtModel, isCapture);
      74            8 :                 CHK_PRT_CONT(retCapture != HCCL_SUCCESS, 
      75              :                     HCCL_ERROR("Get capture status error. return[%d], capture model", retCapture));
      76              :             }
      77            8 :             isHCCS = (userRankSize <= MAX_ALLTOALLV_DIRECT_FULLMESH_RANKSIZE &&
      78           16 :                       serverNum <= MAX_ALLTOALLV_DIRECT_FULLMESH_SERVER_NUM && isCapture) ||
      79              :                       isSingleMeshAggregation;
      80              :             // A+X单机双module启用下, 未使能RDMA不能走directfullmesh算法
      81            8 :             bool isDifModule = serverNum == 1 && !isSingleMeshAggregation && userRankSize > HCCL_ALLTOALLV_P2P_SIZE;
      82            8 :             if (isDifModule && (GetExternalInputIntraRoceSwitch() == 0)) {
      83            0 :                 isHCCS = false;
      84              :             }
      85              :         } else {
      86              :             // alltoall和alltoallvc在A2上仅支持单机
      87            2 :             isHCCS = (isSingleMeshAggregation) ? (true) : (false);
      88            2 :             if (isHCCS) {
      89              :                 // A2场景下alltoall和alltoallvc需满足数据量大于cclbuffer大小条件
      90            2 :                 isSatisfyBuffer = IsAlltoAllvcSatisfyBufferSize(param, userRankSize, cclbufferSize);
      91              :             }
      92              :         }
      93              :     }
      94           10 :     HCCL_DEBUG("[IsSupportDirectFullmeshForAlltoallv]baseInfo[%u], isOpbase[%u], isHCCS[%u], isSatisfyBuffer[%u]",
      95              :         baseInfo, isOpbase, isHCCS, isSatisfyBuffer);
      96           10 :     return baseInfo && isHCCS && isSatisfyBuffer;
      97              : }
      98              : 
      99          150 : bool SatisfyIntraSuperPod(DevType deviceType, u32 rankSize, bool useSuperPodMode, u32 superPodNum)
     100              : {
     101          150 :     bool rankSizeSupport = (rankSize <= MAX_ALLTOALL_MESH_ALGO_RANK_INTRA_MESH);
     102          150 :     bool isDevice91093 = (deviceType == DevType::DEV_TYPE_910_93);
     103          150 :     bool isHCCS = !GetExternalInputInterHccsDisable() && useSuperPodMode;
     104          149 :     bool isSingleSuperPod = superPodNum == 1;
     105          149 :     bool isOpbase = (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OP_BASE);
     106          148 :     return (isDevice91093 && rankSizeSupport && isHCCS && isSingleSuperPod && isOpbase);
     107              : }
     108              : 
     109          149 : bool FullmeshPairwiseSatisfyHighPerfAlltoallMeshCondition(DevType deviceType, u32 rankSize, bool useSuperPodMode,
     110              :     std::vector<HcclAlgoType> algoConfig)
     111              : {
     112          149 :     bool rankSizeSupport = (rankSize <= MAX_ALLTOALL_MESH_ALGO_RANK_INTRA_MESH);
     113          149 :     bool isDevice91093 = (deviceType == DevType::DEV_TYPE_910_93);
     114              :     bool twoLevelIntraUseMesh =
     115          149 :         (algoConfig[HCCL_ALGO_LEVEL_0] == HcclAlgoType::HCCL_ALGO_TYPE_FULLMESH &&
     116            0 :         algoConfig[HCCL_ALGO_LEVEL_1] == HcclAlgoType::HCCL_ALGO_TYPE_PAIRWISE);
     117          149 :     bool isHCCS = !GetExternalInputInterHccsDisable() && useSuperPodMode;
     118          149 :     HCCL_DEBUG("[FullmeshPairwiseSatisfyHighPerfAlltoallMeshCondition]isDevice91093 %u twoLevelIntraUseMesh %u isHCCS %u",
     119              :         isDevice91093, twoLevelIntraUseMesh, isHCCS);
     120          150 :     CHK_PRT_CONT(!(twoLevelIntraUseMesh && !isDevice91093),
     121              :         HCCL_WARNING("[FullmeshPairwiseSatisfyHighPerfAlltoallMeshCondition] AllToAll read only algorithm only "
     122              :             "support 910_93 device type, use default algorithm type"));
     123          150 :     CHK_PRT_CONT(!(twoLevelIntraUseMesh && !isHCCS),
     124              :         HCCL_WARNING("[FullmeshPairwiseSatisfyHighPerfAlltoallMeshCondition] AllToAll read only algorithm depends "
     125              :             "on HCCS, use default algorithm type"));
     126          150 :     return (isDevice91093 && twoLevelIntraUseMesh && rankSizeSupport && isHCCS);
     127              : }
     128              : 
     129           12 : bool IsConfigAHCAlgo(std::map<HcclCMDType, std::vector<HcclAlgoType>> algoConfigMap)
     130              : {
     131              :     const std::set<HcclCMDType> hcclSupportAHCOpSet = {
     132              :         HcclCMDType::HCCL_CMD_ALLREDUCE, HcclCMDType::HCCL_CMD_REDUCE_SCATTER, HcclCMDType::HCCL_CMD_ALLGATHER
     133           24 :     };
     134              :  
     135           48 :     for (const auto& opType : hcclSupportAHCOpSet) {
     136           36 :         HcclAlgoType algoConfigLevel1 = algoConfigMap[opType][HCCL_ALGO_LEVEL_1];
     137           36 :         bool isConfigAHC =
     138           36 :             (algoConfigLevel1 == HcclAlgoType::HCCL_ALGO_TYPE_AHC ||
     139              :             algoConfigLevel1 == HcclAlgoType::HCCL_ALGO_TYPE_AHC_BROKE);
     140           36 :         if (isConfigAHC) {
     141            0 :             return true;
     142              :         }
     143              :     }
     144           12 :     return false;
     145           12 : }
     146              : 
     147              : template<typename keyType>
     148         1995 : std::string GetAlgoString(const std::map<keyType, std::string>& levelMap, keyType key) {
     149         1995 :     auto iter = levelMap.find(key);
     150         1995 :     if (iter == levelMap.end()) {
     151            4 :         return "invalid algo type";
     152              :     } else {
     153         1993 :         return iter->second;
     154              :     }
     155              : }
     156              : 
     157          665 : std::string AlgTypeToStr(const AlgType algType)
     158              : {
     159          665 :     AlgTypeLevel0 algTypeLevel0 = algType.algoLevel0;
     160          665 :     AlgTypeLevel1 algTypeLevel1 = algType.algoLevel1;
     161          665 :     AlgTypeLevel2 algTypeLevel2 = algType.algoLevel2;
     162          665 :     std::string algStrLevel0 = GetAlgoString(HCCL_ALGO_LEVEL0_NAME_MAP, algTypeLevel0);
     163          665 :     std::string algStrLevel1 = GetAlgoString(HCCL_ALGO_LEVEL1_NAME_MAP, algTypeLevel1);
     164          665 :     std::string algStrLevel2 = GetAlgoString(HCCL_ALGO_LEVEL2_NAME_MAP, algTypeLevel2);
     165          665 :     std::string algStr;
     166          665 :     algStr.append("level0:").append(algStrLevel0).append(",level1:").append(algStrLevel1).append(",level2:").append(algStrLevel2);
     167          665 :     return algStr;
     168          665 : }
     169              : 
     170        58880 : bool Is310P3Common(bool isHaveCpuRank, DevType deviceType)
     171              : {
     172        58880 :     return !isHaveCpuRank && !Is310PDevice() && deviceType == DevType::DEV_TYPE_310P3;
     173              : }
     174              : 
     175          150 : u64 CalculatePiplineSliceNum(HcclCMDType opType, u64 dataSize, AlgType algType, DevType deviceType,
     176              :     u32 deviceNumPerAggregation, u32 moduleNum)
     177              : {
     178          150 :     u64 piplineSliceNum = 0;
     179          150 :     bool isInterRing = false;
     180          150 :     if (algType.algoLevel1 == AlgTypeLevel1::ALG_LEVEL1_RING) {
     181           36 :         isInterRing = true;
     182              :     } else {
     183          114 :         isInterRing = false;
     184              :     }
     185              : 
     186              :     do {
     187          150 :         if (!GetExternalInputHcclEnablePipline()) {
     188          150 :             break;
     189              :         }
     190              :         /* 不支持pipline流水的场景 */
     191              :         // 支持的硬件场景
     192            0 :         if (deviceType != DevType::DEV_TYPE_910B || deviceNumPerAggregation < HCCL_DEVICE_NUM_TWO ||
     193              :             moduleNum < HCCL_DEVICE_NUM_TWO) {
     194              :             break;
     195              :         }
     196              :         // 支持的算子和算法场景
     197            0 :         if (opType != HcclCMDType::HCCL_CMD_ALLREDUCE ||
     198            0 :            (isInterRing && moduleNum > MAX_RING_PIPLINE_SERVER_NUM)) {
     199              :             break;
     200              :         }
     201            0 :         u64 sliceNumTemp = std::min(dataSize / deviceNumPerAggregation / MIN_PER_LINK_DATA_SIZE, MAX_PIPLINE_SLICE_NUM);
     202              :         // 图模式切分数量 <= 1时, 不做切分
     203            0 :         if (GetWorkflowMode() == HcclWorkflowMode::HCCL_WORKFLOW_MODE_OPS_KERNEL_INFO_LIB &&
     204              :             sliceNumTemp <= MIN_PIPLINE_SLICE_NUM) {
     205            0 :             break;
     206              :         }
     207              : 
     208              :         /* 支持pipline流水, 但数据量不足以进行切分的场景 */
     209              :         // Server间使用Ring算法, 且单Server数据量<64KB时, 不做切分
     210            0 :         if ((isInterRing && dataSize / moduleNum < MIN_RING_DATA_SIZE)) {
     211            0 :             sliceNumTemp = 1;
     212              :         }
     213              :         // 支持pipline但数据量不满足切分条件时, 返回1, 用于单算子场景预申请流资源
     214            0 :         piplineSliceNum = (sliceNumTemp == 0) ? 1 : sliceNumTemp;
     215              :     } while (0);
     216          150 :     return piplineSliceNum;
     217              : }
     218              : 
     219            7 : bool HcclOpInplaceDefaultCase(const OpParam &param, u8 &isInplaceStatus)
     220              : {
     221              :     // unknown op
     222            7 :     if (param.inputPtr != param.outputPtr) {
     223              :         // 可以走重执行
     224            4 :         HCCL_DEBUG("[CollAlgOperator][IsHcclOpInplace]param.inputPtr[%p] != param.outputPtr[%p]. They do not overlap.",
     225              :             param.inputPtr, param.outputPtr);
     226            4 :         isInplaceStatus = 0;
     227            4 :         return false;
     228              :     } else {
     229            3 :         HCCL_DEBUG("[CollAlgOperator][IsHcclOpInplace]param.inputPtr[%p] == param.outputPtr[%p]. They overlap.",
     230              :             param.inputPtr, param.outputPtr);
     231            3 :         isInplaceStatus = 1;
     232            3 :         return true;
     233              :     }
     234              : }
     235              : 
     236           91 : bool IsInputOutputOverlap(const OpParam &param, u64 inputDataSize, u64 outputDataSize, u8 &isInplaceStatus)
     237              : {
     238           91 :     if (inputDataSize == 0 || outputDataSize == 0) {
     239              :         // 不存在overlap情况
     240            3 :         HCCL_INFO("[CollAlgOperator][OpRetry][AICPU]The inputPtr[%p] dataSize[%llu], the outputPtr[%p] dataSize[%llu]."
     241              :             "They do not overlap.", param.inputPtr, inputDataSize, param.outputPtr, outputDataSize);
     242            4 :         isInplaceStatus = 0;
     243            4 :         return false;
     244              :     }
     245           88 :     u64 inputStart = reinterpret_cast<u64>(param.inputPtr);
     246           88 :     u64 inputEnd = reinterpret_cast<u64>(param.inputPtr) + inputDataSize - 1;
     247           88 :     u64 outputStart = reinterpret_cast<u64>(param.outputPtr);
     248           88 :     u64 outputEnd = reinterpret_cast<u64>(param.outputPtr) + outputDataSize - 1;
     249              : 
     250           88 :     if (inputStart <= outputEnd && outputStart <= inputEnd) {
     251           12 :         HCCL_DEBUG("[CollAlgOperator][OpRetry][AICPU]The inputPtr[%p] dataSize[%llu], the outputPtr[%p] dataSize[%llu]."
     252              :             "They overlap.", param.inputPtr, inputDataSize, param.outputPtr, outputDataSize);
     253           12 :         isInplaceStatus = 2; // The status 2 is overlap with dataSize.
     254           12 :         return true;
     255              :     } else {
     256           76 :         HCCL_DEBUG("[CollAlgOperator][OpRetry][AICPU]The inputPtr[%p] dataSize[%llu], the outputPtr[%p] dataSize[%llu]."
     257              :             "They do not overlap.", param.inputPtr, inputDataSize, param.outputPtr, outputDataSize);
     258           87 :         isInplaceStatus = 0;
     259           87 :         return false;
     260              :     }
     261              : }
     262              : 
     263          101 : bool IsInputOutPtrNotNullPtr(const OpParam &param, u8 &isInplaceStatus)
     264              : {
     265          101 :     if (param.inputPtr == nullptr || param.outputPtr == nullptr) {
     266              :         // 不存在overlap情况
     267            2 :         HCCL_DEBUG("[CollAlgOperator][OpRetry][AICPU]param.tag[%s], the inputPtr[%p], the outputPtr[%p]."
     268              :             "They do not overlap.", param.tag.c_str(), param.inputPtr, param.outputPtr);
     269            2 :         isInplaceStatus = 0;
     270            2 :         return false;
     271              :     } else {
     272           99 :         return true;
     273              :     }
     274              : }
     275              : 
     276          100 : u32 InplaceDataUnitSize(const HcclCMDType &opType, const OpParam &param)
     277              : {
     278          100 :     u32 unitSize = 0;
     279          100 :     if (opType != HcclCMDType::HCCL_CMD_ALLTOALLV && opType != HcclCMDType::HCCL_CMD_ALLTOALLVC &&
     280           97 :         opType != HcclCMDType::HCCL_CMD_ALLTOALL && opType != HcclCMDType::HCCL_CMD_ALLGATHER_V &&
     281           93 :         opType != HcclCMDType::HCCL_CMD_REDUCE_SCATTER_V) {
     282           93 :         if (param.DataDes.dataType >= HCCL_DATA_TYPE_RESERVED) {
     283            0 :             HCCL_WARNING("[InplaceDataUnitSize] out of range[%d, %d]",
     284              :                 HCCL_DATA_TYPE_INT8, static_cast<int>(HCCL_DATA_TYPE_RESERVED) - 1);
     285            0 :             return 0;
     286              :         }
     287           93 :         unitSize = SIZE_TABLE[param.DataDes.dataType];
     288              :     }
     289          100 :     return unitSize;
     290              : }
     291              : 
     292          101 : bool IsHcclOpInplace(const HcclCMDType &opType, const OpParam &param, u32 userRank, u32 userRankSize,
     293              :     u8 &isInplaceStatus)
     294              : {
     295          101 :     if (!IsInputOutPtrNotNullPtr(param, isInplaceStatus)) {
     296            2 :         return false;
     297              :     }
     298           98 :     u32 unitSize = InplaceDataUnitSize(opType, param);
     299           98 :     u64 inputDataSize = 0;
     300           98 :     u64 outputDataSize = 0;
     301           98 :     switch (opType) {
     302            2 :         case HcclCMDType::HCCL_CMD_SEND:
     303              :         case HcclCMDType::HCCL_CMD_RECEIVE:
     304            2 :             isInplaceStatus = 0;
     305            2 :             return false;
     306           63 :         case HcclCMDType::HCCL_CMD_ALLREDUCE:
     307           63 :             inputDataSize = param.DataDes.count * unitSize;
     308           63 :             outputDataSize = param.DataDes.count * unitSize;
     309           63 :             break;
     310            3 :         case HcclCMDType::HCCL_CMD_REDUCE:
     311            3 :             inputDataSize = param.DataDes.count * unitSize;
     312            3 :             if (userRank == param.root) {
     313            2 :                 outputDataSize = param.DataDes.count * unitSize;
     314              :             }
     315            3 :             break;
     316            2 :         case HcclCMDType::HCCL_CMD_ALLGATHER:
     317            2 :             inputDataSize = param.DataDes.count * unitSize;
     318            2 :             outputDataSize = param.DataDes.count * unitSize * userRankSize;
     319            2 :             break;
     320           16 :         case HcclCMDType::HCCL_CMD_REDUCE_SCATTER:
     321           16 :             inputDataSize = param.DataDes.count * unitSize * userRankSize;
     322           16 :             outputDataSize = param.DataDes.count * unitSize;
     323           16 :             break;
     324            2 :         case HcclCMDType::HCCL_CMD_GATHER:
     325            2 :             inputDataSize = param.DataDes.count * unitSize;
     326            2 :             if (userRank == param.root) {
     327            1 :                 outputDataSize = param.DataDes.count * unitSize * userRankSize;
     328              :             }
     329            2 :             break;
     330            2 :         case HcclCMDType::HCCL_CMD_SCATTER:
     331            2 :             if (userRank == param.root) {
     332            1 :                 inputDataSize = param.DataDes.count * unitSize * userRankSize;
     333              :             }
     334            2 :             outputDataSize = param.DataDes.count * unitSize;
     335            2 :             break;
     336            8 :         case HcclCMDType::HCCL_CMD_ALLTOALLV:
     337              :         case HcclCMDType::HCCL_CMD_ALLTOALLVC:
     338              :         case HcclCMDType::HCCL_CMD_ALLTOALL:
     339              :         default:
     340            8 :             return HcclOpInplaceDefaultCase(param, isInplaceStatus);
     341              :             break;
     342              :     }
     343           88 :     return IsInputOutputOverlap(param, inputDataSize, outputDataSize, isInplaceStatus);
     344              : }
     345              : 
     346            9 : bool CheckUserInMemNotLargerThanCCLInMem(const HcclCMDType &opType, OpParam &param,
     347              :     u64 commInputSize, u32 userRankSize)
     348              : {
     349            9 :     u32 unitSize = SIZE_TABLE[param.DataDes.dataType];
     350            9 :     u64 dataSize = 0;
     351            9 :     if (opType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER) {
     352            0 :         dataSize = param.DataDes.count * unitSize * userRankSize;
     353            9 :     } else if (opType == HcclCMDType::HCCL_CMD_ALLREDUCE) {
     354            9 :         dataSize = param.DataDes.count * unitSize;
     355              :     }
     356              : 
     357            9 :     if (dataSize <= commInputSize) {
     358            7 :         HCCL_INFO("[CollAlgOperator][OpRetry][AICPU] UserInMem[%llu] <= CCLInMem[%llu]", dataSize, commInputSize);
     359              :     } else {
     360            2 :         HCCL_INFO("[CollAlgOperator][OpRetry][AICPU] UserInMem[%llu] > CCLInMem[%llu]", dataSize, commInputSize);
     361              :     }
     362            9 :     return dataSize <= commInputSize;
     363              : }
     364              : 
     365            7 : bool ExecutorOnlySupportDMAReduce(const std::string& algName)
     366              : {
     367            7 :     return (algName == "AllReduceMeshSmallCountExecutor") || (algName == "ReduceScatterDeterExecutor");
     368              : }
     369              : 
     370            4 : bool ExecutorCanSupportDMAReduce(const std::string& algName)
     371              : {
     372              :     const std::set<std::string> executorCanSupportDMAReduceSet = {
     373              :         "AllReduceRingFor91093Executor",
     374              :         "AllReduceFastDoubleRingFor91093Executor",
     375              :         "AlignedAllReduceDoubleRingFor91093Executor",
     376              :         "ReduceScatterRingFor91093Executor",
     377              :         "ReduceScatterFastDoubleRingFor91093Executor",
     378              :         "AlignedReduceScatterDoubleRingFor91093Executor",
     379              :         "ReduceScatterPipelineFor91093Executor"
     380            4 :         };
     381            4 :     if (executorCanSupportDMAReduceSet.find(algName) != executorCanSupportDMAReduceSet.end()) {
     382            2 :         return true;
     383              :     }
     384            2 :     return false;
     385            4 : }
     386              : 
     387            5 : bool ExecutorNoSupportDMAReduce(const std::string& algName)
     388              : {
     389            5 :     return (algName == "AllReduceComm") || (algName == "ReduceScatterComm");
     390              : }
     391              : 
     392            7 : bool ExecutorSupportInPlace(const OpParam &param, const std::string& algName, bool retryEnable,
     393              :     InplaceSupportRetryStatus &inPlaceSupportRetryStatus)
     394              : {
     395              :     (void) param;
     396              :     // case 2.2
     397            7 :     if (ExecutorOnlySupportDMAReduce(algName)) {
     398            2 :         if (retryEnable) {
     399            1 :             HCCL_INFO("[CollAlgOperator][OpRetry][AICPU]ExecutorOnlySupportDMAReduce[%s] is not allowed"
     400              :                 " for inplace case, the executor without DMAReduce will be applied.", algName.c_str());
     401            1 :             inPlaceSupportRetryStatus = InplaceSupportRetryStatus::RETRY_1_ALLOW_NO_DMA_REDUCE_CASE1;
     402            1 :             return true;
     403              :         }
     404            1 :         HCCL_INFO("[CollAlgOperator][OpRetry][AICPU]ExecutorOnlySupportDMAReduce[%s] is not allowed"
     405              :             " for inplace case.", algName.c_str());
     406            1 :         inPlaceSupportRetryStatus = InplaceSupportRetryStatus::RETRY_0_NOT_ALLOW_NO_DMA_REDUCE_CASE1;
     407            1 :         return false;
     408            5 :     } else if (ExecutorNoSupportDMAReduce(algName)) {
     409            1 :         HCCL_INFO("[CollAlgOperator][OpRetry][AICPU]ExecutorNoSupportDMAReduce[%s] is allowed"
     410              :             " for inplace case.", algName.c_str());
     411            1 :         inPlaceSupportRetryStatus = InplaceSupportRetryStatus::ALWAYS_NO_DMA_REDUCE;
     412            1 :         return true;
     413            4 :     } else if (ExecutorCanSupportDMAReduce(algName)) {
     414            2 :         if (retryEnable) {
     415              :             // 对应的executor会感应RetryEnable环境变量,走非DMA削减逻辑
     416            1 :             HCCL_INFO("[CollAlgOperator][OpRetry][AICPU]ExecutorCanSupportDMAReduce[%s] is not allowed"
     417              :                 " for inplace case, the executor without DMAReduce will be applied.", algName.c_str());
     418            1 :             inPlaceSupportRetryStatus = InplaceSupportRetryStatus::RETRY_1_ALLOW_NO_DMA_REDUCE_CASE2;
     419            1 :             return true;
     420              :         }
     421            1 :         HCCL_INFO("[CollAlgOperator][OpRetry][AICPU]ExecutorCanSupportDMAReduce[%s] is not allowed"
     422              :             " for inplace case.", algName.c_str());
     423            1 :         inPlaceSupportRetryStatus = InplaceSupportRetryStatus::RETRY_0_NOT_ALLOW_NO_DMA_REDUCE_CASE2;
     424            1 :         return false;
     425              :     } else {
     426            2 :         HCCL_INFO("[CollAlgOperator][OpRetry][AICPU]The unknown executor[%s] does not support "
     427              :             "for an inplace case yet.", algName.c_str());
     428            2 :         inPlaceSupportRetryStatus = InplaceSupportRetryStatus::UNKONWN_EXECUTOR;
     429            2 :         return false;
     430              :     }
     431              : }
     432              : 
     433           13 : bool FitRetryConditionforInPlaceOp(
     434              :     const HcclCMDType &opType, OpParam &param, const std::string& algName, u64 commInputSize, u32 userRankSize,
     435              :     bool retryEnable,
     436              :     InplaceSupportRetryStatus &inPlaceSupportRetryStatus)
     437              : {
     438              :     // case 1 allgather or broadcast
     439           13 :     if (opType == HcclCMDType::HCCL_CMD_ALLGATHER ||
     440           12 :         opType == HcclCMDType::HCCL_CMD_BROADCAST) {
     441            2 :         inPlaceSupportRetryStatus = InplaceSupportRetryStatus::AG_BD_CASE;
     442            2 :         return true;
     443              :     }
     444              :     // case 2 reducescatter or allreduce
     445           11 :     if (opType == HcclCMDType::HCCL_CMD_REDUCE_SCATTER ||
     446           11 :         opType == HcclCMDType::HCCL_CMD_ALLREDUCE) {
     447              :         // case 2.1
     448            9 :         if (CheckUserInMemNotLargerThanCCLInMem(opType, param, commInputSize, userRankSize)) {
     449              :             // case 2.4: 在hccl_communicator.cc的ExecOp之前已经该让图模式走单算子模式了,理论上不会进入此条件
     450            7 :             HCCL_INFO("[CollAlgOperator][OpRetry][AICPU]The retry with inplace case is expected to be supported, "
     451              :                 "therefore HcclWorkflowMode is set to [%u]",
     452              :                 static_cast<u8>(GetWorkflowMode()));
     453            7 :             return ExecutorSupportInPlace(param, algName, retryEnable, inPlaceSupportRetryStatus);
     454              :         } else {
     455              :             // case 2.3 UsrIn > CCLIn
     456            2 :             inPlaceSupportRetryStatus = InplaceSupportRetryStatus::USER_LARGER_THAN_CCL;
     457            2 :             return false;
     458              :         }
     459              :     }
     460              :     // 其他算子类型不支持
     461            2 :     inPlaceSupportRetryStatus = InplaceSupportRetryStatus::NOT_BASIC_OP_CASE;
     462            2 :     return false;
     463              : }
     464              : 
     465            9 : u32 CalGCD(std::vector<u32> &nums)
     466              : {
     467            9 :     if (nums.size() == 0) {
     468            0 :         return 1;
     469              :     }
     470            9 :     std::sort(nums.begin(), nums.end(), [](const u32 &num1, const u32 &num2) {
     471           23 :         return num1 > num2;
     472              :     });
     473              : 
     474            9 :     u32 curGcd = nums[0];
     475           26 :     for (u32 i = 1; i < nums.size(); i++) {
     476           17 :         curGcd = CalGCD(curGcd, nums[i]);
     477              :     }
     478            9 :     HCCL_DEBUG("[CalGCD]size[%u], gcd[%u]", nums.size(), curGcd);
     479            9 :     return curGcd;
     480              : }
     481              : 
     482           17 : u32 CalGCD(u32 a, u32 b)
     483              : {
     484           17 :     if (a == 0 || b == 0) {
     485            0 :         return 1;
     486              :     }
     487              : 
     488           17 :     u32 gcd = b;
     489           22 :     while (a % b != 0) {
     490            5 :         gcd = a % b;
     491            5 :         a = b;
     492            5 :         b = gcd;
     493              :     }
     494           17 :     HCCL_DEBUG("[CalGCD]a[%u] b[%u], gcd[%u]", a, b, gcd);
     495           17 :     return gcd;
     496              : }
     497              : }
        

Generated by: LCOV version 2.0-1