* 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.
*/
#include "bg_tiling.h"
#include <nlohmann/json.hpp>
#include "common/checker.h"
#include "kernel/common_kernel_impl/tiling.h"
#include "aicore/converter/autofuse_node_converter.h"
#include "exe_graph/runtime/tiling_context.h"
#include "base/registry/op_impl_space_registry_v2.h"
#include "graph/utils/op_desc_utils.h"
#include "graph/args_format_desc.h"
#include "graph/utils/graph_utils.h"
#include "register/op_tiling_registry.h"
#include "register/op_tiling/op_tiling_constants.h"
#include "graph_builder/bg_compatible_utils.h"
#include "common/omg_util/omg_util.h"
#include "common/ge_inner_attrs.h"
#include "bg_platform.h"
#include "runtime/subscriber/global_tracer.h"
#include "exe_graph/lowering/frame_selector.h"
#include "value_holder_generator.h"
#include "bg_model_desc.h"
#include "graph/utils/op_type_utils.h"
#include "exe_graph/lowering/data_dependent_interpreter.h"
#include "graph/ge_context.h"
#include "common/op_tiling/tiling_dfx.h"
#include "runtime/rt_model.h"
#include "runtime/dev.h"
#include "adump_pub.h"
#include "mmpa/mmpa_api.h"
#include "common/opskernel/ops_kernel_info_types.h"
namespace gert {
namespace bg {
namespace {
struct TilingAppendDfxInfoInputs {
const std::vector<ValueHolderPtr> &input_shapes;
const std::vector<ValueHolderPtr> &output_shapes;
ValueHolderPtr launch_arg;
ValueHolderPtr workspace_sizes;
LoweringGlobalData &global_data;
};
bool NeedTilingCompatible(const ge::NodePtr &node, const gert::OpImplSpaceRegistryV2Ptr &space_registry_ptr) {
if (space_registry_ptr == nullptr) {
return true;
}
GE_ASSERT_NOTNULL(node);
GE_ASSERT_NOTNULL(node->GetOpDesc());
auto op_funcs = space_registry_ptr->GetOpImpl(node->GetType().c_str());
if ((op_funcs == nullptr) || (op_funcs->tiling_parse == nullptr) || (op_funcs->tiling == nullptr)) {
auto &op_func_map = optiling::OpTilingFuncRegistry::RegisteredOpFuncInfo();
auto iter = op_func_map.find(node->GetType());
if (iter != op_func_map.end()) {
return true;
}
}
return false;
}
bg::ValueHolderPtr BuildCompileInfo(const ge::NodePtr &node, const std::string &json_key,
const ValueHolderPtr &platform_info,
LoweringGlobalData &global_data) {
GE_ASSERT_NOTNULL(node);
const std::string *op_compile_info_json = ge::AttrUtils::GetStr(node->GetOpDescBarePtr(), json_key);
if (op_compile_info_json == nullptr) {
GELOGE(ge::FAILED, "Op[%s] does not have attr[%s].", node->GetName().c_str(), json_key.c_str());
return nullptr;
}
const auto &json_holder =
bg::ValueHolder::CreateConst(op_compile_info_json->c_str(), op_compile_info_json->size() + 1, true);
const auto &node_type = bg::ValueHolder::CreateConst(node->GetTypePtr(), node->GetType().size() + 1, true);
GE_ASSERT_NOTNULL(node->GetOpDesc());
auto opp_impl_version = node->GetOpDesc()->GetOppImplVersion();
const auto space_registry_addr = global_data.GetSpaceRegistryV2(static_cast<gert::OppImplVersionTag>(opp_impl_version));
GE_ASSERT_NOTNULL(space_registry_addr);
const auto &space_registry = bg::ValueHolder::CreateConst(&space_registry_addr, sizeof(void *), false);
return bg::ValueHolder::CreateSingleDataOutput("TilingParse",
{json_holder, platform_info, node_type, space_registry});
}
ge::Status AssembleCompileInfoJson(const ge::OpDesc *const op_desc, std::string &op_compile_info_json) {
nlohmann::json compile_info_json;
try {
compile_info_json = nlohmann::json::parse(op_compile_info_json);
} catch (nlohmann::json::parse_error &ex) {
REPORT_INNER_ERR_MSG("E19999", "Failed to set compile_info_value to json of op[%s]. op_compile_info_json:%s",
op_desc->GetName().c_str(), op_compile_info_json.c_str());
GELOGE(ge::FAILED, "Failed to set compile_info_value to json of op[%s]. op_compile_info_json:%s",
op_desc->GetName().c_str(), op_compile_info_json.c_str());
return ge::FAILED;
}
std::vector<int64_t> atomic_workspace_indices;
(void)ge::AttrUtils::GetListInt(op_desc, "WorkspaceIndexes", atomic_workspace_indices);
compile_info_json["_workspace_index_list"] = atomic_workspace_indices;
op_compile_info_json = compile_info_json.dump();
return ge::SUCCESS;
}
bg::ValueHolderPtr BuildAtomCompileInfo(const ge::NodePtr &node, const std::string &json_key,
LoweringGlobalData &global_data) {
const auto op_desc = node->GetOpDescBarePtr();
GE_ASSERT_NOTNULL(op_desc);
const std::string *json_ptr = ge::AttrUtils::GetStr(op_desc, json_key);
if (json_ptr == nullptr) {
GELOGE(ge::FAILED, "Op[%s] does not have attr[%s].", op_desc->GetName().c_str(), json_key.c_str());
return nullptr;
}
std::string op_compile_info_json = *json_ptr;
if (AssembleCompileInfoJson(op_desc, op_compile_info_json) != ge::SUCCESS) {
GELOGE(ge::FAILED, "Failed to assemble compile info json for op[%s, %s].", op_desc->GetName().c_str(),
op_desc->GetType().c_str());
return nullptr;
}
const auto &json_holder =
bg::ValueHolder::CreateConst(op_compile_info_json.c_str(), op_compile_info_json.size() + 1, true);
std::string node_type;
if (node->GetType() == "MemSet") {
node_type= "MemSet";
} else {
node_type= "DynamicAtomicAddrClean";
}
auto opp_impl_version = op_desc->GetOppImplVersion();
const auto &node_type_holder = bg::ValueHolder::CreateConst(node_type.c_str(), node_type.size() + 1, true);
const auto space_registry_addr = global_data.GetSpaceRegistryV2(static_cast<gert::OppImplVersionTag>(opp_impl_version));
GE_ASSERT_NOTNULL(space_registry_addr);
const auto &space_registry = bg::ValueHolder::CreateConst(&space_registry_addr, sizeof(void *), false);
const auto assembled_platform_info_holders = bg::AppendCoreTypeToPlatform(node, &global_data);
GE_ASSERT_TRUE(assembled_platform_info_holders.size() == static_cast<size_t>(bg::AssemblePlatformInfoIndex::kNums));
const auto platform_info =
assembled_platform_info_holders[static_cast<size_t>(bg::AssemblePlatformInfoIndex::kPlatformInfo)];
return bg::ValueHolder::CreateSingleDataOutput("TilingParse",
{json_holder, platform_info, node_type_holder, space_registry});
}
bg::ValueHolderPtr ParseCompileInfo(const ge::NodePtr &node, const ValueHolderPtr &platform_info,
LoweringGlobalData &global_data) {
return BuildCompileInfo(node, optiling::COMPILE_INFO_JSON, platform_info, global_data);
}
bg::ValueHolderPtr ParseAtomicCompileInfo(const ge::NodePtr &node, LoweringGlobalData &global_data) {
return BuildAtomCompileInfo(node, optiling::ATOMIC_COMPILE_INFO_JSON, global_data);
}
ge::Status CheckArgsInfoType(const ArgsInfo::ArgsInfoType &args_info_type) {
return ((args_info_type < ArgsInfo::ArgsInfoType::TYPE_END) && (args_info_type >= ArgsInfo::ArgsInfoType::INPUT))
? ge::SUCCESS
: ge::PARAM_INVALID;
}
ge::Status CheckArgsInfoFormat(const ArgsInfo::ArgsInfoFormat &args_info_fmt) {
return ((args_info_fmt < ArgsInfo::ArgsInfoFormat::FORMAT_END) &&
(args_info_fmt >= ArgsInfo::ArgsInfoFormat::DIRECT_ADDR))
? ge::SUCCESS
: ge::PARAM_INVALID;
}
ValueHolderPtr GetOrCreateTilingFunc(const std::string &type_str, ge::OppImplVersion opp_impl_version,
LoweringGlobalData &global_data) {
auto builder = [&type_str, &opp_impl_version, &global_data]() -> std::vector<bg::ValueHolderPtr> {
return bg::FrameSelector::OnInitRoot(
[&type_str, &opp_impl_version, &global_data]() -> std::vector<bg::ValueHolderPtr> {
auto node_type = ValueHolder::CreateConst(type_str.c_str(), type_str.size() + 1, true);
auto space_registry = bg::HolderOnInit(bg::GetSpaceRegistry(global_data, opp_impl_version));
return {ValueHolder::CreateSingleDataOutput("FindTilingFunc", {node_type, space_registry})};
});
};
auto tiling_func = global_data.GetOrCreateUniqueValueHolder(
type_str + "_FindTilingFunc_" + std::to_string(static_cast<int64_t>(opp_impl_version)), builder)[0];
return tiling_func;
}
bool NeedSymbolTiling(const ge::NodePtr &node) {
return ge::OpTypeUtils::IsAutofuseNode(node->GetOpDesc());
}
ValueHolderPtr GetTilingFunc(const ge::NodePtr &node, const TilingLowerInput &lower_input) {
ValueHolderPtr tiling_func;
if (NeedSymbolTiling(node)) {
tiling_func = AutofuseNodeConveter::GetAutofuseHandle(
lower_input.global_data, node, GetAutofuseFuncsOutput::kTilingFunc);
} else {
std::string type;
GE_ASSERT_SUCCESS(ge::GetOriginalType(node, type), "Failed to get original type from %s(%s).",
node->GetName().c_str(), node->GetType().c_str());
ge::OppImplVersion opp_impl_version = node->GetOpDesc()->GetOppImplVersion();
tiling_func = GetOrCreateTilingFunc(type, opp_impl_version, lower_input.global_data);
}
return tiling_func;
}
ge::Status BuildTilingFwkDataInputs(const ge::NodePtr &node, const TilingLowerInput &lower_input,
std::vector<ValueHolderPtr> &tiling_input) {
const auto tiling_func = GetTilingFunc(node, lower_input);
GE_ASSERT_NOTNULL(tiling_func);
tiling_input.emplace_back(
bg::ValueHolder::CreateSingleDataOutput("PrepareTilingFwkData", {tiling_func, lower_input.launch_arg}));
return ge::SUCCESS;
}
ge::Status BuildCacheableTilingFwkDataInputs(
const ge::NodePtr &node, const TilingLowerInput &lower_input,
const size_t &data_dependency, const std::string &build_tiling_cache_key_func_name,
std::vector<bg::ValueHolderPtr> &tiling_input) {
const auto tiling_func = GetTilingFunc(node, lower_input);
GE_ASSERT_NOTNULL(tiling_func);
const auto data_dependency_holder = bg::ValueHolder::CreateConst(&data_dependency, sizeof(data_dependency));
const auto build_tiling_cache_key_func_name_holder = bg::ValueHolder::CreateConst(
build_tiling_cache_key_func_name.c_str(), build_tiling_cache_key_func_name.size() + 1, true);
tiling_input.emplace_back(bg::ValueHolder::CreateSingleDataOutput(
"PrepareCacheableTilingFwkData",
{tiling_func, lower_input.launch_arg, data_dependency_holder, build_tiling_cache_key_func_name_holder}));
return ge::SUCCESS;
}
ge::Status BuildTilingDeterministicInput(const ge::NodePtr &node, LoweringGlobalData &global_data,
std::vector<ValueHolderPtr> &tiling_input) {
auto builder = [&node]() -> std::vector<ValueHolderPtr> {
return bg::FrameSelector::OnInitRoot([&node]() -> std::vector<ValueHolderPtr> {
const auto compute_graph = node->GetOwnerComputeGraph();
GE_ASSERT_NOTNULL(compute_graph);
const auto root_compute_graph = ge::GraphUtils::FindRootGraph(compute_graph);
int32_t deterministic = 0;
(void)ge::AttrUtils::GetInt(root_compute_graph, ge::DETERMINISTIC, deterministic);
GELOGI("Get DETERMINISTIC: %d", deterministic);
auto deterministic_holder = bg::HolderOnInit(bg::ValueHolder::CreateConst(&deterministic, sizeof(int32_t)));
int32_t deterministic_level = 0;
(void)ge::AttrUtils::GetInt(root_compute_graph, "ge.deterministicLevel", deterministic_level);
GELOGI("Get DETERMINISTIC LEVEL: %d", deterministic_level);
auto deterministic_level_holder =
bg::HolderOnInit(bg::ValueHolder::CreateConst(&deterministic_level, sizeof(int32_t)));
return {deterministic_holder, deterministic_level_holder};
});
};
auto deterministic_vec = global_data.GetOrCreateUniqueValueHolder("Deterministic", builder);
GE_ASSERT_TRUE(deterministic_vec.size() == 2UL);
tiling_input.insert(tiling_input.end(), deterministic_vec.begin(), deterministic_vec.end());
return ge::SUCCESS;
}
bg::ValueHolderPtr BuildSymbolTilingCacheKey(
const std::vector<bg::ValueHolderPtr> &input_shapes, const ge::NodePtr &node,
const TilingLowerInput &lower_inputs) {
std::vector<bg::ValueHolderPtr> inputs_holders;
auto inputs_with_size = AutofuseNodeConveter::GetSymbolInputsWithSize(
lower_inputs.global_data, input_shapes, node->GetOwnerComputeGraph()->GetName());
inputs_holders.insert(inputs_holders.end(), inputs_with_size.begin(), inputs_with_size.end());
auto get_symbol_tiling_cache_key_func_handle = AutofuseNodeConveter::GetAutofuseHandle(
lower_inputs.global_data, node, GetAutofuseFuncsOutput::kGetTilingCacheKey);
GE_ASSERT_NOTNULL(get_symbol_tiling_cache_key_func_handle);
inputs_holders.emplace_back(get_symbol_tiling_cache_key_func_handle);
auto all_sym_num_handle = AutofuseNodeConveter::GetAllSymbolNumHolder(lower_inputs.global_data, node);
GE_ASSERT_NOTNULL(all_sym_num_handle);
inputs_holders.emplace_back(all_sym_num_handle);
return bg::ValueHolder::CreateSingleDataOutput("GetSymbolTilingCacheKey", inputs_holders);
}
bg::ValueHolderPtr BuildSymbolTilingParse(const ge::NodePtr &node, const TilingLowerInput &lower_inputs) {
auto tiling_parse_func_holder = AutofuseNodeConveter::GetAutofuseHandle(
lower_inputs.global_data, node, GetAutofuseFuncsOutput::kTilingParse);
GE_ASSERT_NOTNULL(tiling_parse_func_holder);
return bg::ValueHolder::CreateSingleDataOutput("SymbolTilingParse",
{lower_inputs.platform_info, tiling_parse_func_holder});
}
std::vector<bg::ValueHolderPtr> BuildCommonSymbolTilingInputs(
const ge::NodePtr &node, const TilingLowerInput &lower_inputs,
const std::vector<bg::ValueHolderPtr> &input_shapes) {
std::vector<bg::ValueHolderPtr> inputs_holders;
auto inputs_with_size = AutofuseNodeConveter::GetSymbolInputsWithSize(
lower_inputs.global_data, input_shapes, node->GetOwnerComputeGraph()->GetName());
inputs_holders.insert(inputs_holders.end(), inputs_with_size.begin(), inputs_with_size.end());
auto tiling_parse_holder = BuildSymbolTilingParse(node, lower_inputs);
GE_ASSERT_NOTNULL(tiling_parse_holder);
inputs_holders.emplace_back(tiling_parse_holder);
return inputs_holders;
}
}
ge::Status CheckArgsInfo(const std::vector<ArgsInfo> &args_infos, const ge::NodePtr &compute_node) {
const auto node_input_num = compute_node->GetInDataNodesAndAnchors().size();
const auto node_output_num = static_cast<size_t>(compute_node->GetAllOutDataAnchorsSize());
for (size_t idx = 0U; idx < args_infos.size(); ++idx) {
GE_ASSERT_SUCCESS(CheckArgsInfoType(args_infos[idx].arg_type));
GE_ASSERT_SUCCESS(CheckArgsInfoFormat(args_infos[idx].arg_format));
GE_ASSERT_TRUE(args_infos[idx].start_index >= -1,
"[PARAM][INVALID] Args info start index[%d], expect >= -1. Please check args info.",
args_infos[idx].start_index);
if (args_infos[idx].start_index == -1 || args_infos[idx].arg_size == 0U) {
GE_ASSERT_TRUE((args_infos[idx].start_index == -1 && args_infos[idx].arg_size == 0U),
"[PARAM][INVALID]Args info index[%zu], start index doesn't match arg size. "
"Start index[%d], expect -1, arg size[%u], expect 0.",
idx, args_infos[idx].start_index, args_infos[idx].arg_size);
continue;
}
if (args_infos[idx].start_index == 0xFFFF) {
continue;
}
if (args_infos[idx].arg_format == ArgsInfosDesc::ArgsInfo::ArgsInfoFormat::DIRECT_ADDR) {
GE_ASSERT_TRUE(args_infos[idx].arg_size == 1U,
"[PARAM][INVALID] Direct addr arg size[%u], expect 1. Please check args info.",
args_infos[idx].arg_size);
}
size_t io_idx_upper_bound = 0U;
GE_ASSERT_TRUE(!ge::AddOverflow(static_cast<size_t>(args_infos[idx].start_index),
static_cast<size_t>(args_infos[idx].arg_size) - 1U, io_idx_upper_bound));
if (args_infos[idx].arg_type == ArgsInfosDesc::ArgsInfo::ArgsInfoType::INPUT) {
GE_ASSERT_TRUE(io_idx_upper_bound < node_input_num,
"[PARAM][INVALID] Input index[%zu], expect in range[0, %zu). Please check args info.",
io_idx_upper_bound, node_input_num);
continue;
}
if (args_infos[idx].arg_type == ArgsInfosDesc::ArgsInfo::ArgsInfoType::OUTPUT) {
GE_ASSERT_TRUE(io_idx_upper_bound < node_output_num,
"[PARAM][INVALID] Output index[%zu], expect in range[0, %zu). Please check args info.",
io_idx_upper_bound, node_output_num);
continue;
}
}
return ge::SUCCESS;
}
void DebugForArgsInfo(const ge::NodePtr &compute_node, const std::vector<ArgsInfo> &args_infos,
size_t received_args_info_num) {
if (GlobalTracer::GetInstance()->GetEnableFlags() == 0U) {
return;
}
auto node_io_num = compute_node->GetInDataNodesAndAnchors().size() + compute_node->GetAllOutDataAnchorsSize();
std::stringstream ss;
ss << "\nPrint created args info:\n"
<< "Node name[" << compute_node->GetName() << "], node type[" << compute_node->GetType() << "], node io num["
<< node_io_num << "], received args info num[" << received_args_info_num << "]. Final args info num["
<< args_infos.size() << "].";
for (size_t idx = 0U; idx < args_infos.size(); ++idx) {
ss << "\nArgs infos[" << idx << "]: arg type[" << static_cast<int32_t>(args_infos[idx].arg_type) << "], arg format["
<< static_cast<size_t>(args_infos[idx].arg_format) << "], arg start index[" << args_infos[idx].start_index
<< "], arg size[" << args_infos[idx].arg_size << "].";
}
GELOGD("%s", ss.str().c_str());
}
ge::Status ParseIoNumFromArgsInfo(const vector<ArgsInfo> &args_infos, size_t &input_args_info_num,
size_t &output_args_info_num, size_t &input_valid_num, size_t &output_valid_num) {
for (auto &args_info : args_infos) {
switch (args_info.arg_type) {
case ArgsInfo::ArgsInfoType::INPUT: {
if (!args_info.be_folded) {
++input_valid_num;
}
++input_args_info_num;
break;
}
case ArgsInfo::ArgsInfoType::OUTPUT: {
if (!args_info.be_folded) {
++output_valid_num;
}
++output_args_info_num;
break;
}
default: {
GELOGE(ge::PARAM_INVALID, "IoType check failed.");
return ge::FAILED;
}
}
}
return ge::SUCCESS;
}
std::vector<ValueHolderPtr> BuildFindCompatibleTilingFunc(const ge::NodePtr &node) {
const auto &node_type = ValueHolder::CreateConst(node->GetTypePtr(), node->GetType().size() + 1, true);
auto find_tiling_func_out_num = static_cast<size_t>(kernel::FindCompatibleTilingFuncOutputIndex::kFindFuncOutputNum);
return ValueHolder::CreateDataOutput("FindCompatibleTilingFunc", {node_type}, find_tiling_func_out_num);
}
ValueHolderPtr BuildCompatibleTilingParse(const ge::NodePtr &node, const ValueHolderPtr &op,
const std::vector<ValueHolderPtr> &tiling_found_ret) {
const auto op_desc = node->GetOpDescBarePtr();
GE_ASSERT_NOTNULL(op_desc);
const std::string *op_compile_info_json = ge::AttrUtils::GetStr(op_desc, optiling::COMPILE_INFO_JSON);
if (op_compile_info_json == nullptr) {
GELOGW("Op[%s] does not have attr[%s].", node->GetName().c_str(), optiling::COMPILE_INFO_JSON.c_str());
return nullptr;
}
const auto &compile_info_json_holder =
bg::ValueHolder::CreateConst(op_compile_info_json->c_str(), op_compile_info_json->size() + 1, true);
const std::string *op_compile_info_key = ge::AttrUtils::GetStr(op_desc, optiling::COMPILE_INFO_KEY);
if (op_compile_info_key == nullptr) {
GELOGW("Op[%s] does not have attr[%s].", node->GetName().c_str(), optiling::COMPILE_INFO_KEY.c_str());
return nullptr;
}
const auto &compile_info_key_holder =
bg::ValueHolder::CreateConst(op_compile_info_key->c_str(), op_compile_info_key->size() + 1, true);
const size_t kTilingVersionIndex = static_cast<size_t>(kernel::FindCompatibleTilingFuncOutputIndex::kTilingVersion);
const size_t kTilingParseFuncIndex =
static_cast<size_t>(kernel::FindCompatibleTilingFuncOutputIndex::kTilingParseFunc);
return bg::ValueHolder::CreateSingleDataOutput(
"CompatibleTilingParse", {op, compile_info_json_holder, compile_info_key_holder,
tiling_found_ret[kTilingVersionIndex], tiling_found_ret[kTilingParseFuncIndex]});
}
* OpBuffer(const) NodeType(const)
* | |
* | FindCompatibleTilingFunc
* CreateOpFromBuffer compile_json | | |
* | | | | |
* | \ | | | |
* | CompatibleTilingParse<-----------|----| |
* | | | |
* CompatibleTiling<------------------------------|
*/
std::vector<ValueHolderPtr> BuildCompatibleTilingInputs(const ge::NodePtr &node,
const std::vector<ValueHolderPtr> &input_shapes,
const std::vector<ValueHolderPtr> &output_shapes,
const std::vector<ValueHolderPtr> &tiling_func_ret,
const ValueHolderPtr &fwk_data) {
auto op_buffer_vec = CompatibleUtils::BuildOpDescBufferConst(node);
constexpr size_t kOpBufferNum = 2U;
if (op_buffer_vec.size() != kOpBufferNum) {
return {};
}
const auto &op_holder = ValueHolder::CreateSingleDataOutput("CreateOpFromBuffer", op_buffer_vec);
const auto &compile_info = BuildCompatibleTilingParse(node, op_holder, tiling_func_ret);
if (compile_info == nullptr) {
return {};
}
* op buffer, compile info, tiling_version, TilingFwkData(tiling_func, ...), all_inputs, all outputs
* 此处为了兼容FFTS, 提供了Legacy实现, legacy实现的kTilingFwkData输入实际为tiling_func
*/
auto build_compatible_tiling_inputs = [&input_shapes, &output_shapes, &op_holder, &compile_info, &fwk_data,
&tiling_func_ret]() {
const auto kTilingVersionIndex = static_cast<size_t>(kernel::FindCompatibleTilingFuncOutputIndex::kTilingVersion);
std::vector<ValueHolderPtr> tiling_inputs;
tiling_inputs.emplace_back(op_holder);
tiling_inputs.emplace_back(compile_info);
tiling_inputs.emplace_back(tiling_func_ret[kTilingVersionIndex]);
tiling_inputs.emplace_back(fwk_data);
tiling_inputs.insert(tiling_inputs.cend(), input_shapes.cbegin(), input_shapes.cend());
tiling_inputs.insert(tiling_inputs.cend(), output_shapes.cbegin(), output_shapes.cend());
return tiling_inputs;
};
return build_compatible_tiling_inputs();
}
std::vector<ValueHolderPtr> BuildTilingCommonInputs(const ge::NodePtr &node,
const std::vector<ValueHolderPtr> &input_shapes,
const std::vector<ValueHolderPtr> &output_shapes,
const TilingLowerInput &lower_inputs) {
std::vector<ValueHolderPtr> tiling_input{input_shapes};
tiling_input.insert(tiling_input.cend(), output_shapes.cbegin(), output_shapes.cend());
const auto &compile_info = ParseCompileInfo(node, lower_inputs.platform_info, lower_inputs.global_data);
tiling_input.emplace_back(compile_info);
tiling_input.emplace_back(lower_inputs.platform_info);
return tiling_input;
}
ge::Status GetArgsFormatForTilingData(const ge::NodePtr &node, std::string &args_format_str,
const LoweringGlobalData::NodeCompileResult *compile_result) {
const auto op_desc = node->GetOpDescBarePtr();
if (ge::AttrUtils::HasAttr(op_desc, ge::ATTR_NAME_ALIAS_ENGINE_NAME)) {
const domi::TaskDef &task_def = compile_result->task_defs.at(0U);
const domi::FftsPlusTaskDef &ffts_plus_task_def = task_def.ffts_plus_task();
const int32_t mixl2_ctx_no = ffts_plus_task_def.ffts_plus_ctx_size() - 1;
GELOGD("[Tiling]MixL2 OP[%s] get task no.%d", op_desc->GetNamePtr(), mixl2_ctx_no);
if (mixl2_ctx_no >= 0) {
const domi::FftsPlusCtxDef &ctx_def = ffts_plus_task_def.ffts_plus_ctx(mixl2_ctx_no);
args_format_str = ctx_def.mix_aic_aiv_ctx().args_format();
}
} else if (op_desc->GetType() == ge::PARTITIONEDCALL) {
GELOGW("Node[%s] ffts task not support", node->GetNamePtr());
return ge::UNSUPPORTED;
} else {
const domi::TaskDef *task_def = GetTaskDef(node, compile_result, TaskDefType::kAICore);
GE_IF_BOOL_EXEC(task_def == nullptr, GELOGW("Node[%s] get task null", node->GetNamePtr());
return ge::UNSUPPORTED);
if (static_cast<ge::ModelTaskType>(task_def->type()) == ge::ModelTaskType::MODEL_TASK_ALL_KERNEL) {
args_format_str = task_def->kernel_with_handle().context().args_format();
} else {
args_format_str = task_def->kernel().context().args_format();
}
}
return ge::SUCCESS;
}
void CheckThirdClassOp(const ge::NodePtr &node, std::vector<int64_t> &out_args_sizes) {
const size_t kMaxDimNum = 8;
const size_t kShapeBufferNum = kMaxDimNum + 1U;
int32_t unknown_shape_type_val = 0;
const auto op_desc = node->GetOpDescBarePtr();
(void)ge::AttrUtils::GetInt(op_desc, ge::ATTR_NAME_UNKNOWN_SHAPE_TYPE, unknown_shape_type_val);
if (static_cast<ge::UnknowShapeOpType>(unknown_shape_type_val) != ge::DEPEND_SHAPE_RANGE) {
return;
}
const size_t shape_buffer_size = node->GetOpDesc()->GetOutputsSize() * (kShapeBufferNum * sizeof(uint64_t));
GELOGI("OP [%s] is third class op, shape buf size:%zu.", op_desc->GetNamePtr(), shape_buffer_size);
if (shape_buffer_size != 0) {
out_args_sizes.push_back(static_cast<int64_t>(shape_buffer_size));
}
}
ge::Status BuildTilingAppendDfxInfo(const ge::NodePtr &node,
std::vector<ValueHolderPtr> &input_vec,
const TilingAppendDfxInfoInputs &dfx_inputs) {
GELOGD("[Tiling] Start build TilingAppendDfxInfo kernel");
const auto op_desc = node->GetOpDescBarePtr();
bool is_mem_check_enable = false;
(void)ge::AttrUtils::GetBool(op_desc, optiling::kMemoryCheck, is_mem_check_enable);
bool is_args_exception_enable = Adx::AdumpGetDumpSwitch(Adx::DumpType::ARGS_EXCEPTION);
if (!is_mem_check_enable && !is_args_exception_enable) {
return ge::SUCCESS;
}
int64_t ori_op_param_size = 0L;
(void)ge::AttrUtils::GetInt(op_desc, "ori_op_para_size", ori_op_param_size);
input_vec.insert(input_vec.cend(), dfx_inputs.input_shapes.cbegin(), dfx_inputs.input_shapes.cend());
input_vec.insert(input_vec.cend(), dfx_inputs.output_shapes.cbegin(), dfx_inputs.output_shapes.cend());
auto output_shapes_sizes = CalcInputOutputTensorSize(false, false, node, dfx_inputs.output_shapes);
input_vec.insert(input_vec.cend(), output_shapes_sizes.cbegin(), output_shapes_sizes.cend());
input_vec.emplace_back(dfx_inputs.launch_arg);
input_vec.emplace_back(dfx_inputs.workspace_sizes);
size_t tiling_ori_param_size = static_cast<size_t>(ori_op_param_size);
input_vec.emplace_back(bg::ValueHolder::CreateConst(static_cast<void *>(&tiling_ori_param_size),
sizeof(size_t), false));
input_vec.emplace_back(bg::ValueHolder::CreateConst(static_cast<void *>(&is_mem_check_enable),
sizeof(bool), false));
input_vec.emplace_back(bg::ValueHolder::CreateConst(static_cast<void *>(&is_args_exception_enable),
sizeof(bool), false));
auto compile_result = dfx_inputs.global_data.FindCompiledResult(node);
GE_IF_BOOL_EXEC(compile_result == nullptr, GELOGW("Node[%s] get compile result null", node->GetNamePtr());
return ge::UNSUPPORTED);
std::string args_format_str;
GE_ASSERT_SUCCESS(GetArgsFormatForTilingData(node, args_format_str, compile_result));
std::vector<int64_t> args_size_list;
std::vector<optiling::ArgsIndexToIoIndex> args_idx_to_io_idx;
const auto &op_desc_ptr = node->GetOpDesc();
if (!args_format_str.empty()) {
GELOGI("OP [%s] has formatted args_format:[%s].", op_desc->GetNamePtr(), args_format_str.c_str());
std::vector<ge::ArgDesc> args_descs;
GE_ASSERT_SUCCESS(ge::ArgsFormatDesc::Parse(op_desc_ptr, args_format_str, args_descs));
GE_ASSERT_SUCCESS(
optiling::TilingDfx::GetArgsSizeWithArgsFormat(op_desc_ptr, args_descs, args_size_list, args_idx_to_io_idx));
} else {
GELOGI("OP [%s] not has formatted args_format. input_shapes size [%zu], out_shape size [%zu]",
op_desc->GetNamePtr(),dfx_inputs.input_shapes.size(), dfx_inputs.output_shapes.size());
GE_ASSERT_SUCCESS(
optiling::TilingDfx::GetArgsSizeWithoutArgsFormat(
dfx_inputs.input_shapes.size(), dfx_inputs.output_shapes.size(), args_size_list, args_idx_to_io_idx));
}
CheckThirdClassOp(node, args_size_list);
if (args_size_list.size() == 0U) {
GELOGI("OP [%s] args size list is empty", op_desc->GetNamePtr());
input_vec.clear();
return ge::SUCCESS;
}
input_vec.emplace_back(CreateContVecHolder(args_size_list));
input_vec.emplace_back(CreateContVecHolder(args_idx_to_io_idx));
return ge::SUCCESS;
}
* / | \ \ \ \
* <input-shapes> <output-shapes> TilingParse PlatformInfo PrepareTilingFrameworkData Deterministic
* / / \ / \
* space_registry json \ FindTilingFunc (向后可扩展框架内部FwkData输入)
* \ / \
* node_type space_registry
*/
std::vector<ValueHolderPtr> Tiling(const ge::NodePtr &node, const std::vector<ValueHolderPtr> &input_shapes,
const std::vector<ValueHolderPtr> &output_shapes,
const TilingLowerInput &lower_inputs) {
constexpr auto tiling_output_num = static_cast<size_t>(kernel::TilingExOutputIndex::kNum);
if ((node == nullptr) || (node->GetOpDescBarePtr() == nullptr)) {
return {static_cast<size_t>(kernel::TilingExOutputIndex::kNum), nullptr};
}
if (NeedSymbolTiling(node)) {
GELOGD("Node %s type %s only support symbol tiling. Try turns to tiling on symbol.", node->GetNamePtr(),
node->GetTypePtr());
auto inputs_holders = BuildCommonSymbolTilingInputs(node, lower_inputs, input_shapes);
GE_ASSERT_TRUE(!inputs_holders.empty());
auto get_tiling_cache_key_holder = BuildSymbolTilingCacheKey(input_shapes, node, lower_inputs);
GE_ASSERT_NOTNULL(get_tiling_cache_key_holder);
inputs_holders.emplace_back(get_tiling_cache_key_holder);
GE_ASSERT_SUCCESS(
BuildCacheableTilingFwkDataInputs(node, lower_inputs, 0U, "BuildSymbolTilingCacheKey", inputs_holders));
GE_ASSERT_SUCCESS(BuildTilingDeterministicInput(node, lower_inputs.global_data, inputs_holders));
return bg::ValueHolder::CreateDataOutput("CacheableTiling", inputs_holders, tiling_output_num);
}
GE_ASSERT_NOTNULL(node);
GE_ASSERT_NOTNULL(node->GetOpDesc());
if (NeedTilingCompatible(node, lower_inputs.global_data.GetSpaceRegistryV2(
static_cast<gert::OppImplVersionTag>(node->GetOpDesc()->GetOppImplVersion())))) {
GELOGD("Node %s type %s only support compatible tiling. Try turns to tiling on compatible version.",
node->GetNamePtr(), node->GetTypePtr());
const auto tiling_func_ret = BuildFindCompatibleTilingFunc(node);
const auto kTilingFuncIndex = static_cast<size_t>(kernel::FindCompatibleTilingFuncOutputIndex::kTilingFunc);
const auto fwk_data = ValueHolder::CreateSingleDataOutput(
"PrepareTilingFwkData", {tiling_func_ret[kTilingFuncIndex], lower_inputs.launch_arg});
const auto &inputs = BuildCompatibleTilingInputs(node, input_shapes, output_shapes, tiling_func_ret, fwk_data);
return bg::ValueHolder::CreateDataOutput("CompatibleTiling", inputs, tiling_output_num);
}
std::vector<ValueHolderPtr> tiling_input = BuildTilingCommonInputs(node, input_shapes, output_shapes, lower_inputs);
std::vector<ValueHolderPtr> tiling_ret;
size_t data_dependency = 0U;
if (TilingCacheUtils::IsOpSupportTilingCache(node, lower_inputs.global_data, data_dependency)) {
GE_ASSERT_SUCCESS(BuildCacheableTilingFwkDataInputs(
node, lower_inputs, data_dependency, "BuildGeneralTilingCacheKey", tiling_input));
GE_ASSERT_SUCCESS(BuildTilingDeterministicInput(node, lower_inputs.global_data, tiling_input));
tiling_ret = ValueHolder::CreateDataOutput("CacheableTiling", tiling_input, tiling_output_num);
} else {
GE_ASSERT_SUCCESS(BuildTilingFwkDataInputs(node, lower_inputs, tiling_input));
GE_ASSERT_SUCCESS(BuildTilingDeterministicInput(node, lower_inputs.global_data, tiling_input));
tiling_ret = ValueHolder::CreateDataOutput("Tiling", tiling_input, tiling_output_num);
}
const auto op_desc = node->GetOpDescBarePtr();
const auto known_workspace = op_desc->GetWorkspaceBytes();
if (!known_workspace.empty()) {
GELOGD("Node: %s has known workspace info.", op_desc->GetNamePtr());
tiling_ret[TilingContext::kOutputWorkspace] = ValueHolder::CreateSingleDataOutput(
"TilingAppendWorkspace", {tiling_ret[TilingContext::kOutputWorkspace], CreateContVecHolder(known_workspace)});
}
std::vector<ValueHolderPtr> input_vec;
const auto ret = BuildTilingAppendDfxInfo(
node, input_vec,
{input_shapes, output_shapes, tiling_ret[static_cast<size_t>(kernel::TilingExOutputIndex::kRtArg)],
tiling_ret[TilingContext::kOutputWorkspace], lower_inputs.global_data});
if ((ret == ge::SUCCESS) && (input_vec.size() > 0U)) {
tiling_ret[TilingContext::kOutputWorkspace] = ValueHolder::CreateSingleDataOutput("TilingAppendDfxInfo", input_vec);
}
return tiling_ret;
}
std::vector<ValueHolderPtr> FallibleTiling(const ge::NodePtr &node, const std::vector<ValueHolderPtr> &input_shapes,
const std::vector<ValueHolderPtr> &output_shapes,
const TilingLowerInput &lower_inputs) {
constexpr auto fallible_output_num = static_cast<size_t>(kernel::FallibleTilingExOutputIndex::kFallibleOutputNum);
if (node == nullptr || (node->GetOpDescBarePtr() == nullptr)) {
return {fallible_output_num, nullptr};
}
GE_ASSERT_NOTNULL(node->GetOpDesc());
ge::OppImplVersion opp_impl_version = node->GetOpDesc()->GetOppImplVersion();
if (NeedTilingCompatible(
node, lower_inputs.global_data.GetSpaceRegistryV2(static_cast<gert::OppImplVersionTag>(opp_impl_version)))) {
GELOGD("Node %s type %s only support compatible tiling. Try turns to tiling on compatible version.",
node->GetNamePtr(), node->GetTypePtr());
const auto tiling_func_ret = BuildFindCompatibleTilingFunc(node);
const auto kTilingFuncIndex = static_cast<size_t>(kernel::FindCompatibleTilingFuncOutputIndex::kTilingFunc);
const auto fwk_data = ValueHolder::CreateSingleDataOutput(
"PrepareTilingFwkData", {tiling_func_ret[kTilingFuncIndex], lower_inputs.launch_arg});
const auto inputs = BuildCompatibleTilingInputs(node, input_shapes, output_shapes, tiling_func_ret, fwk_data);
return bg::ValueHolder::CreateDataOutput("FallibleCompatibleTiling", inputs, fallible_output_num);
}
std::vector<ValueHolderPtr> tiling_input = BuildTilingCommonInputs(node, input_shapes, output_shapes, lower_inputs);
std::vector<ValueHolderPtr> tiling_ret;
size_t data_dependency = 0U;
if (TilingCacheUtils::IsOpSupportTilingCache(node, lower_inputs.global_data, data_dependency)) {
GE_ASSERT_SUCCESS(BuildCacheableTilingFwkDataInputs(
node, lower_inputs, data_dependency, "BuildGeneralTilingCacheKey", tiling_input));
GE_ASSERT_SUCCESS(BuildTilingDeterministicInput(node, lower_inputs.global_data, tiling_input));
tiling_ret = ValueHolder::CreateDataOutput("CacheableFallibleTiling", tiling_input, fallible_output_num);
} else {
GE_ASSERT_SUCCESS(BuildTilingFwkDataInputs(node, lower_inputs, tiling_input));
GE_ASSERT_SUCCESS(BuildTilingDeterministicInput(node, lower_inputs.global_data, tiling_input));
tiling_ret = ValueHolder::CreateDataOutput("FallibleTiling", tiling_input, fallible_output_num);
}
std::vector<ValueHolderPtr> input_vec;
const auto ret = BuildTilingAppendDfxInfo(
node, input_vec,
{input_shapes, output_shapes, tiling_ret[static_cast<size_t>(kernel::TilingExOutputIndex::kRtArg)],
tiling_ret[TilingContext::kOutputWorkspace], lower_inputs.global_data});
if ((ret == ge::SUCCESS) && (input_vec.size() > 0U)) {
tiling_ret[TilingContext::kOutputWorkspace] = ValueHolder::CreateSingleDataOutput("TilingAppendDfxInfo", input_vec);
}
return tiling_ret;
}
std::vector<ValueHolderPtr> TilingForAtomic(const ge::NodePtr &atomic_node, const ValueHolderPtr &workspaces_size,
const std::vector<ValueHolderPtr> &output_clean_sizes,
const ValueHolderPtr &launch_arg, LoweringGlobalData &global_data) {
const auto &compile_info = ParseAtomicCompileInfo(atomic_node, global_data);
std::vector<ValueHolderPtr> inputs;
inputs.emplace_back(workspaces_size);
for (const auto &output_clean_size : output_clean_sizes) {
inputs.emplace_back(output_clean_size);
}
inputs.emplace_back(compile_info);
GE_ASSERT_NOTNULL(atomic_node);
GE_ASSERT_NOTNULL(atomic_node->GetOpDesc());
ge::OppImplVersion opp_impl_version = atomic_node->GetOpDesc()->GetOppImplVersion();
ValueHolderPtr tiling_func = nullptr;
if (atomic_node->GetType() == "MemSet") {
tiling_func = GetOrCreateTilingFunc("MemSet", opp_impl_version, global_data);
} else {
tiling_func = GetOrCreateTilingFunc("DynamicAtomicAddrClean", opp_impl_version, global_data);
}
inputs.emplace_back(ValueHolder::CreateSingleDataOutput("PrepareTilingFwkData", {tiling_func, launch_arg}));
GE_ASSERT_SUCCESS(BuildTilingDeterministicInput(atomic_node, global_data, inputs));
return ValueHolder::CreateDataOutput("Tiling", inputs, static_cast<size_t>(kernel::TilingExOutputIndex::kNum));
}
std::vector<ValueHolderPtr> TilingLegacy(const ge::NodePtr &node, const std::vector<ValueHolderPtr> &input_shapes,
const std::vector<ValueHolderPtr> &output_shapes,
const ValueHolderPtr &platform_info, LoweringGlobalData &global_data) {
if ((node == nullptr) || (node->GetOpDescBarePtr() == nullptr)) {
return {TilingContext::kOutputNum, nullptr};
}
if (NeedTilingCompatible(node, global_data.GetSpaceRegistryV2(static_cast<gert::OppImplVersionTag>(node->GetOpDesc()->GetOppImplVersion())))) {
GELOGD("Node %s type %s only support compatible tiling. Try turns to tiling on compatible version.",
node->GetNamePtr(), node->GetTypePtr());
const auto tiling_func_ret = BuildFindCompatibleTilingFunc(node);
const auto kTilingFuncIndex = static_cast<size_t>(kernel::FindCompatibleTilingFuncOutputIndex::kTilingFunc);
const auto inputs = BuildCompatibleTilingInputs(node, input_shapes, output_shapes, tiling_func_ret,
tiling_func_ret[kTilingFuncIndex]);
return bg::ValueHolder::CreateDataOutput("CompatibleTilingLegacy", inputs, TilingContext::kOutputNum);
}
std::vector<ValueHolderPtr> tiling_input{input_shapes};
tiling_input.insert(tiling_input.cend(), output_shapes.cbegin(), output_shapes.cend());
const auto &compile_info = ParseCompileInfo(node, platform_info, global_data);
tiling_input.emplace_back(compile_info);
tiling_input.emplace_back(platform_info);
std::string type;
GE_ASSERT_SUCCESS(ge::GetOriginalType(node, type), "Failed to get original type from %s(%s).",
node->GetName().c_str(), node->GetType().c_str());
ge::OppImplVersion opp_impl_version = node->GetOpDesc()->GetOppImplVersion();
const auto tiling_func = GetOrCreateTilingFunc(type, opp_impl_version, global_data);
tiling_input.emplace_back(tiling_func);
auto tiling_ret = ValueHolder::CreateDataOutput("TilingLegacy", tiling_input, TilingContext::kOutputNum);
const auto op_desc = node->GetOpDescBarePtr();
const auto known_workspace = op_desc->GetWorkspaceBytes();
if (!known_workspace.empty()) {
GELOGD("Node: %s has known workspace info.", op_desc->GetNamePtr());
tiling_ret[TilingContext::kOutputWorkspace] = ValueHolder::CreateSingleDataOutput(
"TilingAppendWorkspace", {tiling_ret[TilingContext::kOutputWorkspace], CreateContVecHolder(known_workspace)});
}
return tiling_ret;
}
std::vector<ValueHolderPtr> TilingForAtomicLegacy(const ge::NodePtr &atomic_node, const ValueHolderPtr &workspaces_size,
const std::vector<ValueHolderPtr> &output_clean_sizes,
LoweringGlobalData &global_data) {
const auto &compile_info = ParseAtomicCompileInfo(atomic_node, global_data);
std::vector<ValueHolderPtr> inputs;
inputs.emplace_back(workspaces_size);
for (const auto &output_clean_size : output_clean_sizes) {
inputs.emplace_back(output_clean_size);
}
inputs.emplace_back(compile_info);
GE_ASSERT_NOTNULL(atomic_node);
GE_ASSERT_NOTNULL(atomic_node->GetOpDesc());
ge::OppImplVersion opp_impl_version = atomic_node->GetOpDesc()->GetOppImplVersion();
ValueHolderPtr tiling_func = nullptr;
if (atomic_node->GetType() == "MemSet") {
tiling_func = GetOrCreateTilingFunc("MemSet", opp_impl_version, global_data);
} else {
tiling_func = GetOrCreateTilingFunc("DynamicAtomicAddrClean", opp_impl_version, global_data);
}
inputs.emplace_back(tiling_func);
return ValueHolder::CreateDataOutput("TilingLegacy", inputs, TilingContext::kOutputNum);
}
}
}