From c17db5989c2736e4cc43b88afa5c6f43e3453736 Mon Sep 17 00:00:00 2001 From: Ilya Lavrenov Date: Thu, 15 Feb 2024 11:30:04 +0400 Subject: [PATCH] Ported several PRs from master to 2023.3 LTS (#22843) ### Ported: - https://github.com/openvinotoolkit/openvino/pull/22606 - https://github.com/openvinotoolkit/openvino/pull/22734 - https://github.com/openvinotoolkit/openvino/pull/22776 - https://github.com/openvinotoolkit/openvino/pull/22820 - https://github.com/openvinotoolkit/openvino/pull/22827 --------- Signed-off-by: dependabot[bot] Co-authored-by: Andrei Kashchikhin Co-authored-by: Jan Iwaszkiewicz Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/actions/setup_python/action.yml | 3 +- .github/workflows/android_arm64.yml | 2 + .github/workflows/build_doc.yml | 2 +- .github/workflows/code_snippets.yml | 2 +- .../utils/data_helpers/data_dispatcher.py | 12 +- .../tests/test_utils/test_data_dispatch.py | 120 ++++++++++++++++-- src/bindings/python/tests/utils/helpers.py | 20 ++- .../src/shape_inference/shape_inference.cpp | 2 +- vcpkg.json | 4 +- 9 files changed, 142 insertions(+), 25 deletions(-) diff --git a/.github/actions/setup_python/action.yml b/.github/actions/setup_python/action.yml index 76c4d02757f..7b646ed81b2 100644 --- a/.github/actions/setup_python/action.yml +++ b/.github/actions/setup_python/action.yml @@ -26,9 +26,10 @@ runs: - if: ${{ runner.os == 'Linux' && inputs.self-hosted-runner == 'true' }} name: Install 'actions/setup-python@v4' dependencies shell: bash - run: apt-get update && apt-get install -y ca-certificates software-properties-common + run: apt-get update && apt-get install -y ca-certificates software-properties-common gpg-agent tzdata env: DEBIAN_FRONTEND: noninteractive # to prevent apt-get from waiting user input + TZ: "Europe/London" # to prevent tzdata from waiting user input - if: ${{ runner.os == 'Linux' && runner.arch == 'ARM64' }} name: Setup sudo and python3 diff --git a/.github/workflows/android_arm64.yml b/.github/workflows/android_arm64.yml index 2dc6cac5fe7..043f8e69b42 100644 --- a/.github/workflows/android_arm64.yml +++ b/.github/workflows/android_arm64.yml @@ -90,6 +90,8 @@ jobs: uses: actions/checkout@v4 with: repository: 'microsoft/vcpkg' + # Keep in sync with /vcpkg.json + ref: '7ba0ba7334c3346e7eee1e049ba85da193a8d821' path: 'vcpkg' fetch-depth: '0' diff --git a/.github/workflows/build_doc.yml b/.github/workflows/build_doc.yml index 24c0644ce10..8b108ef2a20 100644 --- a/.github/workflows/build_doc.yml +++ b/.github/workflows/build_doc.yml @@ -20,7 +20,7 @@ jobs: lfs: 'true' - name: Install apt-get dependencies - uses: awalsh128/cache-apt-pkgs-action@v1.3.1 + uses: awalsh128/cache-apt-pkgs-action@v1.4.0 with: packages: graphviz texlive liblua5.2-0 libclang1-9 libclang-cpp9 version: 3.0 diff --git a/.github/workflows/code_snippets.yml b/.github/workflows/code_snippets.yml index e4091556da1..b6527e7f37c 100644 --- a/.github/workflows/code_snippets.yml +++ b/.github/workflows/code_snippets.yml @@ -30,7 +30,7 @@ jobs: submodules: 'true' - name: Install OpenCL - uses: awalsh128/cache-apt-pkgs-action@v1.3.1 + uses: awalsh128/cache-apt-pkgs-action@v1.4.0 if: runner.os == 'Linux' with: packages: ocl-icd-opencl-dev opencl-headers diff --git a/src/bindings/python/src/openvino/runtime/utils/data_helpers/data_dispatcher.py b/src/bindings/python/src/openvino/runtime/utils/data_helpers/data_dispatcher.py index d90bc15bd92..57a174ba722 100644 --- a/src/bindings/python/src/openvino/runtime/utils/data_helpers/data_dispatcher.py +++ b/src/bindings/python/src/openvino/runtime/utils/data_helpers/data_dispatcher.py @@ -134,7 +134,7 @@ def _( def to_c_style(value: Any, is_shared: bool = False) -> Any: if not isinstance(value, np.ndarray): if hasattr(value, "__array__"): - return to_c_style(np.array(value, copy=False)) if is_shared else np.array(value, copy=True) + return to_c_style(np.array(value, copy=False), is_shared) if is_shared else np.array(value, copy=True) return value return value if value.flags["C_CONTIGUOUS"] else np.ascontiguousarray(value) @@ -149,7 +149,7 @@ def normalize_arrays( ) -> Any: # Check the special case of the array-interface if hasattr(inputs, "__array__"): - return to_c_style(np.array(inputs, copy=False)) if is_shared else np.array(inputs, copy=True) + return to_c_style(np.array(inputs, copy=False), is_shared) if is_shared else np.array(inputs, copy=True) # Error should be raised if type does not match any dispatchers raise TypeError(f"Incompatible inputs of type: {type(inputs)}") @@ -159,7 +159,7 @@ def _( inputs: dict, is_shared: bool = False, ) -> dict: - return {k: to_c_style(v) if is_shared else v for k, v in inputs.items()} + return {k: to_c_style(v, is_shared) if is_shared else v for k, v in inputs.items()} @normalize_arrays.register(OVDict) @@ -167,7 +167,7 @@ def _( inputs: OVDict, is_shared: bool = False, ) -> dict: - return {i: to_c_style(v) if is_shared else v for i, (_, v) in enumerate(inputs.items())} + return {i: to_c_style(v, is_shared) if is_shared else v for i, (_, v) in enumerate(inputs.items())} @normalize_arrays.register(list) @@ -176,7 +176,7 @@ def _( inputs: Union[list, tuple], is_shared: bool = False, ) -> dict: - return {i: to_c_style(v) if is_shared else v for i, v in enumerate(inputs)} + return {i: to_c_style(v, is_shared) if is_shared else v for i, v in enumerate(inputs)} @normalize_arrays.register(np.ndarray) @@ -184,7 +184,7 @@ def _( inputs: dict, is_shared: bool = False, ) -> Any: - return to_c_style(inputs) if is_shared else inputs + return to_c_style(inputs, is_shared) if is_shared else inputs ### # End of array normalization. ### diff --git a/src/bindings/python/tests/test_utils/test_data_dispatch.py b/src/bindings/python/tests/test_utils/test_data_dispatch.py index 73605850f78..58619c6fea2 100644 --- a/src/bindings/python/tests/test_utils/test_data_dispatch.py +++ b/src/bindings/python/tests/test_utils/test_data_dispatch.py @@ -7,7 +7,7 @@ import pytest from copy import deepcopy import numpy as np -from tests.utils.helpers import generate_relu_compiled_model +from tests.utils.helpers import generate_add_compiled_model, generate_relu_compiled_model from openvino import Core, Model, Type, Shape, Tensor import openvino.runtime.opset13 as ops @@ -20,7 +20,7 @@ def _get_value(value): return value.data if isinstance(value, Tensor) else value -def _run_dispatcher(device, input_data, is_shared, input_shape, input_dtype=np.float32): +def _run_dispatcher_single_input(device, input_data, is_shared, input_shape, input_dtype=np.float32): compiled_model = generate_relu_compiled_model(device, input_shape, input_dtype) infer_request = compiled_model.create_infer_request() result = _data_dispatch(infer_request, input_data, is_shared) @@ -28,6 +28,14 @@ def _run_dispatcher(device, input_data, is_shared, input_shape, input_dtype=np.f return result, infer_request +def _run_dispatcher_multi_input(device, input_data, is_shared, input_shape, input_dtype=np.float32): + compiled_model = generate_add_compiled_model(device, input_shape, input_dtype) + infer_request = compiled_model.create_infer_request() + result = _data_dispatch(infer_request, input_data, is_shared) + + return result, infer_request + + @pytest.mark.parametrize("data_type", [np.float_, np.int_, int, float]) @pytest.mark.parametrize("input_shape", [[], [1]]) @pytest.mark.parametrize("is_shared", [True, False]) @@ -35,7 +43,7 @@ def test_scalars_dispatcher_old(device, data_type, input_shape, is_shared): test_data = data_type(2) expected = Tensor(np.ndarray([], data_type, np.array(test_data))) - result, _ = _run_dispatcher(device, test_data, is_shared, input_shape) + result, _ = _run_dispatcher_single_input(device, test_data, is_shared, input_shape) assert isinstance(result, Tensor) assert result.get_shape() == Shape([]) @@ -56,7 +64,7 @@ def test_scalars_dispatcher_old(device, data_type, input_shape, is_shared): def test_scalars_dispatcher_new_0(device, input_data, input_dtype, input_shape, is_shared): expected = Tensor(np.array(input_data, dtype=input_dtype)) - result, _ = _run_dispatcher(device, input_data, is_shared, input_shape, input_dtype) + result, _ = _run_dispatcher_single_input(device, input_data, is_shared, input_shape, input_dtype) assert isinstance(result, Tensor) assert result.get_shape() == Shape([]) @@ -72,7 +80,7 @@ def test_scalars_dispatcher_new_0(device, input_data, input_dtype, input_shape, ]) @pytest.mark.parametrize("input_shape", [[], [1]]) def test_scalars_dispatcher_new_1(device, input_data, is_shared, expected, input_shape): - result, _ = _run_dispatcher(device, input_data, is_shared, input_shape, np.float32) + result, _ = _run_dispatcher_single_input(device, input_data, is_shared, input_shape, np.float32) assert isinstance(result, type(expected)) if isinstance(result, dict): @@ -90,7 +98,7 @@ def test_tensor_dispatcher(device, input_shape, is_shared): test_data = Tensor(array, is_shared) - result, _ = _run_dispatcher(device, test_data, is_shared, input_shape) + result, _ = _run_dispatcher_single_input(device, test_data, is_shared, input_shape) assert isinstance(result, Tensor) assert result.get_shape() == Shape(input_shape) @@ -107,7 +115,7 @@ def test_tensor_dispatcher(device, input_shape, is_shared): def test_ndarray_shared_dispatcher(device, input_shape): test_data = np.ones(input_shape).astype(np.float32) - result, _ = _run_dispatcher(device, test_data, True, input_shape) + result, _ = _run_dispatcher_single_input(device, test_data, True, input_shape) assert isinstance(result, Tensor) assert result.get_shape() == Shape(test_data.shape) @@ -123,7 +131,7 @@ def test_ndarray_shared_dispatcher(device, input_shape): def test_ndarray_shared_dispatcher_casting(device, input_shape): test_data = np.ones(input_shape) - result, infer_request = _run_dispatcher(device, test_data, True, input_shape) + result, infer_request = _run_dispatcher_single_input(device, test_data, True, input_shape) assert isinstance(result, Tensor) assert result.get_shape() == Shape(test_data.shape) @@ -139,7 +147,7 @@ def test_ndarray_shared_dispatcher_casting(device, input_shape): def test_ndarray_shared_dispatcher_misalign(device, input_shape): test_data = np.asfortranarray(np.ones(input_shape).astype(np.float32)) - result, _ = _run_dispatcher(device, test_data, True, input_shape) + result, _ = _run_dispatcher_single_input(device, test_data, True, input_shape) assert isinstance(result, Tensor) assert result.get_shape() == Shape(test_data.shape) @@ -155,7 +163,7 @@ def test_ndarray_shared_dispatcher_misalign(device, input_shape): def test_ndarray_copied_dispatcher(device, input_shape): test_data = np.ones(input_shape) - result, infer_request = _run_dispatcher(device, test_data, False, input_shape) + result, infer_request = _run_dispatcher_single_input(device, test_data, False, input_shape) assert result == {} assert np.array_equal(infer_request.input_tensors[0].data, test_data) @@ -165,6 +173,98 @@ def test_ndarray_copied_dispatcher(device, input_shape): assert not np.array_equal(infer_request.input_tensors[0].data, test_data) +class FakeTensor(): + def __init__(self, array): + self.array = array + + def __array__(self): + return self.array + + +@pytest.mark.parametrize("input_shape", [[1, 2, 3], [2, 2]]) +def test_array_interface_copied_dispatcher(device, input_shape): + np_data = np.ascontiguousarray(np.ones((input_shape), dtype=np.float32)) + test_data = FakeTensor(np_data) + + result, infer_request = _run_dispatcher_single_input(device, test_data, False, input_shape) + + assert result == {} + assert np.array_equal(infer_request.input_tensors[0].data, test_data) + assert not np.shares_memory(infer_request.input_tensors[0].data, test_data) + + np.array(test_data, copy=False)[0] = 2.0 + + assert not np.array_equal(infer_request.input_tensors[0].data, test_data) + + +@pytest.mark.parametrize("input_shape", [[1, 2, 3], [2, 2]]) +@pytest.mark.parametrize("input_container", [list, tuple, dict]) +def test_array_interface_copied_multi_dispatcher(device, input_shape, input_container): + np_data_one = np.ascontiguousarray(np.ones((input_shape), dtype=np.float32)) + test_data_one = FakeTensor(np_data_one) + + np_data_two = np.ascontiguousarray(np.ones((input_shape), dtype=np.float32)) + test_data_two = FakeTensor(np_data_two) + + if input_container is dict: + test_inputs = {0: test_data_one, 1: test_data_two} + else: + test_inputs = input_container([test_data_one, test_data_two]) + + results, infer_request = _run_dispatcher_multi_input(device, test_inputs, False, input_shape) + + assert results == {} + for i in range(len(results)): + assert np.array_equal(infer_request.input_tensors[i].data, test_inputs[i]) + assert not np.shares_memory(infer_request.input_tensors[i].data, test_inputs[i]) + + np.array(test_inputs[i], copy=False)[0] = 2.0 + + assert not np.array_equal(infer_request.input_tensors[i].data, test_inputs[i]) + + +@pytest.mark.parametrize("input_shape", [[1, 2, 3], [2, 2]]) +def test_array_interface_shared_single_dispatcher(device, input_shape): + np_data = np.ascontiguousarray(np.ones((input_shape), dtype=np.float32)) + test_data = FakeTensor(np_data) + + result, _ = _run_dispatcher_single_input(device, test_data, True, input_shape) + + assert isinstance(result, Tensor) + assert np.array_equal(result.data, test_data) + assert np.shares_memory(result.data, test_data) + + np.array(test_data, copy=False)[0] = 2.0 + + assert np.array_equal(result.data, test_data) + + +@pytest.mark.parametrize("input_shape", [[1, 2, 3], [2, 2]]) +@pytest.mark.parametrize("input_container", [list, tuple, dict]) +def test_array_interface_shared_multi_dispatcher(device, input_shape, input_container): + np_data_one = np.ascontiguousarray(np.ones((input_shape), dtype=np.float32)) + test_data_one = FakeTensor(np_data_one) + + np_data_two = np.ascontiguousarray(np.ones((input_shape), dtype=np.float32)) + test_data_two = FakeTensor(np_data_two) + + if input_container is dict: + test_inputs = {0: test_data_one, 1: test_data_two} + else: + test_inputs = input_container([test_data_one, test_data_two]) + + results, _ = _run_dispatcher_multi_input(device, test_inputs, True, input_shape) + + assert len(results) == 2 + for i in range(len(results)): + assert np.array_equal(results[i].data, test_inputs[i]) + assert np.shares_memory(results[i].data, test_inputs[i]) + + np.array(test_inputs[i], copy=False)[0] = 2.0 + + assert np.array_equal(results[i].data, test_inputs[i]) + + @pytest.mark.parametrize( ("input_data"), [ diff --git a/src/bindings/python/tests/utils/helpers.py b/src/bindings/python/tests/utils/helpers.py index d70907d888f..07d9189b563 100644 --- a/src/bindings/python/tests/utils/helpers.py +++ b/src/bindings/python/tests/utils/helpers.py @@ -202,13 +202,27 @@ def generate_model_and_image(device, input_shape: List[int] = None): return (generate_relu_compiled_model(device, input_shape), generate_image(input_shape)) -def generate_add_model() -> openvino._pyopenvino.Model: - param1 = ops.parameter(Shape([2, 1]), dtype=np.float32, name="data1") - param2 = ops.parameter(Shape([2, 1]), dtype=np.float32, name="data2") +def generate_add_model(input_shape: List[int] = None, input_dtype=np.float32) -> openvino.Model: + if input_shape is None: + input_shape = [2, 1] + param1 = ops.parameter(Shape(input_shape), dtype=np.float32, name="data1") + param2 = ops.parameter(Shape(input_shape), dtype=np.float32, name="data2") add = ops.add(param1, param2) return Model(add, [param1, param2], "TestModel") +def generate_add_compiled_model( + device, + input_shape: List[int] = None, + input_dtype=np.float32, +) -> openvino.CompiledModel: + if input_shape is None: + input_shape = [1, 3, 32, 32] + model = generate_add_model(input_shape, input_dtype) + core = Core() + return core.compile_model(model, device, {}) + + def generate_model_with_memory(input_shape, data_type) -> openvino._pyopenvino.Model: input_data = ops.parameter(input_shape, name="input_data", dtype=data_type) init_val = ops.constant(np.zeros(input_shape), data_type) diff --git a/src/plugins/intel_cpu/src/shape_inference/shape_inference.cpp b/src/plugins/intel_cpu/src/shape_inference/shape_inference.cpp index dd412f4475d..8fe5f51ac29 100644 --- a/src/plugins/intel_cpu/src/shape_inference/shape_inference.cpp +++ b/src/plugins/intel_cpu/src/shape_inference/shape_inference.cpp @@ -206,7 +206,7 @@ public: for (size_t i = 0; i < op->get_input_size(); ++i) { if (auto t = tensor_accessor(i)) { new_inputs.push_back( - std::make_shared(t.get_element_type(), t.get_shape(), t.data())); + std::make_shared(t)); } else if (dynamic_cast(op->get_input_node_ptr(i))) { new_inputs.push_back(op->get_input_node_ptr(i)->clone_with_new_inputs(ov::OutputVector{})); } else { diff --git a/vcpkg.json b/vcpkg.json index 67fded180ec..66a4c34816a 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -1,7 +1,7 @@ { "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", "name": "openvino", - "version": "2023.2.0", + "version": "2023.3.0", "maintainers": "OpenVINO Developers ", "summary": "This is a port for Open Visual Inference And Optimization toolkit for AI inference", "description": [ @@ -14,7 +14,7 @@ "homepage": "https://github.com/openvinotoolkit/openvino", "documentation": "https://docs.openvino.ai/latest/index.html", "license": "Apache-2.0", - "builtin-baseline": "db0473513e5dc73ec6b6f431ff05d2f398eea042", + "builtin-baseline": "7ba0ba7334c3346e7eee1e049ba85da193a8d821", "dependencies": [ "ade", {