forked from openvinotoolkit/openvino
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[MO] Add support to moc_frontend of ":" as delimiter for --input and …
…--output (openvinotoolkit#6543) * [MO] Add support to moc_frontend of ":" as delimiter for --input Additions: Changed default logic for 'Place::get_in(out)put_port' to return nullptr Changed default logic for 'InputModel::get_place_by_tensor(operation)_name' to return nullptr * Corrected comments in code * Missing empty line * Clang format fixes * Fix review comments * Updated test to verify review comments fixes * Update unit tests after rebase * Apply review comments
- Loading branch information
Showing
11 changed files
with
457 additions
and
38 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
246 changes: 246 additions & 0 deletions
246
model-optimizer/unit_tests/mo/moc_frontend/moc_extractor_test_actual.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,246 @@ | ||
# Copyright (C) 2018-2021 Intel Corporation | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
import unittest | ||
|
||
from mo.moc_frontend.extractor import decode_name_with_port | ||
from mo.utils.error import Error | ||
|
||
import pytest | ||
|
||
|
||
mock_available = True | ||
|
||
try: | ||
# pylint: disable=no-name-in-module,import-error | ||
from mock_mo_python_api import get_model_statistic, get_place_statistic, \ | ||
clear_frontend_statistic, clear_model_statistic, clear_place_statistic, \ | ||
clear_setup, set_equal_data, set_max_port_counts | ||
|
||
# pylint: disable=no-name-in-module,import-error | ||
from ngraph.frontend import FrontEndManager | ||
|
||
except Exception: | ||
print("No mock frontend API available," | ||
"ensure to use -DENABLE_TESTS=ON option when running these tests") | ||
mock_available = False | ||
|
||
# FrontEndManager shall be initialized and destroyed after all tests finished | ||
# This is because destroy of FrontEndManager will unload all plugins, | ||
# no objects shall exist after this | ||
if mock_available: | ||
fem = FrontEndManager() | ||
|
||
mock_needed = pytest.mark.skipif(not mock_available, | ||
reason="mock MO fe is not available") | ||
|
||
|
||
class TestMainFrontend(unittest.TestCase): | ||
def setUp(self): | ||
clear_frontend_statistic() | ||
clear_model_statistic() | ||
clear_place_statistic() | ||
clear_setup() | ||
set_max_port_counts(10, 10) | ||
self.fe = fem.load_by_framework('mock_mo_ngraph_frontend') | ||
self.model = self.fe.load('abc.bin') | ||
|
||
# Mock model has 'tensor' tensor place | ||
@mock_needed | ||
def test_decode_name_with_port_tensor(self): | ||
node = decode_name_with_port(self.model, "tensor") | ||
model_stat = get_model_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 1 | ||
assert node | ||
|
||
# Mock model has 'operation' operation place | ||
@mock_needed | ||
def test_decode_name_with_port_op(self): | ||
node = decode_name_with_port(self.model, "operation") | ||
model_stat = get_model_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 1 | ||
assert node | ||
|
||
# pylint: disable=wrong-spelling-in-comment | ||
# Mock model doesn't have 'mocknoname' place | ||
@mock_needed | ||
def test_decode_name_with_port_noname(self): | ||
with self.assertRaisesRegex(Error, 'No\\ node\\ with\\ name.*mocknoname*'): | ||
decode_name_with_port(self.model, 'mocknoname') | ||
model_stat = get_model_statistic() | ||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 1 | ||
|
||
# Mock model has both tensor and operation with same name and non-equal data | ||
# Collision is expected | ||
@mock_needed | ||
def test_decode_name_with_port_collision_op_tensor(self): | ||
with self.assertRaisesRegex(Error, 'Name\\ collision.*tensorAndOp*'): | ||
decode_name_with_port(self.model, 'tensorAndOp') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 1 | ||
assert place_stat.is_equal_data > 0 | ||
|
||
# Mock model has 'operation' and output port up to 10 | ||
@mock_needed | ||
def test_decode_name_with_port_delim_op_out(self): | ||
node = decode_name_with_port(self.model, 'operation:7') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 2 | ||
assert place_stat.get_output_port == 1 | ||
assert place_stat.lastArgInt == 7 | ||
assert node | ||
|
||
# Mock model has 'operation' and input port up to 10 | ||
@mock_needed | ||
def test_decode_name_with_port_delim_op_in(self): | ||
node = decode_name_with_port(self.model, '7:operation') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 2 | ||
assert place_stat.get_input_port == 1 | ||
assert place_stat.lastArgInt == 7 | ||
assert node | ||
|
||
# Mock model has 'operation' and 'operation:0' op places, collision is expected | ||
@mock_needed | ||
def test_decode_name_with_port_delim_op_collision_out(self): | ||
with self.assertRaisesRegex(Error, 'Name\\ collision(?!.*Tensor.*).*operation\\:0*'): | ||
decode_name_with_port(self.model, 'operation:0') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 2 | ||
assert place_stat.is_equal_data > 0 | ||
assert place_stat.get_output_port == 1 | ||
assert place_stat.lastArgInt == 0 | ||
|
||
# Mock model has 'operation' and '0:operation' op places, collision is expected | ||
@mock_needed | ||
def test_decode_name_with_port_delim_op_collision_in(self): | ||
with self.assertRaisesRegex(Error, 'Name\\ collision(?!.*Tensor.*).*0\\:operation*'): | ||
decode_name_with_port(self.model, '0:operation') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 2 | ||
assert place_stat.is_equal_data > 0 | ||
assert place_stat.get_input_port == 1 | ||
assert place_stat.lastArgInt == 0 | ||
|
||
# Mock model has 'tensor' and 'tensor:0' tensor places, no collision is expected | ||
@mock_needed | ||
def test_decode_name_with_port_delim_tensor_no_collision_out(self): | ||
node = decode_name_with_port(self.model, 'tensor:0') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 2 | ||
assert place_stat.get_output_port == 0 | ||
assert node | ||
|
||
# Mock model has 'tensor' and '0:tensor' tensor places, no collision is expected | ||
@mock_needed | ||
def test_decode_name_with_port_delim_tensor_no_collision_in(self): | ||
node = decode_name_with_port(self.model, '0:tensor') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 2 | ||
assert place_stat.get_input_port == 0 | ||
assert node | ||
|
||
# Mock model doesn't have such '1234:operation' or output port=1234 for 'operation' | ||
@mock_needed | ||
def test_decode_name_with_port_delim_no_port_out(self): | ||
with self.assertRaisesRegex(Error, 'No\\ node\\ with\\ name.*operation\\:1234*'): | ||
decode_name_with_port(self.model, 'operation:1234') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 2 | ||
assert place_stat.get_output_port == 1 | ||
assert place_stat.lastArgInt == 1234 | ||
|
||
# Mock model doesn't have such '1234:operation' or input port=1234 for 'operation' | ||
@mock_needed | ||
def test_decode_name_with_port_delim_no_port_in(self): | ||
with self.assertRaisesRegex(Error, 'No\\ node\\ with\\ name.*1234\\:operation*'): | ||
decode_name_with_port(self.model, '1234:operation') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 2 | ||
assert place_stat.get_input_port == 1 | ||
assert place_stat.lastArgInt == 1234 | ||
|
||
# Mock model has tensor with name 'conv2d:0' and operation 'conv2d' with output port = 1 | ||
# It is setup to return 'is_equal_data=True' for these tensor and port | ||
# So no collision is expected | ||
@mock_needed | ||
def test_decode_name_with_port_delim_equal_data_out(self): | ||
set_equal_data('conv2d', 'conv2d') | ||
node = decode_name_with_port(self.model, 'conv2d:0') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 2 | ||
assert place_stat.get_output_port == 1 | ||
assert place_stat.is_equal_data > 0 | ||
assert node | ||
|
||
# Mock model has tensor with name '0:conv2d' and operation 'conv2d' with input port = 1 | ||
# It is setup to return 'is_equal_data=True' for these tensor and port | ||
# So no collision is expected | ||
@mock_needed | ||
def test_decode_name_with_port_delim_equal_data_in(self): | ||
set_equal_data('conv2d', 'conv2d') | ||
node = decode_name_with_port(self.model, '0:conv2d') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 2 | ||
assert place_stat.get_input_port == 1 | ||
assert place_stat.is_equal_data > 0 | ||
assert node | ||
|
||
# Stress case: Mock model has: | ||
# Tensor '8:9' | ||
# Operation '8:9' | ||
# Operation '8' with output port = 9 | ||
# Operation '9' with input port = 8 | ||
# All places point to same data - no collision is expected | ||
@mock_needed | ||
def test_decode_name_with_port_delim_all_same_data(self): | ||
set_equal_data('8', '9') | ||
node = decode_name_with_port(self.model, '8:9') | ||
model_stat = get_model_statistic() | ||
place_stat = get_place_statistic() | ||
|
||
assert model_stat.get_place_by_tensor_name == 1 | ||
assert model_stat.get_place_by_operation_name == 3 | ||
assert place_stat.get_input_port == 1 | ||
assert place_stat.get_output_port == 1 | ||
# At least 3 comparisons of places are expected | ||
assert place_stat.is_equal_data > 2 | ||
assert node |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.