From d314a7c3502b37fa88c23f8dcb1b2389ab917ddc Mon Sep 17 00:00:00 2001 From: Mikhail Ryzhov Date: Tue, 30 Mar 2021 10:46:35 +0300 Subject: [PATCH 01/10] Added version.txt to MO wheel (#4982) --- model-optimizer/setup.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/model-optimizer/setup.py b/model-optimizer/setup.py index 4ba80b119ad37f..4589eec79ff50c 100644 --- a/model-optimizer/setup.py +++ b/model-optimizer/setup.py @@ -15,6 +15,7 @@ from setuptools import setup, find_packages from setuptools.command.install import install from setuptools.command.build_py import build_py +from shutil import copyfile package_name = 'mo' @@ -44,6 +45,11 @@ def run(self): path = os.path.join(self.install_purelib, package_name, name) with open(path, 'wt') as f: f.write('\n'.join(deps)) + # Add version.txt if exists + version_txt = 'version.txt' + if os.path.exists(version_txt): + copyfile(os.path.join(version_txt), + os.path.join(self.install_purelib, package_name, version_txt)) path = os.path.join(self.install_purelib, package_name, '__init__.py') with open(path, 'wt') as f: From 38bb66741f4337c446c4b32ff1d85a108c3fc164 Mon Sep 17 00:00:00 2001 From: Anastasia Kuporosova Date: Tue, 30 Mar 2021 11:45:05 +0300 Subject: [PATCH 02/10] [Python API] use parametrize in blob tests (#5020) Co-authored-by: anastasia.kuporosova --- .../ie_bridges/python/tests/test_Blob.py | 64 +++++-------------- 1 file changed, 16 insertions(+), 48 deletions(-) diff --git a/inference-engine/ie_bridges/python/tests/test_Blob.py b/inference-engine/ie_bridges/python/tests/test_Blob.py index 91c16102b5046b..1f0d00519ab02c 100644 --- a/inference-engine/ie_bridges/python/tests/test_Blob.py +++ b/inference-engine/ie_bridges/python/tests/test_Blob.py @@ -39,7 +39,22 @@ def test_get_buffer(): blob = Blob(tensor_desc, array) assert np.array_equal(blob.buffer, array) -def write_to_buffer(precision, numpy_precision): + +@pytest.mark.parametrize("precision, numpy_precision", [ + ("FP32", np.float32), + ("FP64", np.float64), + ("FP16", np.float16), + ("I8", np.int8), + ("U8", np.uint8), + ("I32", np.int32), + ("I16", np.int16), + ("U16", np.uint16), + ("I64", np.int64), + ("BOOL", np.uint8), + ("BIN", np.int8), + ("BF16", np.float16), +]) +def test_write_to_buffer(precision, numpy_precision): tensor_desc = TensorDesc(precision, [1, 3, 127, 127], "NCHW") array = np.zeros(shape=(1, 3, 127, 127), dtype=numpy_precision) blob = Blob(tensor_desc, array) @@ -47,53 +62,6 @@ def write_to_buffer(precision, numpy_precision): blob.buffer[:] = ones_arr assert np.array_equal(blob.buffer, ones_arr) -def test_write_to_buffer_fp32(): - write_to_buffer("FP32", np.float32) - - -def test_write_to_buffer_fp64(): - write_to_buffer("FP64", np.float64) - - -def test_write_to_buffer_fp16(): - write_to_buffer("FP16", np.float16) - - -def test_write_to_buffer_int8(): - write_to_buffer("I8", np.int8) - - -def test_write_to_buffer_uint8(): - write_to_buffer("U8", np.uint8) - - -def test_write_to_buffer_int32(): - write_to_buffer("I32", np.int32) - - -def test_write_to_buffer_int16(): - write_to_buffer("I16", np.int16) - - -def test_write_to_buffer_uint16(): - write_to_buffer("U16", np.uint16) - - -def test_write_to_buffer_int64(): - write_to_buffer("I64", np.int64) - - -def test_write_to_buffer_bool(): - write_to_buffer("BOOL", np.uint8) - - -def test_write_to_buffer_bin(): - write_to_buffer("BIN", np.int8) - - -def test_write_to_buffer_bf16(): - write_to_buffer("BF16", np.float16) - def test_write_numpy_scalar_int64(): tensor_desc = TensorDesc("I64", [], "SCALAR") From b4a2ac9d1cc94ef37bc0eca40b2cb407adb9a7ce Mon Sep 17 00:00:00 2001 From: Irina Efode Date: Tue, 30 Mar 2021 12:14:35 +0300 Subject: [PATCH 03/10] [IE TESTS] Fix issue with report merge (#5031) --- .../functional_test_utils/layer_tests_summary/merge_xmls.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/merge_xmls.py b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/merge_xmls.py index 414709fdfd1b08..75cebf36223c5d 100644 --- a/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/merge_xmls.py +++ b/inference-engine/tests/ie_test_utils/functional_test_utils/layer_tests_summary/merge_xmls.py @@ -2,7 +2,6 @@ # SPDX-License-Identifier: Apache-2.0 import xml.etree.ElementTree as ET -from jinja2 import Environment, FileSystemLoader import argparse import os from datetime import datetime @@ -81,7 +80,7 @@ def merge_xml(input_folder_paths: list, output_folder_paths: str): logger.error(f" {folder_path} is not a directory!") continue - xml_reports = glob.glob(os.path.join(folder_path, 'report*.xml')) + xml_reports = glob.glob(os.path.join(folder_path, '**/report*.xml')) xml_root = ET.parse(xml_reports[0]).getroot() for op in xml_root.find("ops_list"): @@ -93,6 +92,8 @@ def merge_xml(input_folder_paths: list, output_folder_paths: str): summary.set("timestamp", timestamp) logger.info(f" Processing is finished") + if not os.path.exists(output_folder_paths): + os.mkdir(output_folder_paths) out_file_path = os.path.join(output_folder_paths, "report.xml") with open(out_file_path, "w") as xml_file: xml_file.write(ET.tostring(summary).decode('utf8')) From a2a7320d745ebd4bbf3ddaf193b780fadb0868bf Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Tue, 30 Mar 2021 12:28:18 +0300 Subject: [PATCH 04/10] [MO] Fix EfficientDet conversion (#5029) --- model-optimizer/extensions/front/tf/AutomlEfficientDet.py | 6 ++++-- .../extensions/front/tf/automl_efficientdet.json | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/model-optimizer/extensions/front/tf/AutomlEfficientDet.py b/model-optimizer/extensions/front/tf/AutomlEfficientDet.py index c6302da16cc3ed..2ac2a166b669ea 100644 --- a/model-optimizer/extensions/front/tf/AutomlEfficientDet.py +++ b/model-optimizer/extensions/front/tf/AutomlEfficientDet.py @@ -22,6 +22,7 @@ class EfficientDet(FrontReplacementFromConfigFileGeneral): replacement_id = 'AutomlEfficientDet' + run_not_recursively = True def run_before(self): from extensions.front.ExpandDimsToUnsqueeze import ExpandDimsToUnsqueeze @@ -57,10 +58,11 @@ def transform_graph(self, graph: Graph, replacement_descriptions: dict): # which includes padding and resizing from the model preprocessing_input_node_id = replacement_descriptions['preprocessing_input_node'] assert preprocessing_input_node_id in graph.nodes, 'The node with name "{}" is not found in the graph. This ' \ - 'node should provide scaled image output and is specified' \ + 'should be a last node before image normalization and is specified' \ ' in the json file.'.format(preprocessing_input_node_id) preprocessing_input_node = Node(graph, preprocessing_input_node_id) - preprocessing_input_node.in_port(0).get_connection().set_source(parameter_node.out_port(0)) + consumer_node = preprocessing_input_node.out_port(0).get_connection().get_destination().node + consumer_node.in_port(0).get_connection().set_source(parameter_node.out_port(0)) preprocessing_output_node_id = replacement_descriptions['preprocessing_output_node'] assert preprocessing_output_node_id in graph.nodes, 'The node with name "{}" is not found in the graph. This ' \ diff --git a/model-optimizer/extensions/front/tf/automl_efficientdet.json b/model-optimizer/extensions/front/tf/automl_efficientdet.json index 19eb1122f0c0d4..ebf13c68ab0495 100644 --- a/model-optimizer/extensions/front/tf/automl_efficientdet.json +++ b/model-optimizer/extensions/front/tf/automl_efficientdet.json @@ -2,7 +2,7 @@ { "id": "AutomlEfficientDet", "custom_attributes": { - "preprocessing_input_node": "convert_image", + "preprocessing_input_node": "strided_slice_1", "preprocessing_output_node": "truediv", "aspect_ratios": [1.0, 1.0, 1.4, 0.7, 0.7, 1.4], "variance": [1.0, 1.0, 1.0, 1.0], From 41f0eb51c564dcde74e2dfc1f07fe0b54c675cdb Mon Sep 17 00:00:00 2001 From: Dmitry Kurtaev Date: Tue, 30 Mar 2021 13:56:49 +0300 Subject: [PATCH 05/10] Enable mo.front.common.extractors module (#5018) * Enable mo.front.common.extractors module * Update package_BOM.txt --- model-optimizer/automation/package_BOM.txt | 1 + model-optimizer/mo/front/common/extractors/__init__.py | 0 2 files changed, 1 insertion(+) create mode 100644 model-optimizer/mo/front/common/extractors/__init__.py diff --git a/model-optimizer/automation/package_BOM.txt b/model-optimizer/automation/package_BOM.txt index e209be46f77fe1..16d7486fd2558f 100644 --- a/model-optimizer/automation/package_BOM.txt +++ b/model-optimizer/automation/package_BOM.txt @@ -797,6 +797,7 @@ mo/front/caffe/python_layer_extractor.py mo/front/caffe/register_custom_ops.py mo/front/common/__init__.py mo/front/common/custom_replacement_registry.py +mo/front/common/extractors/__init__.py mo/front/common/extractors/utils.py mo/front/common/find_unsupported_ops.py mo/front/common/layout.py diff --git a/model-optimizer/mo/front/common/extractors/__init__.py b/model-optimizer/mo/front/common/extractors/__init__.py new file mode 100644 index 00000000000000..e69de29bb2d1d6 From 2f257a29556465f09ac2b4eace567b0753545a22 Mon Sep 17 00:00:00 2001 From: Liubov Batanina Date: Tue, 30 Mar 2021 15:06:36 +0300 Subject: [PATCH 06/10] Added GenerateInput to Reduce tests (#5004) * Added GenerateInput to Reduce tests * Skip ReduceProd CPU tests --- .../single_layer/reduce_ops.hpp | 1 + .../src/single_layer/reduce_ops.cpp | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/reduce_ops.hpp b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/reduce_ops.hpp index 050a6528a7277c..ad8b12deb8599e 100644 --- a/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/reduce_ops.hpp +++ b/inference-engine/tests/functional/shared_test_classes/include/shared_test_classes/single_layer/reduce_ops.hpp @@ -32,6 +32,7 @@ class ReduceOpsLayerTest : public testing::WithParamInterface, virtual public LayerTestsUtils::LayerTestsCommon { public: static std::string getTestCaseName(testing::TestParamInfo obj); + InferenceEngine::Blob::Ptr GenerateInput(const InferenceEngine::InputInfo &info) const override; protected: void SetUp() override; diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/reduce_ops.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/reduce_ops.cpp index 35b04950dbcb17..2054bcb935b16a 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/reduce_ops.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/reduce_ops.cpp @@ -69,6 +69,21 @@ void ReduceOpsLayerTest::SetUp() { const ngraph::ResultVector results{std::make_shared(reduce)}; function = std::make_shared(results, params, "Reduce"); } +InferenceEngine::Blob::Ptr ReduceOpsLayerTest::GenerateInput(const InferenceEngine::InputInfo &info) const { + ngraph::helpers::ReductionType reductionType = std::get<3>(GetParam()); + InferenceEngine::Precision netPrecision = std::get<4>(GetParam()); + if (reductionType == ngraph::helpers::ReductionType::LogicalOr || + reductionType == ngraph::helpers::ReductionType::LogicalAnd) { + return FuncTestUtils::createAndFillBlob(info.getTensorDesc(), 2, 0); + } else if (!netPrecision.is_float()) { + return FuncTestUtils::createAndFillBlob(info.getTensorDesc(), 5, 0); + } + auto td = info.getTensorDesc(); + auto blob = make_blob_with_precision(td); + blob->allocate(); + CommonTestUtils::fill_data_random_float(blob, 5, 0, 1000); + return blob; +} InferenceEngine::Blob::Ptr ReduceOpsLayerWithSpecificInputTest::GenerateInput(const InferenceEngine::InputInfo &info) const { auto axis_vec = std::get<0>(GetParam()); From a26aad1cfa06a58fcabd0859e90f74e79b15b942 Mon Sep 17 00:00:00 2001 From: Anastasia Kuporosova Date: Tue, 30 Mar 2021 15:16:48 +0300 Subject: [PATCH 07/10] [Python API] Skip several tests if device is ARM (#4646) --- .../python/tests/test_ExecutableNetwork.py | 9 +++++--- .../ie_bridges/python/tests/test_IECore.py | 23 +++++++++++++++---- .../ie_bridges/python/tests/test_IENetwork.py | 8 ++++--- .../python/tests/test_InferRequest.py | 8 +++++++ 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/inference-engine/ie_bridges/python/tests/test_ExecutableNetwork.py b/inference-engine/ie_bridges/python/tests/test_ExecutableNetwork.py index d722608696cd82..2193a6501c24bb 100644 --- a/inference-engine/ie_bridges/python/tests/test_ExecutableNetwork.py +++ b/inference-engine/ie_bridges/python/tests/test_ExecutableNetwork.py @@ -234,10 +234,11 @@ def test_plugin_accessible_after_deletion(device): del ie_core -@pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") == "ARM", - reason=f"Cannot run test on device {os.environ.get('TEST_DEVICE')}") def test_exec_graph(device): ie_core = ie.IECore() + if device == "CPU": + if ie_core.get_metric(device, "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin due-to get_exec_graph_info method isn't implemented") net = ie_core.read_network(model=test_net_xml, weights=test_net_bin) exec_net = ie_core.load_network(net, device) img = read_image() @@ -294,9 +295,11 @@ def test_get_metric(device): assert network_name == "test_model" -@pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device independent test") +@pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device dependent test") def test_get_config(device): ie_core = ie.IECore() + if ie_core.get_metric(device, "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin due-to CPU dependent test") net = ie_core.read_network(model=test_net_xml, weights=test_net_bin) exec_net = ie_core.load_network(net, device) config = exec_net.get_config("PERF_COUNT") diff --git a/inference-engine/ie_bridges/python/tests/test_IECore.py b/inference-engine/ie_bridges/python/tests/test_IECore.py index 2684def8b41752..41d28f1c41b1f6 100644 --- a/inference-engine/ie_bridges/python/tests/test_IECore.py +++ b/inference-engine/ie_bridges/python/tests/test_IECore.py @@ -4,7 +4,6 @@ import os import pytest from sys import platform -import numpy as np from pathlib import Path from openvino.inference_engine import IENetwork, IECore, ExecutableNetwork @@ -61,8 +60,11 @@ def test_load_network_wrong_device(): def test_query_network(device): - import ngraph as ng ie = IECore() + if device == "CPU": + if ie.get_metric(device, "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin due-to ngraph") + import ngraph as ng net = ie.read_network(model=test_net_xml, weights=test_net_bin) query_res = ie.query_network(net, device) func_net = ng.function_from_cnn(net) @@ -73,18 +75,22 @@ def test_query_network(device): assert next(iter(set(query_res.values()))) == device, "Wrong device for some layers" -@pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device independent test") +@pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device dependent test") def test_register_plugin(): ie = IECore() + if ie.get_metric("CPU", "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin due-to MKLDNNPlugin specific test") ie.register_plugin("MKLDNNPlugin", "BLA") net = ie.read_network(model=test_net_xml, weights=test_net_bin) exec_net = ie.load_network(net, "BLA") assert isinstance(exec_net, ExecutableNetwork), "Cannot load the network to the registered plugin with name 'BLA'" -@pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device independent test") +@pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason="Device dependent test") def test_register_plugins(): ie = IECore() + if ie.get_metric("CPU", "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin due-to MKLDNNPlugin specific test") if platform == "linux" or platform == "linux2": ie.register_plugins(plugins_xml) elif platform == "darwin": @@ -126,11 +132,12 @@ def test_get_metric_list_of_str(): "metric are strings!" - @pytest.mark.skipif(os.environ.get("TEST_DEVICE", "CPU") != "CPU", reason=f"Cannot run test on device {os.environ.get('TEST_DEVICE')}, Plugin specific test") def test_get_metric_tuple_of_two_ints(): ie = IECore() + if ie.get_metric("CPU", "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin due-to unsupported device metric") param = ie.get_metric("CPU", "RANGE_FOR_STREAMS") assert isinstance(param, tuple), "Parameter value for 'RANGE_FOR_STREAMS' " \ f"metric must be tuple but {type(param)} is returned" @@ -142,6 +149,8 @@ def test_get_metric_tuple_of_two_ints(): reason=f"Cannot run test on device {os.environ.get('TEST_DEVICE')}, Plugin specific test") def test_get_metric_tuple_of_three_ints(): ie = IECore() + if ie.get_metric("CPU", "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin due-to unsupported device metric") param = ie.get_metric("CPU", "RANGE_FOR_ASYNC_INFER_REQUESTS") assert isinstance(param, tuple), "Parameter value for 'RANGE_FOR_ASYNC_INFER_REQUESTS' " \ f"metric must be tuple but {type(param)} is returned" @@ -185,21 +194,25 @@ def test_read_network_from_onnx(): net = ie.read_network(model=test_net_onnx) assert isinstance(net, IENetwork) + def test_read_network_from_onnx_as_path(): ie = IECore() net = ie.read_network(model=Path(test_net_onnx)) assert isinstance(net, IENetwork) + def test_read_network_from_prototxt(): ie = IECore() net = ie.read_network(model=test_net_prototxt) assert isinstance(net, IENetwork) + def test_read_network_from_prototxt_as_path(): ie = IECore() net = ie.read_network(model=Path(test_net_prototxt)) assert isinstance(net, IENetwork) + def test_incorrect_xml(): ie = IECore() with pytest.raises(Exception) as e: diff --git a/inference-engine/ie_bridges/python/tests/test_IENetwork.py b/inference-engine/ie_bridges/python/tests/test_IENetwork.py index 60e17268ede4e3..1c3474e689134d 100644 --- a/inference-engine/ie_bridges/python/tests/test_IENetwork.py +++ b/inference-engine/ie_bridges/python/tests/test_IENetwork.py @@ -4,7 +4,6 @@ import os import pytest import warnings -import numpy as np from openvino.inference_engine import IECore, IENetwork, DataPtr, InputInfoPtr, PreProcessInfo from conftest import model_path @@ -183,9 +182,12 @@ def test_batch_size_after_reshape(): assert net.input_info['data'].input_data.shape == [8, 3, 32, 32] -def test_serialize(): - import ngraph as ng +def test_serialize(device): ie = IECore() + if device == "CPU": + if ie.get_metric(device, "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin due-to ngraph") + import ngraph as ng net = ie.read_network(model=test_net_xml, weights=test_net_bin) net.serialize("./serialized_net.xml", "./serialized_net.bin") serialized_net = ie.read_network(model="./serialized_net.xml", weights="./serialized_net.bin") diff --git a/inference-engine/ie_bridges/python/tests/test_InferRequest.py b/inference-engine/ie_bridges/python/tests/test_InferRequest.py index b2783f5cad9c10..5a534703598fc3 100644 --- a/inference-engine/ie_bridges/python/tests/test_InferRequest.py +++ b/inference-engine/ie_bridges/python/tests/test_InferRequest.py @@ -376,6 +376,9 @@ def execute(self, input_data): def test_get_perf_counts(device): ie_core = ie.IECore() + if device == "CPU": + if ie_core.get_metric(device, "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin due-to ngraph") net = ie_core.read_network(test_net_xml, test_net_bin) ie_core.set_config({"PERF_COUNT": "YES"}, device) exec_net = ie_core.load_network(net, device) @@ -395,6 +398,8 @@ def test_get_perf_counts(device): "Dynamic batch fully supported only on CPU") def test_set_batch_size(device): ie_core = ie.IECore() + if ie_core.get_metric(device, "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin due-to dynamic batch isn't supported") ie_core.set_config({"DYN_BATCH_ENABLED": "YES"}, device) net = ie_core.read_network(test_net_xml, test_net_bin) net.batch_size = 10 @@ -438,6 +443,9 @@ def test_set_negative_batch_size(device): def test_blob_setter(device): ie_core = ie.IECore() + if device == "CPU": + if ie_core.get_metric(device, "FULL_DEVICE_NAME") == "arm_compute::NEON": + pytest.skip("Can't run on ARM plugin") net = ie_core.read_network(test_net_xml, test_net_bin) exec_net_1 = ie_core.load_network(network=net, device_name=device, num_requests=1) From 83ec2d321a964cb6e36058f573f9f6418adbeb1f Mon Sep 17 00:00:00 2001 From: Victor Kuznetsov <32412802+just-sparta@users.noreply.github.com> Date: Tue, 30 Mar 2021 15:31:40 +0300 Subject: [PATCH 08/10] Add json file with tests ids to CC tests (#4425) --- tests/conditional_compilation/conftest.py | 35 ++++++++++++++----- tests/conditional_compilation/test_collect.py | 20 ++++++----- tests/conditional_compilation/tests_utils.py | 25 +++++++++++++ 3 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 tests/conditional_compilation/tests_utils.py diff --git a/tests/conditional_compilation/conftest.py b/tests/conditional_compilation/conftest.py index 04618ea9946c9d..764cb497e8fd9f 100644 --- a/tests/conditional_compilation/conftest.py +++ b/tests/conditional_compilation/conftest.py @@ -14,23 +14,22 @@ """ import sys +import pytest +import yaml + from inspect import getsourcefile from pathlib import Path -import pytest -import yaml +from tests_utils import write_session_info, SESSION_INFO_FILE # add ../lib to imports -sys.path.insert( - 0, str((Path(getsourcefile(lambda: 0)) / ".." / ".." / "lib").resolve(strict=True)) -) +sys.path.insert(0, str((Path(getsourcefile(lambda: 0)) / ".." / ".." / "lib").resolve(strict=True))) from path_utils import expand_env_vars # pylint: disable=import-error def pytest_addoption(parser): - """ Define extra options for pytest options - """ + """Define extra options for pytest options.""" parser.addoption( "--test_conf", type=Path, @@ -67,8 +66,7 @@ def pytest_addoption(parser): def pytest_generate_tests(metafunc): - """ Generate tests depending on command line options - """ + """Generate tests depending on command line options.""" params = [] ids = [] @@ -87,6 +85,25 @@ def pytest_generate_tests(metafunc): metafunc.parametrize("test_id, model", params, ids=ids) +@pytest.fixture(scope="function") +def test_info(request, pytestconfig): + """Fixture function for getting the additional attributes of the current test.""" + setattr(request.node._request, "test_info", {}) + if not hasattr(pytestconfig, "session_info"): + setattr(pytestconfig, "session_info", []) + + yield request.node._request.test_info + + pytestconfig.session_info.append(request.node._request.test_info) + + +@pytest.fixture(scope="session", autouse=True) +def save_session_info(pytestconfig, artifacts): + """Fixture function for saving additional attributes to configuration file.""" + yield + write_session_info(path=artifacts / SESSION_INFO_FILE, data=pytestconfig.session_info) + + @pytest.fixture(scope="session") def sea_runtool(request): """Fixture function for command-line option.""" diff --git a/tests/conditional_compilation/test_collect.py b/tests/conditional_compilation/test_collect.py index 055b1cd7b28cac..6014f16e7950bd 100644 --- a/tests/conditional_compilation/test_collect.py +++ b/tests/conditional_compilation/test_collect.py @@ -13,16 +13,19 @@ from proc_utils import cmd_exec # pylint: disable=import-error -def test_cc_collect(test_id, model, sea_runtool, benchmark_app, collector_dir, artifacts): +def test_cc_collect(test_id, model, sea_runtool, benchmark_app, collector_dir, artifacts, test_info): """ Test conditional compilation statistics collection + :param test_info: custom `test_info` field of built-in `request` pytest fixture. + contain a dictionary to store test metadata. """ out = artifacts / test_id + test_info["test_id"] = test_id # cleanup old data if any - prev_results = glob.glob(f"{out}.pid*.csv") - for path in prev_results: + prev_result = glob.glob(f"{out}.pid*.csv") + for path in prev_result: os.remove(path) # run use case - returncode, output = cmd_exec( + return_code, output = cmd_exec( [ sys.executable, str(sea_runtool), @@ -37,7 +40,8 @@ def test_cc_collect(test_id, model, sea_runtool, benchmark_app, collector_dir, a "-nireq=1", ] ) - assert returncode == 0, f"Command exited with non-zero status {returncode}:\n {output}" - assert ( - len(glob.glob(f"{out}.pid*.csv")) == 1 - ), f'Multiple or none "{out}.pid*.csv" files' + out_csv = glob.glob(f"{out}.pid*.csv") + test_info["out_csv"] = out_csv + + assert return_code == 0, f"Command exited with non-zero status {return_code}:\n {output}" + assert (len(out_csv) == 1), f'Multiple or none "{out}.pid*.csv" files' diff --git a/tests/conditional_compilation/tests_utils.py b/tests/conditional_compilation/tests_utils.py new file mode 100644 index 00000000000000..2b186726843017 --- /dev/null +++ b/tests/conditional_compilation/tests_utils.py @@ -0,0 +1,25 @@ +#!/usr/bin/env python3 +# Copyright (C) 2021 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +""" Utility functions for work with json test configuration file. +""" +import json + +from inspect import getsourcefile +from pathlib import Path + + +SESSION_INFO_FILE = "cc_tests.json" + + +def read_session_info(path: Path = Path(getsourcefile(lambda: 0)).parent / SESSION_INFO_FILE): + with open(path, 'r') as json_file: + cc_tests_ids = json.load(json_file) + return cc_tests_ids + + +def write_session_info(path: Path = Path(getsourcefile(lambda: 0)).parent / SESSION_INFO_FILE, + data: dict = None): + with open(path, "w") as json_file: + json.dump(data, json_file, indent=4) From acf778d6553cce5f8aef9288236adc520e7594c0 Mon Sep 17 00:00:00 2001 From: Mateusz Tabaka Date: Tue, 30 Mar 2021 14:43:35 +0200 Subject: [PATCH 09/10] Disallow SoftmaxFusion when input rank is greater than 5 (#5028) --- inference-engine/src/cldnn_engine/cldnn_engine.cpp | 6 ++++++ inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp | 6 ++++++ .../transformations/common_optimizations/softmax_fusion.cpp | 3 +++ 3 files changed, 15 insertions(+) diff --git a/inference-engine/src/cldnn_engine/cldnn_engine.cpp b/inference-engine/src/cldnn_engine/cldnn_engine.cpp index 41aabc518e62ba..51c3f8d3fcd5fe 100644 --- a/inference-engine/src/cldnn_engine/cldnn_engine.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_engine.cpp @@ -32,6 +32,7 @@ #include #include #include "transformations/common_optimizations/convert_quantize_dequantize.hpp" +#include "transformations/common_optimizations/softmax_fusion.hpp" #include #include #include @@ -323,6 +324,11 @@ InferenceEngine::CNNNetwork clDNNEngine::CloneAndTransformNetwork(const Inferenc return false; }); + pass_config->set_callback( + [](const_node_ptr &node) -> bool { + return node->input_value(0).get_partial_shape().rank().get_length() > 5; + }); + // List of enabled/disabled transformations pass_config->disable(); pass_config->disable(); diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp index c4b70fd3b596c6..fcbcdb33423cc2 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp @@ -35,6 +35,7 @@ #include #include "transformations/common_optimizations/convert_quantize_dequantize.hpp" #include +#include #include #include #include @@ -260,6 +261,11 @@ static void Transformation(CNNNetwork& clonedNetwork, const Config& conf) { return MKLDNNMVNNode::checkAxesSuitability(node); }); + pass_config->set_callback( + [](const_node_ptr &node) -> bool { + return node->input_value(0).get_partial_shape().rank().get_length() > 5; + }); + // List of enabled/disabled transformations pass_config->disable(); pass_config->disable(); diff --git a/inference-engine/src/transformations/src/transformations/common_optimizations/softmax_fusion.cpp b/inference-engine/src/transformations/src/transformations/common_optimizations/softmax_fusion.cpp index 6e8a553ad6ffad..25a1a2272d1478 100644 --- a/inference-engine/src/transformations/src/transformations/common_optimizations/softmax_fusion.cpp +++ b/inference-engine/src/transformations/src/transformations/common_optimizations/softmax_fusion.cpp @@ -28,6 +28,9 @@ ngraph::pass::SoftmaxFusion::SoftmaxFusion() { auto div_pattern = ngraph::pattern::wrap_type({exp_pattern, reduce_sum_pattern}); ngraph::matcher_pass_callback callback = [=](pattern::Matcher& m) { + if (transformation_callback(m.get_match_root())) + return false; + const auto& pattern_map = m.get_pattern_value_map(); auto reduce_max_axes = std::dynamic_pointer_cast(pattern_map.at(reduce_max_axes_pattern).get_node_shared_ptr()); From 170223d8424df4a630fa0d817aa521571f987072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Do=C5=82bniak?= Date: Tue, 30 Mar 2021 14:44:44 +0200 Subject: [PATCH 10/10] DeformableConv2D custom ONNX op (#4816) --- .../ngraph/op/deformable_convolution.hpp | 2 +- .../onnx_import/src/core/transform.hpp | 1 + .../deformable_conv_2d.cpp | 51 ++++++++ .../deformable_conv_2d.hpp | 38 ++++++ .../frontend/onnx_import/src/ops_bridge.cpp | 3 + .../deformable_conv_2d.prototxt | 115 ++++++++++++++++++ .../test/onnx/onnx_import_org_openvino.in.cpp | 42 +++++++ ngraph/test/runtime/ie/unit_test.manifest | 3 + .../runtime/interpreter/unit_test.manifest | 5 +- 9 files changed, 258 insertions(+), 2 deletions(-) create mode 100644 ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/deformable_conv_2d.cpp create mode 100644 ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/deformable_conv_2d.hpp create mode 100644 ngraph/test/models/onnx/org.openvinotoolkit/deformable_conv_2d.prototxt diff --git a/ngraph/core/include/ngraph/op/deformable_convolution.hpp b/ngraph/core/include/ngraph/op/deformable_convolution.hpp index cef2cba22367aa..e1a6ad9790b7c6 100644 --- a/ngraph/core/include/ngraph/op/deformable_convolution.hpp +++ b/ngraph/core/include/ngraph/op/deformable_convolution.hpp @@ -26,7 +26,7 @@ namespace ngraph /// /// \param arg Node that produces the input tensor. /// \param deformable_values Node producing the deformable values tensor. - /// \param filters Node producing the filters(kernels) tensor wit OIZYX + /// \param filters Node producing the filters(kernels) tensor with OIZYX /// layout. /// \param strides Convolution strides. /// \param pads_begin Amount of padding to be added to the beginning along diff --git a/ngraph/frontend/onnx_import/src/core/transform.hpp b/ngraph/frontend/onnx_import/src/core/transform.hpp index f2e213a3f94f23..526b0654e2b7d9 100644 --- a/ngraph/frontend/onnx_import/src/core/transform.hpp +++ b/ngraph/frontend/onnx_import/src/core/transform.hpp @@ -42,6 +42,7 @@ namespace ngraph void expand_onnx_functions(ONNX_NAMESPACE::ModelProto& model_proto); static const std::vector legacy_ops_to_fixup = { + "DeformableConv2D", "DetectionOutput", "ExperimentalDetectronDetectionOutput", "ExperimentalDetectronGenerateProposalsSingleImage", diff --git a/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/deformable_conv_2d.cpp b/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/deformable_conv_2d.cpp new file mode 100644 index 00000000000000..f8f81a11efa36a --- /dev/null +++ b/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/deformable_conv_2d.cpp @@ -0,0 +1,51 @@ +//***************************************************************************** +// Copyright 2017-2021 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//***************************************************************************** + +#include "op/org.openvinotoolkit/deformable_conv_2d.hpp" +#include "default_opset.hpp" +#include "ngraph/node.hpp" +#include "ngraph/op/deformable_convolution.hpp" +#include "utils/convpool.hpp" + +namespace ngraph +{ + namespace onnx_import + { + OutputVector op::set_1::deformable_conv_2d(const Node& node) + { + const OutputVector& inputs = node.get_ng_inputs(); + const auto strides = convpool::get_strides(node); + const auto dilations = convpool::get_dilations(node); + const auto paddings = convpool::get_pads(node); + + const auto group = node.get_attribute_value("group", 1); + const auto deformable_groups = + node.get_attribute_value("deformable_groups", 1); + const auto auto_pad_type = convpool::get_auto_pad(node); + + return {std::make_shared(inputs.at(0), + inputs.at(1), + inputs.at(2), + strides, + paddings.first, + paddings.second, + dilations, + auto_pad_type, + group, + deformable_groups)}; + } + } // namespace onnx_import +} // namespace ngraph diff --git a/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/deformable_conv_2d.hpp b/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/deformable_conv_2d.hpp new file mode 100644 index 00000000000000..9f0b7552cb6aac --- /dev/null +++ b/ngraph/frontend/onnx_import/src/op/org.openvinotoolkit/deformable_conv_2d.hpp @@ -0,0 +1,38 @@ +//***************************************************************************** +// Copyright 2017-2021 Intel Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +//***************************************************************************** + +#pragma once + +#include "ngraph/node.hpp" +#include "onnx_import/core/node.hpp" + +namespace ngraph +{ + namespace onnx_import + { + namespace op + { + namespace set_1 + { + OutputVector deformable_conv_2d(const Node& node); + + } // namespace set_1 + + } // namespace op + + } // namespace onnx_import + +} // namespace ngraph diff --git a/ngraph/frontend/onnx_import/src/ops_bridge.cpp b/ngraph/frontend/onnx_import/src/ops_bridge.cpp index b54af15b26e452..e2107c8ade35da 100644 --- a/ngraph/frontend/onnx_import/src/ops_bridge.cpp +++ b/ngraph/frontend/onnx_import/src/ops_bridge.cpp @@ -133,6 +133,7 @@ #include "op/xor.hpp" #include "ops_bridge.hpp" +#include "op/org.openvinotoolkit/deformable_conv_2d.hpp" #include "op/org.openvinotoolkit/detection_output.hpp" #include "op/org.openvinotoolkit/experimental_detectron/detection_output.hpp" #include "op/org.openvinotoolkit/experimental_detectron/generate_proposals_single_image.hpp" @@ -461,6 +462,8 @@ namespace ngraph REGISTER_OPERATOR("Xor", 1, logical_xor); // custom OPs + REGISTER_OPERATOR_WITH_DOMAIN( + OPENVINO_ONNX_DOMAIN, "DeformableConv2D", 1, deformable_conv_2d); REGISTER_OPERATOR_WITH_DOMAIN( OPENVINO_ONNX_DOMAIN, "DetectionOutput", 1, detection_output); REGISTER_OPERATOR_WITH_DOMAIN(OPENVINO_ONNX_DOMAIN, diff --git a/ngraph/test/models/onnx/org.openvinotoolkit/deformable_conv_2d.prototxt b/ngraph/test/models/onnx/org.openvinotoolkit/deformable_conv_2d.prototxt new file mode 100644 index 00000000000000..6151ddd7435349 --- /dev/null +++ b/ngraph/test/models/onnx/org.openvinotoolkit/deformable_conv_2d.prototxt @@ -0,0 +1,115 @@ +ir_version: 7 +producer_name: "nGraph ONNX Importer" +graph { + node { + input: "data" + input: "deformation" + input: "filters" + output: "out" + op_type: "DeformableConv2D" + } + name: "test_graph" + input { + name: "data" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 4 + } + dim { + dim_value: 4 + } + } + } + } + } + input { + name: "deformation" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } + input { + name: "filters" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + dim { + dim_value: 2 + } + } + } + } + } + initializer { + name: "filters" + dims: 1 + dims: 1 + dims: 2 + dims: 2 + data_type: 1 + float_data: 0.1 + float_data: 0.2 + float_data: 0.3 + float_data: 0.4 + } + output { + name: "out" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 1 + } + dim { + dim_value: 3 + } + dim { + dim_value: 3 + } + } + } + } + } +} +opset_import { + version: 7 +} diff --git a/ngraph/test/onnx/onnx_import_org_openvino.in.cpp b/ngraph/test/onnx/onnx_import_org_openvino.in.cpp index b1bb641a14d01e..3407ad8e956bda 100644 --- a/ngraph/test/onnx/onnx_import_org_openvino.in.cpp +++ b/ngraph/test/onnx/onnx_import_org_openvino.in.cpp @@ -590,3 +590,45 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_model_experimental_detectron_topk_rios) test_case.add_expected_output(Shape{1, 4}, {1, 1, 3, 4}); test_case.run(); } + +NGRAPH_TEST(${BACKEND_NAME}, onnx_model_deformable_conv_2d) +{ + auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/org.openvinotoolkit/deformable_conv_2d.prototxt")); + + auto test_case = test::TestCase(function); + + // data + test_case.add_input({1.0f, + 2.0f, + 3.0f, + 4.0f, + 5.0f, + 6.0f, + 7.0f, + 8.0f, + 9.0f, + 10.0f, + 11.0f, + 12.0f, + 13.0f, + 14.0f, + 15.0f, + 16.0f}); + + // deformations + test_case.add_input({0.5f, -0.5f, 0.0f, 1.0f}); + + test_case.add_expected_output(Shape{1, 1, 3, 3}, + {4.5999999f, + 5.2000003f, + 6.4000001f, + 8.4000006f, + 9.8000002f, + 9.6999998f, + 11.5f, + 13.4000006f, + 14.3999996f}); + + test_case.run(); +} diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index 03685c81752f49..2362a2473e975a 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -1586,3 +1586,6 @@ bin_convolution_2D_2batch_1channel # RuntimeError: Unsupported dynamic ops: v4::Interpolate - Ticket: 50691 onnx_upsample6_dynamic + +# random values returned from the plugin: ticket 51762 +onnx_model_deformable_conv_2d diff --git a/ngraph/test/runtime/interpreter/unit_test.manifest b/ngraph/test/runtime/interpreter/unit_test.manifest index e187fbc3bc4cbb..a9c45ca2ceab18 100644 --- a/ngraph/test/runtime/interpreter/unit_test.manifest +++ b/ngraph/test/runtime/interpreter/unit_test.manifest @@ -112,7 +112,7 @@ INTERPRETER.onnx_model_conv_integer_pads onnx_model_lstm_fwd_with_clip_peepholes onnx_model_lstm_bdir_short_input_seq_peepholes # Activation function hardsigmoid unsupported -onnx_model_gru_fwd_activations_relu_hardsigmoid +onnx_model_gru_fwd_activations_relu_hardsigmoid onnx_model_lstm_fwd_hardsigmoid_activation gru_cell_hardsigmoid_activation_function @@ -165,3 +165,6 @@ INTERPRETER.onnx_model_experimental_detectron_prior_grid_generator # Interpreter backend doesn't implement evaluate method for OP ExperimentalDetectronROIFeatureExtractor INTERPRETER.onnx_model_experimental_detectron_roi_feature_extractor + +# No evaluator for DeformableConv2D +onnx_model_deformable_conv_2d