From f45ca99de657d87d49f80b1d2068bec1bfcca43b Mon Sep 17 00:00:00 2001 From: Przemyslaw Wysocki Date: Thu, 31 Mar 2022 11:14:51 +0200 Subject: [PATCH] [PYTHON] Add ov::clone_function bindings (#11331) * Add clone_function bindings * Add clone_function binding tests * Debugging changes * Minor changes * Code style * Add an assert * Update src/bindings/python/tests/test_ngraph/test_basic.py * Update src/bindings/python/src/pyopenvino/graph/model.cpp Co-authored-by: Jan Iwaszkiewicz Co-authored-by: Anastasia Kuporosova --- .../src/openvino/runtime/utils/__init__.py | 1 + .../python/src/pyopenvino/graph/model.cpp | 12 ++++++++++ .../python/src/pyopenvino/graph/util.cpp | 14 +++++++++++ .../python/tests/test_ngraph/test_basic.py | 24 +++++++++++++++++++ 4 files changed, 51 insertions(+) diff --git a/src/bindings/python/src/openvino/runtime/utils/__init__.py b/src/bindings/python/src/openvino/runtime/utils/__init__.py index 90356e3bd98..b2432405f85 100644 --- a/src/bindings/python/src/openvino/runtime/utils/__init__.py +++ b/src/bindings/python/src/openvino/runtime/utils/__init__.py @@ -4,4 +4,5 @@ """Generic utilities. Factor related functions out to separate files.""" from openvino.pyopenvino.util import numpy_to_c +from openvino.pyopenvino.util import clone_model from openvino.pyopenvino.util import get_constant_from_source, replace_node, replace_output_update_name diff --git a/src/bindings/python/src/pyopenvino/graph/model.cpp b/src/bindings/python/src/pyopenvino/graph/model.cpp index 5bc4b6e4dcc..ab76a678623 100644 --- a/src/bindings/python/src/pyopenvino/graph/model.cpp +++ b/src/bindings/python/src/pyopenvino/graph/model.cpp @@ -7,6 +7,7 @@ #include #include +#include "openvino/core/graph_util.hpp" #include "openvino/core/model.hpp" // ov::Model #include "openvino/core/partial_shape.hpp" #include "openvino/op/parameter.hpp" // ov::op::v0::Parameter @@ -656,6 +657,17 @@ void regclass_graph_Model(py::module m) { :rtype: bool )"); + model.def( + "clone", + [](ov::Model& self) { + return ov::clone_model(self); + }, + R"( + Return a copy of self. + :return: A copy of self. + :rtype: openvino.runtime.Model + )"); + model.def("__repr__", [](const ov::Model& self) { std::string class_name = py::cast(self).get_type().attr("__name__").cast(); diff --git a/src/bindings/python/src/pyopenvino/graph/util.cpp b/src/bindings/python/src/pyopenvino/graph/util.cpp index e9d01b32760..4393e64456c 100644 --- a/src/bindings/python/src/pyopenvino/graph/util.cpp +++ b/src/bindings/python/src/pyopenvino/graph/util.cpp @@ -36,6 +36,20 @@ void regmodule_graph_util(py::module m) { from the resulting bound, otherwise Null. :rtype: openvino.runtime.op.Constant or openvino.runtime.Node )"); + mod.def( + "clone_model", + [](ov::Model& model) { + return ov::clone_model(model); + }, + py::arg("model"), + R"( + Creates a copy of a model object. + + :param model: Model to copy. + :type model: openvino.runtime.Model + :return: A copy of Model. + :rtype: openvino.runtime.Model + )"); mod.def("replace_output_update_name", &ov::replace_output_update_name, py::arg("output"), py::arg("target_output")); diff --git a/src/bindings/python/tests/test_ngraph/test_basic.py b/src/bindings/python/tests/test_ngraph/test_basic.py index a355bb80bee..da0f39531ba 100644 --- a/src/bindings/python/tests/test_ngraph/test_basic.py +++ b/src/bindings/python/tests/test_ngraph/test_basic.py @@ -327,6 +327,30 @@ def test_set_argument(): assert np.allclose(data1 + data2, output) +def test_clone_model(): + # Create an original model + shape = [2, 2] + parameter_a = ops.parameter(shape, dtype=np.float32, name="A") + parameter_b = ops.parameter(shape, dtype=np.float32, name="B") + model_original = ov.Model(parameter_a + parameter_b, [parameter_a, parameter_b]) + + # Make copies of it + model_copy1 = ov.utils.clone_model(model_original) + model_copy2 = model_original.clone() + + # Make changes to the copied models' inputs + model_copy1.reshape({"A": [3, 3], "B": [3, 3]}) + model_copy2.reshape({"A": [3, 3], "B": [3, 3]}) + + original_model_shapes = [single_input.get_shape() for single_input in model_original.inputs] + model_copy1_shapes = [single_input.get_shape() for single_input in model_copy1.inputs] + model_copy2_shapes = [single_input.get_shape() for single_input in model_copy2.inputs] + + assert original_model_shapes != model_copy1_shapes + assert original_model_shapes != model_copy2_shapes + assert model_copy1_shapes == model_copy2_shapes + + def test_result(): node = np.array([[11, 10], [1, 8], [3, 4]], dtype=np.float32) result = run_op_node([node], ops.result)