* Copyright (c) 2026 Huawei Technologies Co., Ltd.
* This program is free software, you can redistribute it and/or modify it under the terms and conditions of
* CANN Open Software License Agreement Version 2.0 (the "License").
* Please refer to the License for details. You may not use this file except in compliance with the License.
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
* See LICENSE in the root of the software repository for the full text of the License.
*/
#include <cinttypes>
#include <string>
#include <fstream>
#include <regex>
#include <sys/syscall.h>
#include <unistd.h>
#include "acl/acl_rt.h"
#include "registry/op_impl_space_registry_v2.h"
#include "framework/runtime/rt_session.h"
#include "framework/runtime/dump/model_dump_manager.h"
#include "framework/common/framework_types_internal.h"
#include "runtime/om2_model_executor.h"
#include "common/checker.h"
#include "mmpa/mmpa_api.h"
#include "../../inc/framework/runtime/om2_context.h"
#include "graph/utils/type_utils_inner.h"
#include "graph_metadef/common/ge_common/util.h"
#include "runtime/mem.h"
#include "common/helper/om2/json_file.h"
#include "common/compile_profiling/ge_call_wrapper.h"
#include "file_const_loader.h"
#include "om2_external_weight_manager.h"
#include "om2_file_utils.h"
#include "om2_malloc_helper.h"
#include "om2_var_manager.h"
#include "zip_archive_reader.h"
namespace gert {
namespace {
constexpr size_t kMaxErrorStringLen = 128U;
constexpr size_t FILE_MAGIC_HEADER_SIZE = 4U;
constexpr uint8_t OM2_MAGIC[] = {0x50, 0x4B, 0x03, 0x04};
using Om2ModelHandle = void *;
using CreateFunc = ge::graphStatus (*)(Om2ModelHandle *, rtModel_t *, const char **, const void **, size_t *, int,
void **, void *, uint64_t *, uint32_t, void *);
using LoadFunc = ge::graphStatus (*)(Om2ModelHandle *);
using DestroyFunc = ge::graphStatus (*)(Om2ModelHandle *);
using RunFunc = ge::graphStatus (*)(Om2ModelHandle *, int, void **, int, void **, int32_t streamSyncTimeout);
using RunAsyncFunc = ge::graphStatus (*)(Om2ModelHandle *, rtStream_t, int, void **, int, void **);
struct RunModelInfo {
std::string so_file;
int32_t so_fd = -1;
ge::JsonFile op_attr_json;
void *so_handle = nullptr;
std::string model_name;
std::string root_graph_name;
Om2ModelHandle model_handle = nullptr;
rtModel_t rt_model_handle = nullptr;
CreateFunc create_func = nullptr;
LoadFunc load_func = nullptr;
DestroyFunc destroy_func = nullptr;
RunFunc run_func = nullptr;
RunAsyncFunc run_async_func = nullptr;
};
struct ModelMetaInfo {
size_t work_size = 0U;
std::vector<ge::Om2TensorDesc> input_desc;
std::vector<ge::Om2TensorDesc> output_desc;
std::vector<ge::Om2TensorDesc> input_desc_v2;
std::vector<ge::Om2TensorDesc> output_desc_v2;
std::vector<std::vector<int64_t>> dynamic_batch_info;
int32_t dynamic_type = 0;
std::vector<std::string> dynamic_output_shape;
std::vector<std::string> user_designate_shape_order;
std::vector<std::vector<int64_t>> origin_input_dims;
};
struct KernelBinInfo {
std::string file;
ge::ReadonlyByteBuffer data;
size_t data_size;
};
struct ClassifiedConstItems {
std::vector<Om2ConstItem> internal_consts;
std::vector<Om2ConstItem> combined_consts;
std::vector<Om2ConstItem> individual_consts;
size_t max_index = 0U;
};
std::pair<std::string, std::string> ExtractParentDirAndFileName(const std::string &abs_path) {
if (abs_path.empty()) {
return {"", ""};
}
size_t last_slash = abs_path.find_last_of('/');
if (last_slash == std::string::npos) {
return {"", abs_path};
}
if (last_slash == 0) {
return {"/", abs_path.substr(1)};
}
return {abs_path.substr(0, last_slash + 1), abs_path.substr(last_slash + 1)};
}
void CloseMemFd(int32_t &fd) {
if (fd >= 0) {
(void)mmClose(fd);
fd = -1;
}
}
ge::Status CreateSoMemFd(const std::string &file_name, const void *data, const size_t size,
std::string &fd_path, int32_t &fd) {
GE_ASSERT_NOTNULL(data);
GE_ASSERT_TRUE(size > 0U);
CloseMemFd(fd);
const auto short_name = ExtractParentDirAndFileName(file_name).second;
fd = static_cast<int32_t>(syscall(__NR_memfd_create, short_name.c_str(), 0));
GE_ASSERT_TRUE(fd >= 0, "[OM2][Create][MemFd] Failed, file=%s", file_name.c_str());
GE_DISMISSABLE_GUARD(memfd_cleanup, [&fd]() { CloseMemFd(fd); });
const auto write_count = mmWrite(fd, const_cast<void *>(data), size);
GE_ASSERT_TRUE(write_count == static_cast<mmSsize_t>(size),
"[OM2][Write][MemFd] Failed, file=%s, size=%zu, write_count=%lld",
file_name.c_str(), size, static_cast<long long>(write_count));
GE_ASSERT_TRUE(lseek(fd, 0, SEEK_SET) >= 0, "[OM2][Seek][MemFd] Failed, file=%s", file_name.c_str());
fd_path = "/proc/" + std::to_string(getpid()) + "/fd/" + std::to_string(fd);
GE_DISMISS_GUARD(memfd_cleanup);
return ge::SUCCESS;
}
bool IsFileNameEndsWith(const std::string &file_name, const std::string &ext) {
return file_name.size() >= ext.size() && file_name.compare(file_name.size() - ext.size(), ext.size(), ext) == 0;
}
template <typename T>
ge::Status GetModelJsonValue(const std::string &key, T &out, const ge::JsonFile &json_file) {
GE_ASSERT_TRUE(json_file.IsValid());
GE_ASSERT_TRUE(json_file.Get(key, out));
return ge::SUCCESS;
}
ge::Status SetTensorDesc(ge::JsonFile::json &tensor_array_json, std::vector<ge::Om2TensorDesc> &tensor_desc_array,
const bool new_model_desc = false) {
for (ge::JsonFile::json &tensor : tensor_array_json) {
ge::JsonFile tensor_obj{tensor};
ge::Om2TensorDesc tensor_desc;
std::string name;
GE_ASSERT_TRUE(tensor_obj.Get("name", name));
tensor_desc.SetName(name);
std::string data_type;
GE_ASSERT_TRUE(tensor_obj.Get("data_type", data_type));
tensor_desc.SetDataType(ge::TypeUtilsInner::SerialStringToDataType(data_type));
std::string format;
GE_ASSERT_TRUE(tensor_obj.Get("format", format));
tensor_desc.SetFormat(ge::TypeUtilsInner::SerialStringToFormat(format));
int64_t size;
GE_ASSERT_TRUE(tensor_obj.Get("size", size));
tensor_desc.SetSize(static_cast<size_t>(size));
std::string shape_key = new_model_desc ? "shape_v2" : "shape";
std::vector<int64_t> shape_dims;
GE_ASSERT_TRUE(tensor_obj.Get(shape_key, shape_dims));
tensor_desc.SetShape(shape_dims);
std::vector<std::pair<int64_t, int64_t>> shape_range;
GE_ASSERT_TRUE(tensor_obj.Get("shape_range", shape_range));
tensor_desc.SetShapeRange(shape_range);
tensor_desc_array.emplace_back(tensor_desc);
}
return ge::SUCCESS;
}
uint64_t GetNextSessionId() {
static std::atomic<uint64_t> atomic_session_id(0);
return atomic_session_id.fetch_add(1);
}
uint64_t ResolveSessionId(const Om2ModelLoadArg &load_arg) {
return (load_arg.rt_session == nullptr) ? GetNextSessionId() : load_arg.rt_session->GetSessionId();
}
ge::Status GetOm2MemAndWeightSizeFromArchive(ge::RAIIZipArchive &archive, size_t &work_size,
size_t &internal_weight_size) {
work_size = 0U;
internal_weight_size = 0U;
const auto file_names = archive.ListFiles();
for (const auto &file_name : file_names) {
if (IsFileNameEndsWith(file_name, "model_meta.json")) {
size_t buff_size = 0UL;
auto buff_data = archive.ExtractToMem(file_name, buff_size);
GE_ASSERT_TRUE(buff_data != nullptr && buff_size != 0U);
const ge::JsonFile model_meta_json(buff_data.get(), buff_size);
GE_ASSERT_TRUE(model_meta_json.IsValid());
GE_ASSERT_SUCCESS(GetModelJsonValue("work_size", work_size, model_meta_json));
continue;
}
if (IsFileNameEndsWith(file_name, "_constants_config.json")) {
size_t buff_size = 0UL;
auto buff_data = archive.ExtractToMem(file_name, buff_size);
GE_ASSERT_TRUE(buff_data != nullptr && buff_size != 0U);
const ge::JsonFile constants_json(buff_data.get(), buff_size);
GE_ASSERT_TRUE(constants_json.IsValid());
(void)constants_json.Get("internal_weight_size", internal_weight_size);
continue;
}
}
return ge::SUCCESS;
}
ge::Status RtMallocBuffer(size_t size, void *&ptr) {
ptr = nullptr;
if (size == 0U) {
return ge::SUCCESS;
}
const auto rt_ret = Om2Malloc(&ptr, size, RT_MEMORY_HBM, 0);
if (rt_ret != ACL_SUCCESS) {
GELOGE(ge::FAILED, "[OM2][Alloc] aclrtMalloc failed, size=%zu, rt_ret=%u", size, rt_ret);
return ge::FAILED;
}
return ge::SUCCESS;
}
ge::Status RtMemcpyH2D(void *dst, size_t dst_size, const void *src, size_t size) {
if (size == 0U) {
return ge::SUCCESS;
}
const auto rt_ret = aclrtMemcpy(dst, dst_size, src, size, ACL_MEMCPY_HOST_TO_DEVICE);
if (rt_ret != ACL_SUCCESS) {
GELOGE(ge::FAILED, "[OM2][Memcpy] rtMemcpy H2D failed, size=%zu, rt_ret=%u", size, rt_ret);
return ge::FAILED;
}
return ge::SUCCESS;
}
ge::Status ParseConstItems(const ge::JsonFile &constants_json, std::vector<Om2ConstItem> &const_items,
size_t &internal_weight_size) {
const_items.clear();
internal_weight_size = 0U;
if (!constants_json.IsValid()) {
return ge::SUCCESS;
}
(void)constants_json.Get("internal_weight_size", internal_weight_size);
ge::JsonFile::json consts_json;
if (!constants_json.Get("consts", consts_json) || !consts_json.is_object()) {
return ge::SUCCESS;
}
for (auto iter = consts_json.begin(); iter != consts_json.end(); ++iter) {
ge::JsonFile const_item_json(iter.value());
Om2ConstItem const_item;
GE_ASSERT_TRUE(const_item_json.Get("index", const_item.index));
GE_ASSERT_TRUE(const_item_json.Get("type", const_item.type));
if (const_item.type == "INTERNAL") {
(void)const_item_json.Get("file_name", const_item.file_name);
} else {
GE_ASSERT_TRUE(const_item_json.Get("file_name", const_item.file_name));
GE_ASSERT_TRUE(!const_item.file_name.empty());
}
GE_ASSERT_TRUE(const_item_json.Get("offset", const_item.offset));
GE_ASSERT_TRUE(const_item_json.Get("size", const_item.size));
const_items.emplace_back(const_item);
}
return ge::SUCCESS;
}
ge::Status ClassifyConstItems(const std::vector<Om2ConstItem> &const_items, ClassifiedConstItems &classified_items) {
classified_items = ClassifiedConstItems();
for (const auto &const_item : const_items) {
classified_items.max_index = std::max(classified_items.max_index, const_item.index);
if (const_item.type == "INTERNAL") {
classified_items.internal_consts.emplace_back(const_item);
continue;
}
if (const_item.type == "COMBINED") {
classified_items.combined_consts.emplace_back(const_item);
continue;
}
if (const_item.type == "INDIVIDUAL") {
classified_items.individual_consts.emplace_back(const_item);
continue;
}
GELOGE(ge::FAILED, "[OM2][Check] Unsupported const type, type=%s", const_item.type.c_str());
return ge::FAILED;
}
return ge::SUCCESS;
}
void ParseOpAttrJsonToMapInternal(const ge::JsonFile &op_attr_json,
std::map<std::string, std::map<std::string, std::string>> &attr_map) {
attr_map.clear();
if (!op_attr_json.IsValid()) {
return;
}
const auto &json_data = op_attr_json.Raw();
if (!json_data.is_object()) {
GELOGW("[OM2] op_attr.json root is not an object");
return;
}
for (auto it_op = json_data.begin(); it_op != json_data.end(); ++it_op) {
const std::string op_name = it_op.key();
if (!it_op.value().is_object()) {
continue;
}
for (auto it_attr = it_op.value().begin(); it_attr != it_op.value().end(); ++it_attr) {
const std::string attr_name = it_attr.key();
if (!it_attr.value().is_object()) {
continue;
}
ge::JsonFile attr_obj(it_attr.value());
std::string type;
if (!attr_obj.Get("type", type)) {
continue;
}
if (!attr_obj.Raw().contains("value")) {
continue;
}
try {
std::string value_str;
if (type == "LIST_STRING") {
const auto &value_array = attr_obj.Raw()["value"];
if (value_array.is_array()) {
value_str = value_array.dump();
}
} else {
value_str = attr_obj.Raw()["value"].dump();
}
attr_map[op_name][attr_name] = value_str;
} catch (const std::exception &e) {
GELOGW("[OM2] Failed to serialize attr value for op[%s] attr[%s]: %s",
op_name.c_str(), attr_name.c_str(), e.what());
}
}
}
}
}
class Om2ModelExecutor::Impl {
public:
ge::Status ParseModel(ge::ModelData &model_data, ge::ReadonlyByteBuffer &weight_buf,
ge::JsonFile &constants_json, std::vector<KernelBinInfo> &kernel_bin_info) {
has_model_ = false;
CloseMemFd(run_model_info_.so_fd);
run_model_info_ = RunModelInfo();
model_meta_info_ = ModelMetaInfo();
weight_buf.reset(nullptr);
kernel_bin_info.clear();
ge::RAIIZipArchive archive(static_cast<uint8_t *>(model_data.model_data), model_data.model_len);
if (!archive.IsGood()) {
GELOGE(ACL_ERROR_GE_PARAM_INVALID,
"[Check][Param] Invalid om2 model buffer or model length, archive init failed.");
return ACL_ERROR_GE_PARAM_INVALID;
}
const auto file_names = archive.ListFiles();
for (const auto &file_name : file_names) {
if (IsFileNameEndsWith(file_name, "model_meta.json")) {
size_t buff_size = 0UL;
auto buff_data = archive.ExtractToMem(file_name, buff_size);
GE_ASSERT_TRUE(buff_data != nullptr && buff_size != 0U);
const ge::JsonFile model_meta_json(buff_data.get(), buff_size);
GE_ASSERT_TRUE(model_meta_json.IsValid());
GE_ASSERT_SUCCESS(ParseModelMetaInfo(model_meta_json));
has_model_ = true;
break;
}
}
GE_ASSERT_TRUE(has_model_);
GE_ASSERT_SUCCESS(ParseArchiveFiles(archive, file_names, weight_buf, constants_json, kernel_bin_info));
GE_ASSERT_TRUE(!run_model_info_.so_file.empty(), "[OM2] Om2 compiled so not found, need to check .om2 file.");
return ge::SUCCESS;
}
private:
ge::Status ParseModelMetaInfo(const ge::JsonFile &model_meta_json) {
GE_ASSERT_TRUE(model_meta_json.IsValid());
GE_ASSERT_SUCCESS(GetModelJsonValue("name", run_model_info_.model_name, model_meta_json));
if (!model_meta_json.Get("root_graph_name", run_model_info_.root_graph_name)) {
run_model_info_.root_graph_name = run_model_info_.model_name;
}
GE_ASSERT_SUCCESS(GetModelJsonValue("work_size", model_meta_info_.work_size, model_meta_json));
GE_ASSERT_SUCCESS(GetModelJsonValue("dynamic_batch_info", model_meta_info_.dynamic_batch_info, model_meta_json));
GE_ASSERT_SUCCESS(GetModelJsonValue("dynamic_type", model_meta_info_.dynamic_type, model_meta_json));
GE_ASSERT_SUCCESS(GetModelJsonValue("dynamic_output_shape", model_meta_info_.dynamic_output_shape,
model_meta_json));
GE_ASSERT_SUCCESS(GetModelJsonValue("user_designate_shape_order", model_meta_info_.user_designate_shape_order,
model_meta_json));
ge::JsonFile::json inputs;
GE_ASSERT_TRUE(model_meta_json.Get("inputs", inputs));
GE_ASSERT_SUCCESS(SetTensorDesc(inputs, model_meta_info_.input_desc));
GE_ASSERT_SUCCESS(SetTensorDesc(inputs, model_meta_info_.input_desc_v2, true));
for (const auto &input_item : inputs) {
ge::JsonFile input_obj{input_item};
std::vector<int64_t> origin_dims;
(void)input_obj.Get("origin_input_dims", origin_dims);
model_meta_info_.origin_input_dims.push_back(std::move(origin_dims));
}
ge::JsonFile::json outputs;
GE_ASSERT_TRUE(model_meta_json.Get("outputs", outputs));
GE_ASSERT_SUCCESS(SetTensorDesc(outputs, model_meta_info_.output_desc));
model_meta_info_.output_desc_v2 = model_meta_info_.output_desc;
return ge::SUCCESS;
}
ge::Status ParseArchiveFiles(ge::RAIIZipArchive &archive, const std::vector<std::string> &file_names,
ge::ReadonlyByteBuffer &weight_buf,
ge::JsonFile &constants_json,
std::vector<KernelBinInfo> &kernel_bin_info) {
for (const auto &file_name : file_names) {
if (IsFileNameEndsWith(file_name, "manifest.json") || IsFileNameEndsWith(file_name, "model_meta.json")) {
continue;
}
size_t buff_size = 0UL;
if (std::regex_search(file_name, std::regex("constant_\\d+$"))) {
GELOGI("file name:%s is constant file.", file_name.c_str());
auto buff_data = archive.ExtractToMem(file_name, buff_size);
GE_ASSERT_TRUE(buff_data != nullptr && buff_size != 0U);
weight_buf = std::move(buff_data);
continue;
}
if (IsFileNameEndsWith(file_name, "_constants_config.json")) {
auto buff_data = archive.ExtractToMem(file_name, buff_size);
GE_ASSERT_TRUE(buff_data != nullptr && buff_size != 0U);
constants_json = ge::JsonFile(buff_data.get(), buff_size);
GE_ASSERT_TRUE(constants_json.IsValid());
continue;
}
if (IsFileNameEndsWith(file_name, "op_attr.json")) {
auto buff_data = archive.ExtractToMem(file_name, buff_size);
if (buff_data == nullptr || buff_size == 0U) {
GELOGW("[OM2] op_attr.json not found, using empty json content.");
run_model_info_.op_attr_json = ge::JsonFile(ge::JsonFile::json::object());
} else {
run_model_info_.op_attr_json = ge::JsonFile(buff_data.get(), buff_size);
if (!run_model_info_.op_attr_json.IsValid()) {
GELOGW("[OM2] op_attr.json is not valid, using empty json content.");
run_model_info_.op_attr_json = ge::JsonFile(ge::JsonFile::json::object());
}
}
continue;
}
if (IsFileNameEndsWith(file_name, ".o")) {
auto buff_data = archive.ExtractToMem(file_name, buff_size);
GE_ASSERT_TRUE(buff_data != nullptr && buff_size != 0U);
auto file_info = ExtractParentDirAndFileName(file_name);
kernel_bin_info.push_back({file_info.second, std::move(buff_data), buff_size});
continue;
}
if (IsFileNameEndsWith(file_name, "lib" + run_model_info_.model_name + "_om2.so")) {
auto buff_data = archive.ExtractToMem(file_name, buff_size);
GE_ASSERT_TRUE(buff_data != nullptr && buff_size != 0U);
GE_ASSERT_SUCCESS(CreateSoMemFd(file_name, buff_data.get(), buff_size, run_model_info_.so_file,
run_model_info_.so_fd));
}
}
return ge::SUCCESS;
}
public:
ge::Status LoadSharedObject() {
GELOGI("[OM2] Begin loading so file %s", run_model_info_.so_file.c_str());
GE_ASSERT_TRUE(!run_model_info_.so_file.empty());
run_model_info_.so_handle = mmDlopen(run_model_info_.so_file.c_str(), MMPA_RTLD_NOW);
if (run_model_info_.so_handle == nullptr) {
const char_t *error = mmDlerror();
error = (error == nullptr) ? "" : error;
GELOGE(ge::FAILED, "[OM2][Invoke][DlOpen] Failed to load so, path = [%s], error = [%s]",
run_model_info_.so_file.c_str(), error);
return ge::FAILED;
}
return ge::SUCCESS;
}
ge::Status ResolveSymbols() {
GE_ASSERT_TRUE(run_model_info_.so_handle != nullptr);
run_model_info_.create_func = reinterpret_cast<CreateFunc>(mmDlsym(run_model_info_.so_handle, "Om2ModelCreate"));
GE_ASSERT_NOTNULL(run_model_info_.create_func);
run_model_info_.load_func = reinterpret_cast<LoadFunc>(mmDlsym(run_model_info_.so_handle, "Om2ModelLoad"));
GE_ASSERT_NOTNULL(run_model_info_.load_func);
run_model_info_.destroy_func =
reinterpret_cast<DestroyFunc>(mmDlsym(run_model_info_.so_handle, "Om2ModelDestroy"));
GE_ASSERT_NOTNULL(run_model_info_.destroy_func);
run_model_info_.run_func = reinterpret_cast<RunFunc>(mmDlsym(run_model_info_.so_handle, "Om2ModelRun"));
GE_ASSERT_NOTNULL(run_model_info_.run_func);
run_model_info_.run_async_func =
reinterpret_cast<RunAsyncFunc>(mmDlsym(run_model_info_.so_handle, "Om2ModelRunAsync"));
GE_ASSERT_NOTNULL(run_model_info_.run_async_func);
return ge::SUCCESS;
}
ge::Status CreateModel(ge::ModelData &model_data, ge::ReadonlyByteBuffer &weight_buf,
std::vector<KernelBinInfo> &kernel_bin_info, const ge::JsonFile &constants_json,
const Om2ModelLoadArg &load_arg, uint64_t session_id, std::vector<void *> &constants) {
GE_ASSERT_TRUE(has_model_);
GE_ASSERT_TRUE(load_arg.device_id >= 0, "[OM2][Check] Invalid device id.");
device_id_ = load_arg.device_id;
std::vector<const char *> bin_files(kernel_bin_info.size());
std::vector<const void *> bin_data(kernel_bin_info.size());
std::vector<size_t> bin_sizes(kernel_bin_info.size());
void *work_ptr = nullptr;
for (auto i = 0U; i < kernel_bin_info.size(); ++i) {
bin_files[i] = kernel_bin_info[i].file.c_str();
bin_data[i] = kernel_bin_info[i].data.get();
bin_sizes[i] = kernel_bin_info[i].data_size;
}
session_id_ = session_id;
GE_ASSERT_SUCCESS(PrepareWorkPtr(load_arg, work_ptr));
GE_ASSERT_SUCCESS(PrepareConstants(model_data, weight_buf, constants_json, load_arg, constants));
GE_ASSERT_SUCCESS(run_model_info_.create_func(&run_model_info_.model_handle, &run_model_info_.rt_model_handle,
bin_files.data(), bin_data.data(),
bin_sizes.data(), static_cast<int>(bin_data.size()),
constants.empty() ? nullptr : constants.data(), work_ptr,
&session_id_, load_arg.model_id, dump_manager_.get()));
return ge::GRAPH_SUCCESS;
}
ge::Status CreateAndLoadModel(ge::ModelData &model_data, ge::ReadonlyByteBuffer &weight_buf,
std::vector<KernelBinInfo> &kernel_bin_info, const ge::JsonFile &constants_json,
const Om2ModelLoadArg &load_arg, uint64_t session_id) {
std::vector<void *> constants;
GE_ASSERT_SUCCESS(CreateModel(model_data, weight_buf, kernel_bin_info, constants_json, load_arg, session_id,
constants));
GE_ASSERT_SUCCESS(InitModelDumpInfo(load_arg));
ReportModelLoadBegin();
GE_ASSERT_SUCCESS(LoadModel());
ReportModelLoadEnd();
GE_ASSERT_SUCCESS(DispatchDumpInfo());
weight_buf.reset(nullptr);
kernel_bin_info.clear();
return ge::GRAPH_SUCCESS;
}
ge::Status CreateDumpManager(const Om2ModelLoadArg &load_arg) {
model_id_ = load_arg.model_id;
dump_manager_ = std::unique_ptr<ge::dump::ModelDumpManager>(
new (std::nothrow) ge::dump::ModelDumpManager(load_arg.model_id));
GE_ASSERT_TRUE(dump_manager_ != nullptr);
return ge::SUCCESS;
}
ge::Status InitModelDumpInfo(const Om2ModelLoadArg &load_arg) {
GE_ASSERT_NOTNULL(run_model_info_.rt_model_handle);
GE_ASSERT_TRUE(dump_manager_ != nullptr);
ge::dump::ModelDumpInfo model_dump_info{};
model_dump_info.model_id = load_arg.model_id;
model_dump_info.model_name = run_model_info_.model_name.c_str();
model_dump_info.root_graph_name = run_model_info_.root_graph_name.c_str();
model_dump_info.device_id = static_cast<uint32_t>(load_arg.device_id);
model_dump_info.rt_model_handle = run_model_info_.rt_model_handle;
model_dump_info.step_id_addr = 0U;
model_dump_info.loop_cond_addr = 0U;
model_dump_info.iterations_per_loop_addr = 0U;
GELOGI("[OM2][Dump] Set model dump info: model_id=%u, model_name=%s, root_graph_name=%s, device_id=%u, "
"rt_model_handle=%p, step_id_addr=%" PRIu64 ", loop_cond_addr=%" PRIu64
", iterations_per_loop_addr=%" PRIu64 ".",
model_dump_info.model_id, model_dump_info.model_name, model_dump_info.root_graph_name,
model_dump_info.device_id, model_dump_info.rt_model_handle, model_dump_info.step_id_addr,
model_dump_info.loop_cond_addr, model_dump_info.iterations_per_loop_addr);
GE_ASSERT_SUCCESS(dump_manager_->SetModelDumpInfo(model_dump_info));
GELOGI("[OM2][Dump] Set model dump info success, model_id=%u.", model_dump_info.model_id);
return ge::SUCCESS;
}
void ReportModelLoadBegin() const {
if (dump_manager_ == nullptr) {
return;
}
const ge::Status ret = dump_manager_->ReportModelLoadBegin();
if (ret != ge::SUCCESS) {
GELOGW("[OM2][Profiling] Report model load begin failed, model_id=%u, ret=%u.", model_id_, ret);
}
}
void ReportModelLoadEnd() const {
if (dump_manager_ == nullptr) {
return;
}
const ge::Status ret = dump_manager_->ReportModelLoadEnd();
if (ret != ge::SUCCESS) {
GELOGW("[OM2][Profiling] Report model load end failed, model_id=%u, ret=%u.", model_id_, ret);
}
}
ge::Status LoadModel() {
GE_ASSERT_NOTNULL(run_model_info_.load_func);
GE_ASSERT_NOTNULL(run_model_info_.model_handle);
GE_ASSERT_SUCCESS(run_model_info_.load_func(&run_model_info_.model_handle));
return ge::SUCCESS;
}
ge::Status DispatchDumpInfo() {
GE_ASSERT_TRUE(dump_manager_ != nullptr);
GELOGI("[OM2][Dump] Dispatch dump info begin, model_id=%u, model_name=%s, root_graph_name=%s.",
model_id_, run_model_info_.model_name.c_str(), run_model_info_.root_graph_name.c_str());
GE_ASSERT_SUCCESS(dump_manager_->DispatchDumpInfo());
GELOGI("[OM2][Dump] Dispatch dump info success, model_id=%u, model_name=%s, root_graph_name=%s.",
model_id_, run_model_info_.model_name.c_str(), run_model_info_.root_graph_name.c_str());
return ge::SUCCESS;
}
ge::Status Run(std::vector<gert::Tensor *> &inputs, std::vector<gert::Tensor *> &outputs) {
GE_ASSERT_TRUE(has_model_);
GE_ASSERT_NOTNULL(run_model_info_.run_func);
GE_ASSERT_NOTNULL(run_model_info_.model_handle);
int32_t timeout = GetOm2ThreadLocalContext().StreamSyncTimeout();
GE_ASSERT_SUCCESS(run_model_info_.run_func(&run_model_info_.model_handle, inputs.size(),
reinterpret_cast<void **>(inputs.data()), outputs.size(),
reinterpret_cast<void **>(outputs.data()), timeout));
return ge::GRAPH_SUCCESS;
}
ge::Status RunAsync(void *const stream, std::vector<gert::Tensor *> &inputs, std::vector<gert::Tensor *> &outputs) {
GE_ASSERT_TRUE(has_model_);
GE_ASSERT_NOTNULL(run_model_info_.run_async_func);
GE_ASSERT_NOTNULL(run_model_info_.model_handle);
GE_ASSERT_SUCCESS(run_model_info_.run_async_func(&run_model_info_.model_handle, stream, inputs.size(),
reinterpret_cast<void **>(inputs.data()), outputs.size(),
reinterpret_cast<void **>(outputs.data())));
return ge::GRAPH_SUCCESS;
}
ge::Status GetDynamicBatchInfo(std::vector<std::vector<int64_t>> &dynamic_batch_info, int32_t &dynamic_type) const {
GE_ASSERT_TRUE(has_model_);
dynamic_batch_info = model_meta_info_.dynamic_batch_info;
dynamic_type = model_meta_info_.dynamic_type;
return ge::SUCCESS;
}
ge::Status GetModelAttrs(std::vector<std::string> &dynamic_output_shape) const {
GE_ASSERT_TRUE(has_model_);
dynamic_output_shape = model_meta_info_.dynamic_output_shape;
return ge::SUCCESS;
}
ge::Status GetModelDescInfo(const std::vector<ge::Om2TensorDesc> *&input_desc,
const std::vector<ge::Om2TensorDesc> *&output_desc,
const bool new_model_desc) const {
GE_ASSERT_TRUE(has_model_);
if (new_model_desc) {
input_desc = &model_meta_info_.input_desc_v2;
output_desc = &model_meta_info_.output_desc_v2;
} else {
input_desc = &model_meta_info_.input_desc;
output_desc = &model_meta_info_.output_desc;
}
return ge::SUCCESS;
}
ge::Status GetUserDesignateShapeOrder(std::vector<std::string> &user_designate_shape_order) const {
GE_ASSERT_TRUE(has_model_);
user_designate_shape_order = model_meta_info_.user_designate_shape_order;
return ge::SUCCESS;
}
const std::vector<std::vector<int64_t>> &GetOriginInputDims() const {
return model_meta_info_.origin_input_dims;
}
ge::Status GetOpAttr(std::map<std::string, std::map<std::string, std::string>> &op_attr_map) const {
GE_ASSERT_TRUE(has_model_);
op_attr_map.clear();
if (!run_model_info_.op_attr_json.IsValid()) {
return ge::SUCCESS;
}
ParseOpAttrJsonToMapInternal(run_model_info_.op_attr_json, op_attr_map);
return ge::SUCCESS;
}
ge::Status GetOpDescInfo(const uint32_t device_id, const uint32_t stream_id, const uint32_t task_id,
ge::OpDescInfo &op_desc_info) const {
GE_ASSERT_TRUE(has_model_);
if (device_id_ != static_cast<int32_t>(device_id)) {
GELOGD("[OM2][Get][OpDescInfo] Device id not match, input=%u, model=%d.", device_id, device_id_);
return ge::FAILED;
}
GE_ASSERT_NOTNULL(dump_manager_);
return dump_manager_->GetOpDescInfo(ge::OpDescInfoId(task_id, stream_id, static_cast<int32_t>(device_id)),
op_desc_info) ? ge::SUCCESS : ge::FAILED;
}
ge::Status SetDynamicSize(const std::vector<uint64_t> &batch_num, const int32_t dynamic_type) {
GE_ASSERT_TRUE(has_model_);
int32_t model_dynamic_type = static_cast<int32_t>(ge::FIXED);
std::vector<std::vector<int64_t>> dynamic_batch_info;
ge::Status ret = GetDynamicBatchInfo(dynamic_batch_info, model_dynamic_type);
if (ret != ge::SUCCESS) {
GELOGE(ge::FAILED, "[OM2][SetDynamicSize] GetDynamicBatchInfo failed, ret=%u.", ret);
return ge::FAILED;
}
if (dynamic_type != model_dynamic_type) {
GELOGE(ge::FAILED,
"[OM2][SetDynamicSize] dynamic_type mismatch: requested %d, model compiled with %d.",
dynamic_type, model_dynamic_type);
return ge::FAILED;
}
std::vector<int64_t> requested_gear;
requested_gear.reserve(batch_num.size());
for (const auto v : batch_num) {
requested_gear.push_back(static_cast<int64_t>(v));
}
bool gear_found = false;
for (const auto &gear : dynamic_batch_info) {
if (gear == requested_gear) {
gear_found = true;
break;
}
}
if (!gear_found) {
GELOGE(ge::FAILED,
"[OM2][SetDynamicSize] Requested gear not found in dynamic_batch_info.");
return ge::FAILED;
}
cur_batch_size_ = batch_num;
dynamic_type_ = dynamic_type;
GELOGI("[OM2][SetDynamicSize] Set dynamic size success, type=%d, size=%zu.",
dynamic_type_, cur_batch_size_.size());
return ge::SUCCESS;
}
ge::Status GetCurrentShape(std::vector<int64_t> &batch_info, int32_t &dynamic_type) const {
GE_ASSERT_TRUE(has_model_);
batch_info.clear();
if (cur_batch_size_.empty()) {
GELOGD("[OM2][GetCurrentShape] User has not set dynamic size.");
dynamic_type = static_cast<int32_t>(ge::FIXED);
return ge::SUCCESS;
}
for (const auto v : cur_batch_size_) {
batch_info.emplace_back(static_cast<int64_t>(v));
}
dynamic_type = dynamic_type_;
return ge::SUCCESS;
}
void Cleanup() {
if (dump_manager_ != nullptr) {
dump_manager_.reset();
}
if (run_model_info_.destroy_func != nullptr && run_model_info_.model_handle != nullptr) {
const auto destroy_ret = run_model_info_.destroy_func(&run_model_info_.model_handle);
if (destroy_ret != ge::GRAPH_SUCCESS) {
GELOGI("[OM2] Resource release issue for so file: %s", run_model_info_.so_file.c_str());
}
} else {
GELOGI("[OM2] Destroy func not found or model not created, so file: %s", run_model_info_.so_file.c_str());
}
if (run_model_info_.so_handle != nullptr) {
if (mmDlclose(run_model_info_.so_handle) != 0) {
const char_t *error = mmDlerror();
error = (error == nullptr) ? "" : error;
GELOGI("[OM2][Dlclose] path = %s, error = %s", run_model_info_.so_file.c_str(), error);
}
run_model_info_.so_handle = nullptr;
}
CloseMemFd(run_model_info_.so_fd);
ReleaseOwnedMemory();
Om2VarManagerPool::Instance().RemoveManager(session_id_);
Om2ExternalWeightManagerPool::Instance().RemoveManager(session_id_);
}
private:
ge::Status PrepareWorkPtr(const Om2ModelLoadArg &load_arg, void *&work_ptr) {
const size_t required_work_size = model_meta_info_.work_size;
if (load_arg.work_ptr != nullptr) {
GE_ASSERT_TRUE(load_arg.work_size >= required_work_size, "[OM2][Check] Invalid external work_ptr size.");
work_ptr = load_arg.work_ptr;
return ge::SUCCESS;
}
void *inner_work_ptr = nullptr;
GE_ASSERT_SUCCESS(RtMallocBuffer(required_work_size, inner_work_ptr));
if (inner_work_ptr != nullptr) {
owned_buffers_.push_back(inner_work_ptr);
}
work_ptr = inner_work_ptr;
return ge::SUCCESS;
}
ge::Status PrepareConstants(const ge::ModelData &model_data, const ge::ReadonlyByteBuffer &weight_buf,
const ge::JsonFile &constants_json, const Om2ModelLoadArg &load_arg,
std::vector<void *> &constants) {
std::vector<Om2ConstItem> const_items;
size_t internal_weight_size = 0U;
GE_ASSERT_SUCCESS(ParseConstItems(constants_json, const_items, internal_weight_size));
if (const_items.empty()) {
return ge::SUCCESS;
}
ClassifiedConstItems classified_items;
GE_ASSERT_SUCCESS(ClassifyConstItems(const_items, classified_items));
constants.resize(classified_items.max_index + 1U, nullptr);
std::map<std::string, ge::FileConstantMem> user_file_const_mems;
GE_ASSERT_SUCCESS(BuildUserFileConstMemMap(load_arg.file_constant_mems, user_file_const_mems));
GE_ASSERT_SUCCESS(PrepareInternalConsts(weight_buf, load_arg, classified_items.internal_consts,
internal_weight_size, constants));
GE_ASSERT_SUCCESS(
PrepareCombinedConsts(model_data, user_file_const_mems, classified_items.combined_consts, constants));
GE_ASSERT_SUCCESS(PrepareIndividualConsts(model_data, user_file_const_mems, classified_items.individual_consts,
constants));
return ge::SUCCESS;
}
ge::Status PrepareInternalConsts(const ge::ReadonlyByteBuffer &weight_buf, const Om2ModelLoadArg &load_arg,
const std::vector<Om2ConstItem> &const_items, size_t internal_weight_size,
std::vector<void *> &constants) {
if (const_items.empty()) {
return ge::SUCCESS;
}
GE_ASSERT_TRUE(weight_buf != nullptr, "[OM2][Check] Missing internal host weight buffer.");
const void *host_weight_base = weight_buf.get();
void *device_weight_base = load_arg.weight_ptr;
if (device_weight_base != nullptr) {
GE_ASSERT_TRUE(load_arg.weight_size >= internal_weight_size, "[OM2][Check] Invalid external device weight size.");
} else {
GE_ASSERT_SUCCESS(RtMallocBuffer(internal_weight_size, device_weight_base));
if (device_weight_base != nullptr) {
owned_buffers_.push_back(device_weight_base);
}
}
GE_ASSERT_SUCCESS(RtMemcpyH2D(device_weight_base, internal_weight_size, host_weight_base, internal_weight_size));
auto *device_weight_bytes = static_cast<uint8_t *>(device_weight_base);
for (const auto &const_item : const_items) {
GE_ASSERT_TRUE((const_item.offset + const_item.size) <= internal_weight_size,
"[OM2][Check] Invalid INTERNAL const offset or size.");
constants[const_item.index] = device_weight_bytes + const_item.offset;
}
return ge::SUCCESS;
}
ge::Status PrepareCombinedConsts(const ge::ModelData &model_data,
const std::map<std::string, ge::FileConstantMem> &user_file_const_mems,
const std::vector<Om2ConstItem> &const_items, std::vector<void *> &constants) {
if (const_items.empty()) {
return ge::SUCCESS;
}
FileConstContext file_const_ctx;
GE_ASSERT_SUCCESS(BuildFileConstContext(model_data, user_file_const_mems, file_const_ctx));
GE_ASSERT_SUCCESS(gert::PrepareCombinedConsts(const_items, file_const_ctx, constants));
return ge::SUCCESS;
}
ge::Status PrepareIndividualConsts(const ge::ModelData &model_data,
const std::map<std::string, ge::FileConstantMem> &user_file_const_mems,
const std::vector<Om2ConstItem> &const_items, std::vector<void *> &constants) {
if (const_items.empty()) {
return ge::SUCCESS;
}
FileConstContext file_const_ctx;
GE_ASSERT_SUCCESS(BuildFileConstContext(model_data, user_file_const_mems, file_const_ctx));
GE_ASSERT_SUCCESS(gert::PrepareIndividualConsts(const_items, file_const_ctx, device_id_, constants));
return ge::SUCCESS;
}
ge::Status BuildFileConstContext(const ge::ModelData &model_data,
const std::map<std::string, ge::FileConstantMem> &user_file_const_mems,
FileConstContext &file_const_ctx) {
std::string weight_dir;
GE_ASSERT_SUCCESS(ResolveFileConstWeightDir(model_data, weight_dir));
file_const_ctx.weight_dir = weight_dir;
file_const_ctx.user_file_const_mems = &user_file_const_mems;
file_const_ctx.owned_buffers = &owned_buffers_;
file_const_ctx.session_id = session_id_;
file_const_ctx.device_id = device_id_;
return ge::SUCCESS;
}
void ReleaseOwnedMemory() {
for (auto iter = owned_buffers_.rbegin(); iter != owned_buffers_.rend(); ++iter) {
if (*iter != nullptr) {
(void)aclrtFree(*iter);
}
}
owned_buffers_.clear();
}
RunModelInfo run_model_info_;
ModelMetaInfo model_meta_info_;
std::unique_ptr<ge::dump::ModelDumpManager> dump_manager_;
std::vector<void *> owned_buffers_;
uint32_t model_id_ = 0U;
int32_t device_id_ = -1;
uint64_t session_id_ = 0U;
bool has_model_ = false;
std::vector<uint64_t> cur_batch_size_;
int32_t dynamic_type_ = 0;
};
Om2ModelExecutor::Om2ModelExecutor() : impl_(std::make_unique<Impl>()) {}
Om2ModelExecutor::~Om2ModelExecutor() {
if (impl_) {
impl_->Cleanup();
}
}
ge::Status Om2ModelExecutor::Load(ge::ModelData &model_data, const Om2ModelLoadArg &load_arg,
const uint64_t session_id) const {
ge::ReadonlyByteBuffer weight_buf;
ge::JsonFile constants_json;
std::vector<KernelBinInfo> kernel_bin_info;
GE_CHK_STATUS_RET(impl_->ParseModel(model_data, weight_buf, constants_json, kernel_bin_info),
"[OM2][Load] Parse model failed.");
GE_ASSERT_SUCCESS(impl_->LoadSharedObject());
GE_ASSERT_SUCCESS(impl_->ResolveSymbols());
GE_ASSERT_SUCCESS(impl_->CreateDumpManager(load_arg));
GE_ASSERT_SUCCESS(impl_->CreateAndLoadModel(model_data, weight_buf, kernel_bin_info, constants_json, load_arg,
session_id));
return ge::SUCCESS;
}
ge::Status Om2ModelExecutor::Run(std::vector<gert::Tensor *> &inputs, std::vector<gert::Tensor *> &outputs) const {
return impl_->Run(inputs, outputs);
}
ge::Status Om2ModelExecutor::RunAsync(void *const stream, std::vector<gert::Tensor *> &inputs,
std::vector<gert::Tensor *> &outputs) const {
return impl_->RunAsync(stream, inputs, outputs);
}
ge::Status Om2ModelExecutor::GetModelDescInfo(const std::vector<ge::Om2TensorDesc> *&input_desc,
const std::vector<ge::Om2TensorDesc> *&output_desc,
bool new_model_desc) const {
return impl_->GetModelDescInfo(input_desc, output_desc, new_model_desc);
}
ge::Status Om2ModelExecutor::GetModelAttrs(std::vector<std::string> &dynamic_output_shape) const {
return impl_->GetModelAttrs(dynamic_output_shape);
}
ge::Status Om2ModelExecutor::GetDynamicBatchInfo(std::vector<std::vector<int64_t>> &dynamic_batch_info,
int32_t &dynamic_type) const {
return impl_->GetDynamicBatchInfo(dynamic_batch_info, dynamic_type);
}
ge::Status Om2ModelExecutor::GetUserDesignateShapeOrder(std::vector<std::string> &user_designate_shape_order) const {
return impl_->GetUserDesignateShapeOrder(user_designate_shape_order);
}
ge::Status Om2ModelExecutor::SetDynamicSize(const std::vector<uint64_t> &batch_num, int32_t dynamic_type) {
return impl_->SetDynamicSize(batch_num, dynamic_type);
}
ge::Status Om2ModelExecutor::GetCurrentShape(std::vector<int64_t> &batch_info, int32_t &dynamic_type) const {
return impl_->GetCurrentShape(batch_info, dynamic_type);
}
const std::vector<std::vector<int64_t>> &Om2ModelExecutor::GetOriginInputDims() const {
return impl_->GetOriginInputDims();
}
ge::Status Om2ModelExecutor::GetOpAttr(std::map<std::string, std::map<std::string, std::string>> &op_attr_map) const {
return impl_->GetOpAttr(op_attr_map);
}
ge::Status Om2ModelExecutor::GetOpDescInfo(uint32_t device_id, uint32_t stream_id,
uint32_t task_id, ge::OpDescInfo &op_desc_info) const {
return impl_->GetOpDescInfo(device_id, stream_id, task_id, op_desc_info);
}
ge::Status LoadOm2DataFromFile(const std::string &model_path, ge::ModelData &model_data) {
GELOGI("Begin to load om2 model data from file, path: [%s]", model_path.c_str());
const std::string file_path = ge::om2::RealPath(model_path.c_str());
if (file_path.empty()) {
REPORT_PREDEFINED_ERR_MSG(
"E13026", std::vector<const char_t *>({"pathname", "reason"}),
std::vector<const char_t *>({model_path.c_str(), "It is not a real path. Please check your model path."}));
GELOGE(ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID,
"[Call][RealPath] File path is invalid. Please check your text file '%s'.", model_path.c_str());
return ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID;
}
std::ifstream fs(file_path, std::ios::binary);
if (!fs.is_open()) {
std::array<char_t, kMaxErrorStringLen + 1U> err_buf = {};
const auto err_msg = mmGetErrorFormatMessage(mmGetErrorCode(), &err_buf[0], kMaxErrorStringLen);
const std::string reason = ge::FormatErrnoReason(mmGetErrorCode(), err_msg);
GELOGE(ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID, "[Open][File]Failed, file %s, error %s", model_path.c_str(), err_msg);
REPORT_INNER_ERR_MSG("E19999", "Open file %s failed, reason:%s", model_path.c_str(), reason.c_str());
return ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID;
}
(void)fs.seekg(0, std::ifstream::end);
const int64_t len = fs.tellg();
GE_ASSERT_TRUE(len > 1U);
(void)fs.seekg(0, std::ifstream::beg);
auto *buffer = new (std::nothrow) char_t[static_cast<size_t>(len)];
if (buffer == nullptr) {
GELOGE(ge::FAILED, "[Alloc][Mem] Failed to alloc memory for om2, size: %lld", len);
return ge::FAILED;
}
(void)fs.read(buffer, len);
model_data.model_data = buffer;
model_data.model_len = len;
model_data.om_path = file_path;
GELOGI("Load om2 model data success, path: %s, size: %zu", model_path.c_str(), static_cast<size_t>(len));
return ge::SUCCESS;
}
std::unique_ptr<Om2ModelExecutor> LoadOm2ExecutorFromData(ge::ModelData &model_data, const Om2ModelLoadArg &load_arg,
ge::Status &error_code) {
auto executor = std::unique_ptr<Om2ModelExecutor>(new (std::nothrow) Om2ModelExecutor());
if (executor == nullptr) {
error_code = ge::FAILED;
GELOGE(ge::FAILED, "Constructing Om2ModelExecutor failed.");
return executor;
}
const uint64_t session_id = ResolveSessionId(load_arg);
error_code = executor->Load(model_data, load_arg, session_id);
GE_ASSERT_SUCCESS(error_code);
return executor;
}
ge::Status GetOm2MemAndWeightSize(const std::string &model_path, size_t &work_size, size_t &internal_weight_size) {
ge::ModelData model_data;
GE_CHK_STATUS_RET(LoadOm2DataFromFile(model_path, model_data), "[OM2][Query] Load model data from file failed.");
std::shared_ptr<void> data_guarder(model_data.model_data, [](const void *const p) {
if (p != nullptr) {
delete[] static_cast<const uint8_t *>(p);
}
});
ge::RAIIZipArchive archive(static_cast<uint8_t *>(model_data.model_data), model_data.model_len);
GE_ASSERT_TRUE(archive.IsGood());
GE_ASSERT_SUCCESS(GetOm2MemAndWeightSizeFromArchive(archive, work_size, internal_weight_size));
return ge::SUCCESS;
}
ge::Status GetOm2MemAndWeightSize(const void *model_data, size_t model_size, size_t &work_size,
size_t &internal_weight_size) {
ge::RAIIZipArchive archive(static_cast<const uint8_t *>(model_data), model_size);
GE_ASSERT_TRUE(archive.IsGood());
GE_ASSERT_SUCCESS(GetOm2MemAndWeightSizeFromArchive(archive, work_size, internal_weight_size));
return ge::SUCCESS;
}
ge::Status IsOm2Model(const void *data, size_t size, bool &is_support) {
if (data == nullptr) {
REPORT_PREDEFINED_ERR_MSG("E10001", std::vector<const char *>({"parameter", "value", "reason"}),
std::vector<const char *>({"data", "nullptr", "Model data cannot be nullptr."}));
GELOGE(ACL_ERROR_GE_PARAM_INVALID, "[Check][Param] Invalid om2 model. Model data cannot be nullptr.");
return ACL_ERROR_GE_PARAM_INVALID;
}
if (size < FILE_MAGIC_HEADER_SIZE) {
const std::string err_msg =
"Model data size must be greater than or equal to " + std::to_string(FILE_MAGIC_HEADER_SIZE);
REPORT_PREDEFINED_ERR_MSG("E10001", std::vector<const char *>({"parameter", "value", "reason"}),
std::vector<const char *>({"size", std::to_string(size).c_str(), err_msg.c_str()}));
GELOGE(ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID,
"[Check][Param] Invalid om2 model. Model data size %zu must be greater than or equal to %zu.", size,
FILE_MAGIC_HEADER_SIZE);
return ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID;
}
is_support = std::memcmp(data, OM2_MAGIC, FILE_MAGIC_HEADER_SIZE) == 0;
return ge::SUCCESS;
}
ge::Status IsOm2Model(const char *file_path, bool &is_support) {
const std::string real_path = ge::om2::RealPath(file_path);
if (real_path.empty()) {
std::array<char_t, kMaxErrorStringLen + 1U> err_buf = {};
const auto err_msg = mmGetErrorFormatMessage(mmGetErrorCode(), err_buf.data(), kMaxErrorStringLen);
std::string reason = ge::FormatErrnoReason(mmGetErrorCode(), err_msg);
REPORT_PREDEFINED_ERR_MSG("E13000", std::vector<const char *>({"path", "errmsg"}),
std::vector<const char *>({file_path, reason.c_str()}));
GELOGE(ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID, "[Check][Param]Model file path %s is invalid", file_path);
return ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID;
}
std::ifstream file(file_path, std::ios::binary);
if (!file.is_open()) {
std::array<char_t, kMaxErrorStringLen + 1U> err_buf = {};
const auto err_msg = mmGetErrorFormatMessage(mmGetErrorCode(), &err_buf[0], kMaxErrorStringLen);
const std::string reason = ge::FormatErrnoReason(mmGetErrorCode(), err_msg);
GELOGE(ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID, "[Open][File]Failed, file %s, error %s", file_path, err_msg);
REPORT_INNER_ERR_MSG("E19999", "Open file %s failed, reason:%s", file_path, reason.c_str());
return ACL_ERROR_GE_EXEC_MODEL_PATH_INVALID;
}
(void)file.seekg(0, std::ifstream::end);
const size_t len = static_cast<size_t>(file.tellg());
(void)file.seekg(0, std::ifstream::beg);
if (len < FILE_MAGIC_HEADER_SIZE) {
const std::string reason = "Invalid om2 file. The model data size " + std::to_string(len) + " is smaller than " +
std::to_string(FILE_MAGIC_HEADER_SIZE) + ".";
(void)REPORT_PREDEFINED_ERR_MSG("E10001", std::vector<const char *>({"parameter", "value", "reason"}),
std::vector<const char *>({"file_path", file_path, reason.c_str()}));
GELOGE(ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID,
"[Check][Param] Invalid om2 model. Model data size %" PRIu64 " must be greater than or equal to %zu.", len,
FILE_MAGIC_HEADER_SIZE);
return ACL_ERROR_GE_EXEC_MODEL_DATA_SIZE_INVALID;
}
uint8_t magic[FILE_MAGIC_HEADER_SIZE] = {};
file.read(reinterpret_cast<char *>(magic), FILE_MAGIC_HEADER_SIZE);
const auto read_len = static_cast<size_t>(file.gcount());
GE_ASSERT_SUCCESS(IsOm2Model(magic, read_len, is_support));
return ge::SUCCESS;
}
}