[core][python] ov::serialize (#10945)
* add ov::serialize * create python binding * update python tools * use ov::serialize in benchmark app * remove serialize from python offline_transformations * fix import * revert pot * update docs * apply review comments * add const * make bin path optional * Add docs * add compare test
This commit is contained in:
parent
af874e7754
commit
3de9189d50
@ -199,7 +199,7 @@ void save_example() {
|
||||
// ======== Step 3: Save the model ================
|
||||
std::string xml = "/path/to/some_model_saved.xml";
|
||||
std::string bin = "/path/to/some_model_saved.bin";
|
||||
ov::pass::Serialize(xml, bin).run_on_model(model);
|
||||
ov::serialize(model, xml, bin);
|
||||
//! [ov:preprocess:save]
|
||||
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
#
|
||||
|
||||
from openvino.preprocess import ResizeAlgorithm, ColorFormat
|
||||
from openvino.runtime import Layout, Type
|
||||
from openvino.runtime import Layout, Type, serialize
|
||||
|
||||
|
||||
xml_path = ''
|
||||
@ -210,11 +210,7 @@ model = ppp.build()
|
||||
set_batch(model, 2)
|
||||
|
||||
# ======== Step 3: Save the model ================
|
||||
pass_manager = Manager()
|
||||
pass_manager.register_pass(pass_name="Serialize",
|
||||
xml_path='/path/to/some_model_saved.xml',
|
||||
bin_path='/path/to/some_model_saved.bin')
|
||||
pass_manager.run_passes(model)
|
||||
serialize(model, '/path/to/some_model_saved.xml', '/path/to/some_model_saved.bin')
|
||||
# ! [ov:preprocess:save]
|
||||
|
||||
# ! [ov:preprocess:save_load]
|
||||
|
@ -1103,9 +1103,7 @@ int main(int argc, char* argv[]) {
|
||||
|
||||
if (!FLAGS_exec_graph_path.empty()) {
|
||||
try {
|
||||
std::string fileName = fileNameNoExt(FLAGS_exec_graph_path);
|
||||
ov::pass::Serialize serializer(fileName + ".xml", fileName + ".bin");
|
||||
serializer.run_on_model(std::const_pointer_cast<ov::Model>(compiledModel.get_runtime_model()));
|
||||
ov::serialize(compiledModel.get_runtime_model(), FLAGS_exec_graph_path);
|
||||
slog::info << "executable graph is stored to " << FLAGS_exec_graph_path << slog::endl;
|
||||
} catch (const std::exception& ex) {
|
||||
slog::err << "Can't get executable graph: " << ex.what() << slog::endl;
|
||||
|
@ -15,6 +15,5 @@ from openvino.pyopenvino.offline_transformations import apply_low_latency_transf
|
||||
from openvino.pyopenvino.offline_transformations import apply_pruning_transformation
|
||||
from openvino.pyopenvino.offline_transformations import generate_mapping_file
|
||||
from openvino.pyopenvino.offline_transformations import apply_make_stateful_transformation
|
||||
from openvino.pyopenvino.offline_transformations import serialize
|
||||
from openvino.pyopenvino.offline_transformations import compress_model_transformation
|
||||
from openvino.pyopenvino.offline_transformations import compress_quantize_weights_transformation
|
||||
|
@ -47,6 +47,7 @@ from openvino.pyopenvino import ProfilingInfo
|
||||
from openvino.pyopenvino import get_version
|
||||
from openvino.pyopenvino import get_batch
|
||||
from openvino.pyopenvino import set_batch
|
||||
from openvino.pyopenvino import serialize
|
||||
|
||||
# Import opsets
|
||||
from openvino.runtime import opset1
|
||||
|
@ -505,4 +505,20 @@ py::dict outputs_to_dict(const std::vector<ov::Output<const ov::Node>>& outputs,
|
||||
return res;
|
||||
}
|
||||
|
||||
ov::pass::Serialize::Version convert_to_version(const std::string& version) {
|
||||
using Version = ov::pass::Serialize::Version;
|
||||
|
||||
if (version == "UNSPECIFIED") {
|
||||
return Version::UNSPECIFIED;
|
||||
}
|
||||
if (version == "IR_V10") {
|
||||
return Version::IR_V10;
|
||||
}
|
||||
if (version == "IR_V11") {
|
||||
return Version::IR_V11;
|
||||
}
|
||||
throw ov::Exception("Invoked with wrong version argument: '" + version +
|
||||
"'! The supported versions are: 'UNSPECIFIED'(default), 'IR_V10', 'IR_V11'.");
|
||||
}
|
||||
|
||||
}; // namespace Common
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "openvino/runtime/infer_request.hpp"
|
||||
#include "openvino/runtime/tensor.hpp"
|
||||
#include "openvino/runtime/properties.hpp"
|
||||
#include "openvino/pass/serialize.hpp"
|
||||
#include "pyopenvino/core/containers.hpp"
|
||||
#include "pyopenvino/graph/any.hpp"
|
||||
|
||||
@ -55,6 +56,8 @@ uint32_t get_optimal_number_of_requests(const ov::CompiledModel& actual);
|
||||
|
||||
py::dict outputs_to_dict(const std::vector<ov::Output<const ov::Node>>& outputs, ov::InferRequest& request);
|
||||
|
||||
ov::pass::Serialize::Version convert_to_version(const std::string& version);
|
||||
|
||||
// Use only with classes that are not creatable by users on Python's side, because
|
||||
// Objects created in Python that are wrapped with such wrapper will cause memory leaks.
|
||||
template <typename T>
|
||||
|
@ -21,19 +21,6 @@
|
||||
#include "openvino/pass/low_latency.hpp"
|
||||
#include "openvino/pass/manager.hpp"
|
||||
|
||||
using Version = ov::pass::Serialize::Version;
|
||||
|
||||
inline Version convert_to_version(const std::string& version) {
|
||||
if (version == "UNSPECIFIED")
|
||||
return Version::UNSPECIFIED;
|
||||
if (version == "IR_V10")
|
||||
return Version::IR_V10;
|
||||
if (version == "IR_V11")
|
||||
return Version::IR_V11;
|
||||
throw ov::Exception("Invoked with wrong version argument: '" + version +
|
||||
"'! The supported versions are: 'UNSPECIFIED'(default), 'IR_V10', 'IR_V11'.");
|
||||
}
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
void regmodule_offline_transformations(py::module m) {
|
||||
@ -129,63 +116,4 @@ void regmodule_offline_transformations(py::module m) {
|
||||
manager.run_passes(model);
|
||||
},
|
||||
py::arg("model"));
|
||||
|
||||
// todo: remove as serialize as part of passManager api will be merged
|
||||
m_offline_transformations.def(
|
||||
"serialize",
|
||||
[](std::shared_ptr<ov::Model> model,
|
||||
const std::string& path_to_xml,
|
||||
const std::string& path_to_bin,
|
||||
const std::string& version) {
|
||||
ov::pass::Manager manager;
|
||||
manager.register_pass<ov::pass::Serialize>(path_to_xml, path_to_bin, convert_to_version(version));
|
||||
manager.run_passes(model);
|
||||
},
|
||||
py::arg("model"),
|
||||
py::arg("model_path"),
|
||||
py::arg("weights_path"),
|
||||
py::arg("version") = "UNSPECIFIED",
|
||||
R"(
|
||||
Serialize given model into IR. The generated .xml and .bin files will be saved
|
||||
into provided paths.
|
||||
|
||||
:param model: model which will be converted to IR representation
|
||||
:type model: openvino.runtime.Model
|
||||
:param xml_path: path where .xml file will be saved
|
||||
:type xml_path: str
|
||||
:param bin_path: path where .bin file will be saved
|
||||
:type bin_path: str
|
||||
:param version: sets the version of the IR which will be generated.
|
||||
Supported versions are:
|
||||
- "UNSPECIFIED" (default) : Use the latest or model version
|
||||
- "IR_V10" : v10 IR
|
||||
- "IR_V11" : v11 IR
|
||||
|
||||
:Examples:
|
||||
|
||||
1. Default IR version:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
shape = [2, 2]
|
||||
parameter_a = ov.parameter(shape, dtype=np.float32, name="A")
|
||||
parameter_b = ov.parameter(shape, dtype=np.float32, name="B")
|
||||
parameter_c = ov.parameter(shape, dtype=np.float32, name="C")
|
||||
model = (parameter_a + parameter_b) * parameter_c
|
||||
func = Model(model, [parameter_a, parameter_b, parameter_c], "Model")
|
||||
# IR generated with default version
|
||||
serialize(func, model_path="./serialized.xml", weights_path="./serialized.bin")
|
||||
|
||||
2. IR version 11:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
parameter_a = ov.parameter(shape, dtype=np.float32, name="A")
|
||||
parameter_b = ov.parameter(shape, dtype=np.float32, name="B")
|
||||
parameter_c = ov.parameter(shape, dtype=np.float32, name="C")
|
||||
model = (parameter_a + parameter_b) * parameter_c
|
||||
func = Model(model, [parameter_a, parameter_b, parameter_c], "Model")
|
||||
# IR generated with default version
|
||||
serialize(func, model_path="./serialized.xml", "./serialized.bin", version="IR_V11")
|
||||
)");
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include <pybind11/pybind11.h>
|
||||
|
||||
#include <openvino/core/graph_util.hpp>
|
||||
#include <openvino/core/model.hpp>
|
||||
#include <openvino/core/node.hpp>
|
||||
#include <openvino/core/version.hpp>
|
||||
@ -95,6 +96,60 @@ PYBIND11_MODULE(pyopenvino, m) {
|
||||
py::arg("model"),
|
||||
py::arg("batch_size") = -1);
|
||||
|
||||
m.def(
|
||||
"serialize",
|
||||
[](std::shared_ptr<ov::Model>& model,
|
||||
const std::string& xml_path,
|
||||
const std::string& bin_path,
|
||||
const std::string& version) {
|
||||
ov::serialize(model, xml_path, bin_path, Common::convert_to_version(version));
|
||||
},
|
||||
py::arg("model"),
|
||||
py::arg("xml_path"),
|
||||
py::arg("bin_path") = "",
|
||||
py::arg("version") = "UNSPECIFIED",
|
||||
R"(
|
||||
Serialize given model into IR. The generated .xml and .bin files will be saved
|
||||
into provided paths.
|
||||
:param model: model which will be converted to IR representation
|
||||
:type model: openvino.runtime.Model
|
||||
:param xml_path: path where .xml file will be saved
|
||||
:type xml_path: str
|
||||
:param bin_path: path where .bin file will be saved (optional),
|
||||
the same name as for xml_path will be used by default.
|
||||
:type bin_path: str
|
||||
:param version: version of the generated IR (optional).
|
||||
Supported versions are:
|
||||
- "UNSPECIFIED" (default) : Use the latest or model version
|
||||
- "IR_V10" : v10 IR
|
||||
- "IR_V11" : v11 IR
|
||||
|
||||
:Examples:
|
||||
|
||||
1. Default IR version:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
shape = [2, 2]
|
||||
parameter_a = ov.parameter(shape, dtype=np.float32, name="A")
|
||||
parameter_b = ov.parameter(shape, dtype=np.float32, name="B")
|
||||
parameter_c = ov.parameter(shape, dtype=np.float32, name="C")
|
||||
op = (parameter_a + parameter_b) * parameter_c
|
||||
model = Model(op, [parameter_a, parameter_b, parameter_c], "Model")
|
||||
# IR generated with default version
|
||||
serialize(model, xml_path="./serialized.xml", bin_path="./serialized.bin")
|
||||
2. IR version 11:
|
||||
|
||||
.. code-block:: python
|
||||
parameter_a = ov.parameter(shape, dtype=np.float32, name="A")
|
||||
parameter_b = ov.parameter(shape, dtype=np.float32, name="B")
|
||||
parameter_c = ov.parameter(shape, dtype=np.float32, name="C")
|
||||
op = (parameter_a + parameter_b) * parameter_c
|
||||
model = Model(ops, [parameter_a, parameter_b, parameter_c], "Model")
|
||||
# IR generated with default version
|
||||
serialize(model, xml_path="./serialized.xml", bin_path="./serialized.bin", version="IR_V11")
|
||||
)");
|
||||
|
||||
regclass_graph_PyRTMap(m);
|
||||
regmodule_graph_types(m);
|
||||
regclass_graph_Dimension(m); // Dimension must be registered before PartialShape
|
||||
|
@ -3,9 +3,10 @@
|
||||
|
||||
import os
|
||||
import numpy as np
|
||||
from openvino.runtime import serialize
|
||||
from openvino.offline_transformations import apply_moc_transformations, apply_pot_transformations, \
|
||||
apply_low_latency_transformation, apply_pruning_transformation, apply_make_stateful_transformation, \
|
||||
compress_model_transformation, serialize
|
||||
compress_model_transformation
|
||||
|
||||
from openvino.runtime import Model, PartialShape, Core
|
||||
import openvino.runtime as ov
|
||||
@ -140,6 +141,16 @@ def test_Version_default():
|
||||
os.remove(bin_path)
|
||||
|
||||
|
||||
def test_serialize_default_bin():
|
||||
xml_path = "./serialized_function.xml"
|
||||
bin_path = "./serialized_function.bin"
|
||||
model = get_test_function()
|
||||
serialize(model, xml_path)
|
||||
assert os.path.exists(bin_path)
|
||||
os.remove(xml_path)
|
||||
os.remove(bin_path)
|
||||
|
||||
|
||||
def test_Version_ir_v10():
|
||||
core = Core()
|
||||
xml_path = "./serialized_function.xml"
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "openvino/core/model.hpp"
|
||||
#include "openvino/core/node.hpp"
|
||||
#include "openvino/op/parameter.hpp"
|
||||
#include "openvino/pass/serialize.hpp"
|
||||
|
||||
namespace ov {
|
||||
|
||||
@ -278,4 +279,16 @@ bool replace_output_update_name(Output<Node> node, const Output<Node>& node_inpu
|
||||
|
||||
OPENVINO_API
|
||||
bool replace_node_update_name(const std::shared_ptr<Node>& target, const std::shared_ptr<Node>& replacement);
|
||||
|
||||
/// \brief Serialize given model into IR. The generated .xml and .bin files will be saved into provided paths.
|
||||
/// \param m Model which will be converted to IR representation.
|
||||
/// \param xml_path Path where .xml file will be saved.
|
||||
/// \param bin_path Path where .bin file will be saved (optional).
|
||||
/// The same name as for xml_path will be used by default.
|
||||
/// \param version Version of the generated IR (optional).
|
||||
OPENVINO_API
|
||||
void serialize(const std::shared_ptr<const ov::Model>& m,
|
||||
const std::string& xml_path,
|
||||
const std::string& bin_path = "",
|
||||
ov::pass::Serialize::Version version = ov::pass::Serialize::Version::UNSPECIFIED);
|
||||
} // namespace ov
|
||||
|
@ -808,3 +808,12 @@ bool ov::replace_node_update_name(const std::shared_ptr<Node>& target, const std
|
||||
copy_runtime_info(target, replacement);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ov::serialize(const std::shared_ptr<const ov::Model>& m,
|
||||
const std::string& xml_path,
|
||||
const std::string& bin_path,
|
||||
ov::pass::Serialize::Version version) {
|
||||
ov::pass::Manager manager;
|
||||
manager.register_pass<ov::pass::Serialize>(xml_path, bin_path, version);
|
||||
manager.run_passes(std::const_pointer_cast<ov::Model>(m));
|
||||
}
|
||||
|
@ -24,6 +24,20 @@ public:
|
||||
std::string m_out_xml_path;
|
||||
std::string m_out_bin_path;
|
||||
|
||||
void CompareSerialized(std::function<void(const std::shared_ptr<ov::Model>&)> serializer) {
|
||||
auto expected = ov::test::readModel(m_model_path, m_binary_path);
|
||||
auto orig = ov::clone_model(*expected);
|
||||
serializer(expected);
|
||||
auto result = ov::test::readModel(m_out_xml_path, m_out_bin_path);
|
||||
const auto fc = FunctionsComparator::with_default()
|
||||
.enable(FunctionsComparator::ATTRIBUTES)
|
||||
.enable(FunctionsComparator::CONST_VALUES);
|
||||
const auto res = fc.compare(result, expected);
|
||||
const auto res2 = fc.compare(expected, orig);
|
||||
EXPECT_TRUE(res.valid) << res.message;
|
||||
EXPECT_TRUE(res2.valid) << res2.message;
|
||||
}
|
||||
|
||||
void SetUp() override {
|
||||
m_model_path = ov::util::path_join({SERIALIZED_ZOO, "ir/", std::get<0>(GetParam())});
|
||||
if (!std::get<1>(GetParam()).empty()) {
|
||||
@ -42,17 +56,15 @@ public:
|
||||
};
|
||||
|
||||
TEST_P(SerializationTest, CompareFunctions) {
|
||||
auto expected = ov::test::readModel(m_model_path, m_binary_path);
|
||||
auto orig = ov::clone_model(*expected);
|
||||
ov::pass::Serialize(m_out_xml_path, m_out_bin_path).run_on_model(expected);
|
||||
auto result = ov::test::readModel(m_out_xml_path, m_out_bin_path);
|
||||
const auto fc = FunctionsComparator::with_default()
|
||||
.enable(FunctionsComparator::ATTRIBUTES)
|
||||
.enable(FunctionsComparator::CONST_VALUES);
|
||||
const auto res = fc.compare(result, expected);
|
||||
const auto res2 = fc.compare(expected, orig);
|
||||
EXPECT_TRUE(res.valid) << res.message;
|
||||
EXPECT_TRUE(res2.valid) << res2.message;
|
||||
CompareSerialized([this](const std::shared_ptr<ov::Model>& m) {
|
||||
ov::pass::Serialize(m_out_xml_path, m_out_bin_path).run_on_model(m);
|
||||
});
|
||||
}
|
||||
|
||||
TEST_P(SerializationTest, SerializeHelper) {
|
||||
CompareSerialized([this](const std::shared_ptr<ov::Model>& m) {
|
||||
ov::serialize(m, m_out_xml_path, m_out_bin_path);
|
||||
});
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
|
@ -3,9 +3,8 @@
|
||||
|
||||
from collections import defaultdict
|
||||
import datetime
|
||||
from openvino.runtime import Core, Model, PartialShape, Dimension, Layout, Type
|
||||
from openvino.runtime import Core, Model, PartialShape, Dimension, Layout, Type, serialize
|
||||
from openvino.preprocess import PrePostProcessor
|
||||
from openvino.runtime.passes import Manager
|
||||
|
||||
from .constants import DEVICE_DURATION_IN_SECS, UNKNOWN_DEVICE_TYPE, \
|
||||
CPU_DEVICE_NAME, GPU_DEVICE_NAME
|
||||
@ -308,11 +307,7 @@ def process_help_inference_string(benchmark_app, device_number_streams):
|
||||
|
||||
|
||||
def dump_exec_graph(compiled_model, model_path):
|
||||
weight_path = model_path[:model_path.find(".xml")] + ".bin"
|
||||
pass_manager = Manager()
|
||||
pass_manager.register_pass("Serialize", model_path, weight_path)
|
||||
pass_manager.run_passes(compiled_model.get_runtime_model())
|
||||
|
||||
serialize(compiled_model.get_runtime_model(), model_path)
|
||||
|
||||
|
||||
def print_perf_counters(perf_counts_list):
|
||||
|
@ -54,7 +54,8 @@ def apply_offline_transformations(input_model: str, argv: argparse.Namespace):
|
||||
# to produce correct mapping
|
||||
extract_names = argv.framework in ['tf', 'mxnet', 'kaldi']
|
||||
|
||||
from openvino.offline_transformations import generate_mapping_file, serialize # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.runtime import serialize # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.offline_transformations import generate_mapping_file # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.frontend import FrontEndManager # pylint: disable=no-name-in-module,import-error
|
||||
from openvino.tools.mo.back.preprocessing import apply_preprocessing # pylint: disable=no-name-in-module,import-error
|
||||
|
||||
|
@ -40,7 +40,8 @@ def moc_emit_ir(ngraph_function: Model, argv: argparse.Namespace):
|
||||
|
||||
orig_model_name = os.path.normpath(os.path.join(output_dir, argv.model_name))
|
||||
|
||||
from openvino.offline_transformations import serialize, generate_mapping_file # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.runtime import serialize # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.offline_transformations import generate_mapping_file # pylint: disable=import-error,no-name-in-module
|
||||
serialize(ngraph_function, (orig_model_name + ".xml").encode('utf-8'), (orig_model_name + ".bin").encode('utf-8'))
|
||||
|
||||
del argv.feManager
|
||||
|
@ -51,9 +51,9 @@ def import_core_modules(silent: bool, path_to_module: str):
|
||||
from openvino.offline_transformations import apply_moc_transformations, apply_moc_legacy_transformations,\
|
||||
apply_low_latency_transformation # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.offline_transformations import apply_make_stateful_transformation, generate_mapping_file # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.offline_transformations import generate_mapping_file, apply_make_stateful_transformation, serialize # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.offline_transformations import generate_mapping_file, apply_make_stateful_transformation # pylint: disable=import-error,no-name-in-module
|
||||
|
||||
from openvino.runtime import Model, get_version # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.runtime import Model, serialize, get_version # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.runtime.op import Parameter # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.runtime import PartialShape, Dimension # pylint: disable=import-error,no-name-in-module
|
||||
from openvino.frontend import FrontEndManager, FrontEnd # pylint: disable=no-name-in-module,import-error
|
||||
|
@ -34,6 +34,7 @@ def load_graph(model_config, target_device='ANY'):
|
||||
apply_pot_transformations(model, target_device.encode('utf-8'))
|
||||
bin_path = serialized_bin_path
|
||||
xml_path = serialized_xml_path
|
||||
# TODO: replace by openvino.runtime.serialize
|
||||
pass_manager.register_pass(pass_name="Serialize", xml_path=xml_path, bin_path=bin_path)
|
||||
pass_manager.run_passes(model)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user