LCOV - code coverage report
Current view: top level - ut/conv/conv3d_backprop_input_v2/op_host/op_tiling/arch35 - conv3d_backprop_input_v2_small_kernel_tiling.cpp Coverage Total Hit
Test: CHG Lines: 100.0 % 8 8
Test Date: 2026-08-19 10:00:33
Legend: Lines: hit not hit

            Line data    Source code
       1              : /**
       2              :  * Copyright (c) 2026 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              : /*!
      12              :  * \file conv3d_backprop_input_v2_small_kernel_tiling.cpp
      13              :  * \brief small kernel tiling template: N-axis full load, M-axis split, maximize core utilization
      14              :  */
      15              : 
      16              : #include <map>
      17              : #include <numeric>
      18              : #include <log/log.h>
      19              : #include "error_util.h"
      20              : #include <util/math_util.h>
      21              : #include <graph/utils/type_utils.h>
      22              : #include <register/op_impl_registry.h>
      23              : #include "op_host/tiling_templates_registry.h"
      24              : #include "conv/common/op_host/op_tiling/conv_platform_util.h"
      25              : #include "conv3d_backprop_input_v2_small_kernel_tiling.h"
      26              : 
      27              : namespace {
      28              : constexpr uint8_t ENABLE_SMALL_KERNEL = 4;
      29              : constexpr uint8_t REVERSE_ONLY = 2;
      30              : constexpr uint8_t NO_SPLIT_KERNEL = 0;
      31              : constexpr uint64_t SMALL_KERNEL_COMPUTE_THRESHOLD = 144 * 2048 * 2048;
      32              : constexpr uint64_t CORE_SCORE_TAIL_WEIGHT = 1000;
      33              : constexpr uint64_t CORE_SCORE_IDLE_WEIGHT = 10;
      34              : } // namespace
      35              : 
      36              : namespace Ops {
      37              : namespace NN {
      38              : namespace Conv {
      39              : 
      40              : bool Conv3DDXV2SmallKernelTiling::IsCapable()
      41              : {
      42              :     if (!CheckSmallKernelEnable()) {
      43              :         return false;
      44              :     }
      45              : 
      46              :     uint64_t cinAlign = Ops::Base::CeilAlign(static_cast<uint64_t>(runInfo_.dedx_cin_g),
      47              :                                              static_cast<uint64_t>(tilingRunInfo_.n0));
      48              :     if (cinAlign > MAX_BASE_MN) {
      49              :         return false;
      50              :     }
      51              : 
      52              :     if (Conv3DDXV2InnerProductTiling::GetTilingFromRepo()) {
      53              :         isGetTilingFromRepo = true;
      54              :     }
      55              :     return true;
      56              : }
      57              : 
      58              : ge::graphStatus Conv3DDXV2SmallKernelTiling::DoLibApiTiling()
      59              : {
      60              :     OP_LOGD(opName_, "Enable small kernel tiling");
      61              :     tilingRunInfo_.enableSmallKernel = true;
      62              : 
      63              :     if (isGetTilingFromRepo) {
      64              :         OP_LOGD(context_->GetNodeName(),
      65              :                 "Conv3DBackpropInputV2 AscendC: SmallKernel get tiling from knowledge_tiling success.");
      66              :         PrintTilingSummary();
      67              :         return ge::GRAPH_SUCCESS;
      68              :     }
      69              : 
      70              :     CoreTilingParams coreParams;
      71              :     L0TilingParams l0Params;
      72              :     SetSmallKernelCoreInfo(coreParams, l0Params);
      73              : 
      74              :     InitBaseMNK(l0Params);
      75              : 
      76              :     L1TilingParams l1Params;
      77              :     Conv3DDXV2InnerProductTiling::InitL1Params(l1Params, l0Params);
      78              : 
      79              :     CalStepK(l1Params, l0Params);
      80              : 
      81              :     SetTilingCondition(coreParams, l1Params, l0Params);
      82              :     Conv3DDXV2InnerProductTiling::SetTilingData(coreParams, l1Params, l0Params);
      83              :     Conv3DDXV2InnerProductTiling::PrintTilingSummary();
      84              :     return ge::GRAPH_SUCCESS;
      85              : }
      86              : 
      87              : void Conv3DDXV2SmallKernelTiling::InitBaseMNK(L0TilingParams& l0Params)
      88              : {
      89              :     l0Params.al0Pbuffer = DB_OFF;
      90              :     l0Params.bl0Pbuffer = DB_OFF;
      91              :     l0Params.cl0Pbuffer = DB_OFF;
      92              : 
      93              :     uint64_t coutAlign = Ops::Base::CeilAlign(static_cast<uint64_t>(runInfo_.dedy_cout_g),
      94              :                                               static_cast<uint64_t>(tilingRunInfo_.k0));
      95              :     uint64_t kTotal = coutAlign * runInfo_.kernel_h * runInfo_.kernel_w;
      96              : 
      97              :     auto calcMaxBaseK = [this, &l0Params, kTotal]() -> uint32_t {
      98              :         uint32_t maxBaseKByL0a = static_cast<uint32_t>(platformInfo_.l0_ab_size / l0Params.al0Pbuffer / dtypeByteL0a_ /
      99              :                                                        l0Params.baseM);
     100              :         uint32_t maxBaseKByL0b = static_cast<uint32_t>(platformInfo_.l0_ab_size / l0Params.bl0Pbuffer / dtypeByteL0b_ /
     101              :                                                        l0Params.baseN);
     102              :         uint32_t maxBaseK = std::min({maxBaseKByL0a, maxBaseKByL0b, static_cast<uint32_t>(kTotal)});
     103              :         maxBaseK = std::max(maxBaseK / tilingRunInfo_.k0, ONE_U32) * tilingRunInfo_.k0;
     104              :         maxBaseK = std::min(maxBaseK, static_cast<uint32_t>(kTotal));
     105              :         return maxBaseK == 0 ? tilingRunInfo_.k0 : maxBaseK;
     106              :     };
     107              : 
     108              :     l0Params.baseK = calcMaxBaseK();
     109              : 
     110              :     uint32_t kIter = static_cast<uint32_t>(Ops::Base::CeilDiv(kTotal, static_cast<uint64_t>(l0Params.baseK)));
     111              :     if (kIter >= TWO_U32) {
     112              :         // 开启DB前校验: DB后L0a/L0b至少需容纳k0, 否则calcMaxBaseK内强制对齐k0会导致L0溢出
     113            7 :         uint32_t maxBaseKByL0aDb = static_cast<uint32_t>(platformInfo_.l0_ab_size / DB_ON / dtypeByteL0a_ /
     114            7 :                                                          l0Params.baseM);
     115            7 :         uint32_t maxBaseKByL0bDb = static_cast<uint32_t>(platformInfo_.l0_ab_size / DB_ON / dtypeByteL0b_ /
     116            7 :                                                          l0Params.baseN);
     117            7 :         if (maxBaseKByL0aDb >= tilingRunInfo_.k0 && maxBaseKByL0bDb >= tilingRunInfo_.k0) {
     118            7 :             l0Params.al0Pbuffer = DB_ON;
     119            7 :             l0Params.bl0Pbuffer = DB_ON;
     120            7 :             l0Params.baseK = calcMaxBaseK();
     121              :         }
     122              :     }
     123              : }
     124              : 
     125              : void Conv3DDXV2SmallKernelTiling::SetSmallKernelCoreInfo(CoreTilingParams& coreParams, L0TilingParams& l0Params)
     126              : {
     127              :     enableA1Db_ = false;
     128              :     coreParams.singleCoreDin = ONE_U32;
     129              :     coreParams.singleCoreCout = static_cast<uint32_t>(runInfo_.dedy_cout_g);
     130              : 
     131              :     uint64_t cinAlign = Ops::Base::CeilAlign(static_cast<uint64_t>(runInfo_.dedx_cin_g),
     132              :                                              static_cast<uint64_t>(tilingRunInfo_.n0));
     133              :     if (cinAlign == 0) {
     134              :         coreParams.singleCoreM = 0;
     135              :         l0Params.baseM = 0;
     136              :         return;
     137              :     }
     138              :     coreParams.singleCoreCin = cinAlign;
     139              :     l0Params.baseN = static_cast<uint32_t>(cinAlign);
     140              : 
     141              :     uint64_t hwI = static_cast<uint64_t>(runInfo_.dedx_h) * runInfo_.dedx_w;
     142              :     uint64_t batchDepth = static_cast<uint64_t>(runInfo_.batch_n) * runInfo_.dedx_d;
     143              :     uint64_t coreNum = static_cast<uint64_t>(coreNum_);
     144              :     uint64_t m0 = static_cast<uint64_t>(tilingRunInfo_.m0);
     145              :     if (batchDepth == 0 || coreNum == 0 || m0 == 0) {
     146              :         coreParams.singleCoreM = 0;
     147              :         l0Params.baseM = 0;
     148              :         return;
     149              :     }
     150              : 
     151              :     uint64_t maxSingleCoreMByL0C = CalcSmallKernelMaxMByL0C(cinAlign, l0Params.cl0Pbuffer);
     152              :     uint64_t maxM = std::min(hwI, static_cast<uint64_t>(MAX_BASE_MN));
     153              :     uint64_t maxSingleCoreM = std::min(
     154              :         {maxSingleCoreMByL0C, CalcSmallKernelMaxMByL0A(DB_OFF), CalcMaxSingleCoreMByL1(maxM, DB_OFF)});
     155              :     if (maxSingleCoreM < m0) {
     156              :         coreParams.singleCoreM = 0;
     157              :         l0Params.baseM = 0;
     158              :         return;
     159              :     }
     160              : 
     161              :     // 基本块分块决策: 负载均衡 > 核利用率 > 单轮核数
     162              :     // A1 DB 决策: A1 DB_OFF 优先,存在单核多轮次计算则 A1 DB_ON,若超出buffer约束则回退 A1 DB_OFF
     163              :     uint64_t bestSingleCoreM = SelectSmallKernelCoreMWithBuffering(hwI, batchDepth, coreNum, m0, maxM,
     164              :                                                                    maxSingleCoreMByL0C);
     165              : 
     166              :     coreParams.singleCoreM = bestSingleCoreM;
     167              :     l0Params.baseM = static_cast<uint32_t>(Ops::Base::CeilAlign(bestSingleCoreM, m0));
     168              : }
     169              : 
     170              : uint64_t Conv3DDXV2SmallKernelTiling::SelectSmallKernelCoreMWithBuffering(uint64_t hwI, uint64_t batchDepth,
     171              :                                                                           uint64_t coreNum, uint64_t m0, uint64_t maxM,
     172              :                                                                           uint64_t maxSingleCoreMByL0C)
     173              : {
     174              :     uint64_t bestSingleCoreM = SelectSmallKernelCoreM(
     175              :         hwI, batchDepth, coreNum, m0,
     176              :         std::min({maxSingleCoreMByL0C, CalcSmallKernelMaxMByL0A(DB_OFF), CalcMaxSingleCoreMByL1(maxM, DB_OFF)}));
     177              :     uint64_t baseMCnt = Ops::Base::CeilDiv(hwI, bestSingleCoreM);
     178              :     uint64_t baseTotalCnt = batchDepth * baseMCnt;
     179              :     uint64_t baseUsedCoreNum = std::min(baseTotalCnt, coreNum);
     180              :     uint64_t baseCalRound = baseUsedCoreNum == 0 ? 0 : baseTotalCnt / baseUsedCoreNum;
     181              :     uint64_t baseTailCnt = baseUsedCoreNum == 0 ? 0 : baseTotalCnt - baseCalRound * baseUsedCoreNum;
     182              :     enableA1Db_ = baseCalRound > ONE_U64 || baseTailCnt > 0;
     183              :     if (!enableA1Db_) {
     184              :         return bestSingleCoreM;
     185              :     }
     186              :     uint64_t maxSingleCoreMByDb = std::min(
     187              :         {maxSingleCoreMByL0C, CalcSmallKernelMaxMByL0A(DB_ON), CalcMaxSingleCoreMByL1(maxM, DB_ON)});
     188              :     if (maxSingleCoreMByDb < m0) {
     189              :         enableA1Db_ = false;
     190              :         return bestSingleCoreM;
     191              :     }
     192              :     return SelectSmallKernelCoreM(hwI, batchDepth, coreNum, m0, maxSingleCoreMByDb);
     193              : }
     194              : 
     195              : uint64_t Conv3DDXV2SmallKernelTiling::CalcSmallKernelMaxMByL0C(uint64_t cinAlign, uint32_t cl0Pbuffer) const
     196              : {
     197              :     const uint64_t m0 = tilingRunInfo_.m0;
     198              :     const uint64_t floatSize = ge::GetSizeByDataType(ge::DT_FLOAT);
     199              :     if (cinAlign == 0 || m0 == 0 || cl0Pbuffer == 0 || floatSize == 0) {
     200              :         return 0;
     201              :     }
     202              :     uint64_t l0cElementCount = platformInfo_.l0_c_size / cl0Pbuffer / floatSize;
     203              :     return (l0cElementCount / cinAlign / m0) * m0;
     204              : }
     205              : 
     206              : uint64_t Conv3DDXV2SmallKernelTiling::CalcSmallKernelMaxMByL0A(uint32_t al0Pbuffer) const
     207              : {
     208              :     bool isA16W8 = static_cast<int32_t>(dtypeByteL0a_) == ge::GetSizeByDataType(ge::DT_FLOAT16) &&
     209              :                    static_cast<int32_t>(dtypeByteL0b_) == ge::GetSizeByDataType(ge::DT_INT8);
     210              :     if (!isA16W8) {
     211              :         return UINT64_MAX;
     212              :     }
     213              :     const uint64_t k0 = tilingRunInfo_.k0;
     214              :     const uint64_t m0 = tilingRunInfo_.m0;
     215              :     if (k0 == 0 || m0 == 0 || al0Pbuffer == 0 || dtypeByteL0a_ == 0) {
     216              :         return 0;
     217              :     }
     218              :     uint64_t maxBaseM = platformInfo_.l0_ab_size / (k0 * dtypeByteL0a_ * al0Pbuffer);
     219              :     return maxBaseM / m0 * m0;
     220              : }
     221              : 
     222              : uint64_t Conv3DDXV2SmallKernelTiling::CalcSmallKernelCandidateM(uint64_t hwI, uint64_t mCnt, uint64_t maxMByBuffer,
     223              :                                                                 uint64_t m0) const
     224              : {
     225              :     uint64_t candidate = Ops::Base::CeilAlign(Ops::Base::CeilDiv(hwI, mCnt), m0);
     226              :     candidate = std::min({candidate, hwI, static_cast<uint64_t>(MAX_BASE_MN), maxMByBuffer});
     227              :     uint64_t alignedWi = std::max(candidate / runInfo_.dedx_w, ONE_U64) * runInfo_.dedx_w;
     228              :     if (Ops::Base::CeilDiv(hwI, alignedWi) == Ops::Base::CeilDiv(hwI, candidate)) {
     229              :         candidate = alignedWi;
     230              :     }
     231              :     return Ops::Base::FloorAlign(std::min(candidate, maxMByBuffer), m0);
     232              : }
     233              : 
     234              : uint64_t Conv3DDXV2SmallKernelTiling::CalcSmallKernelCoreScore(uint64_t hwI, uint64_t batchDepth, uint64_t coreNum,
     235              :                                                                uint64_t singleCoreM) const
     236              : {
     237              :     uint64_t totalCnt = batchDepth * Ops::Base::CeilDiv(hwI, singleCoreM);
     238              :     uint64_t usedCoreNum = std::min(totalCnt, coreNum);
     239              :     if (usedCoreNum == 0) {
     240              :         return UINT64_MAX;
     241              :     }
     242              :     uint64_t calRound = totalCnt / usedCoreNum;
     243              :     uint64_t tailCnt = totalCnt - calRound * usedCoreNum;
     244              :     return tailCnt * CORE_SCORE_TAIL_WEIGHT + (coreNum - usedCoreNum) * CORE_SCORE_IDLE_WEIGHT + calRound;
     245              : }
     246              : 
     247              : uint64_t Conv3DDXV2SmallKernelTiling::SelectSmallKernelCoreM(uint64_t hwI, uint64_t batchDepth, uint64_t coreNum,
     248              :                                                              uint64_t m0, uint64_t maxMByBuffer) const
     249              : {
     250              :     uint64_t idealMCnt = std::max(coreNum / batchDepth, ONE_U64);
     251              :     uint64_t minMCnt = std::max(idealMCnt / 2, ONE_U64);
     252              :     uint64_t maxMCnt = std::min(Ops::Base::CeilDiv(hwI, static_cast<uint64_t>(BASIC_BLOCK_SIZE_64)), idealMCnt * 2);
     253              :     uint64_t bestSingleCoreM = CalcSmallKernelCandidateM(hwI, idealMCnt, maxMByBuffer, m0);
     254              :     uint64_t bestScore = CalcSmallKernelCoreScore(hwI, batchDepth, coreNum, bestSingleCoreM);
     255              :     for (uint64_t mCnt = minMCnt; mCnt <= maxMCnt; ++mCnt) {
     256              :         uint64_t singleCoreM = CalcSmallKernelCandidateM(hwI, mCnt, maxMByBuffer, m0);
     257              :         if (singleCoreM < BASIC_BLOCK_SIZE_64) {
     258              :             break;
     259              :         }
     260              :         uint64_t score = CalcSmallKernelCoreScore(hwI, batchDepth, coreNum, singleCoreM);
     261              :         if (score < bestScore) {
     262              :             bestScore = score;
     263              :             bestSingleCoreM = singleCoreM;
     264              :         }
     265              :     }
     266              :     return bestSingleCoreM;
     267              : }
     268              : 
     269              : void Conv3DDXV2SmallKernelTiling::CalStepK(L1TilingParams& l1Params, const L0TilingParams& l0Params)
     270              : {
     271              :     (void)l0Params;
     272              :     l1Params.al1Pbuffer = enableA1Db_ ? DB_ON : DB_OFF;
     273              :     l1Params.bl1Pbuffer = DB_OFF;
     274              :     l1Params.stepKa = ONE_U32;
     275              :     l1Params.stepKb = ONE_U32;
     276              : }
     277              : 
     278              : void Conv3DDXV2SmallKernelTiling::SetTilingCondition(const CoreTilingParams& coreParams, const L1TilingParams& l1Params,
     279              :                                                      const L0TilingParams& l0Params)
     280              : {
     281              :     loadB1Condition_ = ENABLE_SMALL_KERNEL;
     282              :     loadB2Condition_ = (runInfo_.filterFormat == ge::FORMAT_FRACTAL_Z) ? B2_NO_TRANSPOSE_NO_REVERSE : REVERSE_ONLY;
     283              :     kernelSplitMode_ = NO_SPLIT_KERNEL;
     284              :     groupConvMode_ = TILING_GROUP_MODE_ORIGIN;
     285              :     tilingRunInfo_.enableVecTransFlag = false;
     286              : }
     287              : 
     288              : uint64_t Conv3DDXV2SmallKernelTiling::CalSmallKernelLocalHo(uint64_t maxM, uint64_t wi, uint64_t hk, uint64_t dilationH,
     289              :                                                             uint64_t hoExpand)
     290              : {
     291              :     uint64_t hiCount = Ops::Base::CeilDiv(maxM + wi - 1, wi);
     292              :     uint64_t receptiveHo = hiCount + (hk - 1) * dilationH;
     293              :     return std::min(receptiveHo, hoExpand);
     294              : }
     295              : 
     296              : uint64_t Conv3DDXV2SmallKernelTiling::CalcSmallKernelA1Size(uint64_t baseM) const
     297              : {
     298              :     uint64_t hoExpand = (static_cast<uint64_t>(runInfo_.dedy_h) - 1) * runInfo_.stride_h + 1;
     299              :     uint64_t woExpand = (static_cast<uint64_t>(runInfo_.dedy_w) - 1) * runInfo_.stride_w + 1;
     300              :     uint64_t coutAlign = Ops::Base::CeilAlign(static_cast<uint64_t>(runInfo_.dedy_cout_g),
     301              :                                               static_cast<uint64_t>(tilingRunInfo_.k0));
     302              :     uint64_t localHo = Ops::Base::CeilDiv(baseM + runInfo_.dedx_w - 1, static_cast<uint64_t>(runInfo_.dedx_w)) +
     303              :                        (runInfo_.kernel_h - 1) * runInfo_.dilation_h;
     304              :     localHo = std::min(localHo, hoExpand);
     305              :     return localHo * woExpand * coutAlign * dtypeByteL0a_;
     306              : }
     307              : 
     308              : uint64_t Conv3DDXV2SmallKernelTiling::CalcSmallKernelL1FixedSize() const
     309              : {
     310              :     uint64_t coutAlign = Ops::Base::CeilAlign(static_cast<uint64_t>(runInfo_.dedy_cout_g),
     311              :                                               static_cast<uint64_t>(tilingRunInfo_.k0));
     312              :     uint64_t cinAlign = Ops::Base::CeilAlign(static_cast<uint64_t>(runInfo_.dedx_cin_g),
     313              :                                              static_cast<uint64_t>(tilingRunInfo_.n0));
     314              :     uint64_t b1Size = static_cast<uint64_t>(runInfo_.kernel_h) * runInfo_.kernel_w * coutAlign * cinAlign *
     315              :                       dtypeByteL0b_;
     316              :     uint64_t biasSize = 0;
     317              :     if (hasBiasFlag_) {
     318              :         uint64_t dtypeByteBtBuffer = (runInfo_.a_dtype_bytes == ge::GetSizeByDataType(ge::DT_INT8)) ?
     319              :                                          ge::GetSizeByDataType(ge::DT_INT32) :
     320              :                                          ge::GetSizeByDataType(ge::DT_FLOAT);
     321              :         // bias L1 区按 64B 对齐,与 kernel 侧 GetBiasL1SizeBytes 保持一致(scale 起始地址需 64B 对齐,否则 AIC
     322              :         // error)。
     323              :         biasSize = Ops::Base::CeilAlign(cinAlign * dtypeByteBtBuffer, BYTE_64);
     324              :     }
     325              :     uint64_t scaleSize = 0;
     326              :     if (hasScaleFlag_ && runInfo_.quantMode == static_cast<uint8_t>(QuantMode::VECTOR_QUANT)) {
     327              :         scaleSize = cinAlign * ge::GetSizeByDataType(ge::DT_INT64);
     328              :     }
     329              :     return b1Size + biasSize + scaleSize;
     330              : }
     331              : 
     332              : uint64_t Conv3DDXV2SmallKernelTiling::CalcMaxSingleCoreMByL1(uint64_t maxM, uint32_t a1Pbuffer) const
     333              : {
     334              :     const uint64_t m0 = tilingRunInfo_.m0;
     335              :     if (a1Pbuffer == 0 || m0 == 0 || maxM < m0 || platformInfo_.l1_size <= CalcSmallKernelL1FixedSize()) {
     336              :         return 0;
     337              :     }
     338              :     const uint64_t a1BankBudget = (platformInfo_.l1_size - CalcSmallKernelL1FixedSize()) / a1Pbuffer;
     339              :     uint64_t low = 1;
     340              :     uint64_t high = maxM / m0;
     341              :     uint64_t best = 0;
     342              :     while (low <= high) {
     343              :         uint64_t mid = low + (high - low) / 2;
     344              :         uint64_t candidateM = mid * m0;
     345              :         if (CalcSmallKernelA1Size(candidateM) <= a1BankBudget) {
     346              :             best = candidateM;
     347              :             low = mid + 1;
     348              :         } else {
     349              :             high = mid - 1;
     350              :         }
     351              :     }
     352              :     return best;
     353              : }
     354              : 
     355              : bool Conv3DDXV2SmallKernelTiling::HasSupportedSmallKernelDimensions() const
     356              : {
     357              :     return runInfo_.kernel_d == 1 && runInfo_.dedx_d == 1 && runInfo_.dedy_d == 1 && runInfo_.groups == 1;
     358              : }
     359              : 
     360              : bool Conv3DDXV2SmallKernelTiling::HasSupportedSmallKernelFormats() const
     361              : {
     362              :     return runInfo_.outBackpropFormat == ge::FORMAT_NCDHW && runInfo_.yFormat == ge::FORMAT_NCDHW &&
     363              :            (runInfo_.filterFormat == ge::FORMAT_NDHWC || runInfo_.filterFormat == ge::FORMAT_FRACTAL_Z);
     364              : }
     365              : 
     366              : bool Conv3DDXV2SmallKernelTiling::HasSupportedSmallKernelPadding() const
     367              : {
     368              :     return runInfo_.backprop_pad_l >= 0 && runInfo_.backprop_pad_r >= 0 && runInfo_.backprop_pad_u >= 0 &&
     369              :            runInfo_.backprop_pad_d >= 0 && runInfo_.backprop_pad_l <= PAD_DIM_UP &&
     370              :            runInfo_.backprop_pad_r <= PAD_DIM_UP && runInfo_.backprop_pad_u <= PAD_DIM_UP &&
     371              :            runInfo_.backprop_pad_d <= PAD_DIM_UP;
     372              : }
     373              : 
     374              : bool Conv3DDXV2SmallKernelTiling::HasSmallKernelComputationBudget() const
     375              : {
     376              :     uint64_t computation = static_cast<uint64_t>(runInfo_.dedx_h) * runInfo_.dedx_w * runInfo_.kernel_h *
     377              :                            runInfo_.kernel_w * runInfo_.dedy_cout_g * runInfo_.dedx_cin_g;
     378              :     bool isFp16Fp16 = static_cast<int32_t>(dtypeByteL0a_) == ge::GetSizeByDataType(ge::DT_FLOAT16) &&
     379              :                       static_cast<int32_t>(dtypeByteL0b_) == ge::GetSizeByDataType(ge::DT_FLOAT16);
     380              :     if (isFp16Fp16) {
     381              :         return computation < SMALL_KERNEL_COMPUTE_THRESHOLD;
     382              :     }
     383              :     bool isA16W8 = static_cast<int32_t>(dtypeByteL0a_) == ge::GetSizeByDataType(ge::DT_FLOAT16) &&
     384              :                    static_cast<int32_t>(dtypeByteL0b_) == ge::GetSizeByDataType(ge::DT_INT8);
     385              :     if (isA16W8) {
     386              :         return computation < SMALL_KERNEL_COMPUTE_THRESHOLD * TWO;
     387              :     }
     388              :     return true;
     389              : }
     390              : 
     391              : bool Conv3DDXV2SmallKernelTiling::HasSmallKernelBufferBudget() const
     392              : {
     393              :     if (tilingRunInfo_.n0 == 0 || tilingRunInfo_.m0 == 0) {
     394              :         return false;
     395              :     }
     396              :     // The scheduling overhead of small kernel causes a severe performance regression in single-core scenarios.
     397              :     if (coreNum_ == 1) {
     398              :         return false;
     399              :     }
     400              :     uint64_t cinAlign = Ops::Base::CeilAlign(static_cast<uint64_t>(runInfo_.dedx_cin_g),
     401              :                                              static_cast<uint64_t>(tilingRunInfo_.n0));
     402              :     uint64_t maxMByL0C = CalcSmallKernelMaxMByL0C(cinAlign, DB_OFF);
     403              :     uint64_t maxMByL0A = CalcSmallKernelMaxMByL0A(DB_OFF);
     404              :     uint64_t hwI = static_cast<uint64_t>(runInfo_.dedx_h) * runInfo_.dedx_w;
     405              :     uint64_t maxSingleCoreM = CalcMaxSingleCoreMByL1(std::min(hwI, static_cast<uint64_t>(MAX_BASE_MN)), DB_OFF);
     406              :     uint64_t l1UsedSize = CalcSmallKernelL1FixedSize() + CalcSmallKernelA1Size(maxSingleCoreM);
     407              :     return maxMByL0C >= tilingRunInfo_.m0 && maxMByL0A >= tilingRunInfo_.m0 && maxSingleCoreM >= tilingRunInfo_.m0 &&
     408              :            l1UsedSize <= platformInfo_.l1_size;
     409              : }
     410              : 
     411              : bool Conv3DDXV2SmallKernelTiling::CheckSmallKernelEnable()
     412              : {
     413              :     if (!IsSocVersionFuse(context_)) {
     414              :         return false;
     415              :     }
     416              :     // 维度要求: D=1, group=1
     417              :     // format要求: outBackprop/y=NCDHW, filter=NDHWC
     418              :     if (!HasSupportedSmallKernelDimensions() || !HasSupportedSmallKernelFormats() ||
     419              :         !HasSupportedSmallKernelPadding() || !HasSmallKernelComputationBudget()) {
     420              :         return false;
     421              :     }
     422              :     return HasSmallKernelBufferBudget();
     423              : }
     424              : 
     425              : REGISTER_TILING_TEMPLATE("Conv3DBackpropInputV2", Conv3DDXV2SmallKernelTiling, 96);
     426              : 
     427              : } // namespace Conv
     428              : } // namespace NN
     429              : } // namespace Ops
        

Generated by: LCOV version 2.0-1