* 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 <base/err_msg.h>
#include "framework/common/helper/model_helper.h"
#include "common/checker.h"
#include "common/helper/model_parser_base.h"
#include "common/helper/custom_op_so_loader.h"
#include "common/model/ge_model.h"
#include "common/model/ge_root_model.h"
#include "common/op_so_store/op_so_store_utils.h"
#include "graph_metadef/common/plugin/plugin_manager.h"
#include "framework/omg/version.h"
#include "graph/debug/ge_attr_define.h"
#include "graph/unfold/graph_unfolder.h"
#include "graph/utils/graph_utils.h"
#include "graph/utils/graph_utils_ex.h"
#include "framework/omg/omg_inner_types.h"
#include "mmpa/mmpa_api.h"
#include "graph/types.h"
#include "common/proto_util/proto_util.h"
#include "graph/ge_local_context.h"
#include "graph_metadef/graph/utils/file_utils.h"
#include "graph/utils/op_type_utils.h"
#include "graph/build/memory/var_mem_assign_util.h"
#include "graph/manager/graph_var_manager.h"
#include "graph/custom_op_factory.h"
#include "common/math/math_util.h"
#include "common/file_constant_utils/file_constant_utils.h"
#include "common/helper/file_saver.h"
#include "common/model/model_introduction.h"
#include "common/model/model_compress_manager.h"
#include "common/host_resource_center/host_resource_serializer.h"
#include "graph/utils/math_util.h"
#include "ge_context.h"
#include "common/opskernel/ops_kernel_info_types.h"
#include "register/core_num_utils.h"
#include "acl/acl_rt.h"
#include "framework/common/framework_types_internal.h"
#include "graph/compute_graph.h"
#include "graph/node.h"
#include <set>
namespace {
constexpr uint32_t kOriginalOmPartitionNum = 1U;
constexpr int32_t kModuleTypeAicore = 4;
constexpr int32_t kModuleTypeVectorCore = 7;
constexpr int32_t kInfoTypeCoreNum = 3;
const string kOpsProto = "libopsproto_rt2.0.so";
const string kOpMaster = "libopmaster_rt2.0.so";
const string kInner = "built-in";
const string kOpsProtoPath = "/op_proto/lib/";
const string kOpsGraphPath = "/op_graph/lib/";
const string kOpMasterPath = "/op_impl/ai_core/tbe/op_tiling/lib/";
const string kOpHostPath = "/op_impl/ai_core/tbe/op_host/lib/";
const std::string kHcomGroups = "hcom_group_names";
const std::string kSocInfoKey = "SoCInfo";
const std::string kAicCntKey = "ai_core_cnt";
const std::string kVecCoreCntKey = "vector_core_cnt";
const std::string kEnumNameCubeNum = "cube_num";
const std::string kEnumNameVectorNum = "vector_num";
const std::string kSoSuffix = ".so";
const std::string kRt2SoSuffix = "rt2.0.so";
const std::string kRtSoSuffix = "rt.so";
const std::string kLegacySoSuffix = "_legacy.so";
const std::string kCompilerVersion = "compiler_version=";
const std::string kOppVersion = "Version=";
const std::string kVersionInfo = "/version.info";
const std::string kHardwareInfo = "ge.hardwareInfo";
}
namespace ge {
namespace {
std::unordered_set<ModelPartitionType> kSupportBeyond4GTypes = {WEIGHTS_DATA, TBE_KERNELS, CUST_AICPU_KERNELS};
const std::string kMultiBatchNodePostfix = "_ascend_mbatch_batch_";
void UpdateFftsPlusTaskAddr(domi::TaskDef &task_def, const std::map<int64_t, int64_t> &logical_addr_mapping) {
auto *const mutable_ffts_plus_task = task_def.mutable_ffts_plus_task();
for (int32_t i = 0; i < mutable_ffts_plus_task->ffts_plus_ctx_size(); ++i) {
auto *const mutable_ctx_def = mutable_ffts_plus_task->mutable_ffts_plus_ctx(i);
auto *const mutable_mix_aic_aiv_ctx = mutable_ctx_def->mutable_mix_aic_aiv_ctx();
for (int32_t k = 0; k < mutable_mix_aic_aiv_ctx->task_addr_size(); ++k) {
const auto orig_task_addr = mutable_mix_aic_aiv_ctx->task_addr(k);
const auto &it = logical_addr_mapping.find(static_cast<int64_t>(orig_task_addr));
if (it != logical_addr_mapping.cend()) {
mutable_mix_aic_aiv_ctx->set_task_addr(k, static_cast<uint64_t>(it->second));
GELOGD("update task_addr[%d], [%ld] to [%ld]", k, orig_task_addr, it->second);
} else {
GELOGW("update task_addr[%d] [%ld] NOT match", k, orig_task_addr);
}
}
}
}
NodePtr TryGetVarNodeByOffset(const std::map<int64_t, NodePtr> &var_offsets, const int64_t offset) {
const auto find_ret = var_offsets.find(offset);
return (find_ret == var_offsets.cend() ? nullptr : find_ret->second);
}
std::string GetOppPkgPath(const std::string &opp_path, const string &whole_pkg_path,
const string &sub_pkg_path, const string &os_cpu_type, bool &is_sub_pkg) {
is_sub_pkg = false;
const auto idx = opp_path.find(kInner);
if (idx != std::string::npos) {
return PluginManager::GetOppPkgPath(opp_path.substr(0, idx) + kInner, whole_pkg_path, sub_pkg_path, os_cpu_type,
is_sub_pkg);
}
return opp_path;
}
}
std::string ModelHelper::output_file_name_;
Status ModelHelper::SaveModelPartition(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper,
const ModelPartitionType type, const uint8_t* const data,
const size_t size, const size_t model_index) const {
if ((size < 1U) || ((size > UINT32_MAX) && (kSupportBeyond4GTypes.count(type) == 0UL))) {
GELOGE(PARAM_INVALID, "[Add][ModelPartition]Failed, partition size %zu invalid", size);
if (size > UINT32_MAX) {
std::string item = "item";
static std::map<ModelPartitionType, string> item_type_map = {
{MODEL_DEF, "model info"},
{TASK_INFO, "task info"},
{SO_BINS, "so bins"},
{TILING_DATA, "tiling data"},
{MODEL_INOUT_INFO, "model introductions"},
{STATIC_TASK_DESC, "static task desc"},
{DYNAMIC_TASK_DESC, "dynamic task desc"},
{TASK_PARAM, "task param"},
{PRE_MODEL_DESC, "pre model desc"},
{PRE_MODEL_SQE, "pre model task"},
{PRE_KERNEL_ARGS, "pre kernel args"},
{PRE_MODEL_DESC_EXTEND, "pre model desc extend"},
};
if (item_type_map.find(type) != item_type_map.end()) {
item = item_type_map[type];
}
(void)REPORT_PREDEFINED_ERR_MSG(
"E13023", std::vector<const char *>({"size", "item", "maxsize"}),
std::vector<const char *>({std::to_string(size).c_str(), item.c_str(), std::to_string(UINT32_MAX).c_str()}));
}
REPORT_INNER_ERR_MSG("E19999", "Add model partition failed, partition size %zu "
"invalid", size);
return PARAM_INVALID;
}
if (data == nullptr) {
GELOGE(PARAM_INVALID, "[Add][ModelPartition]Failed, data is null");
REPORT_INNER_ERR_MSG("E19999", "Add model partition failed, data is null");
return PARAM_INVALID;
}
ModelPartition partition_model;
partition_model.data = data;
partition_model.size = static_cast<uint64_t>(size);
partition_model.type = type;
if (om_file_save_helper->AddPartition(partition_model, model_index) != SUCCESS) {
GELOGE(PARAM_INVALID, "[Add][ModelPartition]Failed, partition size %zu", size);
REPORT_INNER_ERR_MSG("E19999", "Add model partition failed, partition size %zu", size);
return PARAM_INVALID;
}
GELOGI("[Add][ModelPartition]Success, partition type[%d] size[%zu]", static_cast<int32_t>(type), size);
return SUCCESS;
}
Status ModelHelper::SaveSizeToModelDef(const GeModelPtr &ge_model, const size_t model_index) const {
std::vector<int64_t> om_info;
GELOGD("SaveSizeToModelDef weight_data_size is %zu, ge_model_weight data is %p", ge_model->GetWeightSize(),
ge_model->GetWeightData());
om_info.push_back(static_cast<int64_t>(ge_model->GetWeightSize()));
const auto &tbe_kernel_store = ge_model->GetTBEKernelStore();
GELOGD("SaveSizeToModelDef tbe_kernels_size is %zu", tbe_kernel_store.DataSize());
om_info.push_back(static_cast<int64_t>(tbe_kernel_store.DataSize()));
const auto &cust_aicpu_kernel_store = ge_model->GetCustAICPUKernelStore();
GELOGD("SaveSizeToModelDef cust aicpu kernels size is %zu", cust_aicpu_kernel_store.DataSize());
om_info.push_back(static_cast<int64_t>(cust_aicpu_kernel_store.DataSize()));
const std::shared_ptr<domi::ModelTaskDef> model_task_def = ge_model->GetModelTaskDefPtr();
if (model_task_def == nullptr) {
GELOGD("SaveSizeToModelDef task_info_size is 0.");
om_info.push_back(0);
} else {
const size_t partition_task_size = model_task_def->ByteSizeLong();
GELOGD("SaveSizeToModelDef task_info_size is %zu", partition_task_size);
om_info.push_back(static_cast<int64_t>(partition_task_size));
}
if (model_index == 0U) {
GELOGD("SaveSizeToModelDef so store size is %zu", GetOpStoreDataSize());
om_info.push_back(static_cast<int64_t>(GetOpStoreDataSize()));
} else {
om_info.push_back(0U);
}
GE_CHK_BOOL_EXEC(ge::AttrUtils::SetListInt(*(ge_model.get()), "om_info_list", om_info),
GELOGE(FAILED, "SetListInt of om_info_list failed.");
return FAILED);
return SUCCESS;
}
Status ModelHelper::ConfigureAttrCompressionMode(const string &mode) {
if (mode != "true" && mode != "false") {
GELOGE(PARAM_INVALID, "[Validate][AttrCompressionMode] Invalid value '%s'. "
"Only 'true' or 'false' are allowed.", mode.c_str());
return PARAM_INVALID;
}
attr_compression_enabled_ = (mode == "true");
GELOGI("[AttrCompression] Configured from options: enabled=%s",
attr_compression_enabled_ ? "true" : "false");
return SUCCESS;
}
Status ModelHelper::SaveModelDef(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper, const GeModelPtr &ge_model,
ge::Buffer &model_buffer, const size_t model_index) const {
const bool should_compress = ShouldCompress();
GELOGD("[AttrCompression] enabled=%s, is_offline=%d, is_need_compress=%d, decision=%s",
attr_compression_enabled_ ? "true" : "false",
static_cast<int32_t>(is_offline_),
static_cast<int32_t>(is_need_compress_),
should_compress ? "COMPRESS" : "SKIP");
if (should_compress) {
(void)ModelCompressManager::Compress(ge_model);
}
const ModelPtr model_tmp = ge::MakeShared<ge::Model>(ge_model->GetName(), ge_model->GetPlatformVersion());
if (model_tmp == nullptr) {
GELOGE(FAILED, "[Creat][Model]Failed, Model %s Ptr", ge_model->GetName().c_str());
REPORT_INNER_ERR_MSG("E19999", "Create Model %s Ptr failed", ge_model->GetName().c_str());
return FAILED;
}
model_tmp->SetGraph(ge_model->GetGraph());
model_tmp->SetVersion(ge_model->GetVersion());
const Status ret = SaveSizeToModelDef(ge_model, model_index);
if (ret != SUCCESS) {
GELOGE(ret, "[Save][SizeToModelDef]Failed, model %s, error_code %u",
ge_model->GetName().c_str(), ret);
REPORT_INNER_ERR_MSG("E19999", "Save SizeToModelDef failed, model %s, error_code %u",
ge_model->GetName().c_str(), ret);
return ret;
}
model_tmp->SetAttr(ge_model->MutableAttrMap());
GE_ASSERT_SUCCESS(model_tmp->SaveWithoutSeparate(model_buffer));
GELOGD("MODEL_DEF size is %zu", model_buffer.GetSize());
if (model_buffer.GetSize() > 0U) {
if (SaveModelPartition(om_file_save_helper, ModelPartitionType::MODEL_DEF, model_buffer.GetData(),
model_buffer.GetSize(), model_index) != SUCCESS) {
GELOGE(PARAM_INVALID, "[Add][ModelPartition]Failed, model %s, model_def size %zu, model_index %zu",
ge_model->GetName().c_str(), model_buffer.GetSize(), model_index);
REPORT_INNER_ERR_MSG("E19999", "Add model graph partititon failed, model %s, model_def %zu, "
"model_index %zu", ge_model->GetName().c_str(), model_buffer.GetSize(), model_index);
return PARAM_INVALID;
}
}
return SUCCESS;
}
Status ModelHelper::SaveModelWeights(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper, const GeModelPtr &ge_model,
const size_t model_index) const {
GELOGD("WEIGHTS_DATA size is %zu, %p", ge_model->GetWeightSize(), ge_model->GetWeightData());
if (ge_model->GetWeightSize() > 0U) {
GE_CHK_STATUS_RET(SaveModelPartition(om_file_save_helper,
ModelPartitionType::WEIGHTS_DATA,
ge_model->GetWeightData(),
ge_model->GetWeightSize(),
model_index),
"Add weight partition failed");
}
return SUCCESS;
}
Status ModelHelper::SaveModelTbeKernel(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper,
const GeModelPtr &ge_model, const size_t model_index) const {
const auto &tbe_kernel_store = ge_model->GetTBEKernelStore();
GELOGD("TBE_KERNELS size is %zu", tbe_kernel_store.DataSize());
if (tbe_kernel_store.DataSize() > 0U) {
GE_CHK_STATUS_RET(
SaveModelPartition(om_file_save_helper, ModelPartitionType::TBE_KERNELS,
tbe_kernel_store.Data(), tbe_kernel_store.DataSize(),
model_index),
"Add tbe kernel partition failed");
}
return SUCCESS;
}
Status ModelHelper::SaveModelCustAICPU(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper,
const GeModelPtr &ge_model, const size_t model_index) const {
const auto &cust_aicpu_kernel_store = ge_model->GetCustAICPUKernelStore();
GELOGD("cust aicpu kernels size is %zu", cust_aicpu_kernel_store.DataSize());
if (cust_aicpu_kernel_store.DataSize() > 0U) {
GE_CHK_STATUS_RET(SaveModelPartition(om_file_save_helper,
ModelPartitionType::CUST_AICPU_KERNELS,
cust_aicpu_kernel_store.Data(),
cust_aicpu_kernel_store.DataSize(), model_index),
"Add cust aicpu kernel partition failed");
}
return SUCCESS;
}
Status ModelHelper::SaveModelIntroduction(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper,
const GeModelPtr &ge_model, const bool is_dynamic) const {
std::unique_ptr<ModelIntroduction> modelIntroduction = ge::MakeUnique<ModelIntroduction>();
GE_IF_BOOL_EXEC(modelIntroduction == nullptr,
REPORT_INNER_ERR_MSG("E19999", "ModelIntroduction failed, it is nullptr, model %s",
ge_model->GetName().c_str());
GELOGE(ACL_ERROR_GE_MEMORY_ALLOCATION, "[Create][ModelIntroduction]Failed, it is nullptr, "
"model %s", ge_model->GetName().c_str()); return ACL_ERROR_GE_MEMORY_ALLOCATION);
GE_ASSERT_SUCCESS(modelIntroduction->Init(ge_model, is_dynamic),
"ModelIntroduction Init Failed, model %s", ge_model->GetName().c_str());
std::shared_ptr<uint8_t> buff = modelIntroduction->Data();
ge_model->SetModelInOutInfo(buff);
GELOGD("MODEL_INOUT_INFO size is %d", modelIntroduction->DataSize());
if (modelIntroduction->DataSize() > 0U) {
GE_CHK_STATUS_RET(SaveModelPartition(om_file_save_helper,
ModelPartitionType::MODEL_INOUT_INFO,
buff.get(),
static_cast<size_t>(modelIntroduction->DataSize()), 0U),
"Add model introduction partition failed");
}
return SUCCESS;
}
Status ModelHelper::SaveModelTaskDef(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper, const GeModelPtr &ge_model,
ge::Buffer &task_buffer, const size_t model_index) const {
const std::shared_ptr<domi::ModelTaskDef> model_task_def = ge_model->GetModelTaskDefPtr();
if (model_task_def == nullptr) {
GELOGE(ACL_ERROR_GE_MEMORY_ALLOCATION, "[Creat][ModelTaskDef]Failed, it is nullptr, "
"model %s", ge_model->GetName().c_str());
REPORT_INNER_ERR_MSG("E19999", "Creat model task def failed, it is nullptr, model %s",
ge_model->GetName().c_str());
return ACL_ERROR_GE_MEMORY_ALLOCATION;
}
const size_t partition_task_size = model_task_def->ByteSizeLong();
GE_IF_BOOL_EXEC((partition_task_size == 0U) || (static_cast<int32_t>(partition_task_size) > INT_MAX),
GELOGE(FAILED, "[Check][ModelDefSize]Invalid, size %zu, model %s",
partition_task_size, ge_model->GetName().c_str());
REPORT_INNER_ERR_MSG("E19999", "Model def size %zu check invalid, model %s",
partition_task_size, ge_model->GetName().c_str());
return FAILED);
task_buffer = ge::Buffer(partition_task_size);
if (task_buffer.GetSize() == 0U) {
GELOGE(ACL_ERROR_GE_MEMORY_ALLOCATION, "[Allocate][ModelTaskDefBuffer]Failed, "
"model def size %zu, model %s", partition_task_size, ge_model->GetName().c_str());
REPORT_INNER_ERR_MSG("E19999", "Allocate model task def buffer failed, model def size %zu "
"model %s", partition_task_size, ge_model->GetName().c_str());
return ACL_ERROR_GE_MEMORY_ALLOCATION;
}
(void)model_task_def->SerializePartialToArray(task_buffer.GetData(), static_cast<int32_t>(partition_task_size));
GELOGD("TASK_INFO op_size:%d, stream_num:%u", model_task_def->op().size(), model_task_def->stream_num());
GELOGD("TASK_INFO size is %zu", partition_task_size);
if (SaveModelPartition(om_file_save_helper, ModelPartitionType::TASK_INFO, task_buffer.GetData(),
partition_task_size, model_index) != SUCCESS) {
GELOGE(PARAM_INVALID, "[Add][ModelTaskDefPartition]Failed, model def size %zu, "
"model_index %zu, model %s",
partition_task_size, model_index, ge_model->GetName().c_str());
REPORT_INNER_ERR_MSG("E19999", "Add model task def partition failed, model def size %zu "
"model_index %zu, model %s",
partition_task_size, model_index, ge_model->GetName().c_str());
return PARAM_INVALID;
}
return SUCCESS;
}
Status ModelHelper::SaveModelHeader(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper, const GeModelPtr &ge_model,
const size_t model_num, const bool need_check_os_cpu,
const bool is_unknow_shape) const {
ModelFileHeader &model_header = om_file_save_helper->GetModelFileHeader();
model_header.platform_type = ge_model->GetPlatformType();
model_header.om_ir_version = ge_model->GetVersion();
model_header.model_num = static_cast<uint32_t>(model_num);
model_header.is_unknow_model = is_unknow_shape ? 1U : 0U;
const std::string platform_version = ge_model->GetPlatformVersion();
errno_t err = memcpy_s(model_header.platform_version, static_cast<size_t>(PLATFORM_VERSION_LEN),
platform_version.c_str(), platform_version.size() + 1U);
if (err != EOK) {
GELOGE(ACL_ERROR_GE_MEMORY_ALLOCATION,
"[Save][Model]Failed while allocating memory for platform_version %s, model %s, "
"errno %d",
platform_version.c_str(), ge_model->GetName().c_str(), err);
REPORT_INNER_ERR_MSG("E19999",
"ModelHelper save model %s failed while "
"allocating memory for platform_version %s, errno %d",
ge_model->GetName().c_str(), platform_version.c_str(), err);
return ACL_ERROR_GE_MEMORY_ALLOCATION;
}
const std::string version = reinterpret_cast<char_t *>(model_header.platform_version);
GELOGD("Platform version save: %s", version.c_str());
if (need_check_os_cpu) {
model_header.need_check_os_cpu_info = static_cast<uint8_t>(OsCpuInfoCheckTyep::NEED_CHECK);
GELOGD("need_check_os_cpu_info save:%u", model_header.need_check_os_cpu_info);
}
size_t name_size = ge_model->GetName().size();
name_size = (name_size > (MODEL_NAME_LENGTH - 1U)) ? (MODEL_NAME_LENGTH - 1U) : name_size;
err = memcpy_s(model_header.name, MODEL_NAME_LENGTH, ge_model->GetName().c_str(), name_size);
if (err != EOK) {
GELOGE(ACL_ERROR_GE_MEMORY_ALLOCATION,
"[Save][Model]Failed while allocating memory for model %s, errno %d",
ge_model->GetName().c_str(), err);
REPORT_INNER_ERR_MSG("E19999", "ModelHelper save model failed while allocating memory "
"for model %s,errno %d", ge_model->GetName().c_str(), err);
return ACL_ERROR_GE_MEMORY_ALLOCATION;
}
const std::string model_name = reinterpret_cast<char_t *>(model_header.name);
GELOGD("Model name save:%s", model_name.c_str());
return SUCCESS;
}
Status ModelHelper::LoadAndStoreOppSo(const std::unordered_set<std::string> &op_so_set, const SoBinType so_bin_type) {
for (const auto &op_so : op_so_set) {
uint32_t bin_len = 0U;
auto op_so_bin = GetBinDataFromFile(op_so, bin_len);
GE_ASSERT_NOTNULL(op_so_bin, "open so fail, path=%s", op_so.c_str());
const auto &pos = op_so.find_last_of("/");
GE_ASSERT_TRUE(pos != std::string::npos);
const auto &so_name = op_so.substr(pos + 1UL);
const auto &vendor_name = op_so.substr(0, pos);
const auto proto_bin = ge::MakeShared<OpSoBin>(so_name, vendor_name, std::move(op_so_bin), bin_len, so_bin_type);
GE_ASSERT_NOTNULL(proto_bin);
op_so_store_.AddKernel(proto_bin);
GELOGD("Add op so:%s[%u] success.", op_so.c_str(), so_bin_type);
}
return SUCCESS;
}
Status ModelHelper::LoadAndStoreOppSo(const string &path, bool is_split, bool is_sub_pkg) {
const bool is_built_in_path = (path.find(kInner) != std::string::npos);
std::vector<std::string> op_so_list;
if ((!is_sub_pkg) && is_built_in_path) {
const std::string so_buff = is_split ? kRtSoSuffix : kRt2SoSuffix;
ge::PluginManager::GetFileListWithSuffix(path, so_buff, op_so_list);
} else {
ge::PluginManager::GetFileListWithSuffix(path, kSoSuffix, op_so_list);
}
if (is_built_in_path && op_so_list.empty()) {
GELOGE(FAILED, "Cannot find any op so in path:%s", path.c_str());
return FAILED;
}
std::unordered_set<std::string> op_so_set(op_so_list.begin(), op_so_list.end());
GE_ASSERT_SUCCESS(LoadAndStoreOppSo(op_so_set, SoBinType::kSpaceRegistry));
return SUCCESS;
}
Status ModelHelper::GetSoBinData(const string &cpu_info, const string &os_info) {
const auto is_split = PluginManager::IsSplitOpp();
std::vector<std::string> vendors;
PluginManager::GetPackageSoPath(vendors);
const std::string os_cpu_type = os_info + "/" + cpu_info;
bool is_sub_pkg = false;
for (size_t i = 0U; i < vendors.size(); i++) {
if (vendors[i].empty()) {
continue;
}
GELOGD("Begin to scan op proto and master so from path:%s", vendors[i].c_str());
const auto last_kernel_num = op_so_store_.GetKernelNum();
const auto op_proto_path = GetOppPkgPath(vendors[i] + kOpsProtoPath + os_cpu_type, kOpsProtoPath,
kOpsGraphPath, os_cpu_type, is_sub_pkg);
GE_ASSERT_SUCCESS(LoadAndStoreOppSo(op_proto_path, is_split, is_sub_pkg),
"Load and store op proto so failed, path:%s",
op_proto_path.c_str());
const auto op_master_path = GetOppPkgPath(vendors[i] + kOpMasterPath + os_cpu_type, kOpMasterPath,
kOpHostPath, os_cpu_type, is_sub_pkg);
GE_ASSERT_SUCCESS(LoadAndStoreOppSo(op_master_path, is_split, is_sub_pkg),
"Load and store op master so failed, path:%s",
op_master_path.c_str());
if ((vendors[i].find(kInner) == std::string::npos) && (op_so_store_.GetKernelNum() > last_kernel_num)) {
std::string compiler_version;
if (PluginManager::GetVersionFromPathWithName(vendors[i] + kVersionInfo, compiler_version, kCompilerVersion)) {
(void)custom_compiler_versions_.emplace(compiler_version);
}
}
}
if (is_split) {
std::vector<std::string> path_vec;
std::string ops_proto_path;
if (PluginManager::GetUpgradedOpsProtoPath(ops_proto_path) == ge::SUCCESS) {
PluginManager::SplitPath(ops_proto_path, path_vec);
for (const auto &path : path_vec) {
const auto root_path = GetOppPkgPath(path + "/lib/" + os_cpu_type, kOpsProtoPath, kOpsGraphPath, os_cpu_type,
is_sub_pkg);
(void)LoadAndStoreOppSo(root_path, true, is_sub_pkg);
}
}
path_vec.clear();
std::string op_tiling_path;
if (PluginManager::GetUpgradedOpMasterPath(op_tiling_path) == ge::SUCCESS) {
PluginManager::SplitPath(op_tiling_path, path_vec);
for (const auto &path : path_vec) {
const auto root_path = GetOppPkgPath(path + "/op_tiling/lib/" + os_cpu_type, kOpMasterPath, kOpHostPath,
os_cpu_type, is_sub_pkg);
(void)LoadAndStoreOppSo(root_path, true, is_sub_pkg);
}
}
}
return SUCCESS;
}
const uint8_t *ModelHelper::GetOpSoStoreData() const { return op_so_store_.Data(); }
size_t ModelHelper::GetOpStoreDataSize() const { return op_so_store_.DataSize(); }
Status ModelHelper::SetModelCompilerVersion(const GeModelPtr &first_ge_model) {
if (!custom_compiler_versions_.empty()) {
std::string compiler_version;
for (const auto &it : custom_compiler_versions_) {
compiler_version.empty() ? compiler_version.append(it) : compiler_version.append("," + it);
}
GE_ASSERT_TRUE(ge::AttrUtils::SetStr(*(first_ge_model.get()), ATTR_MODEL_COMPILER_VERSION, compiler_version),
"Ge model set compiler version failed");
GELOGD("Ge model set compiler version:%s success.", compiler_version.c_str());
}
return SUCCESS;
}
Status ModelHelper::SaveSpaceRegistrySoBin(const GeRootModelPtr &ge_root_model, const GeModelPtr &first_ge_model,
string &output_file_name) {
if (!OpSoStoreUtils::IsSoBinType(ge_root_model->GetSoInOmFlag(), SoBinType::kSpaceRegistry)) {
return SUCCESS;
}
std::string host_env_os;
std::string host_env_cpu;
(void)GetThreadLocalContext().GetOption("ge.host_env_os", host_env_os);
(void)GetThreadLocalContext().GetOption("ge.host_env_cpu", host_env_cpu);
GELOGI("get host env cpu:%s, os:%s", host_env_cpu.c_str(), host_env_os.c_str());
if (host_env_os.empty() || host_env_cpu.empty()) {
GELOGW("[SaveSoStoreModelPartitionInfo] get cpu or os info empty!!");
return SUCCESS;
}
GE_ASSERT_SUCCESS(GetSoBinData(host_env_cpu, host_env_os));
const auto position = output_file_name.find(".om");
const string cpu_os_str = "_" + host_env_os + "_" + host_env_cpu;
if (position < output_file_name.length()) {
(void)output_file_name.insert(position, cpu_os_str);
} else {
(void)output_file_name.append(cpu_os_str);
}
GE_ASSERT_SUCCESS(SetModelCompilerVersion(first_ge_model));
is_so_store_ = true;
GELOGI("[SpaceRegistry]Save to OpSoStore success.");
return SUCCESS;
}
Status ModelHelper::SaveOpMasterDeviceSoBin(const GeRootModelPtr &ge_root_model) {
if (!OpSoStoreUtils::IsSoBinType(ge_root_model->GetSoInOmFlag(), SoBinType::kOpMasterDevice)) {
return SUCCESS;
}
GE_ASSERT_SUCCESS(LoadAndStoreOppSo(ge_root_model->GetOpMasterDeviceSoSet(), SoBinType::kOpMasterDevice));
GELOGI("[OpMasterDevice]Save to OpSoStore success.");
return SUCCESS;
}
Status ModelHelper::SaveAutofuseSoBin(const GeRootModelPtr &ge_root_model) {
GE_ASSERT_NOTNULL(ge_root_model);
auto root_graph = ge_root_model->GetRootGraph();
GE_ASSERT_NOTNULL(root_graph);
auto bin_file_buffer = root_graph->GetExtAttr<std::map<std::string, ge::OpSoBinPtr>>("bin_file_buffer");
if (bin_file_buffer != nullptr) {
GELOGD("No need to save autofuse so to om, since bin_file_buffer already exists.");
return SUCCESS;
}
if (!OpSoStoreUtils::IsSoBinType(ge_root_model->GetSoInOmFlag(), SoBinType::kAutofuse)) {
return SUCCESS;
}
GE_ASSERT_SUCCESS(LoadAndStoreOppSo(ge_root_model->GetAutofuseSoSet(), SoBinType::kAutofuse));
GELOGI("[AutofuseSo]Save to AutofuseSo success.");
return SUCCESS;
}
Status ModelHelper::SaveCustomOpSoBin(const GeRootModelPtr &ge_root_model) {
GE_ASSERT_NOTNULL(ge_root_model);
if (!OpSoStoreUtils::IsSoBinType(ge_root_model->GetSoInOmFlag(), SoBinType::kCustomOp)) {
return SUCCESS;
}
GE_ASSERT_SUCCESS(LoadAndStoreOppSo(ge_root_model->GetCustomOpSoSet(), SoBinType::kCustomOp));
GELOGI("[CustomOp]Save %zu custom op so to OpSoStore success.", ge_root_model->GetCustomOpSoSet().size());
return SUCCESS;
}
Status ModelHelper::SaveSoStoreModelPartitionInfo(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper,
const GeRootModelPtr &ge_root_model, string &output_file_name,
const GeModelPtr &first_ge_model) {
GELOGI("so in om flag:0x%x", ge_root_model->GetSoInOmFlag());
if (ge_root_model->GetSoInOmFlag() == 0U) {
output_file_name_ = output_file_name;
return SUCCESS;
}
GE_ASSERT_SUCCESS(SaveSpaceRegistrySoBin(ge_root_model, first_ge_model, output_file_name));
GE_ASSERT_SUCCESS(SaveOpMasterDeviceSoBin(ge_root_model));
GE_ASSERT_SUCCESS(SaveAutofuseSoBin(ge_root_model));
GE_ASSERT_SUCCESS(SaveCustomOpSoBin(ge_root_model));
GE_ASSERT_TRUE(op_so_store_.Build(), "Build op so store failed.");
const auto op_so_data = GetOpSoStoreData();
const auto data_size = GetOpStoreDataSize();
GE_ASSERT_SUCCESS(SaveModelPartition(om_file_save_helper, ModelPartitionType::SO_BINS, op_so_data, data_size, 0UL),
"Add so store failed");
output_file_name_ = output_file_name;
return SUCCESS;
}
Status ModelHelper::SaveTilingData(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper,
const GeRootModelPtr &ge_root_model) {
const HostResourceCenterPtr &host_resource_center = ge_root_model->GetHostResourceCenterPtr();
GE_ASSERT_NOTNULL(host_resource_center);
uint8_t *data{nullptr};
size_t data_len{0UL};
GE_ASSERT_SUCCESS(host_serializer_.SerializeTilingData(*host_resource_center, data, data_len));
if (data_len > 0UL) {
GELOGI("Tiling data partition size: %zu.", data_len);
GE_ASSERT_SUCCESS(SaveModelPartition(om_file_save_helper, ModelPartitionType::TILING_DATA, data, data_len, 0U),
"Save tiling data to model failed.");
}
return SUCCESS;
}
Status ModelHelper::SaveAllModelPartiton(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper,
const GeModelPtr &ge_model, ge::Buffer &model_buffer, ge::Buffer &task_buffer,
const size_t model_index) const {
GE_CHK_STATUS_RET(EnsureKernelBuilt(ge_model), "ensure kernel built failed, model=%s.", ge_model->GetName().c_str());
if (SaveModelDef(om_file_save_helper, ge_model, model_buffer, model_index) != SUCCESS) {
GELOGE(FAILED, "[Save][ModelDef]Failed, model %s, model index %zu",
ge_model->GetName().c_str(), model_index);
return FAILED;
}
if (SaveModelWeights(om_file_save_helper, ge_model, model_index) != SUCCESS) {
GELOGE(FAILED, "[Save][ModelWeights]Failed, model %s, model index %zu",
ge_model->GetName().c_str(), model_index);
REPORT_INNER_ERR_MSG("E19999", "ModelHelper save mode weights failed, model %s, model index %zu",
ge_model->GetName().c_str(), model_index);
return FAILED;
}
if (SaveModelTbeKernel(om_file_save_helper, ge_model, model_index) != SUCCESS) {
GELOGE(FAILED, "[Save][ModelTbeKernel]Failed, model %s, model index %zu",
ge_model->GetName().c_str(), model_index);
REPORT_INNER_ERR_MSG("E19999", "ModelHelper save model tbe kernel failed, model %s, "
"model index %zu", ge_model->GetName().c_str(), model_index);
return FAILED;
}
if (SaveModelCustAICPU(om_file_save_helper, ge_model, model_index) != SUCCESS) {
GELOGE(FAILED, "[Save][ModelCustAICPU]Failed, model %s, model index %zu",
ge_model->GetName().c_str(), model_index);
REPORT_INNER_ERR_MSG("E19999", "ModelHelper save model cust aicpu failed, model %s "
"model index %zu", ge_model->GetName().c_str(), model_index);
return FAILED;
}
if (SaveModelTaskDef(om_file_save_helper, ge_model, task_buffer, model_index) != SUCCESS) {
GELOGE(FAILED, "[Save][TaskDef]Failed, model %s, model index %zu",
ge_model->GetName().c_str(), model_index);
return FAILED;
}
return SUCCESS;
}
Status ModelHelper::SaveRootModelPartitionsForOmModel(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper,
const GeRootModelPtr &ge_root_model, string &output_file_name,
const GeModelPtr &ge_model) {
if (is_offline_) {
GE_ASSERT_SUCCESS(SaveSoStoreModelPartitionInfo(om_file_save_helper, ge_root_model, output_file_name, ge_model),
"[SaveSoStoreModelPartition]Failed");
GE_ASSERT_SUCCESS(SaveCustomOpsPartition(om_file_save_helper, ge_root_model),
"[Save][CustomOpsPartition]Failed");
}
GE_ASSERT_SUCCESS(SaveTilingData(om_file_save_helper, ge_root_model), "Save tiling data to model failed.");
return SUCCESS;
}
Status ModelHelper::SetModelAttributes(const GeModelPtr &ge_model) const {
GE_CHK_BOOL_EXEC(ge::AttrUtils::SetStr(*(ge_model.get()), ATTR_MODEL_ATC_CMDLINE,
domi::GetContext().atc_cmdline),
GELOGE(FAILED, "SetStr for atc_cmdline failed.");
return FAILED);
std::string cur_version;
auto ret = GetOppVersion(cur_version);
if ((ret != SUCCESS) || (!ge::AttrUtils::SetStr(*(ge_model.get()), ATTR_MODEL_OPP_VERSION, cur_version))) {
GELOGW("Ge model set opp version unsuccessful!");
}
return SUCCESS;
}
Status ModelHelper::SaveToOmModel(const GeModelPtr &ge_model, const std::string &output_file,
ModelBufferData &model, const GeRootModelPtr &ge_root_model) {
GE_ASSERT_NOTNULL(ge_model, "Ge_model is nullptr");
if (output_file.empty()) {
GELOGE(FAILED, "[Save][Model]GraphBuilder SaveModel received invalid file name prefix, "
"model %s", ge_model->GetName().c_str());
REPORT_INNER_ERR_MSG("E19999", "GraphBuilder SaveModel received invalid file name prefix, "
"model %s", ge_model->GetName().c_str());
return FAILED;
}
std::shared_ptr<OmFileSaveHelper> om_file_save_helper = ge::MakeShared<OmFileSaveHelper>();
GE_CHECK_NOTNULL(om_file_save_helper);
ge::Buffer model_buffer;
ge::Buffer task_buffer;
GE_ASSERT_SUCCESS(SetModelAttributes(ge_model));
string output_file_name = output_file;
if (ge_root_model != nullptr) {
GE_ASSERT_SUCCESS(SaveRootModelPartitionsForOmModel(om_file_save_helper, ge_root_model, output_file_name, ge_model));
}
GE_IF_BOOL_EXEC(SaveModelIntroduction(om_file_save_helper, ge_model) != SUCCESS,
GELOGE(FAILED, "[Save][ModelIntroduction]Failed");
REPORT_INNER_ERR_MSG("E19999", "Save model introduction failed.");
return FAILED);
auto ret = SaveAllModelPartiton(om_file_save_helper, ge_model, model_buffer, task_buffer);
if (ret != SUCCESS) {
GELOGE(ret, "[Save][AllModelPartition]Failed, model %s, error_code %u",
ge_model->GetName().c_str(), ret);
REPORT_INNER_ERR_MSG("E19999", "OmFileSaveHelper save all model partition failed, model %s "
"error_code %u", ge_model->GetName().c_str(), ret);
return ret;
}
ret = SaveModelHeader(om_file_save_helper, ge_model, 1U, is_so_store_);
if (ret != SUCCESS) {
GELOGE(ret, "[Save][ModelHeader]Failed, model %s, error_code %u",
ge_model->GetName().c_str(), ret);
REPORT_INNER_ERR_MSG("E19999", "OmFileSaveHelper save model header failed, model %s "
"error_code %u", ge_model->GetName().c_str(), ret);
return ret;
}
ret = om_file_save_helper->SaveModel(output_file_name.c_str(), model, is_offline_ && save_to_file_);
if (ret != SUCCESS) {
GELOGE(FAILED, "[Save][Model]Failed, model %s, output file %s",
ge_model->GetName().c_str(), output_file.c_str());
REPORT_INNER_ERR_MSG("E19999", "OmFileSaveHelper save model failed, model %s, "
"output file %s", ge_model->GetName().c_str(), output_file.c_str());
}
return ret;
}
void ModelHelper::SaveOutNodesFromRootGraph(const GeRootModelPtr &ge_root_model, GeModelPtr &first_ge_model) const {
for (const auto &ge_model : ge_root_model->GetSubgraphInstanceNameToModel()) {
std::vector<std::string> out_node_name;
(void)ge::AttrUtils::GetListStr(ge_model.second, ge::ATTR_MODEL_OUT_NODES_NAME, out_node_name);
if (!out_node_name.empty()) {
GELOGD("Get model out node names from %s success, size = %zu", ge_model.first.c_str(), out_node_name.size());
(void)ge::AttrUtils::SetListStr(first_ge_model, ge::ATTR_MODEL_OUT_NODES_NAME, out_node_name);
break;
}
}
}
Status ModelHelper::SaveRootModelPartitions(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper,
const GeRootModelPtr &ge_root_model, const GeModelPtr &first_ge_model,
string &output_file_name, const bool has_asc_node) {
if (is_offline_ || has_asc_node) {
GE_ASSERT_SUCCESS(SaveSoStoreModelPartitionInfo(om_file_save_helper, ge_root_model,
output_file_name, first_ge_model), "[SaveSoStoreModelPartitionInfo]Failed");
GE_ASSERT_SUCCESS(SaveCustomOpsPartition(om_file_save_helper, ge_root_model),
"[Save][CustomOpsPartition]Failed");
}
GE_ASSERT_SUCCESS(SaveTilingData(om_file_save_helper, ge_root_model));
return SUCCESS;
}
Status ModelHelper::SaveRootModelLoop(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper,
const std::vector<std::string> &model_names,
const std::map<std::string, GeModelPtr> &name_to_ge_model,
std::vector<ge::Buffer> &model_buffers,
std::vector<ge::Buffer> &task_buffers,
size_t &cur_index) const {
for (; cur_index < model_names.size(); ++cur_index) {
const auto model_name = model_names[cur_index];
GELOGD("cur model %s index is %zu", model_name.c_str(), cur_index);
const GeModelPtr &ge_model = name_to_ge_model.at(model_name);
GE_ASSERT_SUCCESS(SaveAllModelPartiton(om_file_save_helper, ge_model, model_buffers[cur_index],
task_buffers[cur_index], cur_index),
"[Save][AllModelPartition]Failed, model name %s, cur_index %zu", model_name.c_str(), cur_index);
}
return SUCCESS;
}
Status ModelHelper::InitFirstGeModel(const GeRootModelPtr &ge_root_model,
const std::map<std::string, GeModelPtr> &name_to_ge_model,
GeModelPtr &first_ge_model) const {
const auto &first_model_it = name_to_ge_model.find(ge_root_model->GetRootGraph()->GetName());
if (first_model_it == name_to_ge_model.end()) {
first_ge_model = MakeShared<GeModel>();
GE_CHECK_NOTNULL(first_ge_model);
first_ge_model->SetGraph(ge_root_model->GetRootGraph());
} else {
first_ge_model = first_model_it->second;
}
GE_CHK_BOOL_EXEC(ge::AttrUtils::SetStr(*(first_ge_model.get()), ATTR_MODEL_ATC_CMDLINE,
domi::GetContext().atc_cmdline),
GELOGE(FAILED, "SetStr for atc_cmdline failed.");
return FAILED);
std::string cur_version;
const auto get_ret = GetOppVersion(cur_version);
if ((get_ret != SUCCESS) || (!ge::AttrUtils::SetStr(*(first_ge_model.get()), ATTR_MODEL_OPP_VERSION, cur_version))) {
GELOGW("Ge model set opp version unsuccessful!");
}
return SUCCESS;
}
Status ModelHelper::SavePartitionedFirstModel(std::shared_ptr<OmFileSaveHelper> &om_file_save_helper,
const GeRootModelPtr &ge_root_model, GeModelPtr &first_ge_model,
const ComputeGraphPtr &root_graph, bool is_unknown_shape,
std::vector<ge::Buffer> &model_buffers,
std::vector<ge::Buffer> &task_buffers, size_t &cur_index) {
SaveOutNodesFromRootGraph(ge_root_model, first_ge_model);
GE_ASSERT_SUCCESS(SaveModelIntroduction(om_file_save_helper, first_ge_model, is_unknown_shape));
if (gert::GraphUnfolder::IsGraphNeedUnfold(root_graph)) {
GELOGD("only save first model MODEL_DEF");
GE_ASSERT_SUCCESS(SaveModelDef(om_file_save_helper, first_ge_model, model_buffers[cur_index], cur_index),
"Save model def failed, cur_index %zu", cur_index);
} else {
GE_ASSERT_SUCCESS(SaveAllModelPartiton(om_file_save_helper, first_ge_model, model_buffers[cur_index],
task_buffers[cur_index], cur_index));
}
is_need_compress_ = false;
++cur_index;
return SUCCESS;
}
Status ModelHelper::SaveToOmRootModel(const GeRootModelPtr &ge_root_model, const std::string &output_file,
ModelBufferData &model, const bool is_unknown_shape) {
GE_ASSERT_NOTNULL(ge_root_model, "[Check][GERootModel]Ge_root_model is nullptr");
GE_ASSERT_TRUE(!output_file.empty(), "[Save][Model]GraphBuilder SaveModel received invalid file name prefix.");
const auto &name_to_ge_model = ge_root_model->GetSubgraphInstanceNameToModel();
GE_ASSERT_TRUE(!name_to_ge_model.empty(), "[Get][SubModel]Ge_root_model has no sub model.");
if (!is_unknown_shape) {
auto &model_root = name_to_ge_model.begin()->second;
return SaveToOmModel(model_root, output_file, model, ge_root_model);
}
GeModelPtr first_ge_model;
GE_ASSERT_SUCCESS(InitFirstGeModel(ge_root_model, name_to_ge_model, first_ge_model));
std::vector<std::string> model_names{ge_root_model->GetRootGraph()->GetName()};
for (auto &item : name_to_ge_model) {
if (item.first != model_names.front()) {
(void)model_names.emplace_back(item.first);
}
}
std::vector<ge::Buffer> model_buffers(model_names.size());
std::vector<ge::Buffer> task_buffers(model_names.size());
is_need_compress_ = true;
const auto &root_graph = ge_root_model->GetRootGraph();
GE_ASSERT_NOTNULL(root_graph);
const auto asc_node_ascbackend = root_graph->FindFirstNodeMatchType("AscBackend");
const auto asc_node_fusedascbackend = root_graph->FindFirstNodeMatchType("FusedAscBackend");
const bool has_asc_node = (asc_node_ascbackend != nullptr) || (asc_node_fusedascbackend != nullptr);
if (has_asc_node) {
is_need_compress_ = false;
GE_ASSERT_SUCCESS(ge_root_model->CheckAndSetNeedSoInOM(), "Check so in om failed, model id:%u.", ge_root_model->GetModelId());
}
string output_file_name = output_file;
std::shared_ptr<OmFileSaveHelper> om_file_save_helper = ge::MakeShared<OmFileSaveHelper>();
GE_CHECK_NOTNULL(om_file_save_helper);
GE_ASSERT_SUCCESS(SaveRootModelPartitions(om_file_save_helper, ge_root_model, first_ge_model, output_file_name, has_asc_node));
size_t cur_index = 0U;
bool is_partitioned = false;
(void) AttrUtils::GetBool(root_graph, ATTR_NAME_DYNAMIC_SHAPE_PARTITIONED, is_partitioned);
if (is_partitioned) {
GE_ASSERT_SUCCESS(SavePartitionedFirstModel(om_file_save_helper, ge_root_model, first_ge_model,
root_graph, is_unknown_shape, model_buffers, task_buffers, cur_index));
}
GE_ASSERT_SUCCESS(SaveRootModelLoop(om_file_save_helper, model_names, name_to_ge_model,
model_buffers, task_buffers, cur_index));
GE_ASSERT_SUCCESS(
SaveModelHeader(om_file_save_helper, first_ge_model, model_names.size(), is_so_store_, is_unknown_shape),
"[Save][ModelHeader]Failed, model name %s", first_ge_model->GetName().c_str());
GE_ASSERT_SUCCESS(om_file_save_helper->SaveModel(output_file_name.c_str(), model, is_offline_ && save_to_file_),
"[Save][Model]OmFileSaveHelper save model eturn fail, output_file %s", output_file_name.c_str());
return SUCCESS;
}
Status ModelHelper::SaveOriginalGraphToOmModel(const ge::Graph &graph, const std::string &output_file) const {
if (output_file.empty()) {
GELOGE(FAILED, "[Save][Model]Received invalid file name prefix, output_file %s", output_file.c_str());
(void)REPORT_PREDEFINED_ERR_MSG(
"E10059", std::vector<const char *>({"stage", "reason"}),
std::vector<const char *>({"SaveOriginalGraphToOmModel", "the model output file name cannot be empty"}));
return FAILED;
}
const auto compute_graph = ge::GraphUtilsEx::GetComputeGraph(graph);
if (compute_graph == nullptr) {
GELOGE(FAILED, "[Save][Model]Failed for compute_graph null");
REPORT_INNER_ERR_MSG("E19999", "Save model failed for compute_graph null");
return FAILED;
}
GE_DUMP(compute_graph, "OriginalGraph");
const ModelPtr model_ptr = ge::MakeUnique<ge::Model>();
GE_CHECK_NOTNULL_EXEC(model_ptr, return MEMALLOC_FAILED);
const std::string original_model_name = compute_graph->GetName() + "_original";
model_ptr->SetName(original_model_name);
model_ptr->SetGraph(compute_graph);
model_ptr->SetVersion(static_cast<uint32_t>(OM_PROTO_VERSION));
std::string framework_version;
const Status frame_rt = PlatformVersionManager::GetPlatformVersion(framework_version);
if (frame_rt == SUCCESS) {
const std::string model_framework_version = framework_version + "." + std::to_string(0);
model_ptr->SetPlatformVersion(model_framework_version);
}
ge::Buffer model_buffer;
const ge::graphStatus status = model_ptr->SaveWithoutSeparate(model_buffer);
if (status != ge::GRAPH_SUCCESS) {
GELOGE(FAILED, "[Save][Model]Failed for save buffer fail, model %s",
model_ptr->GetName().c_str());
REPORT_INNER_ERR_MSG("E19999", "Save model %s failed for save buffer fail",
model_ptr->GetName().c_str());
return FAILED;
}
const std::unique_ptr<OmFileSaveHelper> om_file_save_helper = ge::MakeUnique<OmFileSaveHelper>();
GE_CHECK_NOTNULL_EXEC(om_file_save_helper, return MEMALLOC_FAILED);
ModelPartition partition_model;
partition_model.data = model_buffer.GetData();
partition_model.size = static_cast<uint32_t>(model_buffer.GetSize());
partition_model.type = ModelPartitionType::MODEL_DEF;
GELOGI("Original Model type[%u],size[%" PRIu64 "]", partition_model.type, partition_model.size);
if ((partition_model.data != nullptr) && (partition_model.size > 0U)) {
(void)om_file_save_helper->AddPartition(partition_model);
}
ModelFileHeader &model_header = om_file_save_helper->GetModelFileHeader();
model_header.om_ir_version = model_ptr->GetVersion();
model_header.headsize = MODEL_FILE_HEAD_LEN;
const std::string platform_version = model_ptr->GetPlatformVersion();
errno_t
err = memcpy_s(model_header.platform_version, static_cast<size_t>(PLATFORM_VERSION_LEN), platform_version.c_str(),
platform_version.size() + 1U);
if (err != EOK) {
GELOGE(FAILED, "[Save][Model]Failed for platform_version %s, model %s, errno %d",
platform_version.c_str(), model_ptr->GetName().c_str(), err);
REPORT_INNER_ERR_MSG("E19999", "Save model %s failed for platform_version %s, errno %d",
model_ptr->GetName().c_str(), platform_version.c_str(), err);
return FAILED;
}
size_t name_size = model_ptr->GetName().size();
name_size = (name_size > (MODEL_NAME_LENGTH - 1U)) ? (MODEL_NAME_LENGTH - 1U) : name_size;
err = memcpy_s(model_header.name, MODEL_NAME_LENGTH, model_ptr->GetName().c_str(), name_size);
if (err != EOK) {
GELOGE(FAILED, "[Save][Model]Failed for memory copy %s failed, errno %d",
model_ptr->GetName().c_str(), err);
REPORT_INNER_ERR_MSG("E19999", "Save model failed for memory copy %s failed, errno %d",
model_ptr->GetName().c_str(), err);
return FAILED;
}
ModelBufferData model;
const Status ret = om_file_save_helper->SaveModel(output_file.c_str(), model, is_offline_ && save_to_file_);
return ((ret == SUCCESS) ? SUCCESS : FAILED);
}
Status ModelHelper::SaveBundleModelBufferToMem(const std::vector<ModelBufferData> &model_buffers, uint64_t var_size,
ModelBufferData &output_buffer) {
const size_t model_num = model_buffers.size();
constexpr size_t var_partition_num = 1U;
constexpr size_t var_size_len = sizeof(uint64_t);
const size_t mem_info_partition_num = model_num + var_partition_num;
const size_t header_size =
sizeof(ModelFileHeader) + sizeof(ModelPartitionTable) + sizeof(ModelPartitionMemInfo) * mem_info_partition_num;
size_t sub_model_size{0UL};
for (size_t i = 0UL; i < model_num; ++i) {
sub_model_size += model_buffers[i].length;
}
const size_t total_size = header_size + var_size_len + sub_model_size;
auto buff_data = MakeUnique<uint8_t[]>(total_size);
ModelFileHeader *header = PtrToPtr<uint8_t, ModelFileHeader>(buff_data.get());
GE_ASSERT_NOTNULL(header);
header->modeltype = MODEL_TYPE_BUNDLE_MODEL;
header->model_num = static_cast<uint32_t>(model_num);
header->model_length = total_size;
ModelPartitionTable *table = PtrToPtr<uint8_t, ModelPartitionTable>(&buff_data[sizeof(ModelFileHeader)]);
GE_ASSERT_NOTNULL(table);
table->num = static_cast<uint32_t>(mem_info_partition_num);
size_t offset{sizeof(ModelPartitionTable) + sizeof(ModelPartitionMemInfo) * mem_info_partition_num};
table->partition[0].type = BUNDLE_MODEL_VAR_INFO;
table->partition[0].mem_size = sizeof(int64_t);
table->partition[0].mem_offset = offset;
*reinterpret_cast<uint64_t*>(&buff_data[sizeof(ModelFileHeader) + offset]) = var_size;
offset += var_size_len;
for (size_t i = 0U; i < model_num; ++i) {
const size_t sub_model_id = i + var_partition_num;
table->partition[sub_model_id].type = BUNDLE_MODEL_INFO;
table->partition[sub_model_id].mem_size = model_buffers[i].length;
table->partition[sub_model_id].mem_offset = offset;
GE_ASSERT_SUCCESS(
ge::GeMemcpy(&buff_data[sizeof(ModelFileHeader) + offset], sub_model_size,
model_buffers[i].data.get(), model_buffers[i].length),
"Copy model buffer failed.");
sub_model_size -= model_buffers[i].length;
offset += model_buffers[i].length;
}
output_buffer.data.reset(buff_data.release(), std::default_delete<uint8_t[]>());
output_buffer.length = total_size;
GELOGI("Gathering bundle model successfully, total size: %[%zu], var_size is %lu", total_size, var_size);
return SUCCESS;
}
Status ModelHelper::LoadModel(const ge::ModelData &model_data) {
if ((model_data.model_data == nullptr) || (model_data.model_len == 0U)) {
GELOGE(ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID,
"[Load][Model]Model_data is nullptr or model_data_size is 0");
REPORT_INNER_ERR_MSG("E19999", "Load model failed, "
"Model_data is nullptr or model_data_size is 0");
return ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID;
}
if (is_assign_model_) {
GELOGE(ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED, "[Load][Model]Model helper has already loaded!");
return ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED;
}
uint8_t *model_data_addr = nullptr;
uint64_t model_data_size = 0UL;
Status status = ModelParserBase::ParseModelContent(model_data, model_data_addr, model_data_size);
if (status != SUCCESS) {
GELOGE(ACL_ERROR_GE_PARAM_INVALID, "[Parse][ModelContent]Failed!");
return ACL_ERROR_GE_PARAM_INVALID;
}
file_header_ = reinterpret_cast<ModelFileHeader *>(model_data.model_data);
OmFileLoadHelper om_load_helper;
status = om_load_helper.Init(model_data_addr, model_data_size, file_header_);
if (status != SUCCESS) {
GELOGE(status, "[Init][OmLoadHelper]Failed");
model_data_addr = nullptr;
return status;
}
const auto partition_table = reinterpret_cast<ModelPartitionTable *>(model_data_addr);
if (partition_table->num == kOriginalOmPartitionNum) {
model_data_addr = nullptr;
GELOGE(ACL_ERROR_GE_PARAM_INVALID, "[Check][OmModel]Error, please use executable om model");
return ACL_ERROR_GE_PARAM_INVALID;
}
model_data_addr = nullptr;
GeModelPtr first_ge_model = nullptr;
status = GenerateGeModel(om_load_helper, model_, first_ge_model, 0U, false);
if (status != SUCCESS) {
GELOGE(status, "[Generate][GEModel]Failed");
return status;
}
GELOGD("in ModelHelper::LoadModel, is_assign_model_ is setted to true!");
is_assign_model_ = true;
return SUCCESS;
}
Status ModelHelper::LoadPartInfoFromModel(const ge::ModelData &model_data, ModelPartition &partition) {
if ((model_data.model_data == nullptr) || (model_data.model_len == 0U)) {
GELOGE(ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID, "[Load][RootModel] "
"Model_data is nullptr or model data is empty.");
REPORT_INNER_ERR_MSG("E19999", "Load root model failed, model_data is nullptr or its size is 0");
return ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID;
}
GE_IF_BOOL_EXEC(is_assign_model_,
GELOGE(ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED, "[Load][RootModel]Model helper ha already loaded!");
return ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED);
uint8_t *model_data_addr = nullptr;
uint64_t model_data_size = 0U;
Status status = ModelParserBase::ParseModelContent(model_data, model_data_addr, model_data_size);
GE_IF_BOOL_EXEC(status != SUCCESS,
GELOGE(ACL_ERROR_GE_PARAM_INVALID, "[Parse][RootModelContent]Failed!");
return ACL_ERROR_GE_PARAM_INVALID);
file_header_ = reinterpret_cast<ModelFileHeader *>(model_data.model_data);
OmFileLoadHelper om_load_helper;
status = om_load_helper.Init(model_data_addr, model_data_size, file_header_);
GE_IF_BOOL_EXEC(status != SUCCESS,
GELOGE(status, "[Init][OmLoeadHelper]Failed");
model_data_addr = nullptr;
return status);
model_data_addr = nullptr;
GE_IF_BOOL_EXEC(om_load_helper.GetModelPartition(partition.type, partition) != SUCCESS,
GELOGE(FAILED, "[Get][ModelPartition]Failed, partition type is %d", partition.type);
REPORT_INNER_ERR_MSG("E19999", "[Get][ModelPartition]Failed, partition type is %d", partition.type);
return FAILED);
is_assign_model_ = true;
return SUCCESS;
}
Status ModelHelper::GetModelFileHead(const ge::ModelData &model_data, const ModelFileHeader *&file_header) {
if (model_data.model_data == nullptr) {
(void)REPORT_PREDEFINED_ERR_MSG("E10001", std::vector<const char*>({"parameter", "value", "reason"}),
std::vector<const char*>({"om", model_data.om_name.c_str(), "Model data cannot be nullptr."}));
GELOGE(ACL_ERROR_GE_PARAM_INVALID, "[Check][Param] Invalid model. Model data cannot be nullptr.");
return ACL_ERROR_GE_PARAM_INVALID;
}
if (model_data.model_len < sizeof(ModelFileHeader)) {
std::string reason = "Invalid om file. The model data size " + std::to_string(model_data.model_len) +
" is smaller than " + std::to_string(sizeof(ModelFileHeader)) + ".";
(void)REPORT_PREDEFINED_ERR_MSG("E10001", std::vector<const char *>({"parameter", "value", "reason"}),
std::vector<const char *>({"om", model_data.om_name.c_str(), reason.c_str()}));
GELOGE(ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID,
"[Check][Param] Invalid model. Model data size %" PRIu64 " must be greater than or equal to %zu.",
model_data.model_len, sizeof(ModelFileHeader));
return ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID;
}
file_header = reinterpret_cast<const ModelFileHeader *>(model_data.model_data);
return SUCCESS;
}
Status ModelHelper::GetOppVersion(std::string &version) {
std::string opp_path;
(void)PluginManager::GetOppPath(opp_path);
const std::string version_path = opp_path + "/version.info";
if (!PluginManager::GetVersionFromPathWithName(version_path, version, kOppVersion)) {
GELOGW("Get opp version information from %s unsuccessful!", version_path.c_str());
return FAILED;
}
return SUCCESS;
}
Status ModelHelper::CheckOsCpuInfoAndOppVersion() {
if (file_header_->need_check_os_cpu_info == static_cast<uint8_t>(OsCpuInfoCheckTyep::NEED_CHECK)) {
std::string host_env_os;
std::string host_env_cpu;
(void) ge::AttrUtils::GetStr(*(model_.get()), ATTR_MODEL_HOST_ENV_OS, host_env_os);
(void) ge::AttrUtils::GetStr(*(model_.get()), ATTR_MODEL_HOST_ENV_CPU, host_env_cpu);
std::string cur_host_env_os;
std::string cur_host_env_cpu;
ge::PluginManager::GetCurEnvPackageOsAndCpuType(cur_host_env_os, cur_host_env_cpu);
if ((host_env_os.compare(cur_host_env_os) != 0) || (host_env_cpu.compare(cur_host_env_cpu) != 0)) {
REPORT_INNER_ERR_MSG("E19999", "The os/cpu type of the model does not match the current system,"
"Model is[%s][%s], system is[%s][%s], please use the matching platform",
host_env_os.c_str(), host_env_cpu.c_str(),
cur_host_env_os.c_str(), cur_host_env_cpu.c_str());
GELOGE(FAILED, "The os/cpu type of the model does not match the current system,"
"Model is[%s][%s], system is[%s][%s]",
host_env_os.c_str(), host_env_cpu.c_str(),
cur_host_env_os.c_str(), cur_host_env_cpu.c_str());
return FAILED;
}
GELOGD("Check os[%s], cpu[%s] success.", host_env_os.c_str(), host_env_cpu.c_str());
const auto &so_in_om_info = root_model_->GetSoInOmInfo();
GE_ASSERT_TRUE(PluginManager::IsVendorVersionValid(so_in_om_info.opp_version, so_in_om_info.compiler_version),
"Invalid opp version [%s] or compiler_version [%s],"
"Please check if it is within the required range",
so_in_om_info.opp_version.c_str(), so_in_om_info.compiler_version.c_str());
GELOGD("Check opp_version[%s], compiler_version[%s] success.", so_in_om_info.opp_version.c_str(),
so_in_om_info.compiler_version.c_str());
}
if ((file_header_->need_check_os_cpu_info == static_cast<uint8_t>(OsCpuInfoCheckTyep::NO_CHECK))
&& is_unknown_shape_model_) {
std::string version;
(void) ge::AttrUtils::GetStr(*(model_.get()), ATTR_MODEL_OPP_VERSION, version);
std::string cur_version;
if ((GetOppVersion(cur_version) == SUCCESS) && (version.compare(cur_version) != 0)) {
REPORT_INNER_ERR_MSG("E19999", "The opp version of the model does not match the current opp run package,"
"Model is[%s], opp run package is[%s], try to convert the om again!",
version.c_str(), cur_version.c_str());
GELOGE(FAILED, "The opp version of the model does not match the current opp run package,"
"Model is[%s], opp run package is[%s]", version.c_str(), cur_version.c_str());
return FAILED;
}
GELOGD("Check opp version[%s] success.", version.c_str());
}
return SUCCESS;
}
Status ModelHelper::CheckIfWeightPathValid(const ge::ComputeGraphPtr &graph,
const ge::ModelData &model_data) const {
size_t index = 0UL;
GE_ASSERT_NOTNULL(graph);
for (const auto &node : graph->GetAllNodes()) {
if (node->GetType() == FILECONSTANT) {
index++;
}
}
if ((index == 0UL) && (!model_data.weight_path.empty())) {
GELOGE(FAILED, "Weight path[%s] should be empty if model has no external weight",
model_data.weight_path.c_str());
return FAILED;
}
return SUCCESS;
}
Status ModelHelper::LoadRootModel(const ge::ModelData &model_data) {
if (is_assign_model_) {
GELOGE(ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED, "[Load][RootModel]Model helper has already loaded!");
return ACL_ERROR_GE_EXEC_LOAD_MODEL_REPEATED;
}
GE_CHK_STATUS_RET(GetModelFileHead(model_data, file_header_), "[Get][ModelFileHead] failed.");
GE_ASSERT_TRUE(file_header_->modeltype != static_cast<uint8_t>(MODEL_TYPE_BUNDLE_MODEL),
"The bundle model does not support loading through non-bundle interfaces.");
is_unknown_shape_model_ = ModelParserBase::IsDynamicModel(*file_header_);
GELOGD("Cur om model is ge root model or no %d, model version %u, model num: %u.",
static_cast<int32_t>(is_unknown_shape_model_), file_header_->version, file_header_->model_num);
uint8_t *model_data_addr = nullptr;
uint64_t model_data_size = 0UL;
Status status = ModelParserBase::ParseModelContent(model_data, model_data_addr, model_data_size);
if (status != SUCCESS) {
GELOGE(ACL_ERROR_GE_PARAM_INVALID, "[Parse][RootModelContent]Failed!");
return ACL_ERROR_GE_PARAM_INVALID;
}
OmFileLoadHelper om_load_helper;
if (is_unknown_shape_model_) {
status = om_load_helper.Init(model_data_addr, model_data_size, file_header_->model_num, file_header_);
} else {
status = om_load_helper.Init(model_data_addr, model_data_size, file_header_);
}
if (status != SUCCESS) {
GELOGE(status, "[Init][OmLoadHelper]Failed");
model_data_addr = nullptr;
return status;
}
model_data_addr = nullptr;
GE_ASSERT_SUCCESS(GenerateGeRootModel(om_load_helper, model_data));
std::string file_constant_weight_dir;
GE_ASSERT_SUCCESS(CheckIfWeightPathValid(root_model_->GetRootGraph(), model_data));
GE_ASSERT_SUCCESS(FileConstantUtils::GetExternalWeightDir(model_data, file_constant_weight_dir));
root_model_->SetFileConstantWeightDir(file_constant_weight_dir);
GELOGD("In ModelHelper::LoadRootModel, is_assign_model_ is setted to true!");
is_assign_model_ = true;
if (is_repack_so_) {
GELOGD("ModelHelper::repack so!");
return SUCCESS;
}
if (CheckOsCpuInfoAndOppVersion() != SUCCESS) {
GELOGE(FAILED, "[Check][OsCpuOppVersion]Failed");
return FAILED;
}
return SUCCESS;
}
Status ModelHelper::GenerateGeModel(const OmFileLoadHelper &om_load_helper, GeModelPtr &cur_model,
GeModelPtr &first_ge_model, const size_t mode_index,
const bool is_dyn_root) const {
cur_model = MakeShared<GeModel>();
GE_CHECK_NOTNULL(cur_model);
Status ret = LoadModelData(om_load_helper, cur_model, first_ge_model, mode_index);
if (ret != SUCCESS) {
return ACL_ERROR_GE_EXEC_LOAD_MODEL_PARTITION_FAILED;
}
if (is_dyn_root && IsPartitionedGraph(cur_model)) {
first_ge_model = MakeShared<GeModel>();
GE_CHECK_NOTNULL(first_ge_model);
first_ge_model->SetGraph(cur_model->GetGraph());
first_ge_model->SetName(cur_model->GetName());
first_ge_model->SetVersion(cur_model->GetVersion());
first_ge_model->SetPlatformVersion(cur_model->GetPlatformVersion());
first_ge_model->SetAttrMap(cur_model->MutableAttrMap());
if (gert::GraphUnfolder::IsGraphNeedUnfold(cur_model->GetGraph())) {
return SUCCESS;
}
}
ret = LoadWeights(om_load_helper, cur_model, mode_index);
if (ret != SUCCESS) {
return ACL_ERROR_GE_EXEC_LOAD_WEIGHT_PARTITION_FAILED;
}
ret = LoadTask(om_load_helper, cur_model, mode_index);
if (ret != SUCCESS) {
return ACL_ERROR_GE_EXEC_LOAD_TASK_PARTITION_FAILED;
}
ret = LoadTBEKernelStore(om_load_helper, cur_model, mode_index);
if (ret != SUCCESS) {
return ACL_ERROR_GE_EXEC_LOAD_KERNEL_PARTITION_FAILED;
}
ret = LoadCustAICPUKernelStore(om_load_helper, cur_model, mode_index);
if (ret != SUCCESS) {
return ACL_ERROR_GE_EXEC_LOAD_KERNEL_PARTITION_FAILED;
}
return SUCCESS;
}
Status ModelHelper::GenerateGeRootModel(const OmFileLoadHelper &om_load_helper, const ModelData &model_data) {
GELOGD("Begin to generate ge root model");
root_model_ = MakeShared<GeRootModel>();
GE_CHECK_NOTNULL(root_model_);
GeModelPtr first_ge_model = nullptr;
if (!is_unknown_shape_model_) {
GE_CHK_STATUS_RET(GenerateGeModel(om_load_helper, model_, first_ge_model, 0U, false),
"[Generate][GERootModel]Failed");
GE_CHECK_NOTNULL(model_);
GE_ASSERT_SUCCESS(root_model_->Initialize(model_->GetGraph()));
root_model_->SetModelName(model_->GetName());
GE_CHK_STATUS_RET(LoadOpSoBin(om_load_helper, root_model_), "[Generate][LoadOpSoBin]Failed");
GE_CHK_STATUS_RET(LoadCustomOps(om_load_helper), "[Generate][LoadCustomOps]Failed");
GE_CHK_STATUS_RET(LoadTilingData(om_load_helper, root_model_), "[Generate][LoadTilingData]Failed");
root_model_->SetSubgraphInstanceNameToModel(model_->GetGraph()->GetName(), model_);
return SUCCESS;
}
for (size_t mode_index = 0U; mode_index < file_header_->model_num; ++mode_index) {
GeModelPtr cur_model;
GE_CHK_STATUS_RET_NOLOG(GenerateGeModel(om_load_helper, cur_model, first_ge_model, mode_index, mode_index == 0U));
GE_ASSERT_NOTNULL(cur_model->GetGraph());
if (mode_index == 0U) {
GE_ASSERT_SUCCESS(root_model_->Initialize(cur_model->GetGraph()));
root_model_->SetModelName(cur_model->GetName());
model_ = cur_model;
GE_CHK_STATUS_RET(LoadOpSoBin(om_load_helper, root_model_), "[Generate][LoadOpSoBin]Failed");
GE_CHK_STATUS_RET(LoadCustomOps(om_load_helper), "[Generate][LoadCustomOps]Failed");
GE_CHK_STATUS_RET(LoadTilingData(om_load_helper, root_model_), "[Generate][LoadTilingData]Failed");
if (IsPartitionedGraph(cur_model)) {
if (!gert::GraphUnfolder::IsGraphNeedUnfold(cur_model->GetGraph())) {
root_model_->SetSubgraphInstanceNameToModel(cur_model->GetGraph()->GetName(), cur_model);
}
continue;
}
}
cur_model->SetOmName(model_data.om_name);
root_model_->SetSubgraphInstanceNameToModel(cur_model->GetGraph()->GetName(), cur_model);
}
GE_ASSERT_SUCCESS(root_model_->ModifyOwnerGraphForSubModels());
return SUCCESS;
}
bool ModelHelper::IsPartitionedGraph(const GeModelPtr &cur_model) const {
bool is_partitioned = false;
const auto &root_graph = cur_model->GetGraph();
(void)AttrUtils::GetBool(root_graph, ATTR_NAME_DYNAMIC_SHAPE_PARTITIONED, is_partitioned);
return is_partitioned;
}
Status ModelHelper::SetModelToGeModel(const GeModelPtr &ge_model, const GeModelPtr &first_ge_model, Model &model) {
ge_model->SetGraph(model.GetGraph());
ge_model->SetName(model.GetName());
ge_model->SetVersion(model.GetVersion());
ge_model->SetPlatformVersion(model.GetPlatformVersion());
ge_model->SetAttrMap(model.MutableAttrMap());
if (first_ge_model != nullptr) {
GE_ASSERT_SUCCESS(ModelCompressManager::CpyModelAttrs2Dst(first_ge_model, ge_model));
}
GE_ASSERT_SUCCESS(ModelCompressManager::Decompress(ge_model));
if (first_ge_model != nullptr) {
ModelCompressManager::DeleteModelAttrs(ge_model);
}
return SUCCESS;
}
Status ModelHelper::LoadModelData(const OmFileLoadHelper &om_load_helper, const GeModelPtr &cur_model,
const GeModelPtr &first_ge_model, const size_t mode_index) const {
ModelPartition partition_model_def;
(void) om_load_helper.GetModelPartition(ModelPartitionType::MODEL_DEF, partition_model_def, mode_index);
GELOGD("Model_def partition addr:%p,size:%" PRIu64 "", partition_model_def.data, partition_model_def.size);
ge::Model model;
if (ge::Model::LoadWithMultiThread(partition_model_def.data,
static_cast<size_t>(partition_model_def.size), model) != SUCCESS) {
GELOGE(INTERNAL_ERROR, "[Load][Model]Failed, model_def partition addr:%p, size:%" PRIu64 "",
partition_model_def.data, partition_model_def.size);
REPORT_INNER_ERR_MSG("E19999", "Load model failed, model_def partition addr:%p, size:%" PRIu64 "",
partition_model_def.data, partition_model_def.size);
return INTERNAL_ERROR;
}
if ((mode_index == 0U) && !is_repack_so_) {
GE_ASSERT_SUCCESS(om_load_helper.CheckModelCompatibility(model), "Check model compatibility failed.");
}
GE_ASSERT_SUCCESS(SetModelToGeModel(cur_model, first_ge_model, model));
return SUCCESS;
}
Status ModelHelper::LoadWeights(const OmFileLoadHelper &om_load_helper, const GeModelPtr &cur_model,
const size_t mode_index) const {
ModelPartition partition;
if (om_load_helper.GetModelPartition(ModelPartitionType::WEIGHTS_DATA, partition, mode_index) != SUCCESS) {
GELOGE(FAILED, "[Get][ModelPartition]Failed, GetWeight size:%" PRIu64 "", partition.size);
REPORT_INNER_ERR_MSG("E19999", "[Get][ModelPartition]Failed, GetWeight size:%" PRIu64 "",
partition.size);
return FAILED;
}
if (is_shared_weight_) {
GELOGD("current weight is shared, size:%" PRIu64 "", partition.size);
DataBuffer weight_buf(const_cast<uint8_t *>(partition.data), static_cast<size_t>(partition.size));
cur_model->SetWeightDataBuf(weight_buf);
} else {
const ge::Buffer weight = ge::Buffer::CopyFrom(partition.data, static_cast<size_t>(partition.size));
cur_model->SetWeight(weight);
}
GELOGD("GetWeight size:%" PRIu64 "", partition.size);
return SUCCESS;
}
Status ModelHelper::LoadTask(const OmFileLoadHelper &om_load_helper, const GeModelPtr &cur_model,
const size_t mode_index) const {
ModelPartition task_partition;
if (om_load_helper.GetModelPartition(ModelPartitionType::TASK_INFO, task_partition, mode_index) != SUCCESS) {
GELOGE(FAILED, "Get task model partition failed.");
GELOGE(FAILED, "[Get][ModelTaskPartition]Failed, task_partition size %" PRIu64 ", mode_index %zu",
task_partition.size, mode_index);
REPORT_INNER_ERR_MSG("E19999", "Get model task partition failed, "
"task_partition size %" PRIu64 ", mode_index %zu", task_partition.size, mode_index);
return FAILED;
}
const std::shared_ptr<domi::ModelTaskDef> task = ge::MakeShared<domi::ModelTaskDef>();
GE_CHECK_NOTNULL(task);
if (task_partition.size != 0U) {
if (!ReadProtoFromArray(task_partition.data, static_cast<int32_t>(task_partition.size), task.get())) {
GELOGE(INTERNAL_ERROR, "[Read][ProtoFromArray]Failed, task_partition size %" PRIu64 "",
task_partition.size);
REPORT_INNER_ERR_MSG("E19999", "Read proto from array failed, task_partition size %" PRIu64 "",
task_partition.size);
return INTERNAL_ERROR;
}
GELOGD("TASK_INFO op_size:%d, stream_num:%u", task->op().size(), task->stream_num());
}
cur_model->SetModelTaskDef(task);
return SUCCESS;
}
Status ModelHelper::LoadTBEKernelStore(const OmFileLoadHelper &om_load_helper, const GeModelPtr &cur_model,
const size_t mode_index) const {
ModelPartition partition_kernel_def;
if (om_load_helper.GetModelPartition(ModelPartitionType::TBE_KERNELS, partition_kernel_def, mode_index) == SUCCESS) {
GELOGD("Kernels partition size:%" PRIu64 "", partition_kernel_def.size);
if (cur_model->LoadTBEKernelStore(partition_kernel_def.data, static_cast<size_t>(partition_kernel_def.size))) {
GELOGD("Load tbe kernels success");
} else {
GELOGW("Load tbe kernels unsuccessful");
}
}
return SUCCESS;
}
Status ModelHelper::LoadCustAICPUKernelStore(const OmFileLoadHelper &om_load_helper, const GeModelPtr &cur_model,
const size_t mode_index) const {
ModelPartition partition_kernel_def;
if (om_load_helper.GetModelPartition(ModelPartitionType::CUST_AICPU_KERNELS, partition_kernel_def, mode_index)
== SUCCESS) {
GELOGD("Kernels partition size:%" PRIu64 "", partition_kernel_def.size);
if (cur_model->LoadAICPUKernelStore(partition_kernel_def.data, partition_kernel_def.size)) {
GELOGD("Load cust aicpu kernels success");
} else {
GELOGW("Load cust aicpu kernels unsuccessful");
}
}
return SUCCESS;
}
Status ModelHelper::LoadOpSoBin(const OmFileLoadHelper &om_load_helper,
const GeRootModelPtr &ge_root_model) const {
ModelPartition partition_kernel_def;
if (om_load_helper.GetModelPartition(ModelPartitionType::SO_BINS, partition_kernel_def, 0U)
== SUCCESS) {
GELOGD("Kernels partition size:%" PRIu64 "", partition_kernel_def.size);
if (ge_root_model->LoadSoBinData(partition_kernel_def.data, partition_kernel_def.size)) {
auto root_graph = ge_root_model->GetRootGraph();
GE_ASSERT_NOTNULL(root_graph);
std::map<std::string, ge::OpSoBinPtr> bin_file_buffer;
auto all_so_bin = ge_root_model->GetAllSoBin();
std::vector<OpSoBinPtr> custom_op_so_bins;
for (const auto &op_so_bin_ptr : all_so_bin) {
if (op_so_bin_ptr == nullptr) {
continue;
}
if (op_so_bin_ptr->GetSoBinType() == SoBinType::kAutofuse) {
std::string so_path = op_so_bin_ptr->GetVendorName() + "/" + op_so_bin_ptr->GetSoName();
bin_file_buffer[so_path] = op_so_bin_ptr;
GELOGD("Added autofuse so_path:%s", so_path.c_str());
} else if (op_so_bin_ptr->GetSoBinType() == SoBinType::kCustomOp) {
custom_op_so_bins.emplace_back(op_so_bin_ptr);
}
}
if (!bin_file_buffer.empty()) {
root_graph->SetExtAttr<std::map<std::string, ge::OpSoBinPtr>>("bin_file_buffer", bin_file_buffer);
}
GE_ASSERT_SUCCESS(LoadCustomOpSoBins(custom_op_so_bins));
SaveOpSoInfo(ge_root_model);
GELOGD("Load so bin store success");
} else {
GELOGW("Load so bin store unsuccessful");
GE_ASSERT_TRUE(partition_kernel_def.size == 0U,
"Load so bin store failed when SO_BINS partition is non-empty, size:%" PRIu64,
partition_kernel_def.size);
}
}
return SUCCESS;
}
Status ModelHelper::LoadCustomOpSoBins(const std::vector<OpSoBinPtr> &custom_so_bins) const {
if (custom_so_bins.empty()) {
return SUCCESS;
}
GE_ASSERT_SUCCESS(CustomOpSoLoader::GetInstance().LoadCustomOpSoBins(custom_so_bins),
"Load custom op so bins from SO_BINS failed.");
return SUCCESS;
}
Status ModelHelper::LoadTilingData(const OmFileLoadHelper &om_load_helper, const GeRootModelPtr &ge_root_model) const {
ModelPartition partition_kernel_def;
(void)om_load_helper.GetModelPartition(ModelPartitionType::TILING_DATA, partition_kernel_def, 0U);
GELOGI("Tiling data partition size:%" PRIu64 "", partition_kernel_def.size);
if (partition_kernel_def.size > 0UL) {
GE_ASSERT_NOTNULL(ge_root_model->GetRootGraph());
const HostResourceCenterPtr &host_resource_center = ge_root_model->GetHostResourceCenterPtr();
GE_ASSERT_NOTNULL(host_resource_center);
GE_ASSERT_SUCCESS(HostResourceSerializer::DeSerializeTilingData(*host_resource_center, partition_kernel_def.data,
partition_kernel_def.size));
GE_ASSERT_SUCCESS(
HostResourceSerializer::RecoverOpRunInfoToExtAttrs(*host_resource_center, ge_root_model->GetRootGraph()));
}
return SUCCESS;
}
void ModelHelper::SaveOpSoInfo(const GeRootModelPtr &ge_root_model) const {
SoInOmInfo so_info;
(void) ge::AttrUtils::GetStr(*(model_.get()), "host_env_os", so_info.os_info);
(void) ge::AttrUtils::GetStr(*(model_.get()), "host_env_cpu", so_info.cpu_info);
(void) ge::AttrUtils::GetStr(*(model_.get()), ATTR_MODEL_OPP_VERSION, so_info.opp_version);
(void) ge::AttrUtils::GetStr(*(model_.get()), ATTR_MODEL_COMPILER_VERSION, so_info.compiler_version);
GELOGD("Save so info with host_env_os:%s, host_env_cpu:%s, opp_version:%s, compiler_version:%s",
so_info.os_info.c_str(), so_info.cpu_info.c_str(), so_info.opp_version.c_str(),
so_info.compiler_version.c_str());
ge_root_model->SetSoInOmInfo(so_info);
}
GeModelPtr ModelHelper::GetGeModel() {
if (model_ != nullptr) {
return model_;
}
GELOGD("Model has not been loaded!");
const std::shared_ptr<ge::GeModel> out_model = ge::MakeShared<ge::GeModel>();
if (out_model == nullptr) {
return nullptr;
}
return out_model;
}
GeRootModelPtr ModelHelper::GetGeRootModel() {
if (root_model_ != nullptr) {
return root_model_;
}
GELOGD("Model has not been loaded!");
const std::shared_ptr<ge::GeRootModel> out_model = ge::MakeShared<ge::GeRootModel>();
if (out_model == nullptr) {
return nullptr;
}
if (model_ != nullptr) {
const auto root_graph = model_->GetGraph();
if (root_graph != nullptr) {
GE_ASSERT_SUCCESS(out_model->Initialize(root_graph));
out_model->SetModelName(model_->GetName());
out_model->SetSubgraphInstanceNameToModel(root_graph->GetName(), model_);
}
}
return out_model;
}
Status ModelHelper::GetBaseNameFromFileName(const std::string &file_name, std::string &base_name) const {
GELOGD("Get base_name from file, file_name:%s", file_name.c_str());
if (file_name.empty()) {
GELOGW("File path may not valid, check params --output");
return FAILED;
}
size_t start_position = 0U;
size_t filename_suffixes = 0U;
if (file_name.find_last_of('.') != std::string::npos) {
filename_suffixes = file_name.length() - file_name.find_last_of('.');
}
if (file_name.find_last_of('/') != std::string::npos) {
start_position = file_name.find_last_of('/') + 1U;
}
const size_t end_position = file_name.length() - filename_suffixes;
base_name = file_name.substr(start_position, end_position - start_position);
if (base_name.empty()) {
GELOGW("Get base_name unsuccessful, check params --output");
return FAILED;
}
GELOGD("Get base_name from file success, base_name:%s", base_name.c_str());
return SUCCESS;
}
Status ModelHelper::GetHardwareInfo(std::map<std::string, std::string> &options) const {
int32_t device_id = -1;
(void)aclrtGetDevice(&device_id);
const auto iter = options.find(SOC_VERSION);
GE_ASSERT_TRUE(iter != options.end());
const auto soc_version = iter->second;
fe::PlatformInfo platform_info;
int32_t virtual_type = 0;
GE_CHK_STATUS_RET(GetPlatformInfo(device_id, soc_version, platform_info, virtual_type, options),
"Get platform info failed, device id: %d, soc_version: %s.", device_id, soc_version.c_str());
fe::PlatFormInfos platform_infos;
GE_CHK_STATUS_RET(SetPlatformInfos(soc_version, platform_info, platform_infos), "Set platform infos failed.");
std::stringstream platform_option;
platform_option << "ai_core_cnt:" << std::to_string(platform_info.soc_info.ai_core_cnt)
<< ";cube_core_cnt:" << std::to_string(platform_info.soc_info.ai_core_cnt)
<< ";vector_core_cnt:" << std::to_string(platform_info.soc_info.vector_core_cnt)
<< ";l2_size:" << std::to_string(platform_info.soc_info.l2_size)
<< ";memory_size:" << std::to_string(platform_info.soc_info.memory_size);
(void)options.emplace(std::make_pair(kHardwareInfo, platform_option.str()));
GELOGI("Soc_version: %s, set attr %s, value: %s.", soc_version.c_str(), kHardwareInfo.c_str(), platform_option.str().c_str());
if (virtual_type > 0) {
(void)options.emplace(std::make_pair(VIRTUAL_TYPE, std::to_string(virtual_type)));
GELOGI("Set attr %s, value: %d.", VIRTUAL_TYPE.c_str(), virtual_type);
}
return SUCCESS;
}
Status ModelHelper::InitRuntimePlatform() {
int32_t device_id = -1;
GE_CHK_RT_RET(aclrtGetDevice(&device_id));
const char *soc_version = aclrtGetSocName();
GE_ASSERT_NOTNULL(soc_version);
GE_ASSERT_TRUE(fe::PlatformInfoManager::GeInstance().InitRuntimePlatformInfos(std::string(soc_version)) == 0U,
"[Init][PlatformInfo]init runtime platform info failed, SocVersion = %s", soc_version);
int64_t aicore_num = 0;
GE_ASSERT_RT_OK(aclrtGetDeviceInfo(static_cast<uint32_t>(device_id), ACL_DEV_ATTR_AICORE_CORE_NUM, &aicore_num));
int64_t vec_core_num = 0U;
GE_ASSERT_RT_OK(aclrtGetDeviceInfo(static_cast<uint32_t>(device_id), ACL_DEV_ATTR_VECTOR_CORE_NUM, &vec_core_num));
fe::PlatFormInfos platform_infos;
GE_ASSERT_TRUE(
fe::PlatformInfoManager::GeInstance().GetRuntimePlatformInfosByDevice(device_id, platform_infos) == 0,
"Get runtime platformInfos by device failed, deviceId = %d", device_id);
std::map<std::string, std::string> res;
GE_ASSERT_TRUE(platform_infos.GetPlatformResWithLock(kSocInfoKey, res));
res[kAicCntKey] = std::to_string(aicore_num);
res[kVecCoreCntKey] = std::to_string(vec_core_num);
platform_infos.SetPlatformResWithLock(kSocInfoKey, res);
GE_ASSERT_TRUE(
fe::PlatformInfoManager::GeInstance().UpdateRuntimePlatformInfosByDevice(device_id, platform_infos) == 0U,
"Update runtime platformInfos by device failed, deviceId = %d", device_id);
return SUCCESS;
}
Status ModelHelper::InitRuntimeAndGetDevicePlatformInfos(int32_t device_id, const std::string &soc_version,fe::PlatFormInfos &platform_infos_device) const {
GE_ASSERT_TRUE(fe::PlatformInfoManager::GeInstance().InitRuntimePlatformInfos(soc_version) == 0U,
"[Init][PlatformInfo]init runtime platform info failed, SocVersion = %s", soc_version.c_str());
GE_ASSERT_TRUE(fe::PlatformInfoManager::GeInstance().GetRuntimePlatformInfosByDevice(static_cast<uint32_t>(device_id), platform_infos_device, true) == 0,
"Get runtime platformInfos by device failed, deviceId = %d", device_id);
return SUCCESS;
}
Status ModelHelper::HandleDeviceInfo(fe::PlatFormInfos &platform_infos) const {
fe::PlatformInfo platform_info;
return HandleDeviceInfo(platform_infos, platform_info);
}
Status ModelHelper::HandleDeviceInfo(fe::PlatFormInfos &platform_infos, fe::PlatformInfo &origin_platform_info) const {
GELOGD("Begin to handle device info.");
int32_t device_id = -1;
GE_CHK_RT_RET(aclrtGetDevice(&device_id));
const char *soc_version = aclrtGetSocName();
GE_ASSERT_NOTNULL(soc_version);
GE_ASSERT_SUCCESS(CoreNumUtils::GetGeDefaultPlatformInfo(soc_version, origin_platform_info));
fe::PlatformInfo platform_info;
int32_t virtual_type = 0;
GE_CHK_STATUS_RET(GetPlatformInfo(device_id, soc_version, platform_info, virtual_type), "Get platform info failed.");
GE_CHK_STATUS_RET(SetPlatformInfos(soc_version, platform_info, platform_infos), "Set platform infos failed.");
GELOGD("Succeed to handle device info, device id: %d, soc_version: %s, virtual_type: %d.", device_id, soc_version,
virtual_type);
return SUCCESS;
}
Status ModelHelper::GetPlatformInfo(int32_t device_id, const std::string &soc_version,
fe::PlatformInfo &platform_info, int32_t &virtual_type) const {
std::map<std::string, std::string> options;
return GetPlatformInfo(device_id, soc_version, platform_info, virtual_type, options);
}
Status ModelHelper::GetPlatformInfo(int32_t device_id, const std::string &soc_version,
fe::PlatformInfo &platform_info, int32_t &virtual_type,
std::map<std::string, std::string> &options) const {
#ifdef __GNUC__
GE_ASSERT_SUCCESS(CoreNumUtils::GetGeDefaultPlatformInfo(soc_version, platform_info));
#endif
const uint32_t aicore_cnt_ini = platform_info.soc_info.ai_core_cnt;
const uint32_t vec_core_cnt_ini = platform_info.soc_info.vector_core_cnt;
fe::PlatFormInfos platformInfos_device;
GE_CHK_STATUS_RET(InitRuntimeAndGetDevicePlatformInfos(device_id, soc_version, platformInfos_device));
GE_CHK_STATUS_RET(UpdatePlatfromInfoWithRuntime(device_id, aicore_cnt_ini, vec_core_cnt_ini, platform_info,
virtual_type));
GE_CHK_STATUS_RET(UpdatePlatfromInfoWithDevice(platformInfos_device, aicore_cnt_ini, vec_core_cnt_ini, platform_info));
GE_CHK_STATUS_RET(UpdatePlatfromInfoWithOption(options, aicore_cnt_ini, vec_core_cnt_ini, platform_info));
GELOGI("Get platform info of device id: %d, aicore num: %u, vector core num: %u, l2size: %u bytes, memory_size: "
"%zu bytes, virtual_type: %d.", device_id, platform_info.soc_info.ai_core_cnt, platform_info.soc_info.vector_core_cnt,
platform_info.soc_info.l2_size, platform_info.soc_info.memory_size, virtual_type);
return SUCCESS;
}
Status ModelHelper::UpdatePlatfromInfoWithOption(std::map<std::string, std::string> &options, const uint32_t ai_core_cnt_ini,
const uint32_t vector_core_cnt_ini, fe::PlatformInfo &platform_info) const {
GE_CHK_STATUS_RET(UpdateCoreCountWithOption(AICORE_NUM, AICORE_NUM, ai_core_cnt_ini,
platform_info.soc_info.ai_core_cnt, options));
GE_CHK_STATUS_RET(UpdateCoreCountWithOption(kVectorCoreNum, kVectorCoreNum, vector_core_cnt_ini,
platform_info.soc_info.vector_core_cnt, options));
return SUCCESS;
}
Status ModelHelper::UpdatePlatfromInfoWithDevice(fe::PlatFormInfos &platformInfos_device, const uint32_t ai_core_cnt_ini,
const uint32_t vector_core_cnt_ini, fe::PlatformInfo &platform_info) const {
std::map<std::string, std::string> res;
(void)platformInfos_device.GetPlatformResWithLock(kSocInfoKey, res);
std::string aicore_num_device = res[kAicCntKey];
std::string vec_core_num_device = res[kVecCoreCntKey];
GELOGI("Get platform info from device, aicore_num: %s, vector_core_num: %s.",
aicore_num_device.c_str(), vec_core_num_device.c_str());
GE_CHK_STATUS_RET(UpdateCoreCountWithDevice(kEnumNameCubeNum, ai_core_cnt_ini, aicore_num_device,
platform_info.soc_info.ai_core_cnt));
GE_CHK_STATUS_RET(UpdateCoreCountWithDevice(kEnumNameVectorNum, vector_core_cnt_ini, vec_core_num_device,
platform_info.soc_info.vector_core_cnt));
return SUCCESS;
}
Status ModelHelper::UpdatePlatfromInfoWithRuntime(const int32_t device_id, const uint32_t ai_core_cnt_ini, const uint32_t vector_core_cnt_ini,
fe::PlatformInfo &platform_info, int32_t &virtual_type) const {
if (device_id < 0) {
GELOGI("Offline scene, skip update platform info from runtime.");
return SUCCESS;
}
int64_t aic_core_cnt = 0;
if (aclrtGetDeviceInfo(static_cast<uint32_t>(device_id), ACL_DEV_ATTR_AICORE_CORE_NUM, &aic_core_cnt) != ACL_SUCCESS) {
GELOGE(FAILED, "Failed to get AICore count from device.");
return FAILED;
}
if (static_cast<uint32_t>(aic_core_cnt) < ai_core_cnt_ini) {
virtual_type = 1;
}
int64_t vector_core_cnt = kModuleTypeVectorCore;
(void)aclrtGetDeviceInfo(static_cast<uint32_t>(device_id), ACL_DEV_ATTR_VECTOR_CORE_NUM, &vector_core_cnt);
UpdateCoreCountWithRuntime(AICORE_NUM, ai_core_cnt_ini, aic_core_cnt,
platform_info.soc_info.ai_core_cnt);
UpdateCoreCountWithRuntime(kVectorCoreNum, vector_core_cnt_ini, vector_core_cnt,
platform_info.soc_info.vector_core_cnt);
size_t free_mem = 0U;
size_t total_mem_size = 0U;
if (aclrtGetMemInfo(ACL_HBM_MEM, &free_mem, &total_mem_size) == ACL_SUCCESS) {
GELOGI("Change memory_size from platform %lu to rts %zu bytes.",
platform_info.soc_info.memory_size, total_mem_size);
platform_info.soc_info.memory_size = total_mem_size;
}
return SUCCESS;
}
Status ModelHelper::SetPlatformInfos(const std::string &soc_version, const fe::PlatformInfo &platform_info,
fe::PlatFormInfos &platform_infos) const {
#ifdef __GNUC__
fe::OptionalInfos optional_infos;
if (fe::PlatformInfoManager::GeInstance().GetPlatformInfos(soc_version, platform_infos, optional_infos) != 0) {
GELOGE(FAILED, "Unable to get platform info of soc_version: %s.", soc_version.c_str());
return FAILED;
}
std::map<std::string, std::string> res;
if (!platform_infos.GetPlatformResWithLock("SoCInfo", res)) {
GELOGE(FAILED, "Unable to get platform info.");
return FAILED;
}
res["ai_core_cnt"] = std::to_string(platform_info.soc_info.ai_core_cnt);
res["cube_core_cnt"] = std::to_string(platform_info.soc_info.ai_core_cnt);
res["vector_core_cnt"] = std::to_string(platform_info.soc_info.vector_core_cnt);
res["l2_size"] = std::to_string(platform_info.soc_info.l2_size);
res["memory_size"] = std::to_string(platform_info.soc_info.memory_size);
GELOGD("Begin to update platform infos, aicore_cnt: %d, vector_core_cnt: %d, cube_core_cnt: %s, l2_size: %d, memory_size: %d",
platform_info.soc_info.ai_core_cnt, platform_info.soc_info.vector_core_cnt, res["cube_core_cnt"].c_str(),
platform_info.soc_info.l2_size, platform_info.soc_info.memory_size);
platform_infos.SetPlatformResWithLock("SoCInfo", res);
GE_ASSERT_TRUE(fe::PlatformInfoManager::GeInstance().UpdatePlatformInfos(soc_version, platform_infos) == 0U, "Update platform infos of GeInstance failed.");
GE_ASSERT_TRUE(fe::PlatformInfoManager::Instance().InitializePlatformInfo() == 0U, "Initialize platform info of Instance failed.");
GE_ASSERT_TRUE(fe::PlatformInfoManager::Instance().UpdatePlatformInfos(soc_version, platform_infos) == 0U, "Update platform infos of Instance failed.");
#endif
return SUCCESS;
}
void ModelHelper::SetRepackSoFlag(const bool val) {
is_repack_so_ = val;
}
Status ModelHelper::PackSoToModelData(const ModelData &model_data, const std::string &output_file,
ModelBufferData &model_buffer, const bool save_to_file) {
GE_ASSERT_NOTNULL(root_model_);
const auto &compute_graph = root_model_->GetRootGraph();
GE_CHECK_NOTNULL(compute_graph);
GE_CHK_STATUS_RET(FileConstantUtils::ChangeFilePath(compute_graph, output_file),
"Failed to change file path, graph name:%s", compute_graph->GetName().c_str());
save_to_file_ = save_to_file;
is_offline_ = true;
GE_ASSERT_SUCCESS(root_model_->CheckAndSetNeedSoInOM(), "Check so in om failed, model id:%u.",
root_model_->GetModelId());
if (root_model_->GetSoInOmFlag() == 0U) {
if (save_to_file) {
const Status ret =
FileSaver::SaveToFile(output_file, static_cast<void *>(model_data.model_data), model_data.model_len);
if (ret == SUCCESS) {
FileSaver::PrintModelSaveLog();
}
return ret;
} else {
model_buffer.length = model_data.model_len;
model_buffer.data = std::shared_ptr<uint8_t>(PtrToPtr<void, uint8_t>(model_data.model_data),
[](const uint8_t *const pointer) { (void)pointer; });
return SUCCESS;
}
}
const auto &root_graph = root_model_->GetRootGraph();
GE_ASSERT_NOTNULL(root_graph);
if (gert::GraphUnfolder::IsGraphNeedUnfold(root_graph)) {
const auto root_ge_model = GetGeModel();
root_model_->SetSubgraphInstanceNameToModel(root_graph->GetName(), root_ge_model);
}
GE_ASSERT_SUCCESS(SaveToOmRootModel(root_model_, output_file, model_buffer, is_unknown_shape_model_),
"SaveToOmRootModel fail");
GELOGD("SaveToOmRootModel success.");
return SUCCESS;
}
Status ModelHelper::EnsureKernelBuilt(const GeModelPtr &model) {
if (model->GetTBEKernelStore().DataSize() == 0U) {
TBEKernelStore tbe_kernel_store = model->GetTBEKernelStore();
GE_CHK_BOOL_RET_STATUS(tbe_kernel_store.Build(), FAILED, "tbe_kernel_store build failed, model=%s.",
model->GetName().c_str());
model->SetTBEKernelStore(tbe_kernel_store);
}
if (model->GetCustAICPUKernelStore().DataSize() == 0U) {
CustAICPUKernelStore cust_aicpu_kernel_store = model->GetCustAICPUKernelStore();
GE_CHK_BOOL_RET_STATUS(cust_aicpu_kernel_store.Build(), FAILED, "cust_aicpu_kernel_store build failed, model=%s.",
model->GetName().c_str());
model->SetCustAICPUKernelStore(cust_aicpu_kernel_store);
}
return SUCCESS;
}
REGISTER_MODEL_SAVE_HELPER(OM_FORMAT_DEFAULT, ModelHelper);
Status ModelHelper::UpdateCoreCountWithOption(const std::string &key, const std::string &context_key, uint32_t core_num_ini,
uint32_t &platform_info_count, std::map<std::string, std::string> &options) const {
std::string core_num_str;
auto iter = options.find(key);
if (iter != options.end()) {
core_num_str = iter->second;
GELOGI("%s in options, value: [%s].", key.c_str(), core_num_str.c_str());
} else {
(void)GetThreadLocalContext().GetOption(context_key, core_num_str);
GELOGI("%s in ThreadLocalContext, value: [%s].", context_key.c_str(), core_num_str.c_str());
}
int32_t core_num = -1;
if (!core_num_str.empty()) {
GE_CHK_STATUS_RET(CoreNumUtils::ParseAndValidateCoreNum(ge::GetContext().GetReadableName(AICORE_NUM), core_num_str, 0, core_num_ini, core_num));
}
if (core_num > 0) {
GELOGI("Change %s from platform %u to option %d.", key.c_str(), core_num_ini, core_num);
platform_info_count = static_cast<uint32_t>(core_num);
}
return SUCCESS;
}
Status ModelHelper::UpdateCoreCountWithDevice(const std::string &key, uint32_t core_num_ini,
const std::string &core_num_str, uint32_t &platform_info_count) const {
int32_t core_num = -1;
if (!core_num_str.empty()) {
GE_CHK_STATUS_RET(CoreNumUtils::ParseAndValidateCoreNum(ge::GetContext().GetReadableName(AICORE_NUM), core_num_str, 0, core_num_ini, core_num));
}
if (core_num > 0) {
GELOGI("Change %s from platform %u to device %d.", key.c_str(), core_num_ini, core_num);
platform_info_count = static_cast<uint32_t>(core_num);
}
return SUCCESS;
}
void ModelHelper::UpdateCoreCountWithRuntime(const std::string &key, uint32_t platform_count, const int64_t core_num_rts,
uint32_t &platform_info_count) const {
GELOGI("Change %s from platform %u to rts %ld.", key.c_str(), platform_count, core_num_rts);
platform_info_count = static_cast<uint32_t>(core_num_rts);
}
Status ModelHelper::UpdateGeRootModelTaskAddr(const GeRootModelPtr &ge_root_model,
const ComputeGraphPtr &root_graph,
std::set<ComputeGraph *> &refreshed_graphs,
const bool is_cache) {
GE_ASSERT_NOTNULL(root_graph);
GE_ASSERT_NOTNULL(ge_root_model);
std::map<int64_t, int64_t> logical_addr_mapping;
const auto session_id = root_graph->GetSessionID();
GE_CHK_STATUS_RET(
RefreshAndGetAddrMapping(root_graph, session_id, is_cache, logical_addr_mapping, refreshed_graphs),
"Refresh and get addr mapping in submodel graph failed. graph name %s", root_graph->GetName().c_str());
GE_CHK_STATUS_RET(UpdateModelTaskAddr(ge_root_model, session_id, logical_addr_mapping, refreshed_graphs));
return SUCCESS;
}
Status ModelHelper::RefreshAndGetAddrMapping(const ComputeGraphPtr &graph, const uint64_t session_id,
const bool is_cache,
std::map<int64_t, int64_t> &logical_addr_mapping,
std::set<ComputeGraph *> &refreshed_graphs) {
if (refreshed_graphs.find(graph.get()) != refreshed_graphs.cend()) {
GELOGI("graph[%s] has been refreshed, no need refresh again", graph->GetName().c_str());
return SUCCESS;
}
std::map<int64_t, NodePtr> unrefreshed_offsets;
for (const auto &node : graph->GetAllNodes()) {
const auto &node_type = node->GetType();
GE_CHK_BOOL_RET_STATUS((is_cache || !OpTypeUtils::IsVariableNode(node_type)), FAILED,
"Variable in om is not supported in current version. Node %s is variable.",
node->GetName().c_str());
if ((node_type == VARIABLE) || (node_type == CONSTANTOP) || (node_type == FILECONSTANT)) {
const auto &op_desc = node->GetOpDesc();
GE_CHECK_NOTNULL(op_desc);
const auto &output_offsets = op_desc->GetOutputOffset();
GE_CHK_BOOL_RET_STATUS(!output_offsets.empty(), FAILED, "Node:%s output offsets is empty",
node->GetName().c_str());
(void) unrefreshed_offsets.emplace(output_offsets[0U], node);
if (node_type == VARIABLE) {
const auto &name = node->GetName();
const auto pos = name.find(kMultiBatchNodePostfix);
if (pos != std::string::npos) {
VarManager::Instance(session_id)->SetBatchVariablesKeyName(name, name.substr(0, pos));
}
}
}
}
NodeRefreshInfo inputs_need_refresh;
NodeRefreshInfo outputs_need_refresh;
GE_CHK_STATUS_RET(RecordOffsetsRefreshInfo(graph, unrefreshed_offsets, inputs_need_refresh, outputs_need_refresh),
"Failed to record nodes need refresh offsets in graph:%s", graph->GetName().c_str());
GE_CHK_STATUS_RET(VarMemAssignUtil::AssignConstantOpMemory(graph),
"assign constant op memory failed, graph_name=%s.", graph->GetName().c_str());
GE_CHK_STATUS_RET(RefreshNodeOffset(inputs_need_refresh, outputs_need_refresh, logical_addr_mapping),
"Failed to refresh node offset in graph:%s", graph->GetName().c_str());
(void)refreshed_graphs.emplace(graph.get());
return SUCCESS;
}
Status ModelHelper::RecordOffsetsRefreshInfo(const ComputeGraphPtr &graph,
const std::map<int64_t, NodePtr> &unrefreshed_offsets,
NodeRefreshInfo &inputs_need_refresh,
NodeRefreshInfo &outputs_need_refresh) {
for (const auto &node : graph->GetAllNodes()) {
const auto &op_desc = node->GetOpDesc();
GE_CHECK_NOTNULL(op_desc);
const auto &input_offsets = op_desc->GetInputOffset();
const auto &input_descs = op_desc->GetAllInputsDescPtr();
GE_CHK_BOOL_RET_STATUS(input_offsets.size() <= input_descs.size(), PARAM_INVALID,
"number of input offsets(%zu) mismatches that of input tensor descs'(%zu)",
input_offsets.size(), input_descs.size());
for (size_t i = 0U; i < input_offsets.size(); ++i) {
auto offset = input_offsets[i];
int64_t inner_offset = 0;
(void) ge::AttrUtils::GetInt(input_descs.at(i), ATTR_NAME_INNER_OFFSET, inner_offset);
GELOGD("Node[%s] input[%zu], offset = %ld, inner_offset = %ld, raw_offset = %ld",
op_desc->GetName().c_str(), i, inner_offset, offset, offset - inner_offset);
GE_ASSERT_SUCCESS(CheckInt64SubOverflow(offset, inner_offset));
offset -= inner_offset;
const auto &var_node = TryGetVarNodeByOffset(unrefreshed_offsets, offset);
if ((var_node == nullptr) || (var_node == node)) {
continue;
}
(void)inputs_need_refresh[var_node][node].emplace_back(i, inner_offset);
GELOGI("Find node:%s input offset:%zu use var:%s offset:%ld", node->GetName().c_str(), i,
var_node->GetName().c_str(), offset);
}
const auto &output_offsets = op_desc->GetOutputOffset();
GE_CHECK_LE(output_offsets.size(), std::numeric_limits<uint32_t>::max());
for (size_t i = 0U; i < output_offsets.size(); ++i) {
auto offset = output_offsets[i];
int64_t inner_offset = 0;
(void) ge::AttrUtils::GetInt(op_desc->GetOutputDesc(static_cast<uint32_t>(i)),
ATTR_NAME_INNER_OFFSET, inner_offset);
GELOGD("Node[%s] output[%zu], offset = %ld, inner_offset = %ld, raw_offset = %ld",
op_desc->GetName().c_str(), i, offset, inner_offset, offset - inner_offset);
GE_ASSERT_SUCCESS(CheckInt64SubOverflow(offset, inner_offset));
offset -= inner_offset;
const auto &var_node = TryGetVarNodeByOffset(unrefreshed_offsets, offset);
if ((var_node == nullptr) || (var_node == node)) {
continue;
}
(void)outputs_need_refresh[var_node][node].emplace_back(i, inner_offset);
GELOGI("Find node:%s output offset:%zu use var:%s offset:%ld", node->GetName().c_str(), i,
var_node->GetName().c_str(), offset);
}
}
GELOGI("Success to record offsets refresh info of graph:%s", graph->GetName().c_str());
return SUCCESS;
}
Status ModelHelper::RefreshNodeOffset(const NodeRefreshInfo &inputs_need_refresh,
const NodeRefreshInfo &outputs_need_refresh,
std::map<int64_t, int64_t> &logical_addr_mapping) {
for (const auto &item : inputs_need_refresh) {
const auto &var_node = item.first;
const auto &var_output_offsets = var_node->GetOpDesc()->GetOutputOffset();
GE_CHK_BOOL_RET_STATUS(!var_output_offsets.empty(), FAILED, "Failed to get output offset of node:%s",
var_node->GetName().c_str());
const int64_t var_offset = var_node->GetOpDesc()->GetOutputOffset()[0U];
for (const auto &node_to_refresh_inputs : item.second) {
const auto &refresh_node = node_to_refresh_inputs.first;
std::vector<int64_t> input_offsets = refresh_node->GetOpDesc()->GetInputOffset();
for (const auto &index_and_inner_offset : node_to_refresh_inputs.second) {
const size_t index = index_and_inner_offset.first;
const int64_t inner_offset = index_and_inner_offset.second;
GE_CHK_BOOL_RET_STATUS((index < input_offsets.size()), FAILED,
"Node:%s input index:%zu is out of range, output size:%zu",
refresh_node->GetName().c_str(), index, input_offsets.size());
const auto orig_input_offset = input_offsets[index];
GE_ASSERT_SUCCESS(CheckInt64AddOverflow(var_offset, inner_offset));
const int64_t new_input_offset = var_offset + inner_offset;
if (new_input_offset != orig_input_offset) {
input_offsets[index] = new_input_offset;
GELOGI("Node:%s input:[%zu] offset use var offset:%ld",
refresh_node->GetName().c_str(),
index,
new_input_offset);
logical_addr_mapping[orig_input_offset] = new_input_offset;
GELOGD("mapping [%ld] to [%ld]", orig_input_offset, new_input_offset);
}
}
refresh_node->GetOpDesc()->SetInputOffset(input_offsets);
}
}
for (const auto &item : outputs_need_refresh) {
const auto &var_node = item.first;
const auto &var_output_offsets = var_node->GetOpDesc()->GetOutputOffset();
GE_CHK_BOOL_RET_STATUS(!var_output_offsets.empty(), FAILED, "Failed to get output offset of node:%s",
var_node->GetName().c_str());
const int64_t var_offset = var_node->GetOpDesc()->GetOutputOffset()[0U];
for (const auto &node_to_refresh_outputs : item.second) {
const auto &refresh_node = node_to_refresh_outputs.first;
std::vector<int64_t> output_offsets = refresh_node->GetOpDesc()->GetOutputOffset();
for (const auto &index_and_inner_offset : node_to_refresh_outputs.second) {
const size_t index = index_and_inner_offset.first;
const int64_t inner_offset = index_and_inner_offset.second;
GE_CHK_BOOL_RET_STATUS((index < output_offsets.size()), FAILED,
"Node:%s output index:%zu is out of range, output size:%zu",
refresh_node->GetName().c_str(), index, output_offsets.size());
const auto orig_output_offset = output_offsets[index];
GE_ASSERT_SUCCESS(CheckInt64AddOverflow(var_offset, inner_offset));
const int64_t new_output_offset = var_offset + inner_offset;
if (new_output_offset != orig_output_offset) {
output_offsets[index] = new_output_offset;
GELOGI("Node:%s output:[%zu] offset use var offset:%ld",
refresh_node->GetName().c_str(),
index,
new_output_offset);
logical_addr_mapping[orig_output_offset] = new_output_offset;
GELOGD("mapping [%ld] to [%ld]", output_offsets[index], new_output_offset);
}
}
refresh_node->GetOpDesc()->SetOutputOffset(output_offsets);
}
}
return SUCCESS;
}
Status ModelHelper::UpdateModelTaskAddr(const GeRootModelPtr &ge_root_model, const uint64_t session_id,
const std::map<int64_t, int64_t> &logical_addr_mapping,
std::set<ComputeGraph *> &refreshed_graphs) {
GE_ASSERT_NOTNULL(ge_root_model);
for (auto &name_and_model : ge_root_model->GetSubgraphInstanceNameToModel()) {
const auto &ge_model = name_and_model.second;
GE_ASSERT_NOTNULL(ge_model);
auto model_task_def = ge_model->GetModelTaskDefPtr();
if (model_task_def != nullptr) {
for (int32_t task_idx = 0; task_idx < model_task_def->task_size(); ++task_idx) {
auto *task_def = model_task_def->mutable_task(task_idx);
if (static_cast<ModelTaskType>(task_def->type()) == ModelTaskType::MODEL_TASK_FFTS_PLUS) {
UpdateFftsPlusTaskAddr(*task_def, logical_addr_mapping);
}
}
}
const auto model_graph = ge_model->GetGraph();
GE_ASSERT_NOTNULL(model_graph);
std::map<int64_t, int64_t> useless_mapping;
GE_CHK_STATUS_RET(RefreshAndGetAddrMapping(model_graph, session_id, true, useless_mapping, refreshed_graphs),
"Refresh and get addr mapping in ge model graph failed. graph name %s", model_graph->GetName().c_str());
}
return SUCCESS;
}
Status ModelHelper::UpdateSessionGraphId(const ComputeGraphPtr &graph,
const std::string &session_graph_id,
bool &refreshed) {
GE_CHECK_NOTNULL(graph);
std::string value;
const std::string* value_ptr = AttrUtils::GetStr(*graph, ATTR_NAME_SESSION_GRAPH_ID);
if (value_ptr != nullptr) {
value = *value_ptr;
if (value == session_graph_id) {
GELOGD("graph[%s] session graph id is same, no need update.", graph->GetName().c_str());
return SUCCESS;
}
}
refreshed = true;
GELOGI("need update graph[%s] session graph id from %s to %s.", graph->GetName().c_str(), value.c_str(),
session_graph_id.c_str());
GE_CHK_BOOL_RET_STATUS(AttrUtils::SetStr(*graph, ATTR_NAME_SESSION_GRAPH_ID, session_graph_id), FAILED,
"Set ATTR_NAME_SESSION_GRAPH_ID[%s] failed for graph:%s", session_graph_id.c_str(),
graph->GetName().c_str());
for (const auto &node : graph->GetDirectNode()) {
const auto &opdesc = node->GetOpDesc();
GE_CHECK_NOTNULL(opdesc);
const std::string* op_session_graph_id = AttrUtils::GetStr(opdesc, ATTR_NAME_SESSION_GRAPH_ID);
if (op_session_graph_id != nullptr && (*op_session_graph_id != session_graph_id)) {
GE_CHK_BOOL_RET_STATUS(AttrUtils::SetStr(opdesc, ATTR_NAME_SESSION_GRAPH_ID, session_graph_id), FAILED,
"Set ATTR_NAME_SESSION_GRAPH_ID[%s] failed for op:%s", session_graph_id.c_str(),
opdesc->GetName().c_str());
}
}
for (const auto &subgraph : graph->GetAllSubgraphs()) {
GE_CHK_BOOL_RET_STATUS(AttrUtils::SetStr(*subgraph, ATTR_NAME_SESSION_GRAPH_ID, session_graph_id), FAILED,
"Set ATTR_NAME_SESSION_GRAPH_ID[%s] failed for graph:%s", session_graph_id.c_str(),
subgraph->GetName().c_str());
}
return SUCCESS;
}
ModelSaveHelperFactory &ModelSaveHelperFactory::Instance() {
static ModelSaveHelperFactory instance;
return instance;
}
}