* Copyright (c) 2025 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 upsample_bilinear2d_grad_tiling.cpp
* \brief
*/
#include <cmath>
#include "register/op_impl_registry.h"
#include "register/tilingdata_base.h"
#include "tiling/tiling_api.h"
#include "tiling/platform/platform_ascendc.h"
#include "log/log.h"
#include "upsample_bilinear2d_grad_tiling.h"
#include "op_host/tiling_util.h"
namespace optiling {
ge::graphStatus UpsampleBilinear2dGradTilingArch35(gert::TilingContext* context);
constexpr uint32_t BEST_PERFORMANCE_SIZE = 16;
constexpr uint32_t BYTE = 8;
constexpr uint32_t BYTE_REPEAT = 256;
constexpr uint32_t BYTE_BASIC_BLOCK = 1024;
constexpr uint64_t TILING_KEY_HALF = 1;
constexpr uint64_t TILING_KEY_FLOAT = 2;
constexpr uint64_t TILING_KEY_BF16 = 3;
constexpr uint64_t WORK_SPACE_SIZE = 32 * 1024 * 1024;
constexpr uint32_t BYTE_LEN_4 = 4;
constexpr uint32_t BYTE_LEN_2 = 2;
constexpr float MIN_SUPPORT_SCALE = 0.02;
constexpr uint64_t DATE_TYPE_FLOAT16 = 1;
constexpr uint64_t DATE_TYPE_FLOAT = 2;
constexpr uint64_t DATE_TYPE_HALF = 3;
constexpr int8_t SHAPE_SIZE = 4;
constexpr int8_t N_INDEX = 0;
constexpr int8_t C_INDEX = 1;
constexpr int8_t H_INDEX = 2;
constexpr int8_t W_INDEX = 3;
constexpr int32_t DOUBLE_VALUE = 2;
constexpr int32_t RESERVED_VALUE = 4;
constexpr int32_t EIGHT_VALUE = 8;
constexpr uint8_t SCHEDULE_MODE = 1;
class UpsampleBilinear2dGradTiling {
public:
explicit UpsampleBilinear2dGradTiling(gert::TilingContext* context) : tilingContext(context) {};
ge::graphStatus Init() const;
ge::graphStatus RunBigKernelTiling();
ge::graphStatus ParseInputAttrs();
private:
void setScale();
inline float compute_scale_value(const int64_t in_size, const int64_t out_size, const bool align_corner,
const float* scale);
void getWorkSpace(uint32_t needCoreNum);
void getOutputShape();
void getSlideSize();
uint8_t GetDataTypeSize() const;
uint64_t GetDataTypeVal() const;
uint64_t GetTilingKeyVal() const;
uint32_t GetNeedCoreNum(const uint32_t coreNumPlatForm);
uint32_t GetNeedCoreNumW(const uint32_t coreNumPlatform);
uint32_t GetNeedCoreNumH(const uint32_t coreNumPlatform);
void setSingleCoreK();
void FillTilingData();
void getTCubeTiling_w();
void getTCubeTiling_h();
template <typename T1, typename T2>
inline T1 CeilA2B(T1 a, T2 b) const;
template <typename T1>
inline int32_t Ceil(T1 x) const;
private:
int64_t slide_size = 16;
UpsampleBilinear2dGradTilingData tilingData;
gert::TilingContext* tilingContext = nullptr;
ge::DataType dataType = ge::DT_UNDEFINED;
uint16_t dataTypeSize = 0;
gert::Shape input_shape;
uint8_t dim = 0;
const bool* align_corners = nullptr;
const float* scale_h = nullptr;
const float* scale_w = nullptr;
float realScale_h = 0.0f;
float realScale_w = 0.0f;
const gert::ContinuousVector* output_size = nullptr;
const gert::ContinuousVector* input_size = nullptr;
int64_t slideStartList_w[MAX_CORE_CONT] = {0};
int64_t slideEndList_w[MAX_CORE_CONT] = {0};
int64_t tailRowStartList_w[MAX_CORE_CONT] = {0};
int64_t tailRowEndList_w[MAX_CORE_CONT] = {0};
int64_t tailSlideStartList_w[MAX_CORE_CONT] = {0};
int64_t tailSlideEndList_w[MAX_CORE_CONT] = {0};
int64_t slideStartList_h[MAX_CORE_CONT] = {0};
int64_t slideEndList_h[MAX_CORE_CONT] = {0};
int64_t tailSlideStartList_h[MAX_CORE_CONT] = {0};
int64_t tailSlideEndList_h[MAX_CORE_CONT] = {0};
int64_t tailRowStartList_h[MAX_CORE_CONT] = {0};
int64_t tailRowEndList_h[MAX_CORE_CONT] = {0};
int32_t tailBatchStartList_h[MAX_CORE_CONT] = {0};
int32_t tailBatchEndList_h[MAX_CORE_CONT] = {0};
int64_t output_shapes[4] = {0};
int64_t input_shapes[4] = {0};
TCubeTiling matmulTiling_w;
TCubeTiling matmulTiling_h;
int32_t singleCoreK_w = 0;
int32_t singleCoreK_h = 0;
};
inline bool FloatEqual(const float a, const float b)
{
const float closeTo0 = float(1e-6);
if (a > b) {
return a - b < closeTo0;
} else {
return b - a < closeTo0;
}
};
ge::graphStatus UpsampleBilinear2dGradTiling::Init() const { return ge::GRAPH_SUCCESS; }
void UpsampleBilinear2dGradTiling::setScale()
{
if (dim == H_INDEX) {
const int64_t* output_size_array = reinterpret_cast<const int64_t*>(output_size->GetData());
realScale_h = compute_scale_value(input_shape.GetDim(H_INDEX), output_size_array[H_INDEX], *align_corners,
scale_h);
realScale_w = compute_scale_value(input_shape.GetDim(W_INDEX), output_size_array[W_INDEX], *align_corners,
scale_w);
if (*align_corners) {
tilingData.set_align_corners(C_INDEX);
} else {
tilingData.set_align_corners(H_INDEX);
}
tilingData.set_scale_h(realScale_h);
tilingData.set_scale_w(realScale_w);
}
}
inline float UpsampleBilinear2dGradTiling::compute_scale_value(const int64_t in_size, const int64_t out_size,
const bool align_corner, const float* scale)
{
if (align_corner) {
if (in_size > 1) {
return static_cast<float>(out_size - 1) / static_cast<float>(in_size - 1);
} else {
return static_cast<float>(0);
}
} else {
if (scale != nullptr && *scale > 0) {
return static_cast<float>(*scale);
} else {
return in_size != 0 ? static_cast<float>(out_size) / static_cast<float>(in_size) : 1;
}
}
}
void UpsampleBilinear2dGradTiling::setSingleCoreK()
{
getSlideSize();
setScale();
getOutputShape();
if (!FloatEqual(realScale_w, static_cast<float>(0.0))) {
singleCoreK_w = Ceil((slide_size + RESERVED_VALUE) / realScale_w) + DOUBLE_VALUE * RESERVED_VALUE;
singleCoreK_w = (singleCoreK_w + EIGHT_VALUE - 1) / EIGHT_VALUE * EIGHT_VALUE;
if (singleCoreK_w < slide_size) {
singleCoreK_w = slide_size;
}
} else {
singleCoreK_w = input_shapes[W_INDEX];
if (singleCoreK_w < slide_size) {
singleCoreK_w = slide_size;
}
}
if (!FloatEqual(realScale_h, static_cast<float>(0.0))) {
singleCoreK_h = Ceil((slide_size + RESERVED_VALUE) / realScale_h) + DOUBLE_VALUE * RESERVED_VALUE;
singleCoreK_h = (singleCoreK_h + EIGHT_VALUE - 1) / EIGHT_VALUE * EIGHT_VALUE;
if (singleCoreK_h < slide_size) {
singleCoreK_h = slide_size;
}
} else {
singleCoreK_h = input_shapes[H_INDEX];
if (singleCoreK_h < slide_size) {
singleCoreK_h = slide_size;
}
}
}
ge::graphStatus UpsampleBilinear2dGradTiling::ParseInputAttrs()
{
auto srcTensor = tilingContext->GetInputTensor(0);
if (srcTensor == nullptr) {
return ge::GRAPH_FAILED;
}
const gert::RuntimeAttrs* attrs = tilingContext->GetAttrs();
if (attrs == nullptr) {
return ge::GRAPH_FAILED;
}
input_size = attrs->GetAttrPointer<gert::ContinuousVector>(0);
OP_CHECK_IF(input_size == nullptr, OP_LOGE(tilingContext->GetNodeName(), "input_size == nullptr"),
return ge::GRAPH_FAILED);
output_size = attrs->GetAttrPointer<gert::ContinuousVector>(1);
OP_CHECK_IF(output_size == nullptr, OP_LOGE(tilingContext->GetNodeName(), "output_size == nullptr"),
return ge::GRAPH_FAILED);
align_corners = attrs->GetAttrPointer<bool>(H_INDEX);
OP_CHECK_IF(align_corners == nullptr, OP_LOGE(tilingContext->GetNodeName(), "align_corners == nullptr"),
return ge::GRAPH_FAILED);
scale_h = attrs->GetAttrPointer<float>(W_INDEX);
OP_CHECK_IF(scale_h == nullptr, OP_LOGE(tilingContext->GetNodeName(), "scale_h == nullptr"),
return ge::GRAPH_FAILED);
scale_w = attrs->GetAttrPointer<float>(RESERVED_VALUE);
OP_CHECK_IF(scale_w == nullptr, OP_LOGE(tilingContext->GetNodeName(), "scale_w == nullptr"),
return ge::GRAPH_FAILED);
auto tmp = tilingContext->GetInputDesc(0);
if (tmp == nullptr) {
return ge::GRAPH_FAILED;
}
ge::DataType srcDtype = tmp->GetDataType();
if (dataType == ge::DT_UNDEFINED) {
dataType = srcDtype;
dataTypeSize = GetDataTypeSize();
} else if (srcDtype != dataType) {
return ge::GRAPH_FAILED;
}
return ge::GRAPH_SUCCESS;
}
ge::graphStatus UpsampleBilinear2dGradTiling::RunBigKernelTiling()
{
bool regBase = Ops::Cv::OpTiling::IsRegbaseSocVersion(tilingContext);
if (regBase) {
OP_LOGI(tilingContext->GetNodeName(), "enter UpsampleBilinear2dGradTilingArch35");
return UpsampleBilinear2dGradTilingArch35(tilingContext);
}
OP_CHECK_IF(ParseInputAttrs() != ge::GRAPH_SUCCESS, OP_LOGE(tilingContext->GetNodeName(), "ParseInputAttrs failed"),
return ge::GRAPH_FAILED);
auto srcShape = tilingContext->GetInputShape(0);
dim = srcShape->GetStorageShape().GetDimNum() - 2;
input_shape = srcShape->GetOriginShape();
auto compileInfo = reinterpret_cast<const UpsampleBilinear2dGradCompileInfo*>(tilingContext->GetCompileInfo());
const uint32_t coreNumPlatForm = compileInfo->coreNum;
tilingContext->SetTilingKey(GetTilingKeyVal());
setSingleCoreK();
uint32_t needCoreNum = GetNeedCoreNum(coreNumPlatForm);
getWorkSpace(needCoreNum);
tilingContext->SetBlockDim(needCoreNum);
FillTilingData();
return ge::GRAPH_SUCCESS;
}
uint32_t UpsampleBilinear2dGradTiling::GetNeedCoreNumH(const uint32_t coreNumPlatform)
{
int64_t outputSize = output_shapes[2];
int64_t output_w = output_shapes[3];
int64_t slideNum = CeilA2B(outputSize, slide_size);
int64_t eachCoreSlideNum = 0;
int64_t remainder = 0;
if (coreNumPlatform != 0) {
eachCoreSlideNum = slideNum / coreNumPlatform;
remainder = slideNum % coreNumPlatform;
}
int64_t inputBatch = input_shapes[0] * input_shapes[1];
int64_t tailAvergingBatch = 0;
int64_t input_w = output_shapes[3];
int64_t groupCoreNum = coreNumPlatform;
int64_t tailAvergingRows = BEST_PERFORMANCE_SIZE;
if (remainder != 0) {
int64_t minAvergingRows = BEST_PERFORMANCE_SIZE;
groupCoreNum = coreNumPlatform / remainder;
tailAvergingBatch = CeilA2B(inputBatch, groupCoreNum);
tailAvergingRows = std::max(CeilA2B(output_w, groupCoreNum), minAvergingRows);
groupCoreNum = std::min(groupCoreNum, CeilA2B(inputBatch, tailAvergingBatch));
}
uint32_t needCoreNum_h = 0;
int64_t tailStartSlideNum = eachCoreSlideNum * coreNumPlatform;
for (uint32_t coreIndex = 0; coreIndex < coreNumPlatform; coreIndex++) {
slideStartList_h[coreIndex] = coreIndex * eachCoreSlideNum * slide_size;
slideEndList_h[coreIndex] = (std::min((coreIndex + 1) * eachCoreSlideNum, slideNum)) * slide_size;
if (remainder != 0) {
int64_t groupIndex = groupCoreNum != 0 ? coreIndex / groupCoreNum : 1;
if (groupIndex < remainder) {
tailSlideStartList_h[coreIndex] = (tailStartSlideNum + groupIndex) * slide_size;
tailSlideEndList_h[coreIndex] = std::min(tailSlideStartList_h[coreIndex] + slide_size,
static_cast<int64_t>(outputSize));
int64_t coreIndexInGroup = groupCoreNum != 0 ? coreIndex % groupCoreNum : 1;
tailRowStartList_h[coreIndex] = coreIndexInGroup * tailAvergingRows;
tailRowEndList_h[coreIndex] = std::min(tailRowStartList_h[coreIndex] + tailAvergingRows,
static_cast<int64_t>(input_w));
tailBatchStartList_h[coreIndex] = coreIndexInGroup * tailAvergingBatch;
tailBatchEndList_h[coreIndex] = std::min(tailBatchStartList_h[coreIndex] + tailAvergingBatch,
static_cast<int64_t>(inputBatch));
needCoreNum_h++;
}
}
}
if (eachCoreSlideNum > 0) {
needCoreNum_h = coreNumPlatform;
}
tilingData.set_need_core_num_h(needCoreNum_h);
return needCoreNum_h;
}
void UpsampleBilinear2dGradTiling::getTCubeTiling_h()
{
auto mmDataType = static_cast<matmul_tiling::DataType>(dataType);
matmul_tiling::MatmulApiTiling mmTiling_h;
mmTiling_h.SetAType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, mmDataType, false);
mmTiling_h.SetBType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, mmDataType, false);
mmTiling_h.SetCType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, mmDataType);
mmTiling_h.SetOrgShape(output_shapes[H_INDEX], output_shapes[W_INDEX], input_shapes[W_INDEX]);
mmTiling_h.SetShape(slide_size, output_shapes[W_INDEX], singleCoreK_h);
if (mmTiling_h.GetTiling(tilingData.matmulTiling_h) == -1) {
return;
}
}
void UpsampleBilinear2dGradTiling::getTCubeTiling_w()
{
auto mmDataType = static_cast<matmul_tiling::DataType>(dataType);
matmul_tiling::MatmulApiTiling mmTiling_w;
mmTiling_w.SetAType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, mmDataType, false);
mmTiling_w.SetBType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, mmDataType, false);
mmTiling_w.SetCType(matmul_tiling::TPosition::GM, matmul_tiling::CubeFormat::ND, mmDataType);
mmTiling_w.SetOrgShape(input_shape.GetDim(N_INDEX) * input_shape.GetDim(C_INDEX) * input_shape.GetDim(H_INDEX),
output_shapes[W_INDEX], input_shape.GetDim(W_INDEX));
mmTiling_w.SetShape(input_shape.GetDim(0) * input_shape.GetDim(C_INDEX) * input_shape.GetDim(H_INDEX), slide_size,
singleCoreK_w);
if (mmTiling_w.GetTiling(tilingData.matmulTiling_w) == -1) {
return;
}
}
void UpsampleBilinear2dGradTiling::getWorkSpace(uint32_t needCoreNum)
{
size_t* workspaces = tilingContext->GetWorkspaceSizes(1);
uint64_t intermediate_matrix_size = output_shapes[0] * output_shapes[1] * input_shape.GetDim(2) * output_shapes[3];
uint32_t radioMatrixWorkspaceSize = slide_size * singleCoreK_w;
uint32_t radioMatrixWorkspaceSize_h = slide_size * singleCoreK_h;
uint32_t maxRadioMatrixWorkspaceSize = std::max(radioMatrixWorkspaceSize, radioMatrixWorkspaceSize_h);
workspaces[0] = (intermediate_matrix_size + maxRadioMatrixWorkspaceSize * needCoreNum) * BYTE + WORK_SPACE_SIZE;
tilingData.set_radio_matrix_size(radioMatrixWorkspaceSize);
tilingData.set_radio_matrix_size_h(radioMatrixWorkspaceSize_h);
tilingData.set_intermediate_matrix_size(intermediate_matrix_size);
}
void UpsampleBilinear2dGradTiling::getOutputShape()
{
const int64_t* output_size_arr = reinterpret_cast<const int64_t*>(output_size->GetData());
for (int8_t i = 0; i < SHAPE_SIZE; i++) {
input_shapes[i] = input_shape.GetDim(i);
output_shapes[i] = input_shape.GetDim(i);
if (i > 1) {
output_shapes[i] = output_size_arr[i];
}
}
tilingData.set_input_shapes(input_shapes);
tilingData.set_output_shapes(output_shapes);
}
void UpsampleBilinear2dGradTiling::getSlideSize()
{
slide_size = BEST_PERFORMANCE_SIZE;
tilingData.set_slide_size(slide_size);
}
template <typename T1, typename T2>
inline auto UpsampleBilinear2dGradTiling::CeilA2B(T1 a, T2 b) const -> T1
{
if (b != 0) {
return (a + b - 1) / b;
} else {
return a;
}
}
template <typename T1>
inline int32_t UpsampleBilinear2dGradTiling::Ceil(T1 x) const
{
return static_cast<int32_t>(std::ceil(x));
}
uint8_t UpsampleBilinear2dGradTiling::GetDataTypeSize() const
{
switch (dataType) {
case ge::DT_FLOAT:
return BYTE_LEN_4;
case ge::DT_FLOAT16:
return BYTE_LEN_2;
case ge::DT_BF16:
return BYTE_LEN_2;
default:
return BYTE_LEN_4;
}
}
uint64_t UpsampleBilinear2dGradTiling::GetDataTypeVal() const
{
switch (dataType) {
case ge::DT_FLOAT:
return DATE_TYPE_FLOAT;
case ge::DT_BF16:
return DATE_TYPE_HALF;
case ge::DT_FLOAT16:
return DATE_TYPE_FLOAT16;
default:
return 0;
}
}
uint64_t UpsampleBilinear2dGradTiling::GetTilingKeyVal() const
{
switch (dataType) {
case ge::DT_BF16:
return TILING_KEY_BF16;
case ge::DT_FLOAT:
return TILING_KEY_FLOAT;
case ge::DT_FLOAT16:
return TILING_KEY_HALF;
default:
return 0;
}
}
uint32_t UpsampleBilinear2dGradTiling::GetNeedCoreNum(const uint32_t coreNumPlatForm)
{
uint32_t needCoreNumW = 0;
uint32_t needCoreNumH = 0;
if (!FloatEqual(realScale_w, 1.0)) {
needCoreNumW = GetNeedCoreNumW(coreNumPlatForm);
getTCubeTiling_w();
tilingData.set_need_core_num_w(needCoreNumW);
}
if ((!FloatEqual(realScale_h, 1.0)) || (FloatEqual(realScale_w, 1.0))) {
needCoreNumH = GetNeedCoreNumH(coreNumPlatForm);
getTCubeTiling_h();
}
uint32_t needCoreNum = std::max(needCoreNumW, needCoreNumH);
needCoreNum = needCoreNum < 1 ? 1 : needCoreNum;
return needCoreNum;
}
uint32_t UpsampleBilinear2dGradTiling::GetNeedCoreNumW(const uint32_t coreNumPlatform)
{
int64_t outputSize = output_shapes[3];
int64_t slideNum = CeilA2B(outputSize, slide_size);
int64_t eachCoreSlideNum = coreNumPlatform != 0 ? slideNum / coreNumPlatform : 1;
int64_t remainder = coreNumPlatform != 0 ? slideNum % coreNumPlatform : 1;
int64_t input_h = input_shape.GetDim(0) * input_shape.GetDim(1) * input_shape.GetDim(2);
int64_t minAvergingRows = slide_size;
int64_t groupCoreNum = coreNumPlatform / remainder;
int64_t tailAvergingRows = std::max(CeilA2B(input_h, groupCoreNum), minAvergingRows);
groupCoreNum = std::min(groupCoreNum, CeilA2B(input_h, tailAvergingRows));
int64_t needCore = 0;
int64_t tailStartSlideNum = eachCoreSlideNum * coreNumPlatform;
for (uint32_t coreIndex = 0; coreIndex < coreNumPlatform; coreIndex++) {
slideStartList_w[coreIndex] = coreIndex * eachCoreSlideNum * slide_size;
slideEndList_w[coreIndex] = (std::min((coreIndex + 1) * eachCoreSlideNum, slideNum)) * slide_size;
int64_t groupIndex = groupCoreNum != 0 ? coreIndex / groupCoreNum : 1;
if (groupIndex < remainder) {
tailSlideStartList_w[coreIndex] = (tailStartSlideNum + groupIndex) * slide_size;
tailSlideEndList_w[coreIndex] = std::min(tailSlideStartList_w[coreIndex] + slide_size,
static_cast<int64_t>(outputSize));
int64_t coreIndexInGroup = groupCoreNum != 0 ? coreIndex % groupCoreNum : 1;
tailRowStartList_w[coreIndex] = coreIndexInGroup * tailAvergingRows;
tailRowEndList_w[coreIndex] = std::min(tailRowStartList_w[coreIndex] + tailAvergingRows,
static_cast<int64_t>(input_h));
needCore++;
}
}
if (eachCoreSlideNum > 0) {
needCore = coreNumPlatform;
}
return needCore;
}
void UpsampleBilinear2dGradTiling::FillTilingData()
{
tilingData.set_slideStartList_w(slideStartList_w);
tilingData.set_slideEndList_w(slideEndList_w);
tilingData.set_tailSlideStartList_w(tailSlideStartList_w);
tilingData.set_tailSlideEndList_w(tailSlideEndList_w);
tilingData.set_tailRowStartList_w(tailRowStartList_w);
tilingData.set_tailRowEndList_w(tailRowEndList_w);
tilingData.set_dataType(GetDataTypeVal());
tilingData.set_slideStartList_h(slideStartList_h);
tilingData.set_slideEndList_h(slideEndList_h);
tilingData.set_tailSlideStartList_h(tailSlideStartList_h);
tilingData.set_tailSlideEndList_h(tailSlideEndList_h);
tilingData.set_tailRowStartList_h(tailRowStartList_h);
tilingData.set_tailRowEndList_h(tailRowEndList_h);
tilingData.set_tailBatchStartList_h(tailBatchStartList_h);
tilingData.set_tailBatchEndList_h(tailBatchEndList_h);
tilingData.SaveToBuffer(tilingContext->GetRawTilingData()->GetData(),
tilingContext->GetRawTilingData()->GetCapacity());
tilingContext->GetRawTilingData()->SetDataSize(tilingData.GetDataSize());
}
static ge::graphStatus tiling4UpsampleBilinear2dGradTiling(gert::TilingContext* context)
{
UpsampleBilinear2dGradTiling tilingObject(context);
context->SetScheduleMode(SCHEDULE_MODE);
return tilingObject.RunBigKernelTiling();
}
static ge::graphStatus tilingPrepareTiling(gert::TilingParseContext* context)
{
auto compileInfo = context->GetCompiledInfo<UpsampleBilinear2dGradCompileInfo>();
OP_CHECK_NULL_WITH_CONTEXT(context, compileInfo);
auto platformInfo = context->GetPlatformInfo();
auto ascendcPlatform = platform_ascendc::PlatformAscendC(platformInfo);
compileInfo->coreNum = ascendcPlatform.GetCoreNumAic();
OP_CHECK_IF(compileInfo->coreNum <= 0,
OP_LOGE(context->GetNodeName(), "UpsampleBilinear2dGrad GetHardwareInfo Failed, vectorCoreNum:%u",
compileInfo->coreNum),
return ge::GRAPH_FAILED);
return ge::GRAPH_SUCCESS;
}
IMPL_OP_OPTILING(UpsampleBilinear2dGrad)
.Tiling(tiling4UpsampleBilinear2dGradTiling)
.TilingParse<UpsampleBilinear2dGradCompileInfo>(tilingPrepareTiling);
}