* 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 "faker/ge_model_builder.h"
#include "faker/aicpu_taskdef_faker.h"
#include "faker/aicore_taskdef_faker.h"
#include "faker/dvpp_taskdef_faker.h"
#include "utils/tensor_utils.h"
#include "common/debug/log.h"
#include "graph/debug/ge_attr_define.h"
#include "common/host_resource_center/host_resource_center.h"
#include "common/env_path.h"
#include "common/ge_common/scope_guard.h"
namespace gert {
namespace {
std::vector<char> CreateStubBin() {
auto ascend_install_path = ge::EnvPath().GetAscendInstallPath();
std::string op_bin_path = ascend_install_path + "/fwkacllib/lib64/switch_by_index.o";
std::vector<char> buf;
std::ifstream file(op_bin_path.c_str(), std::ios::binary | std::ios::in);
if (!file.is_open()) {
std::cout << "file:" << op_bin_path << "does not exist or is unaccessible." << std::endl;
return buf;
}
GE_MAKE_GUARD(file_guard, [&file]() {
(void)file.close();
});
const std::streampos begin = file.tellg();
(void)file.seekg(0, std::ios::end);
const std::streampos end = file.tellg();
auto buf_len = static_cast<uint32_t>(end - begin);
buf.resize(buf_len + 1);
(void)file.seekg(0, std::ios::beg);
(void)file.read(const_cast<char *>(buf.data()), buf_len);
std::cout << std::string(buf.data()) << std::endl;
return buf;
}
}
GeModelBuilder::GeModelBuilder(ge::ComputeGraphPtr compute_graph) : compute_graph_(compute_graph),
use_default_task_(true) {
ge_model = std::make_shared<ge::GeModel>();
ge_model->SetName(compute_graph->GetName());
model_task_def = std::make_shared<domi::ModelTaskDef>();
ge_model->SetModelTaskDef(model_task_def);
weight_buffer_.reserve(1024);
}
GeModelBuilder &GeModelBuilder::ConstWeight(const std::string &node_name) {
auto const_node = compute_graph_->FindNode(node_name);
if (const_node->GetType() != ge::CONSTANT) {
return *this;
}
ge::ConstGeTensorPtr weight;
if (!ge::AttrUtils::GetTensor(const_node->GetOpDesc(), "value", weight)) {
GELOGE(ge::INTERNAL_ERROR, "weight is empty. node = %s", const_node->GetName().c_str());
return *this;
}
ge::GeTensorDesc &tensor_desc = const_cast<ge::GeTensorDesc &>(weight->GetTensorDesc());
ge::TensorUtils::SetSize(tensor_desc, weight->GetData().GetSize());
ge::TensorUtils::SetDataOffset(tensor_desc, weight_buffer_.size());
weight_buffer_.insert(weight_buffer_.end(), weight->GetData().GetData(),
weight->GetData().GetData() + weight->GetData().GetSize());
return *this;
}
void GeModelBuilder::SetTaskDef(TaskDefFaker &task_def, int64_t node_id) {
auto tasks = task_def.CreateTaskDef(node_id);
for (auto &task : tasks) {
task_indexes_to_node_id_[model_task_def->task_size()] = node_id;
auto task_ptr = model_task_def->add_task();
*task_ptr = task;
}
}
void GeModelBuilder::SetTaskDefs() {
for (const auto &faker : append_task_def_fakers_) {
SetTaskDef(*faker, -1);
}
for (const auto &node : compute_graph_->GetDirectNode()) {
auto iter = node_name_or_types_to_task_def_faker_.find(node->GetName());
if (iter != node_name_or_types_to_task_def_faker_.end()) {
SetTaskDef(*iter->second, node->GetOpDesc()->GetId());
continue;
}
iter = node_name_or_types_to_task_def_faker_.find(node->GetType());
if (iter != node_name_or_types_to_task_def_faker_.end()) {
SetTaskDef(*iter->second, node->GetOpDesc()->GetId());
continue;
}
if (all_task_def_faker_ != nullptr) {
SetTaskDef(*all_task_def_faker_, node->GetOpDesc()->GetId());
continue;
}
}
}
void GeModelBuilder::FakeTbeBinToNodes() {
const char *compile_info_json =
"{\"vars\": {\"srcFormat\": \"NCHW\", \"dstFormat\": \"NC1HWC0\", \"dType\": \"float16\", \"ub_size\": 126464, "
"\"block_dim\": 32, \"input_size\": 0, \"hidden_size\": 0, \"group\": 1}}";
for (const auto &node : compute_graph_->GetDirectNode()) {
auto iter = node_names_or_types_to_tbe_bin_fake_cfg_.find(node->GetName());
if (iter == node_names_or_types_to_tbe_bin_fake_cfg_.end()) {
iter = node_names_or_types_to_tbe_bin_fake_cfg_.find(node->GetType());
if (iter == node_names_or_types_to_tbe_bin_fake_cfg_.end()) {
std::cout << "Cannot find node: " << node->GetName() << ", type: " << node->GetType() << std::endl;
continue;
}
}
const auto &cfg = iter->second;
ge::AttrUtils::SetStr(node->GetOpDesc(), "compile_info_json", compile_info_json);
ge::AttrUtils::SetInt(node->GetOpDesc(), "op_para_size", 2048);
auto name = node->GetName() + "_faked_kernel";
auto bin = std::make_shared<ge::OpKernelBin>(name, CreateStubBin());
node->GetOpDesc()->SetExtAttr(ge::OP_EXTATTR_NAME_TBE_KERNEL, bin);
ge::AttrUtils::SetStr(node->GetOpDesc(), ge::TVM_ATTR_NAME_MAGIC, "RT_DEV_BINARY_MAGIC_ELF_AIVEC");
ge::AttrUtils::SetStr(node->GetOpDesc(), ge::TVM_ATTR_NAME_METADATA, "FakeMeta");
ge::AttrUtils::SetStr(node->GetOpDesc(), node->GetName() + "_kernelname", name);
ge::AttrUtils::SetStr(node->GetOpDesc(), "_kernelname", name);
if (cfg.need_atomic) {
ge::AttrUtils::SetStr(node->GetOpDesc(), "_atomic_compile_info_json", "{}");
ge::AttrUtils::SetInt(node->GetOpDesc(), "atomic_op_para_size", 2048);
name = node->GetName() + "_faked_atomic_kernel";
auto atomic_bin = std::make_shared<ge::OpKernelBin>(name, CreateStubBin());
node->GetOpDesc()->SetExtAttr(ge::EXT_ATTR_ATOMIC_TBE_KERNEL, atomic_bin);
ge::AttrUtils::SetStr(node->GetOpDesc(), ge::ATOMIC_ATTR_TVM_MAGIC, "RT_DEV_BINARY_MAGIC_ELF_AIVEC");
ge::AttrUtils::SetStr(node->GetOpDesc(), ge::ATOMIC_ATTR_TVM_METADATA, "FakeAtomicMeta");
ge::AttrUtils::SetStr(node->GetOpDesc(), node->GetName() + "_atomic_kernelname", name);
ge::AttrUtils::SetStr(node->GetOpDesc(), ge::ATOMIC_ATTR_TBE_KERNEL_NAME, name);
}
}
}
GeModelBuilder &GeModelBuilder::AddTaskDef(const std::string &node_type_or_name, const TaskDefFaker &task_def) {
use_default_task_ = false;
node_name_or_types_to_task_def_faker_[node_type_or_name] = task_def.Clone();
return *this;
}
GeModelBuilder &GeModelBuilder::AddTaskDefForAll(const TaskDefFaker &task_def) {
use_default_task_ = false;
all_task_def_faker_ = task_def.Clone();
return *this;
}
GeModelBuilder &GeModelBuilder::AddWeight() {
weight_buffer_ = std::vector<uint8_t>(1024, 100);
return *this;
}
void GeModelBuilder::AddTbeKernelStore() {
bool without_kernel_store = false;
ge::AttrUtils::GetBool(compute_graph_, "without_kernel_store", without_kernel_store);
ge::TBEKernelStore tbe_kernel_store;
if (!without_kernel_store) {
std::vector<char> kernel_bin(64, '\0');
ge::TBEKernelPtr kernel_handle = ge::MakeShared<ge::OpKernelBin>("dumy_kernel_name", std::move(kernel_bin));
tbe_kernel_store.AddTBEKernel(kernel_handle);
}
for (const auto &node : compute_graph_->GetDirectNode()) {
auto bin = node->GetOpDesc()->TryGetExtAttr(ge::OP_EXTATTR_NAME_TBE_KERNEL, ge::TBEKernelPtr());
if (bin != nullptr) {
tbe_kernel_store.AddTBEKernel(bin);
}
bin = node->GetOpDesc()->TryGetExtAttr(ge::EXT_ATTR_ATOMIC_TBE_KERNEL, ge::TBEKernelPtr());
if (bin != nullptr) {
tbe_kernel_store.AddTBEKernel(bin);
}
}
tbe_kernel_store.Build();
ge_model->SetTBEKernelStore(tbe_kernel_store);
}
ge::TBEKernelStore GeModelBuilder::BuildKernelStoreFromNodes() const {
ge::TBEKernelStore tbe_kernel_store;
for (const auto &node : compute_graph_->GetDirectNode()) {
auto bin = node->GetOpDesc()->TryGetExtAttr(ge::OP_EXTATTR_NAME_TBE_KERNEL, ge::TBEKernelPtr());
if (bin != nullptr) {
tbe_kernel_store.AddTBEKernel(bin);
}
bin = node->GetOpDesc()->TryGetExtAttr(ge::EXT_ATTR_ATOMIC_TBE_KERNEL, ge::TBEKernelPtr());
if (bin != nullptr) {
tbe_kernel_store.AddTBEKernel(bin);
}
}
tbe_kernel_store.Build();
return tbe_kernel_store;
}
ge::CustAICPUKernelStore GeModelBuilder::BuildCustAicpuKernelStoreFromNodes() const {
ge::CustAICPUKernelStore cust_aicpu_kernel_store;
for (const auto &node : compute_graph_->GetDirectNode()) {
auto bin = node->GetOpDesc()->TryGetExtAttr(ge::OP_EXTATTR_CUSTAICPU_KERNEL, ge::OpKernelBinPtr());
if (bin != nullptr) {
cust_aicpu_kernel_store.AddCustAICPUKernel(bin);
}
}
cust_aicpu_kernel_store.Build();
return cust_aicpu_kernel_store;
}
void GeModelBuilder::AddTbeKernelStoreFromNodes() {
FakeTbeBinToNodes();
ge_model->SetTBEKernelStore(BuildKernelStoreFromNodes());
ge_model->SetCustAICPUKernelStore(BuildCustAicpuKernelStoreFromNodes());
}
void GeModelBuilder::BuildCommon() {
SetTaskDefs();
ge_model->SetGraph(compute_graph_);
}
void GeModelBuilder::AddCustAicpuKernelStore(const std::string &name) {
ge::CustAICPUKernelStore cust_aicpu_kernel_store;
std::vector<char> kernel_bin(64, '\0');
ge::OpKernelBinPtr cust_aicpu_kernel = std::make_shared<ge::OpKernelBin>(name, std::move(kernel_bin));
cust_aicpu_kernel_store.AddCustAICPUKernel(cust_aicpu_kernel);
ge_model->SetCustAICPUKernelStore(cust_aicpu_kernel_store);
}
void GeModelBuilder::SetAttrs() {
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_MEMORY_SIZE, 10240);
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_STREAM_NUM, 1);
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_EVENT_NUM, 1);
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_LABEL_NUM, 0);
ge::AttrUtils::SetInt(ge_model, ge::MODEL_ATTR_TASK_GEN_BASE_ADDR, 0x100000000);
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_TASK_GEN_VAR_ADDR, 137438953472);
ge::AttrUtils::SetInt(ge_model, ge::MODEL_ATTR_TASK_GEN_WEIGHT_ADDR, 0x1000000000);
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_VAR_SIZE, 5120);
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_ZERO_COPY_MEMORY_SIZE, 5120);
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_SESSION_SCOPE_MEMORY_SIZE, 512);
if (set_sub_mem_infos_) {
std::vector<std::vector<int64_t>> sub_memory_infos;
sub_memory_infos.push_back({RT_MEMORY_HBM, 0, 2560});
sub_memory_infos.push_back({RT_MEMORY_HBM, 2560, 2560});
sub_memory_infos.push_back({RT_MEMORY_HBM, 5120, 5120});
(void)ge::AttrUtils::SetListListInt(ge_model, ge::ATTR_MODEL_SUB_MEMORY_INFO, sub_memory_infos);
}
}
ge::GeModelPtr GeModelBuilder::Build() {
AddTbeKernelStore();
ge_model->SetCustAICPUKernelStore(BuildCustAicpuKernelStoreFromNodes());
BuildCommon();
SetAttrs();
AddDefaultTasks();
AddDefaultWeights();
return ge_model;
}
GeModelBuilder::ModelResult GeModelBuilder::BuildDetail() {
auto model = Build();
return {model, task_indexes_to_node_id_};
}
ge::GeRootModelPtr GeModelBuilder::BuildGeRootModel() {
compute_graph_->SetGraphUnknownFlag(true);
AddTbeKernelStoreFromNodes();
BuildCommon();
AddDefaultTasks();
AddDefaultWeights();
GELOGD("Model has not been loaded!");
std::shared_ptr<ge::GeRootModel> out_model = ge::MakeShared<ge::GeRootModel>();
if (out_model == nullptr) {
return nullptr;
}
ge::AttrUtils::SetStr(ge_model, ge::ATTR_MODEL_OPP_VERSION, "3.20.T100.0.B356");
ge::AttrUtils::SetStr(ge_model, ge::ATTR_MODEL_HOST_ENV_OS, "linux");
ge::AttrUtils::SetStr(ge_model, ge::ATTR_MODEL_HOST_ENV_CPU, "x86_64");
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_STREAM_NUM, root_model_stream_num_);
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_EVENT_NUM, root_model_event_num_);
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_VAR_SIZE, 512 *1024 * 1024);
ge::AttrUtils::SetInt(ge_model, ge::ATTR_MODEL_TASK_GEN_VAR_ADDR, 137438953472);
const auto root_graph = ge_model->GetGraph();
if (root_graph != nullptr) {
out_model->Initialize(root_graph);
out_model->SetSubgraphInstanceNameToModel(root_graph->GetName(), ge_model);
}
for (auto subgraph : root_graph->GetAllSubgraphs()) {
const auto &parent_graph = subgraph->GetParentGraph();
if ((parent_graph != nullptr) && (parent_graph != root_graph) && (!parent_graph->GetGraphUnknownFlag())) {
continue;
}
const auto &fuctional_node = subgraph->GetParentNode();
if ((fuctional_node != nullptr) && (fuctional_node->GetOpDesc()->HasAttr(ge::ATTR_NAME_FFTS_PLUS_SUB_GRAPH))) {
continue;
}
GeModelBuilder builder(subgraph);
if (all_task_def_faker_ != nullptr) {
builder.AddTaskDefForAll(*(all_task_def_faker_.get()));
}
out_model->SetSubgraphInstanceNameToModel(subgraph->GetName(), builder.Build());
}
return out_model;
}
GeModelBuilder &GeModelBuilder::FakeTbeBin(const std::vector<TbeConfig> &configs) {
for (const auto &cfg : configs) {
node_names_or_types_to_tbe_bin_fake_cfg_[cfg.node_name_or_type] = cfg;
}
return *this;
}
GeModelBuilder &GeModelBuilder::AddDefaultTasks() {
if (!use_default_task_) {
return *this;
}
for (auto node : compute_graph_->GetDirectNode()) {
std::shared_ptr<TaskDefFaker> faker;
std::string kernel_lib = node->GetOpDesc()->GetOpKernelLibName();
if (kernel_lib == ge::kEngineNameDvpp) {
faker = std::make_shared<DvppTaskDefFaker>();
} else if (kernel_lib == ge::kEngineNameAiCore) {
faker = std::make_shared<AiCoreTaskDefFaker>();
FakeTbeBin({node->GetType().c_str()});
} else if (kernel_lib == ge::kEngineNameAiCpu) {
faker = std::make_shared<AiCpuCCTaskDefFaker>();
} else if (kernel_lib == ge::kEngineNameAiCpuTf) {
faker = std::make_shared<AiCpuTfTaskDefFaker>();
} else {
GELOGI("node[%s] appoint invalid engine type[%s], skip fake task.",
node->GetName().c_str(), kernel_lib.c_str());
continue;
}
SetTaskDef(*faker, node->GetOpDesc()->GetId());
}
return *this;
}
GeModelBuilder &GeModelBuilder::AddDefaultWeights() {
for (auto const_node : compute_graph_->GetDirectNode()) {
if (const_node->GetType() != "Const") {
continue;
}
ge::GeTensorPtr weight;
if (!ge::AttrUtils::MutableTensor(const_node->GetOpDesc(), "value", weight)) {
GELOGE(ge::INTERNAL_ERROR, "weight is empty. node = %s", const_node->GetName().c_str());
continue;
}
auto op_desc = const_node->GetOpDesc();
if (op_desc == nullptr) {
GELOGE(ge::INTERNAL_ERROR, "op_desc is empty. node = %s", const_node->GetName().c_str());
continue;
}
ge::GeTensorDesc &tensor_desc = weight->MutableTensorDesc();
auto tensor_data = weight->GetData();
ge::TensorUtils::SetSize(tensor_desc, tensor_data.GetSize());
ge::TensorUtils::SetWeightSize(tensor_desc, tensor_data.GetSize());
ge::TensorUtils::SetDataOffset(tensor_desc, weight_buffer_.size());
ge::TensorUtils::SetSize(*op_desc->MutableOutputDesc(0U), tensor_data.GetSize());
weight_buffer_.insert(weight_buffer_.end(), tensor_data.GetData(),
tensor_data.GetData() + tensor_data.GetSize());
}
ge_model->SetWeight(ge::Buffer::CopyFrom((uint8_t *)weight_buffer_.data(), weight_buffer_.size()));
GELOGI("model[%s], set weight size[%zu]", ge_model->GetName().c_str(), weight_buffer_.size());
return *this;
}
GeModelBuilder &GeModelBuilder::AppendTaskDef(const TaskDefFaker &task_def) {
append_task_def_fakers_.emplace_back(task_def.Clone());
return *this;
}
}