* Copyright (c) 2026 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
* \file prelu_tiling.cpp
* \brief Prelu 算子 Tiling 实现
*/
#include "register/op_def_registry.h"
#include "graph/utils/type_utils.h"
#include "op_common/log/log.h"
#include "op_common/op_host/util/math_util.h"
#include "op_common/op_host/util/platform_util.h"
#include "../op_kernel/prelu_tiling_data.h"
#include "../op_kernel/prelu_tiling_key.h"
#include <algorithm>
#include <limits>
namespace optiling {
constexpr uint32_t WS_SYS_SIZE = 0U;
constexpr uint32_t BLOCK_SIZE = 32U;
constexpr uint32_t CORE_ALIGN_SIZE = 512U;
constexpr int64_t MAX_AIV_CORE_NUM = 40;
constexpr uint64_t MIN_PARALLEL_TILE_NUM = 2U;
constexpr uint64_t UB_RESERVED_SIZE = 1024U;
constexpr uint64_t SMALL_L_WEIGHT_REUSE_MAX_INNER_SIZE = 16U;
constexpr uint64_t SPLIT_C_WEIGHT_REUSE_MAX_INNER_SIZE = 64U;
constexpr uint64_t LARGE_L_SPLIT_C_WEIGHT_REUSE_MAX_INNER_SIZE = 1024U;
constexpr uint64_t LARGE_L_SPLIT_C_WEIGHT_REUSE_MAX_CHANNEL_SIZE = 1024U;
constexpr uint64_t LARGE_C_WEIGHT_REUSE_MIN_CHANNEL_SIZE = 32U;
constexpr uint64_t MIN_SPLIT_C_WEIGHT_REUSE_CORE_NUM = 10U;
static ge::graphStatus GetPlatformInfo(gert::TilingContext* context, uint64_t& ubSize, int64_t& coreNum)
{
fe::PlatFormInfos* platformInfoPtr = context->GetPlatformInfo();
OP_CHECK_NULL_WITH_CONTEXT(context, platformInfoPtr);
auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfoPtr);
coreNum = ascendcPlatform.GetCoreNumAiv();
OP_CHECK_IF(coreNum == 0, OP_LOGE(context, "coreNum is 0"), return ge::GRAPH_FAILED);
coreNum = std::min(coreNum, MAX_AIV_CORE_NUM);
ascendcPlatform.GetCoreMemSize(platform_ascendc::CoreMemType::UB, ubSize);
OP_CHECK_IF(ubSize == 0, OP_LOGE(context, "ubSize is 0"), return ge::GRAPH_FAILED);
return ge::GRAPH_SUCCESS;
}
static ge::graphStatus GetWorkspaceSize(gert::TilingContext* context)
{
size_t* currentWorkspace = context->GetWorkspaceSizes(1);
if (currentWorkspace != nullptr) {
currentWorkspace[0] = WS_SYS_SIZE;
}
return ge::GRAPH_SUCCESS;
}
static ge::graphStatus GetShapeAndDtypeInfo(gert::TilingContext* context, int64_t& totalNum, int64_t& weightSize,
int64_t& weightMode, int64_t& channelSize, int64_t& innerSize,
int64_t& rowNum, ge::DataType& dataType, uint32_t& typeLength)
{
auto inputX = context->GetInputShape(0);
OP_CHECK_NULL_WITH_CONTEXT(context, inputX);
auto inputWeight = context->GetInputShape(1);
OP_CHECK_NULL_WITH_CONTEXT(context, inputWeight);
auto outputY = context->GetOutputShape(0);
OP_CHECK_NULL_WITH_CONTEXT(context, outputY);
auto xShape = inputX->GetStorageShape();
auto wShape = inputWeight->GetStorageShape();
auto yShape = outputY->GetStorageShape();
OP_CHECK_IF(xShape.GetDimNum() != yShape.GetDimNum(), OP_LOGE(context, "Prelu: x/y rank mismatch"),
return ge::GRAPH_FAILED);
for (size_t i = 0; i < xShape.GetDimNum(); ++i) {
OP_CHECK_IF(xShape.GetDim(i) != yShape.GetDim(i), OP_LOGE(context, "Prelu: x/y shape mismatch"),
return ge::GRAPH_FAILED);
}
auto xDesc = context->GetInputDesc(0);
auto weightDesc = context->GetInputDesc(1);
auto yDesc = context->GetOutputDesc(0);
OP_CHECK_NULL_WITH_CONTEXT(context, xDesc);
OP_CHECK_NULL_WITH_CONTEXT(context, weightDesc);
OP_CHECK_NULL_WITH_CONTEXT(context, yDesc);
dataType = xDesc->GetDataType();
OP_CHECK_IF(dataType != ge::DT_FLOAT && dataType != ge::DT_FLOAT16 && dataType != ge::DT_BF16,
OP_LOGE(context, "Prelu: unsupported dtype"), return ge::GRAPH_FAILED);
OP_CHECK_IF(weightDesc->GetDataType() != dataType || yDesc->GetDataType() != dataType,
OP_LOGE(context, "Prelu: x, weight and y must have the same dtype"), return ge::GRAPH_FAILED);
ge::TypeUtils::GetDataTypeLength(dataType, typeLength);
OP_CHECK_IF(typeLength == 0, OP_LOGE(context, "Prelu: dtype length is 0"), return ge::GRAPH_FAILED);
OP_CHECK_IF(wShape.GetDimNum() != 1,
OP_LOGE(context, "Prelu: weight must be 1-D, got dim num %zu", wShape.GetDimNum()),
return ge::GRAPH_FAILED);
weightSize = wShape.GetDim(0);
OP_CHECK_IF(weightSize <= 0, OP_LOGE(context, "Prelu: weight size must be positive"), return ge::GRAPH_FAILED);
weightMode = 0;
channelSize = 1;
innerSize = 1;
rowNum = 0;
if (weightSize != 1) {
OP_CHECK_IF(xShape.GetDimNum() < 2, OP_LOGE(context, "Prelu: channel weight requires x rank >= 2"),
return ge::GRAPH_FAILED);
int64_t batchSize = xShape.GetDim(0);
OP_CHECK_IF(batchSize <= 0, OP_LOGE(context, "Prelu: N must be positive, got %ld", batchSize),
return ge::GRAPH_FAILED);
channelSize = xShape.GetDim(1);
OP_CHECK_IF(channelSize <= 0, OP_LOGE(context, "Prelu: channel size must be positive, got %ld", channelSize),
return ge::GRAPH_FAILED);
OP_CHECK_IF(
weightSize != channelSize,
OP_LOGE(context, "Prelu: weight size must be 1 or match channel size, weight size=%ld, channel size=%ld",
weightSize, channelSize),
return ge::GRAPH_FAILED);
innerSize = 1;
for (size_t i = 2; i < xShape.GetDimNum(); ++i) {
int64_t dimValue = xShape.GetDim(i);
OP_CHECK_IF(dimValue <= 0, OP_LOGE(context, "Prelu: x dim %zu must be positive, got %ld", i, dimValue),
return ge::GRAPH_FAILED);
OP_CHECK_IF(innerSize > std::numeric_limits<int64_t>::max() / dimValue,
OP_LOGE(context, "Prelu: L exceeds int64 range"), return ge::GRAPH_FAILED);
innerSize *= dimValue;
}
OP_CHECK_IF(static_cast<uint64_t>(batchSize) >
static_cast<uint64_t>(std::numeric_limits<int64_t>::max()) / static_cast<uint64_t>(channelSize),
OP_LOGE(context, "Prelu: rowNum exceeds int64 range"), return ge::GRAPH_FAILED);
rowNum = batchSize * channelSize;
weightMode = 1;
}
totalNum = inputX->GetOriginShape().GetShapeSize();
return ge::GRAPH_SUCCESS;
}
static uint64_t GetBufferBytesPerElement(ge::DataType dataType)
{
if (dataType == ge::DT_FLOAT) {
return 24U;
}
if (dataType == ge::DT_FLOAT16) {
return 12U;
}
return 20U;
}
static uint64_t GetNcWeightReuseBufferBytesPerElement(ge::DataType dataType)
{
if (dataType == ge::DT_FLOAT) {
return 28U;
}
if (dataType == ge::DT_FLOAT16) {
return 14U;
}
return 24U;
}
static uint64_t GetNcResidentWeightBufferBytesPerElement(ge::DataType dataType)
{
if (dataType == ge::DT_FLOAT) {
return 28U;
}
if (dataType == ge::DT_FLOAT16) {
return 14U;
}
return 24U;
}
static uint64_t GetNcWeightCacheBytesPerElement(ge::DataType dataType, uint32_t typeLength)
{
uint64_t bytes = typeLength;
if (dataType == ge::DT_BF16) {
bytes += sizeof(float);
}
return bytes;
}
static uint64_t GetWeightVecBytesPerElement(ge::DataType dataType, uint32_t typeLength)
{
if (dataType == ge::DT_BF16) {
return sizeof(float);
}
return typeLength;
}
static uint64_t CeilDiv(uint64_t value, uint64_t factor) { return (value + factor - 1U) / factor; }
static uint64_t AlignUp(uint64_t value, uint64_t align) { return CeilDiv(value, align) * align; }
static ge::graphStatus CalcTiling(gert::TilingContext* context, uint64_t ubSize, int64_t coreNum, int64_t totalNum,
ge::DataType dataType, uint32_t typeLength, int64_t weightMode, int64_t channelSize,
int64_t innerSize, int64_t rowNum, PreluTilingData* tiling, uint32_t& usedCoreNum,
bool& useSplitLParallel, bool& useNcWeightReuse, bool& useNcSplitCWeightReuse,
bool& useNcResidentWeightReuse)
{
useSplitLParallel = false;
useNcWeightReuse = false;
useNcSplitCWeightReuse = false;
useNcResidentWeightReuse = false;
uint64_t bufferBytesPerElement = GetBufferBytesPerElement(dataType);
uint64_t usableUbSize = (ubSize > UB_RESERVED_SIZE) ? (ubSize - UB_RESERVED_SIZE) : ubSize;
uint64_t blockElementNum = BLOCK_SIZE / typeLength;
uint64_t maxTileElements = usableUbSize / bufferBytesPerElement;
OP_CHECK_IF(maxTileElements < blockElementNum, OP_LOGE(context, "Prelu: UB is too small for one aligned tile"),
return ge::GRAPH_FAILED);
uint64_t ubFactor = (maxTileElements / blockElementNum) * blockElementNum;
tiling->totalLength = totalNum;
tiling->tileLength = static_cast<int64_t>(ubFactor);
tiling->channelSize = channelSize;
tiling->innerSize = innerSize;
tiling->innerSizeAligned = innerSize;
tiling->baseRows = 0;
tiling->extraRows = 0;
tiling->tilesPerRow = 0;
tiling->baseTasks = 0;
tiling->extraTasks = 0;
uint64_t coreLimit = static_cast<uint64_t>(coreNum);
if (weightMode == 0) {
uint64_t coreAlignElementNum = CORE_ALIGN_SIZE / typeLength;
uint64_t totalCoreElements = CeilDiv(static_cast<uint64_t>(totalNum), coreLimit);
uint64_t blockFactor = (CeilDiv(totalCoreElements, coreAlignElementNum)) * coreAlignElementNum;
if (blockFactor == 0) {
blockFactor = coreAlignElementNum;
}
uint64_t finalCoreNum = static_cast<uint64_t>(totalNum) == 0 ?
1U :
CeilDiv(static_cast<uint64_t>(totalNum), blockFactor);
finalCoreNum = std::min(coreLimit, finalCoreNum);
uint64_t tailLength = 0;
uint64_t formerNum = 0;
if (totalNum > 0) {
formerNum = finalCoreNum > 0 ? finalCoreNum - 1U : 0U;
tailLength = static_cast<uint64_t>(totalNum) - formerNum * blockFactor;
}
tiling->usedCoreNum = static_cast<int64_t>(finalCoreNum);
tiling->formerNum = static_cast<int64_t>(formerNum);
tiling->formerLength = static_cast<int64_t>(blockFactor);
tiling->tailLength = static_cast<int64_t>(tailLength);
usedCoreNum = static_cast<uint32_t>(finalCoreNum);
return ge::GRAPH_SUCCESS;
}
OP_CHECK_IF(innerSize <= 0, OP_LOGE(context, "Prelu: L must be positive"), return ge::GRAPH_FAILED);
OP_CHECK_IF(static_cast<uint64_t>(innerSize) > std::numeric_limits<uint64_t>::max() - blockElementNum + 1U,
OP_LOGE(context, "Prelu: L is too large to align"), return ge::GRAPH_FAILED);
uint64_t innerSizeAligned = CeilDiv(static_cast<uint64_t>(innerSize), blockElementNum) * blockElementNum;
OP_CHECK_IF(innerSizeAligned > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()),
OP_LOGE(context, "Prelu: aligned L exceeds int64 range"), return ge::GRAPH_FAILED);
uint64_t rowNumU64 = static_cast<uint64_t>(rowNum);
tiling->formerNum = 0;
tiling->formerLength = 0;
tiling->tailLength = 0;
tiling->innerSizeAligned = static_cast<int64_t>(innerSizeAligned);
uint64_t batchSize = rowNumU64 / static_cast<uint64_t>(channelSize);
bool preferWeightReuseByRow = innerSize == 1 ||
(static_cast<uint64_t>(innerSize) <= SPLIT_C_WEIGHT_REUSE_MAX_INNER_SIZE &&
static_cast<uint64_t>(channelSize) >= LARGE_C_WEIGHT_REUSE_MIN_CHANNEL_SIZE) ||
(static_cast<uint64_t>(innerSize) <= LARGE_L_SPLIT_C_WEIGHT_REUSE_MAX_INNER_SIZE &&
static_cast<uint64_t>(channelSize) <=
LARGE_L_SPLIT_C_WEIGHT_REUSE_MAX_CHANNEL_SIZE &&
static_cast<uint64_t>(channelSize) >= LARGE_C_WEIGHT_REUSE_MIN_CHANNEL_SIZE);
if (preferWeightReuseByRow && channelSize > 1 && batchSize > 0) {
OP_CHECK_IF(static_cast<uint64_t>(channelSize) >
std::numeric_limits<uint64_t>::max() / static_cast<uint64_t>(innerSize),
OP_LOGE(context, "Prelu: C*L exceeds uint64 range"), return ge::GRAPH_FAILED);
uint64_t rowElements = static_cast<uint64_t>(channelSize) * static_cast<uint64_t>(innerSize);
uint64_t alignedRowElements = AlignUp(rowElements, blockElementNum);
uint64_t alignedChannelSize = AlignUp(static_cast<uint64_t>(channelSize), blockElementNum);
uint64_t weightCacheBytesPerElement = GetNcWeightCacheBytesPerElement(dataType, typeLength);
bool weightCacheSizeValid = alignedChannelSize <=
std::numeric_limits<uint64_t>::max() / weightCacheBytesPerElement;
uint64_t weightCacheBytes = weightCacheSizeValid ? alignedChannelSize * weightCacheBytesPerElement : 0U;
uint64_t ncResidentWeightCacheBytes = dataType == ge::DT_BF16 ? weightCacheBytes : 0U;
if (weightCacheSizeValid && weightCacheBytes < usableUbSize) {
uint64_t ncBufferBytesPerElement = innerSize == 1 ? GetNcResidentWeightBufferBytesPerElement(dataType) :
GetNcWeightReuseBufferBytesPerElement(dataType);
uint64_t ncWeightCacheBytes = innerSize == 1 ? ncResidentWeightCacheBytes : weightCacheBytes;
uint64_t ncMaxTileElements = ((usableUbSize - ncWeightCacheBytes) / ncBufferBytesPerElement /
alignedRowElements) *
alignedRowElements;
if (ncMaxTileElements >= alignedRowElements) {
uint64_t finalCoreNum = std::min(coreLimit, batchSize);
tiling->tileLength = static_cast<int64_t>(ncMaxTileElements);
tiling->innerSizeAligned = static_cast<int64_t>(alignedRowElements);
tiling->usedCoreNum = static_cast<int64_t>(finalCoreNum);
tiling->baseRows = static_cast<int64_t>(batchSize / finalCoreNum);
tiling->extraRows = static_cast<int64_t>(batchSize % finalCoreNum);
usedCoreNum = static_cast<uint32_t>(finalCoreNum);
bool isResidentWeightReuse = innerSize == 1;
useNcResidentWeightReuse = isResidentWeightReuse;
useNcWeightReuse = !isResidentWeightReuse;
return ge::GRAPH_SUCCESS;
}
}
if (innerSize == 1) {
uint64_t splitCBytesPerElement = weightCacheBytesPerElement +
GetNcWeightReuseBufferBytesPerElement(dataType);
uint64_t maxSplitCElements = usableUbSize / splitCBytesPerElement;
uint64_t splitCTileLength = (maxSplitCElements / blockElementNum) * blockElementNum;
if (splitCTileLength >= blockElementNum) {
uint64_t cTileNum = CeilDiv(static_cast<uint64_t>(channelSize), splitCTileLength);
OP_CHECK_IF(cTileNum > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()),
OP_LOGE(context, "Prelu: split-C tile count exceeds int64 range"), return ge::GRAPH_FAILED);
OP_CHECK_IF(batchSize > std::numeric_limits<uint64_t>::max() / cTileNum,
OP_LOGE(context, "Prelu: split-C total task count exceeds uint64 range"),
return ge::GRAPH_FAILED);
uint64_t totalTaskNum = batchSize * cTileNum;
OP_CHECK_IF(totalTaskNum > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()),
OP_LOGE(context, "Prelu: split-C total task count exceeds int64 range"),
return ge::GRAPH_FAILED);
uint64_t finalCoreNum = std::min(coreLimit, totalTaskNum);
tiling->tileLength = static_cast<int64_t>(splitCTileLength);
tiling->innerSizeAligned = static_cast<int64_t>(splitCTileLength);
tiling->usedCoreNum = static_cast<int64_t>(finalCoreNum);
tiling->tilesPerRow = static_cast<int64_t>(cTileNum);
tiling->baseTasks = static_cast<int64_t>(totalTaskNum / finalCoreNum);
tiling->extraTasks = static_cast<int64_t>(totalTaskNum % finalCoreNum);
usedCoreNum = static_cast<uint32_t>(finalCoreNum);
useNcSplitCWeightReuse = true;
return ge::GRAPH_SUCCESS;
}
} else {
uint64_t splitCBytesPerChannel = weightCacheBytesPerElement +
GetNcWeightReuseBufferBytesPerElement(dataType) *
static_cast<uint64_t>(innerSize);
uint64_t maxSplitCChannels = usableUbSize / splitCBytesPerChannel;
uint64_t splitCTileChannels = (maxSplitCChannels / blockElementNum) * blockElementNum;
if (splitCTileChannels >= blockElementNum) {
uint64_t alignedSplitCElements = AlignUp(splitCTileChannels * static_cast<uint64_t>(innerSize),
blockElementNum);
uint64_t cTileNum = CeilDiv(static_cast<uint64_t>(channelSize), splitCTileChannels);
OP_CHECK_IF(cTileNum > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()),
OP_LOGE(context, "Prelu: small-L split-C tile count exceeds int64 range"),
return ge::GRAPH_FAILED);
OP_CHECK_IF(batchSize > std::numeric_limits<uint64_t>::max() / cTileNum,
OP_LOGE(context, "Prelu: small-L split-C total task count exceeds uint64 range"),
return ge::GRAPH_FAILED);
uint64_t totalTaskNum = batchSize * cTileNum;
OP_CHECK_IF(totalTaskNum > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()),
OP_LOGE(context, "Prelu: small-L split-C total task count exceeds int64 range"),
return ge::GRAPH_FAILED);
uint64_t finalCoreNum = std::min(coreLimit, totalTaskNum);
if (finalCoreNum >= std::min(coreLimit, MIN_SPLIT_C_WEIGHT_REUSE_CORE_NUM)) {
tiling->tileLength = static_cast<int64_t>(splitCTileChannels);
tiling->innerSizeAligned = static_cast<int64_t>(alignedSplitCElements);
tiling->usedCoreNum = static_cast<int64_t>(finalCoreNum);
tiling->tilesPerRow = static_cast<int64_t>(cTileNum);
tiling->baseTasks = static_cast<int64_t>(totalTaskNum / finalCoreNum);
tiling->extraTasks = static_cast<int64_t>(totalTaskNum % finalCoreNum);
usedCoreNum = static_cast<uint32_t>(finalCoreNum);
useNcSplitCWeightReuse = true;
return ge::GRAPH_SUCCESS;
}
}
}
}
uint64_t minParallelTileLength = CORE_ALIGN_SIZE / typeLength;
uint64_t minParallelL = minParallelTileLength * MIN_PARALLEL_TILE_NUM;
if (rowNumU64 * 2U <= coreLimit && static_cast<uint64_t>(innerSize) >= minParallelL) {
uint64_t targetTilesPerRow = CeilDiv(coreLimit, rowNumU64);
uint64_t parallelTileLength = AlignUp(CeilDiv(static_cast<uint64_t>(innerSize), targetTilesPerRow),
minParallelTileLength);
parallelTileLength = std::max(parallelTileLength, minParallelTileLength);
parallelTileLength = std::min(parallelTileLength, ubFactor);
uint64_t tilesPerRow = CeilDiv(static_cast<uint64_t>(innerSize), parallelTileLength);
OP_CHECK_IF(tilesPerRow > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()),
OP_LOGE(context, "Prelu: tilesPerRow exceeds int64 range"), return ge::GRAPH_FAILED);
OP_CHECK_IF(rowNumU64 > std::numeric_limits<uint64_t>::max() / tilesPerRow,
OP_LOGE(context, "Prelu: totalTaskNum exceeds uint64 range"), return ge::GRAPH_FAILED);
uint64_t totalTaskNum = rowNumU64 * tilesPerRow;
OP_CHECK_IF(totalTaskNum > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()),
OP_LOGE(context, "Prelu: totalTaskNum exceeds int64 range"), return ge::GRAPH_FAILED);
uint64_t finalCoreNum = std::min(coreLimit, totalTaskNum);
uint64_t minBenefitCoreNum = std::min(coreLimit, rowNumU64 * 2U);
if (finalCoreNum >= minBenefitCoreNum) {
tiling->tileLength = static_cast<int64_t>(parallelTileLength);
tiling->tilesPerRow = static_cast<int64_t>(tilesPerRow);
tiling->usedCoreNum = static_cast<int64_t>(finalCoreNum);
tiling->baseTasks = static_cast<int64_t>(totalTaskNum / finalCoreNum);
tiling->extraTasks = static_cast<int64_t>(totalTaskNum % finalCoreNum);
usedCoreNum = static_cast<uint32_t>(finalCoreNum);
useSplitLParallel = true;
return ge::GRAPH_SUCCESS;
}
}
uint64_t finalCoreNum = rowNumU64 == 0 ? 1U : std::min(coreLimit, rowNumU64);
if (innerSizeAligned > ubFactor) {
uint64_t tilesPerRow = CeilDiv(static_cast<uint64_t>(innerSize), ubFactor);
OP_CHECK_IF(tilesPerRow > static_cast<uint64_t>(std::numeric_limits<int64_t>::max()),
OP_LOGE(context, "Prelu: tilesPerRow exceeds int64 range"), return ge::GRAPH_FAILED);
tiling->tilesPerRow = static_cast<int64_t>(tilesPerRow);
}
tiling->usedCoreNum = static_cast<int64_t>(finalCoreNum);
tiling->baseRows = static_cast<int64_t>(rowNumU64 / finalCoreNum);
tiling->extraRows = static_cast<int64_t>(rowNumU64 % finalCoreNum);
usedCoreNum = static_cast<uint32_t>(finalCoreNum);
return ge::GRAPH_SUCCESS;
}
static ge::graphStatus PreluTilingFunc(gert::TilingContext* context)
{
uint64_t ubSize;
int64_t coreNum;
OP_CHECK_IF(GetPlatformInfo(context, ubSize, coreNum) != ge::GRAPH_SUCCESS,
OP_LOGE(context, "GetPlatformInfo error"), return ge::GRAPH_FAILED);
OP_CHECK_IF(GetWorkspaceSize(context) != ge::GRAPH_SUCCESS, OP_LOGE(context, "GetWorkspaceSize error"),
return ge::GRAPH_FAILED);
int64_t totalNum = 0;
int64_t weightSize = 1;
int64_t weightMode = 0;
int64_t channelSize = 1;
int64_t innerSize = 1;
int64_t rowNum = 0;
ge::DataType dataType = ge::DT_FLOAT;
uint32_t typeLength = 0;
OP_CHECK_IF(GetShapeAndDtypeInfo(context, totalNum, weightSize, weightMode, channelSize, innerSize, rowNum,
dataType, typeLength) != ge::GRAPH_SUCCESS,
OP_LOGE(context, "GetShapeAndDtypeInfo error"), return ge::GRAPH_FAILED);
PreluTilingData* tiling = context->GetTilingData<PreluTilingData>();
OP_CHECK_NULL_WITH_CONTEXT(context, tiling);
uint32_t usedCoreNum = 1;
bool useSplitLParallel = false;
bool useNcWeightReuse = false;
bool useNcSplitCWeightReuse = false;
bool useNcResidentWeightReuse = false;
OP_CHECK_IF(CalcTiling(context, ubSize, coreNum, totalNum, dataType, typeLength, weightMode, channelSize, innerSize,
rowNum, tiling, usedCoreNum, useSplitLParallel, useNcWeightReuse, useNcSplitCWeightReuse,
useNcResidentWeightReuse) != ge::GRAPH_SUCCESS,
OP_LOGE(context, "CalcTiling error"), return ge::GRAPH_FAILED);
context->SetBlockDim(usedCoreNum);
uint64_t tilingKey = GET_TPL_TILING_KEY(PRELU_TPL_SCALAR_MODE);
if (weightMode == 1) {
if (useNcResidentWeightReuse) {
tilingKey = GET_TPL_TILING_KEY(PRELU_TPL_CHANNEL_NC_RESIDENT_WEIGHT_MODE);
} else if (useNcWeightReuse) {
tilingKey = GET_TPL_TILING_KEY(PRELU_TPL_CHANNEL_NC_WEIGHT_REUSE_MODE);
} else if (useNcSplitCWeightReuse) {
tilingKey = GET_TPL_TILING_KEY(PRELU_TPL_CHANNEL_NC_SPLIT_C_WEIGHT_REUSE_MODE);
} else if (useSplitLParallel) {
tilingKey = GET_TPL_TILING_KEY(PRELU_TPL_CHANNEL_SPLIT_L_PARALLEL_MODE);
} else if (tiling->innerSizeAligned <= tiling->tileLength) {
tilingKey = GET_TPL_TILING_KEY(PRELU_TPL_CHANNEL_FULL_L_MODE);
} else {
tilingKey = GET_TPL_TILING_KEY(PRELU_TPL_CHANNEL_SPLIT_L_MODE);
}
}
context->SetTilingKey(tilingKey);
return ge::GRAPH_SUCCESS;
}
static ge::graphStatus TilingParseForPrelu([[maybe_unused]] gert::TilingParseContext* context)
{
return ge::GRAPH_SUCCESS;
}
struct PreluCompileInfo {};
IMPL_OP_OPTILING(Prelu).Tiling(PreluTilingFunc).TilingParse<PreluCompileInfo>(TilingParseForPrelu);
}