* 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 "rt_external_mem.h"
#include "common/helper/om2/json_file.h"
#include "nlohmann/json.hpp"
#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"
#include "common/om2/om2_model_data.h"
#include "om2_aipp_utils.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, Om2ProfInfos *);
using RunAsyncFunc = ge::graphStatus (*)(Om2ModelHandle *, rtStream_t, int, void **, int, void **, Om2ProfInfos *);
struct RunModelInfo {
std::string so_file;
int32_t so_fd = -1;
std::map<std::string, std::map<std::string, std::string>> op_attr_map;
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;
size_t zero_copy_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;
}
ge::Status ExtractEntryToString(const ge::RAIIZipArchive &archive, const std::string &entry_name, std::string &out) {
size_t buffer_size{0U};
const auto buffer = archive.ExtractToMem(entry_name, buffer_size);
GE_ASSERT_NOTNULL(buffer, "[OM2] Failed to extract entry %s", entry_name.c_str());
GE_ASSERT_TRUE(buffer_size > 0U, "[OM2] Empty archive entry %s", entry_name.c_str());
out.assign(reinterpret_cast<const char *>(buffer.get()), buffer_size);
return ge::SUCCESS;
}
ge::Status ExtractEntryToBytes(const ge::RAIIZipArchive &archive, const std::string &entry_name,
std::vector<uint8_t> &out) {
size_t buffer_size{0U};
const auto buffer = archive.ExtractToMem(entry_name, buffer_size);
GE_ASSERT_NOTNULL(buffer, "[OM2] Failed to extract entry %s", entry_name.c_str());
GE_ASSERT_TRUE(buffer_size > 0U, "[OM2] Empty archive entry %s", entry_name.c_str());
out.assign(buffer.get(), buffer.get() + buffer_size);
return ge::SUCCESS;
}
ge::Status ParseTensorDescFromJson(const ge::JsonFile &json_file, ge::Om2TensorDesc &desc) {
ge::JsonFile::TryGetAndApply<std::string>(json_file, "name", [&](const std::string &v) { desc.SetName(v); });
ge::JsonFile::TryGetAndApply<std::vector<int64_t>>(json_file, "shape",
[&](const std::vector<int64_t> &v) { desc.SetShape(v); });
ge::JsonFile::TryGetAndApply<std::string>(json_file, "data_type", [&](const std::string &v) {
desc.SetDataType(ge::TypeUtilsInner::SerialStringToDataType(v));
});
ge::JsonFile::TryGetAndApply<std::string>(
json_file, "format", [&](const std::string &v) { desc.SetFormat(ge::TypeUtilsInner::SerialStringToFormat(v)); });
ge::JsonFile::TryGetAndApply<size_t>(json_file, "size", [&](const size_t &v) { desc.SetSize(v); });
ge::JsonFile::TryGetAndApply<std::vector<std::pair<int64_t, int64_t>>>(
json_file, "shape_range", [&](const std::vector<std::pair<int64_t, int64_t>> &v) { desc.SetShapeRange(v); });
return ge::SUCCESS;
}
ge::Status ParseOpAttrMapJson(const uint8_t *data, size_t data_size,
std::map<std::string, std::map<std::string, std::string>> &op_attr_map) {
try {
const auto json_obj = ge::JsonFile::json::parse(data, data + data_size);
if (!json_obj.is_object()) {
GELOGW("[OM2] op_attr.json root is not an object");
return ge::FAILED;
}
for (auto &[op_name, attrs] : json_obj.items()) {
if (!attrs.is_object()) {
GELOGW("[OM2] op_attr for %s is not an object", op_name.c_str());
continue;
}
std::map<std::string, std::string> op_attrs;
for (auto &[attr_name, value] : attrs.items()) {
if (value.is_string()) {
op_attrs[attr_name] = value.get<std::string>();
} else {
op_attrs[attr_name] = value.dump();
}
}
op_attr_map[op_name] = op_attrs;
}
return ge::SUCCESS;
} catch (const ge::JsonFile::json::exception &e) {
GELOGE(ge::FAILED, "[OM2] Failed to parse op_attr.json: %s", e.what());
return ge::FAILED;
}
}
ge::Status DeserializeCodegenEntry(const ge::RAIIZipArchive &archive, const std::string &entry,
gert::Om2ModelData &model_data) {
ge::Om2CodegenArtifact artifact;
artifact.file_name = ExtractParentDirAndFileName(entry).second;
std::string content;
GE_ASSERT_SUCCESS(ExtractEntryToString(archive, entry, content));
artifact.data = std::move(content);
model_data.program_body.so_artifact = std::move(artifact);
return ge::SUCCESS;
}
ge::Status DeserializeWeightEntry(const ge::RAIIZipArchive &archive, const std::string &entry,
gert::Om2ModelData &model_data) {
GE_ASSERT_SUCCESS(ExtractEntryToBytes(archive, entry, model_data.constants_data.weight_data));
return ge::SUCCESS;
}
ge::Status DeserializeConstantsConfigEntry(const ge::RAIIZipArchive &archive, const std::string &entry,
gert::Om2ModelData &model_data) {
size_t buff_size = 0U;
auto buff_data = archive.ExtractToMem(entry, buff_size);
GE_ASSERT_NOTNULL(buff_data, "[OM2] Failed to extract %s", entry.c_str());
GE_ASSERT_TRUE(buff_size > 0U);
const ge::JsonFile json_file(buff_data.get(), buff_size);
GE_ASSERT_TRUE(json_file.IsValid(), "[OM2] Invalid constants config JSON from entry %s", entry.c_str());
size_t internal_weight_size{0U};
(void)json_file.Get("internal_weight_size", internal_weight_size);
model_data.constants_data.internal_weight_size = internal_weight_size;
ge::JsonFile::json consts_json;
if (json_file.Get("consts", consts_json) && consts_json.is_object()) {
for (auto &[key, val] : consts_json.items()) {
(void)key;
const ge::JsonFile val_file(val);
ge::Om2ConstMeta meta;
(void)val_file.Get("index", meta.index);
(void)val_file.Get("type", meta.type);
(void)val_file.Get("file_name", meta.file_name);
(void)val_file.Get("file_path", meta.file_path);
(void)val_file.Get("offset", meta.offset);
(void)val_file.Get("size", meta.size);
(void)val_file.Get("op_name", meta.op_name);
(void)model_data.constants_data.consts.emplace_back(std::move(meta));
}
}
return ge::SUCCESS;
}
ge::Status DeserializeKernelEntry(const ge::RAIIZipArchive &archive, const std::string &entry,
gert::Om2ModelData &model_data) {
gert::Om2KernelBinary kernel_binary;
kernel_binary.name = ExtractParentDirAndFileName(entry).second;
GE_ASSERT_SUCCESS(ExtractEntryToBytes(archive, entry, kernel_binary.data));
(void)model_data.kernel_binaries.emplace_back(std::move(kernel_binary));
return ge::SUCCESS;
}
ge::Status DeserializeModelMetaEntry(const ge::RAIIZipArchive &archive, const std::string &entry,
gert::Om2ModelData &model_data) {
size_t buff_size = 0U;
auto buff_data = archive.ExtractToMem(entry, buff_size);
GE_ASSERT_NOTNULL(buff_data, "[OM2] Failed to extract %s", entry.c_str());
GE_ASSERT_TRUE(buff_size > 0U);
const ge::JsonFile json_file(buff_data.get(), buff_size);
GE_ASSERT_TRUE(json_file.IsValid(), "[OM2] Invalid model_meta.json");
ge::JsonFile::json inputs_json;
if (json_file.Get("inputs", inputs_json) && inputs_json.is_array()) {
for (const auto &input_json : inputs_json) {
const ge::JsonFile input_file(input_json);
std::vector<int64_t> shape_v2;
GE_ASSERT_TRUE(input_file.Get("shape_v2", shape_v2), "[OM2] input shape_v2 not found in model_meta.json");
ge::Om2TensorDesc desc;
GE_ASSERT_SUCCESS(ParseTensorDescFromJson(input_file, desc));
model_data.model_meta.input_desc.emplace_back(desc);
ge::Om2TensorDesc desc_v2 = desc;
desc_v2.SetShape(shape_v2);
model_data.model_meta.input_desc_v2.emplace_back(desc_v2);
std::vector<int64_t> origin_input_dims;
if (input_file.Get("origin_input_dims", origin_input_dims)) {
model_data.model_meta.origin_input_dims.emplace_back(std::move(origin_input_dims));
} else {
(void)model_data.model_meta.origin_input_dims.emplace_back(desc.GetShape());
}
}
}
ge::JsonFile::json outputs_json;
if (json_file.Get("outputs", outputs_json) && outputs_json.is_array()) {
for (const auto &output_json : outputs_json) {
const ge::JsonFile output_file(output_json);
ge::Om2TensorDesc desc;
GE_ASSERT_SUCCESS(ParseTensorDescFromJson(output_file, desc));
model_data.model_meta.output_desc.emplace_back(desc);
model_data.model_meta.output_desc_v2.emplace_back(desc);
}
}
(void)json_file.Get("dynamic_output_shape", model_data.model_meta.dynamic_output_shape);
(void)json_file.Get("dynamic_batch_info", model_data.model_meta.dynamic_batch_info);
(void)json_file.Get("user_designate_shape_order", model_data.model_meta.user_designate_shape_order);
(void)json_file.Get("dynamic_type", model_data.model_meta.dynamic_type);
(void)json_file.Get("work_size", model_data.model_meta.work_size);
(void)json_file.Get("zero_copy_size", model_data.model_meta.zero_copy_size);
(void)json_file.Get("name", model_data.model_meta.model_name);
(void)json_file.Get("root_graph_name", model_data.model_meta.root_graph_name);
ge::JsonFile aipp_json;
if (json_file.Get("aipp", aipp_json) && aipp_json.IsValid()) {
const ge::Status aipp_ret =
om2::ParseAippJson(aipp_json, model_data.model_meta.aipp_infos, model_data.model_meta.has_aipp);
if (aipp_ret != ge::SUCCESS) {
GELOGW("[OM2][AIPP] ParseAippJson failed, ret=%u", aipp_ret);
}
}
return ge::SUCCESS;
}
ge::Status DeserializeOpAttrEntry(const ge::RAIIZipArchive &archive, const std::string &entry,
gert::Om2ModelData &model_data) {
size_t buff_size = 0U;
auto buff_data = archive.ExtractToMem(entry, buff_size);
GE_ASSERT_NOTNULL(buff_data, "[OM2] Failed to extract %s", entry.c_str());
GE_ASSERT_TRUE(buff_size > 0U);
if (ParseOpAttrMapJson(buff_data.get(), buff_size, model_data.debug_info.op_attr_map) != ge::SUCCESS) {
GELOGW("[OM2] Failed to parse op_attr.json, using empty map");
model_data.debug_info.op_attr_map.clear();
}
return ge::SUCCESS;
}
ge::Status DeserializeVisualEntry(const ge::RAIIZipArchive &archive, const std::string &entry,
gert::Om2ModelData &model_data) {
GE_ASSERT_SUCCESS(ExtractEntryToString(archive, entry, model_data.debug_info.visual_json));
return ge::SUCCESS;
}
ge::Status HandleArchiveEntry(const ge::RAIIZipArchive &archive, const std::string &entry,
gert::Om2ModelData &model_data) {
if (entry.find("/runtime/") != std::string::npos && IsFileNameEndsWith(entry, ".so")) {
GE_ASSERT_SUCCESS(DeserializeCodegenEntry(archive, entry, model_data));
return ge::SUCCESS;
}
if (entry.find("/debug/") != std::string::npos) {
if (IsFileNameEndsWith(entry, "op_attr.json")) {
GE_ASSERT_SUCCESS(DeserializeOpAttrEntry(archive, entry, model_data));
} else {
const std::string debug_file = ExtractParentDirAndFileName(entry).second;
if ((debug_file.find("ge_visual_") != std::string::npos) && IsFileNameEndsWith(debug_file, ".json")) {
GE_ASSERT_SUCCESS(DeserializeVisualEntry(archive, entry, model_data));
}
}
return ge::SUCCESS;
}
if (IsFileNameEndsWith(entry, "model_meta.json")) {
GE_ASSERT_SUCCESS(DeserializeModelMetaEntry(archive, entry, model_data));
return ge::SUCCESS;
}
if (entry.find("data/constants/") != std::string::npos) {
if (IsFileNameEndsWith(entry, "_constants_config.json")) {
GE_ASSERT_SUCCESS(DeserializeConstantsConfigEntry(archive, entry, model_data));
} else if (entry.find("data/constants/constant_") != std::string::npos) {
GE_ASSERT_SUCCESS(DeserializeWeightEntry(archive, entry, model_data));
}
return ge::SUCCESS;
}
if (entry.find("data/kernels_") != std::string::npos && IsFileNameEndsWith(entry, ".o")) {
GE_ASSERT_SUCCESS(DeserializeKernelEntry(archive, entry, model_data));
}
return ge::SUCCESS;
}
ge::Status DeserializeOm2ModelDataFromArchive(ge::RAIIZipArchive &archive, gert::Om2ModelData &model_data) {
const auto &entries = archive.ListFiles();
if (entries.empty()) {
GELOGE(ACL_ERROR_GE_PARAM_INVALID, "[OM2] ZIP archive is empty");
return ACL_ERROR_GE_PARAM_INVALID;
}
for (const auto &entry : entries) {
GE_ASSERT_SUCCESS(HandleArchiveEntry(archive, entry, model_data));
}
GE_ASSERT_TRUE(!model_data.model_meta.model_name.empty(), "[OM2] model_meta.json not found in ZIP archive.");
GE_ASSERT_TRUE(!model_data.program_body.so_artifact.file_name.empty(),
"[OM2] Compiled .so not found in ZIP archive.");
return ge::SUCCESS;
}
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 GetOm2ModelMetadataFromArchive(ge::RAIIZipArchive &archive, std::vector<ge::Om2TensorDesc> &input_desc,
std::vector<ge::Om2TensorDesc> &input_desc_v2,
std::vector<ge::Om2TensorDesc> &output_desc,
std::vector<ge::Om2TensorDesc> &output_desc_v2) {
const auto file_names = archive.ListFiles();
for (const auto &file_name : file_names) {
if (!IsFileNameEndsWith(file_name, "model_meta.json")) {
continue;
}
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::JsonFile::json inputs;
GE_ASSERT_TRUE(model_meta_json.Get("inputs", inputs));
GE_ASSERT_SUCCESS(SetTensorDesc(inputs, input_desc));
GE_ASSERT_SUCCESS(SetTensorDesc(inputs, input_desc_v2, true));
ge::JsonFile::json outputs;
GE_ASSERT_TRUE(model_meta_json.Get("outputs", outputs));
GE_ASSERT_SUCCESS(SetTensorDesc(outputs, output_desc));
output_desc_v2 = output_desc;
return ge::SUCCESS;
}
GE_ASSERT_TRUE(false, "[OM2] model_meta.json not found in archive.");
return ge::FAILED;
}
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 gert::Om2ConstantsData &config, std::vector<Om2ConstItem> &const_items,
size_t &internal_weight_size) {
const_items.clear();
internal_weight_size = config.internal_weight_size;
for (const auto &meta : config.consts) {
Om2ConstItem const_item;
const_item.index = meta.index;
const_item.type = meta.type;
const_item.file_name = meta.file_name;
if (const_item.type != "INTERNAL") {
GE_ASSERT_TRUE(!const_item.file_name.empty());
}
const_item.offset = static_cast<size_t>(meta.offset);
const_item.size = static_cast<size_t>(meta.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;
}
}
class Om2ModelExecutor::Impl {
public:
ge::Status LoadFromOm2ModelData(const gert::Om2ModelData &om2_data, ge::ReadonlyByteBuffer &weight_buf,
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_ASSERT_SUCCESS(LoadModelMetaFromStruct(om2_data.model_meta));
has_model_ = true;
GE_ASSERT_SUCCESS(BuildKernelBinInfoFromStruct(om2_data.kernel_binaries, kernel_bin_info));
GE_ASSERT_SUCCESS(LoadSoFromBuffer(om2_data.program_body.so_artifact));
GE_ASSERT_TRUE(!run_model_info_.so_file.empty(), "[OM2] Om2 compiled so not found in Om2ModelData.");
if (!om2_data.debug_info.op_attr_map.empty()) {
run_model_info_.op_attr_map = om2_data.debug_info.op_attr_map;
}
if (!om2_data.constants_data.weight_data.empty()) {
weight_buf = ge::ReadonlyByteBuffer(om2_data.constants_data.weight_data.data(), ge::ConditionalDeleter{false});
}
return ge::SUCCESS;
}
private:
ge::Status LoadModelMetaFromStruct(const gert::Om2ModelMeta &meta) {
run_model_info_.model_name = meta.model_name;
run_model_info_.root_graph_name = meta.root_graph_name.empty() ? meta.model_name : meta.root_graph_name;
model_meta_info_.work_size = meta.work_size;
GE_ASSERT_TRUE(meta.zero_copy_size >= 0, "[OM2][Check] Invalid zero_copy_size=%ld.", meta.zero_copy_size);
const auto zero_copy_size = static_cast<size_t>(meta.zero_copy_size);
GE_ASSERT_TRUE(zero_copy_size <= meta.work_size,
"[OM2][Check] zero_copy_size exceeds work_size, zero_copy_size=%zu, work_size=%zu.", zero_copy_size,
meta.work_size);
model_meta_info_.zero_copy_size = zero_copy_size;
model_meta_info_.dynamic_batch_info = meta.dynamic_batch_info;
model_meta_info_.dynamic_type = meta.dynamic_type;
model_meta_info_.dynamic_output_shape = meta.dynamic_output_shape;
model_meta_info_.user_designate_shape_order = meta.user_designate_shape_order;
model_meta_info_.input_desc = meta.input_desc;
model_meta_info_.input_desc_v2 = meta.input_desc_v2;
model_meta_info_.origin_input_dims = meta.origin_input_dims;
model_meta_info_.output_desc = meta.output_desc;
model_meta_info_.output_desc_v2 = meta.output_desc_v2;
has_aipp_ = meta.has_aipp;
aipp_infos_ = meta.aipp_infos;
return ge::SUCCESS;
}
ge::Status BuildKernelBinInfoFromStruct(const std::vector<gert::Om2KernelBinary> &kernels,
std::vector<KernelBinInfo> &info) {
info.clear();
for (const auto &k : kernels) {
KernelBinInfo bin_info;
bin_info.file = k.name;
if (!k.data.empty()) {
bin_info.data = ge::ReadonlyByteBuffer(k.data.data(), ge::ConditionalDeleter{false});
bin_info.data_size = k.data.size();
} else {
bin_info.data_size = 0U;
}
info.push_back(std::move(bin_info));
}
return ge::SUCCESS;
}
ge::Status LoadSoFromBuffer(const ge::Om2CodegenArtifact &so) {
if (so.data.empty() || so.file_name.empty()) {
GELOGE(ge::FAILED, "[OM2] SO artifact data or file_name is empty.");
return ge::FAILED;
}
GE_ASSERT_SUCCESS(
CreateSoMemFd(so.file_name, so.data.data(), so.data.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 PrepareConstantsFromStruct(const gert::Om2ConstantsData &constants_data,
const ge::ReadonlyByteBuffer &weight_buf, const Om2ModelLoadArg &load_arg,
std::vector<void *> &constants) {
std::vector<Om2ConstItem> const_items;
size_t internal_weight_size = 0U;
GE_ASSERT_SUCCESS(ParseConstItems(constants_data, 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(load_arg.weight_path, load_arg.om_path, user_file_const_mems,
classified_items.combined_consts, constants));
GE_ASSERT_SUCCESS(PrepareIndividualConsts(load_arg.weight_path, load_arg.om_path, user_file_const_mems,
classified_items.individual_consts, constants));
return ge::SUCCESS;
}
ge::Status CreateModelFromStruct(const gert::Om2ConstantsData &constants_data, ge::ReadonlyByteBuffer &weight_buf,
std::vector<KernelBinInfo> &kernel_bin_info, 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(PrepareConstantsFromStruct(constants_data, weight_buf, 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 CreateAndLoadModelFromStruct(const gert::Om2ConstantsData &constants_data,
ge::ReadonlyByteBuffer &weight_buf,
std::vector<KernelBinInfo> &kernel_bin_info, const Om2ModelLoadArg &load_arg,
uint64_t session_id) {
std::vector<void *> constants;
GE_ASSERT_SUCCESS(
CreateModelFromStruct(constants_data, weight_buf, kernel_bin_info, 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);
dump_manager_->SetClearDfxCacheFlagAfterLoad(load_arg.need_clear_dfx_cache);
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();
Om2ProfUnit prof_units[OM2_PROF_TYPE_COUNT];
Om2ProfInfos prof_info = {kOm2ProfInfosVersion, 0, prof_units, step_id_};
Om2ProfInfos *prof_info_ptr = dump_manager_ != nullptr ? &prof_info : nullptr;
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, prof_info_ptr));
if (prof_info_ptr != nullptr) {
GELOGD("[OM2][Prof] Run done, model_id=%u, prof_count=%u, step_id=%lu", model_id_, prof_info.count, step_id_);
dump_manager_->ReportModelLevelProf(prof_info);
} else {
GELOGD("[OM2][Prof] Run skip, dump_manager is null, model_id=%u", model_id_);
}
++step_id_;
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);
Om2ProfUnit prof_units[OM2_PROF_TYPE_COUNT];
Om2ProfInfos prof_info = {kOm2ProfInfosVersion, 0, prof_units, step_id_};
Om2ProfInfos *prof_info_ptr = dump_manager_ != nullptr ? &prof_info : nullptr;
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()), prof_info_ptr));
if (prof_info_ptr != nullptr) {
GELOGD("[OM2][Prof] RunAsync done, model_id=%u, prof_count=%u, step_id=%lu", model_id_, prof_info.count,
step_id_);
dump_manager_->ReportModelLevelProf(prof_info);
} else {
GELOGD("[OM2][Prof] RunAsync skip, dump_manager is null, model_id=%u", model_id_);
}
++step_id_;
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_map.empty()) {
return ge::SUCCESS;
}
op_attr_map = run_model_info_.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;
}
ge::Status GetAippInfo(const uint32_t index, ge::AippConfigInfo &aipp_info) const {
if (!has_aipp_ || index >= aipp_infos_.size()) {
return ACL_ERROR_GE_AIPP_NOT_EXIST;
}
if (aipp_infos_[index].aipp_type == ge::DATA_WITHOUT_AIPP) {
return ACL_ERROR_GE_AIPP_NOT_EXIST;
}
aipp_info = aipp_infos_[index].aipp_config_info;
return ge::SUCCESS;
}
ge::Status GetAippType(const uint32_t index, ge::InputAippType &aipp_type, size_t &aipp_data_index) const {
if (!has_aipp_ || index >= aipp_infos_.size()) {
aipp_type = ge::DATA_WITHOUT_AIPP;
aipp_data_index = 0xFFFFFFFFU;
return ge::SUCCESS;
}
aipp_type = aipp_infos_[index].aipp_type;
aipp_data_index = aipp_infos_[index].aipp_data_index;
return ge::SUCCESS;
}
ge::Status GetOrigInputInfo(const uint32_t index, ge::OriginInputInfo &orig_input_info) const {
if (!has_aipp_ || index >= aipp_infos_.size()) {
return ACL_ERROR_GE_AIPP_NOT_EXIST;
}
if (aipp_infos_[index].aipp_type == ge::DATA_WITHOUT_AIPP) {
return ACL_ERROR_GE_AIPP_NOT_EXIST;
}
const auto &input_info = aipp_infos_[index].orig_input_info;
if ((input_info.format != ge::FORMAT_RESERVED) || (input_info.data_type != ge::DT_UNDEFINED)) {
orig_input_info = input_info;
}
return ge::SUCCESS;
}
ge::Status GetAllAippInputOutputDims(const uint32_t index, std::vector<ge::InputOutputDims> &input_dims,
std::vector<ge::InputOutputDims> &output_dims) const {
if (!has_aipp_ || index >= aipp_infos_.size()) {
return ACL_ERROR_GE_AIPP_NOT_EXIST;
}
if (aipp_infos_[index].aipp_type == ge::DATA_WITHOUT_AIPP) {
return ACL_ERROR_GE_AIPP_NOT_EXIST;
}
input_dims = aipp_infos_[index].aipp_input_dims;
output_dims = aipp_infos_[index].aipp_output_dims;
return ge::SUCCESS;
}
ge::Status GetBatchInfoSize(size_t &shape_count) const {
std::vector<std::vector<int64_t>> batch_info;
int32_t dynamic_type = 0;
const auto ret = GetDynamicBatchInfo(batch_info, dynamic_type);
if (ret != ge::SUCCESS) {
return ret;
}
if (batch_info.empty()) {
shape_count = 1U;
} else {
shape_count = batch_info.size();
}
return ge::SUCCESS;
}
ge::Status SetDynamicAippData(void *dynamic_input_addr, const uint64_t length,
const std::vector<kAippDynamicBatchPara> &aipp_batch_para,
const kAippDynamicPara &aipp_parms) {
if (dynamic_input_addr == nullptr) {
REPORT_INNER_ERR_MSG("E19999", "Param dynamic_input_addr is nullptr, check invalid");
GELOGE(ACL_ERROR_GE_DYNAMIC_INPUT_ADDR_INVALID, "[Check][Param] Dynamic aipp input addr is nullptr");
return ACL_ERROR_GE_DYNAMIC_INPUT_ADDR_INVALID;
}
if (aipp_batch_para.empty()) {
REPORT_INNER_ERR_MSG("E19999", "Param aipp_batch_para is empty, check invalid");
GELOGE(ACL_ERROR_GE_AIPP_BATCH_EMPTY, "[Check][Param] aipp_batch_para is empty");
return ACL_ERROR_GE_AIPP_BATCH_EMPTY;
}
const uint64_t batch_num = aipp_batch_para.size();
constexpr uint64_t real_aipp_params_size = sizeof(kAippDynamicPara) - sizeof(kAippDynamicBatchPara);
const uint64_t struct_len = (batch_num * sizeof(kAippDynamicBatchPara)) + real_aipp_params_size;
if (struct_len > length) {
REPORT_INNER_ERR_MSG("E19999", "input dynamic aipp param len:%" PRIu64 " is larger than aipp_data size:%" PRIu64,
struct_len, length);
GELOGE(ACL_ERROR_GE_DYNAMIC_INPUT_LENGTH_INVALID,
"[Check][Param] input dynamic aipp param len [%" PRIu64 "] is larger than aipp_data size [%" PRIu64 "]",
struct_len, length);
return ACL_ERROR_GE_DYNAMIC_INPUT_LENGTH_INVALID;
}
aclError rt_ret =
aclrtMemcpy(dynamic_input_addr, length, &aipp_parms, real_aipp_params_size, ACL_MEMCPY_HOST_TO_DEVICE);
if (rt_ret != ACL_SUCCESS) {
REPORT_INNER_ERR_MSG("E19999", "Call aclrtMemcpy failed, size:%" PRIu64 ", ret:%d", length, rt_ret);
GELOGE(ge::FAILED, "[Call][aclrtMemcpy] memcpy aipp_parms failed! size:%" PRIu64 ", ret:%d", length, rt_ret);
return ge::FAILED;
}
for (uint64_t i = 0U; i < batch_num; ++i) {
const uint64_t offset = real_aipp_params_size + (i * sizeof(kAippDynamicBatchPara));
rt_ret = aclrtMemcpy(static_cast<uint8_t *>(dynamic_input_addr) + offset, length - offset, &aipp_batch_para[i],
sizeof(kAippDynamicBatchPara), ACL_MEMCPY_HOST_TO_DEVICE);
if (rt_ret != ACL_SUCCESS) {
REPORT_INNER_ERR_MSG("E19999", "Call aclrtMemcpy failed, ret:%d", rt_ret);
GELOGE(ge::FAILED, "[Call][aclrtMemcpy] memcpy kAippDynamicBatchPara input data failed! ret:%d", rt_ret);
return ge::FAILED;
}
}
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 = load_arg.reuse_zero_copy
? model_meta_info_.work_size - model_meta_info_.zero_copy_size
: model_meta_info_.work_size;
if (load_arg.work_ptr != nullptr) {
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 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 std::string &weight_path, const std::string &om_path,
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(weight_path, om_path, 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 std::string &weight_path, const std::string &om_path,
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(weight_path, om_path, 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 std::string &weight_path, const std::string &om_path,
const std::map<std::string, ge::FileConstantMem> &user_file_const_mems,
FileConstContext &file_const_ctx) {
std::string weight_dir;
GE_ASSERT_SUCCESS(ResolveFileConstWeightDir(weight_path, om_path, 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;
uint64_t step_id_ = 1U;
std::vector<uint64_t> cur_batch_size_;
int32_t dynamic_type_ = 0;
std::vector<Om2AippInfo> aipp_infos_;
bool has_aipp_ = false;
};
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 {
gert::Om2ModelData om2_data;
ge::RAIIZipArchive archive(static_cast<const uint8_t *>(model_data.model_data), model_data.model_len);
if (!archive.IsGood()) {
GELOGE(ACL_ERROR_GE_PARAM_INVALID, "[OM2] Failed to open OM2 ZIP archive for deserialization");
return ACL_ERROR_GE_PARAM_INVALID;
}
GE_ASSERT_SUCCESS(DeserializeOm2ModelDataFromArchive(archive, om2_data));
Om2ModelLoadArg load_arg_with_path = load_arg;
load_arg_with_path.om_path = model_data.om_path;
load_arg_with_path.weight_path = model_data.weight_path;
return Load(om2_data, load_arg_with_path, session_id);
}
ge::Status Om2ModelExecutor::Load(const gert::Om2ModelData &model_data, const Om2ModelLoadArg &load_arg,
const uint64_t session_id) const {
ge::ReadonlyByteBuffer weight_buf;
std::vector<KernelBinInfo> kernel_bin_info;
GE_CHK_STATUS_RET(impl_->LoadFromOm2ModelData(model_data, weight_buf, kernel_bin_info),
"[OM2][Load] Load from Om2ModelData failed.");
GE_ASSERT_SUCCESS(impl_->LoadSharedObject());
GE_ASSERT_SUCCESS(impl_->ResolveSymbols());
GE_ASSERT_SUCCESS(impl_->CreateDumpManager(load_arg));
GE_ASSERT_SUCCESS(impl_->CreateAndLoadModelFromStruct(model_data.constants_data, weight_buf, kernel_bin_info,
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 Om2ModelExecutor::GetAippInfo(uint32_t index, ge::AippConfigInfo &aipp_info) const {
return impl_->GetAippInfo(index, aipp_info);
}
ge::Status Om2ModelExecutor::GetAippType(uint32_t index, ge::InputAippType &aipp_type, size_t &aipp_data_index) const {
return impl_->GetAippType(index, aipp_type, aipp_data_index);
}
ge::Status Om2ModelExecutor::GetOrigInputInfo(uint32_t index, ge::OriginInputInfo &orig_input_info) const {
return impl_->GetOrigInputInfo(index, orig_input_info);
}
ge::Status Om2ModelExecutor::GetAllAippInputOutputDims(uint32_t index, std::vector<ge::InputOutputDims> &input_dims,
std::vector<ge::InputOutputDims> &output_dims) const {
return impl_->GetAllAippInputOutputDims(index, input_dims, output_dims);
}
ge::Status Om2ModelExecutor::GetBatchInfoSize(size_t &shape_count) const {
return impl_->GetBatchInfoSize(shape_count);
}
ge::Status Om2ModelExecutor::SetDynamicAippData(void *dynamic_input_addr, const uint64_t length,
const std::vector<kAippDynamicBatchPara> &aipp_batch_para,
const kAippDynamicPara &aipp_parms) {
return impl_->SetDynamicAippData(dynamic_input_addr, length, aipp_batch_para, aipp_parms);
}
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 GetOm2ModelMetadata(const std::string &model_path, std::vector<ge::Om2TensorDesc> &input_desc,
std::vector<ge::Om2TensorDesc> &input_desc_v2,
std::vector<ge::Om2TensorDesc> &output_desc,
std::vector<ge::Om2TensorDesc> &output_desc_v2) {
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(GetOm2ModelMetadataFromArchive(archive, input_desc, input_desc_v2, output_desc, output_desc_v2));
return ge::SUCCESS;
}
ge::Status GetOm2ModelMetadata(const void *model_data, size_t model_size, std::vector<ge::Om2TensorDesc> &input_desc,
std::vector<ge::Om2TensorDesc> &input_desc_v2,
std::vector<ge::Om2TensorDesc> &output_desc,
std::vector<ge::Om2TensorDesc> &output_desc_v2) {
ge::RAIIZipArchive archive(static_cast<const uint8_t *>(model_data), model_size);
GE_ASSERT_TRUE(archive.IsGood());
GE_ASSERT_SUCCESS(GetOm2ModelMetadataFromArchive(archive, input_desc, input_desc_v2, output_desc, output_desc_v2));
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;
}
}