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

Generated by: LCOV version 2.0-1