From 53b865eb58f79f5ba1c57a1f0c7bf4dd2a87fe60 Mon Sep 17 00:00:00 2001 From: Mateusz Bencer Date: Thu, 29 Oct 2020 07:51:51 +0100 Subject: [PATCH] ONNX Loop (#2847) * Loop op ngraph implementation, update IE IR Reader and ngraph to cnn converter * refactoring SubGraphOp class * type prop unit tests * ngraph code style * update comment * single layer tests for Loop operation * fix file name * Add SpecialBodyPorts attribute in Loop op, update single layer tests * first debug version * more tests * missing test file * removed not needed shapes from test data * move test data to new folder * shape infer tests * Added execution tests * add several new tests cases, strict checks in Loop impl, temporary disable single layer tests * ngraph codestyle, refactoring, clone_new_args test * resolve review remarks * fix build * fix tests * more execution tests * add a new constructor of Loop op, resolve review remarks * execution tests * synchro with current version * handle scalars and more tests * scalar test enabled * loop reference impl * bug fixes in tests, onnx importer part and in the ref implementation of the Loop op * applied remarks * handle unsupported cases * rewrite unit tests * update INTERPRETER manifest * is_termination_condition_always_true simplification * [TEST] update python models tests * review remarks * added xfail to tiny_yolov3 * missing model test * revert test data * fixed numbers of failing tests * fixed failed test description * fix test message * fix xfail test * zoo models tests clean-up * missing comma Co-authored-by: Ivan Tikhonov --- ngraph/frontend/onnx_import/src/op/loop.cpp | 215 +++++----- .../frontend/onnx_import/src/ops_bridge.cpp | 2 +- ngraph/python/tests/__init__.py | 14 +- .../python/tests/test_onnx/test_zoo_models.py | 20 +- .../onnx/{ => loop}/loop_2d_add.prototxt | 31 +- ...add_cond_and_trip_count_as_inputs.prototxt | 163 +++++++ .../loop_2d_add_const_cond.prototxt | 37 -- ...onst_no_identity_termination_cond.prototxt | 149 +++++++ ...d_add_incorrect_access_body_scope.prototxt | 49 --- ...add_initializer_from_parent_scope.prototxt | 40 +- ...add_no_identity_termination_cond.prototxt} | 54 +-- ..._identity_termination_cond_false.prototxt} | 64 +-- ...oop_2d_add_node_from_parent_scope.prototxt | 64 +-- .../loop_2d_add_the_same_name.prototxt | 61 +-- ...d_add_trip_count_and_cond_skipped.prototxt | 138 ++++++ .../loop_2d_add_trip_count_dynamic.prototxt | 149 +++++++ .../onnx/loop/loop_concat_values.prototxt | 157 +++++++ .../models/onnx/loop/loop_infinite.prototxt | 202 +++++++++ ...op_no_variadic_inputs_and_outputs.prototxt | 123 ++++++ .../test/models/onnx/loop/loop_pow.prototxt | 175 ++++++++ .../onnx/{ => loop}/loop_scalars_add.prototxt | 0 .../test/onnx/onnx_import_controlflow.in.cpp | 402 ++++++++++++------ ngraph/test/runtime/ie/unit_test.manifest | 30 +- .../runtime/interpreter/unit_test.manifest | 41 +- 24 files changed, 1773 insertions(+), 607 deletions(-) rename ngraph/test/models/onnx/{ => loop}/loop_2d_add.prototxt (81%) create mode 100644 ngraph/test/models/onnx/loop/loop_2d_add_cond_and_trip_count_as_inputs.prototxt rename ngraph/test/models/onnx/{ => loop}/loop_2d_add_const_cond.prototxt (78%) create mode 100644 ngraph/test/models/onnx/loop/loop_2d_add_const_no_identity_termination_cond.prototxt rename ngraph/test/models/onnx/{ => loop}/loop_2d_add_incorrect_access_body_scope.prototxt (72%) rename ngraph/test/models/onnx/{ => loop}/loop_2d_add_initializer_from_parent_scope.prototxt (77%) rename ngraph/test/models/onnx/{loop_2d_add_no_identity_cond.prototxt => loop/loop_2d_add_no_identity_termination_cond.prototxt} (80%) rename ngraph/test/models/onnx/{loop_2d_add_input_from_parent_scope.prototxt => loop/loop_2d_add_no_identity_termination_cond_false.prototxt} (73%) rename ngraph/test/models/onnx/{ => loop}/loop_2d_add_node_from_parent_scope.prototxt (68%) rename ngraph/test/models/onnx/{ => loop}/loop_2d_add_the_same_name.prototxt (78%) create mode 100644 ngraph/test/models/onnx/loop/loop_2d_add_trip_count_and_cond_skipped.prototxt create mode 100644 ngraph/test/models/onnx/loop/loop_2d_add_trip_count_dynamic.prototxt create mode 100644 ngraph/test/models/onnx/loop/loop_concat_values.prototxt create mode 100644 ngraph/test/models/onnx/loop/loop_infinite.prototxt create mode 100644 ngraph/test/models/onnx/loop/loop_no_variadic_inputs_and_outputs.prototxt create mode 100644 ngraph/test/models/onnx/loop/loop_pow.prototxt rename ngraph/test/models/onnx/{ => loop}/loop_scalars_add.prototxt (100%) diff --git a/ngraph/frontend/onnx_import/src/op/loop.cpp b/ngraph/frontend/onnx_import/src/op/loop.cpp index 7cbd5cf4993..6c4e6e3e6e6 100644 --- a/ngraph/frontend/onnx_import/src/op/loop.cpp +++ b/ngraph/frontend/onnx_import/src/op/loop.cpp @@ -19,6 +19,7 @@ #include #include "ngraph/function.hpp" +#include "ngraph/log.hpp" #include "ngraph/op/util/op_types.hpp" #include "onnx_import/core/graph.hpp" #include "onnx_import/core/null_node.hpp" @@ -26,8 +27,6 @@ #include "onnx_import/exceptions.hpp" #include "onnx_import/utils/reshape.hpp" -NGRAPH_SUPPRESS_DEPRECATED_START - namespace ngraph { namespace onnx_import @@ -38,48 +37,28 @@ namespace ngraph { namespace { - /// \brief The termination condition input is not supported by - /// TensorIterator now. If it is possible to determine - // that termination condition is always true, - // it can be ignored and execute using current version - // of TensorIterator. + /// \brief Check if termination condition is true during all Loop + /// iterations. + /// It allows to replace termination condition body output with + /// Constant. + /// As a result ngraph Loop shape inference is able to handle more + /// cases. /// - /// \param[in] loop_cond Termination loop condition input of Loop - /// operator (initial value). - /// \param[in] body_cond Termination loop condition input of the body of + /// \param[in] body_out_cond Termination loop condition input of the body of /// the Loop (value updated during Loop iterations). /// /// \return true if termination condition is true and it cannot be changed /// during Loop iterations, false otherwise. - bool is_termination_condition_always_true(const Output& loop_cond, - const Output& body_cond) + bool is_termination_condition_always_true( + const Output& body_out_cond) { - bool loop_cond_value = false; - if (ngraph::op::is_constant(loop_cond.get_node()) && - loop_cond.get_element_type() == element::boolean) - { - loop_cond_value = as_type_ptr( - loop_cond.get_node_shared_ptr()) - ->cast_vector() - .at(0); - } - // According to ONNX skipped cond input (is_null) means - // that is has true value - bool is_loop_cond_true = - ngraph::op::is_null(loop_cond) || loop_cond_value == true; - - if (!is_loop_cond_true) - { - return false; - } - // If body termination condition input matches Indentity op pattern the has // value of loop_cond - true // Identity op for boolean value is represented by LogicalOr op whose second // input is always false - if (is_type(body_cond.get_node_shared_ptr())) + if (is_type(body_out_cond.get_node_shared_ptr())) { - const auto second_input = body_cond.get_node_shared_ptr() + const auto second_input = body_out_cond.get_node_shared_ptr() ->input_value(1) .get_node_shared_ptr(); if (ngraph::op::is_constant(second_input) && @@ -98,28 +77,102 @@ namespace ngraph OutputVector loop(const Node& node) { const auto& ng_inputs = node.get_ng_inputs(); - // optional inputs - const Output trip_count = ng_inputs.at(0); - const Output loop_cond = ng_inputs.at(1); - - // At this moment nGraph TensorIterator doesn't have support for conditional - // termination of iterations. - CHECK_VALID_NODE(node, - !ngraph::op::is_null(trip_count), - "Currently nGraph requires trip count input to be provided."); const OutputVector loop_carried_dependencies{std::next(ng_inputs.begin(), 2), ng_inputs.end()}; - // required const Subgraph& body_graph{node.get_attribute_value("body")}; - const auto& graph_outputs = body_graph.get_ng_outputs(); - const auto& graph_inputs = body_graph.get_ng_parameters(); + auto body_outputs = body_graph.get_ng_outputs(); + const auto& body_inputs = body_graph.get_ng_parameters(); + + // optional inputs + Output trip_count; + if (ngraph::op::is_null(ng_inputs.at(0))) // trip count skipped + { + // -1 means infinite Loop + trip_count = ngraph::op::Constant::create(ngraph::element::i64, {1}, {-1}); + } + else + { + trip_count = ng_inputs.at(0); + } + + Output + termination_cond; // true means that first interation should be run + if (ngraph::op::is_null( + ng_inputs.at(1).get_node_shared_ptr())) // termination condition skipped + { + termination_cond = + ngraph::op::Constant::create(ngraph::element::boolean, {1}, {true}); + } + else if (ngraph::op::is_constant(ng_inputs.at(1).get_node_shared_ptr())) + { + const auto term_cond_const = as_type_ptr( + ng_inputs.at(1).get_node_shared_ptr()); + if (term_cond_const->cast_vector()[0]) + { + termination_cond = + ngraph::op::Constant::create(ngraph::element::boolean, {1}, {true}); + } + else + { + // no iteration is performed so initial values are returned + OutputVector node_outputs; + // final values + for (const auto& dep : loop_carried_dependencies) + { + node_outputs.push_back(dep); + } + // scan outputs + for (const auto& dep : loop_carried_dependencies) + { + node_outputs.push_back(dep); + } + return node_outputs; + } + } + else + { + // It is temporary solution caused by not supported termination_cond==false + // (for not consant case) by nG Loop + termination_cond = + ngraph::op::Constant::create(ngraph::element::boolean, {1}, {true}); + } + + const int64_t concat_axis = 0; + const auto concat_axis_const = + ngraph::op::Constant::create(ngraph::element::i64, {1}, {concat_axis}); + // provide scalar handing for scan outputs + for (int i = loop_carried_dependencies.size() + 1; i < body_outputs.size(); ++i) + { + auto body_output_shape = body_outputs[i].get_partial_shape(); + if (body_output_shape.is_static() && + ngraph::is_scalar(body_output_shape.to_shape())) + { + body_outputs[i] = std::make_shared( + body_outputs[i], concat_axis_const); + } + } + + const auto& body_loop_out_cond = body_outputs.at(0).get_node_shared_ptr(); + // optimization allow to improve nG Loop shape inference + if (is_termination_condition_always_true(body_loop_out_cond)) + { + body_outputs[0] = + ngraph::op::Constant::create(ngraph::element::boolean, {1}, {true}); + } + else + { + NGRAPH_WARN + << "ONNX Loop: No identity or constant termination condition output " + << "body is not supported in current version\n"; + // TODO: It should be removed after introduction fix to nG Loop + } CHECK_VALID_NODE(node, - graph_inputs.size() >= loop_carried_dependencies.size() + 2, + body_inputs.size() >= loop_carried_dependencies.size() + 2, "The provided loop body graph inputs size (", - graph_inputs.size(), + body_inputs.size(), "), is not greater than the sum of loop carried dependencies " "and two mandatory" " inputs (", @@ -127,70 +180,42 @@ namespace ngraph ")"); CHECK_VALID_NODE(node, - graph_outputs.size() >= loop_carried_dependencies.size() + 1, + body_outputs.size() >= loop_carried_dependencies.size() + 1, "The provided loop body graph outputs size (", - graph_outputs.size(), - ") has to small number of outpus. Required at least: ", + body_outputs.size(), + ") is not greater than number of outputs. Required at least: ", loop_carried_dependencies.size() + 1); - const auto& body_loop_cond = graph_outputs.at(0).get_node_shared_ptr(); - CHECK_VALID_NODE( - node, - is_termination_condition_always_true(loop_cond, body_loop_cond), - "Given termination loop condition input is not supported by Loop operator"); - - // TODO: Remove when loop condition would be supported. - const auto& cond_node = - default_opset::Constant::create(element::boolean, Shape{}, {true}); - - // create the loop body - const auto body = - std::make_shared(graph_outputs, graph_inputs); - auto tensor_iterator = std::make_shared(); - tensor_iterator->set_body(body); - - // TensorIterator need to iterate over some input, thus we have to create - // 1 dim tensor with number of values equal to value provided by trip_count - // input. - const auto loop_trip_count = std::make_shared( - default_opset::Constant::create( - trip_count.get_element_type(), Shape{}, {0}), - ngraph::onnx_import::reshape::interpret_as_scalar(trip_count), - default_opset::Constant::create( - trip_count.get_element_type(), Shape{}, {1}), - trip_count.get_element_type()); - - // We iterate over trip_count input. - // start=0, stride=1, part_size=1, end=-1, axis=0 - tensor_iterator->set_sliced_input( - graph_inputs.at(0), loop_trip_count, 0, 1, 1, -1, 0); - - // Set loop condition input, which should be changing over the iterations. - tensor_iterator->set_merged_input( - graph_inputs.at(1), cond_node, graph_outputs.at(0)); + ParameterVector body_params(body_inputs.begin() + 2, body_inputs.end()); + body_params.emplace(body_params.begin(), + body_inputs[0]); // termination condition body input + const auto body = std::make_shared(body_outputs, body_params); + auto loop = std::make_shared(trip_count, termination_cond); + ngraph::opset5::Loop::SpecialBodyPorts spec_ports{0, 0}; + loop->set_special_body_ports(spec_ports); + loop->set_function(body); // Setting up other Loop body inputs. - auto graph_inputs_it = std::next(graph_inputs.begin(), 2); - auto graph_outputs_it = std::next(graph_outputs.begin(), 1); + // body_inputs[0] is iteration number, body_inputs[1] is termination condition + auto body_inputs_it = std::next(body_inputs.begin(), 2); + // body_outputs[0] is termination condition output + auto body_outputs_it = std::next(body_outputs.begin(), 1); // Set-up loop carried dependencies and final output values OutputVector final_values; for (const auto& dep : loop_carried_dependencies) { - tensor_iterator->set_merged_input( - *graph_inputs_it++, dep, *graph_outputs_it); - final_values.push_back( - tensor_iterator->get_iter_value(*graph_outputs_it++, -1)); + loop->set_merged_input(*body_inputs_it++, dep, *body_outputs_it); + final_values.push_back(loop->get_iter_value(*body_outputs_it++, -1)); } // Set-up scan outputs OutputVector scan_outputs; - for (; graph_outputs_it != graph_outputs.end(); graph_outputs_it++) + for (; body_outputs_it != body_outputs.end(); body_outputs_it++) { - // TODO: does concatenating along 0 axis is right? // start=0, stride=1, part_size=1, end=-1, axis=0 - scan_outputs.push_back(tensor_iterator->get_concatenated_slices( - *graph_outputs_it, 0, 1, 1, -1, 0)); + scan_outputs.push_back(loop->get_concatenated_slices( + *body_outputs_it, 0, 1, 1, -1, concat_axis)); } OutputVector node_outputs; diff --git a/ngraph/frontend/onnx_import/src/ops_bridge.cpp b/ngraph/frontend/onnx_import/src/ops_bridge.cpp index fabfe5877bc..5fff1437228 100644 --- a/ngraph/frontend/onnx_import/src/ops_bridge.cpp +++ b/ngraph/frontend/onnx_import/src/ops_bridge.cpp @@ -361,7 +361,7 @@ namespace ngraph REGISTER_OPERATOR("Log", 1, log); REGISTER_OPERATOR("LogSoftmax", 1, log_softmax); REGISTER_OPERATOR("LogSoftmax", 13, log_softmax); - // REGISTER_OPERATOR("Loop", 1, loop); // Loop operator disabled for the 2021.1 release + REGISTER_OPERATOR("Loop", 1, loop); REGISTER_OPERATOR("LpNormalization", 1, lp_norm); REGISTER_OPERATOR("LRN", 1, lrn); REGISTER_OPERATOR("LSTM", 1, lstm); diff --git a/ngraph/python/tests/__init__.py b/ngraph/python/tests/__init__.py index 56ac242dd98..5db87e4298d 100644 --- a/ngraph/python/tests/__init__.py +++ b/ngraph/python/tests/__init__.py @@ -139,6 +139,16 @@ xfail_issue_38714 = xfail_test(reason="RuntimeError: While validating ONNX node "While validating node 'v1:: (sizes[0]:i64{4}," "Convert_29306[0]:f32{4}) -> (dynamic?)' with friendly_name '':" "Argument element types are inconsistent.") +xfail_issue_41813 = xfail_test(reason="RuntimeError: While validating ONNX node" + " ''" + "While validating ONNX node '':" + "vector::_M_range_check: __n (which is 2) >= this->size() (which is 2") +xfail_issue_41814 = xfail_test(reason="RuntimeError: While validating ONNX node '':" + "While validating ONNX node '':" + "Check 'tensor_rank.is_static()' failed at" + " ngraph/core/src/validation_util.cpp:882:") xfail_issue_38715 = xfail_test(reason="RuntimeError: While validating ONNX node '':" "While validating node 'v1::OneHot OneHot_" "(Convert_13525[0]:i64{3}, depth[0]:f32{}," @@ -178,8 +188,6 @@ xfail_issue_36533 = xfail_test(reason="AssertionError: zoo models results mismat xfail_issue_36537 = xfail_test(reason="ngraph.exceptions.UserInputError: (Provided tensor's shape:" "%s does not match the expected: %s." ">, >)") -xfail_issue_37687 = xfail_test(reason="RuntimeError: nGraph does not support the following ONNX operations:" - "Loop") xfail_issue_39682 = xfail_test(reason="model with IR version >= 3 must specify opset_import for ONNX") xfail_issue_39683 = xfail_test(reason="convolution.W in initializer but not in graph input") xfail_issue_39684 = xfail_test(reason="ngraph.exceptions.UserInputError:" @@ -215,3 +223,5 @@ xfail_issue_39661 = xfail_test(reason="RuntimeError: NonMaxSuppression operation xfail_issue_39662 = xfail_test(reason="RuntimeError: 'ScatterElementsUpdate' layer with name 'y' have " "indices value that points to non-existing output tensor element") xfail_issue_39663 = xfail_test(reason="RuntimeError: Unsupported primitive of type: ROIAlign name: Y") +xfail_issue_41815 = xfail_test(reason="RuntimeError: Unsupported dynamic ops: v5::NonMaxSuppression casted " + "(yolo_evaluation_layer_1/concat_6:0_btc[0]:f32{1,2535,4},") diff --git a/ngraph/python/tests/test_onnx/test_zoo_models.py b/ngraph/python/tests/test_onnx/test_zoo_models.py index 4e596e30ba3..0b5fc8bdf86 100644 --- a/ngraph/python/tests/test_onnx/test_zoo_models.py +++ b/ngraph/python/tests/test_onnx/test_zoo_models.py @@ -26,7 +26,9 @@ from tests.test_onnx.utils.model_importer import ModelImportRunner from tests import ( xfail_issue_38701, xfail_issue_39682, - xfail_issue_37687, + xfail_issue_41813, + xfail_issue_41815, + xfail_issue_41814, xfail_issue_39683, xfail_issue_36533, xfail_issue_39684, @@ -112,17 +114,12 @@ if len(zoo_models) > 0: import_xfail_list = [ # ONNX Model Zoo (xfail_issue_38701, "test_onnx_model_zoo_text_machine_comprehension_bidirectional_attention_flow_model_bidaf_9_bidaf_bidaf_cpu"), - (xfail_issue_37687, "test_onnx_model_zoo_vision_object_detection_segmentation_ssd_mobilenetv1_model_ssd_mobilenet_v1_10_ssd_mobilenet_v1_ssd_mobilenet_v1_cpu"), - (xfail_issue_37687, "test_onnx_model_zoo_vision_object_detection_segmentation_yolov3_model_yolov3_10_yolov3_yolov3_cpu"), - (xfail_issue_37687, "test_onnx_model_zoo_vision_object_detection_segmentation_tiny_yolov3_model_tiny_yolov3_11_yolov3_tiny_cpu"), + (xfail_issue_41813, "test_onnx_model_zoo_vision_object_detection_segmentation_ssd_mobilenetv1_model_ssd_mobilenet_v1_10_ssd_mobilenet_v1_ssd_mobilenet_v1_cpu"), (xfail_issue_38726, "test_onnx_model_zoo_text_machine_comprehension_t5_model_t5_decoder_with_lm_head_12_t5_decoder_with_lm_head_cpu"), # Model MSFT - (xfail_issue_37687, "test_MSFT_opset10_mlperf_ssd_mobilenet_300_ssd_mobilenet_v1_coco_2018_01_28_cpu"), - (xfail_issue_37687, "test_MSFT_opset10_mlperf_ssd_resnet34_1200_ssd_resnet34_mAP_20.2_cpu"), - (xfail_issue_37687, "test_MSFT_opset10_yolov3_yolov3_cpu"), - (xfail_issue_37687, "test_MSFT_opset11_tinyyolov3_yolov3_tiny_cpu"), - (xfail_issue_37687, "test_MSFT_opset10_mlperf_ssd_resnet34_1200_ssd_resnet34_mAP_20.2_cpu"), + (xfail_issue_41813, "test_MSFT_opset10_mlperf_ssd_mobilenet_300_ssd_mobilenet_v1_coco_2018_01_28_cpu"), + (xfail_issue_41814, "test_MSFT_opset10_mlperf_ssd_resnet34_1200_ssd_resnet34_mAP_20.2_cpu"), (xfail_issue_37957, "test_MSFT_opset10_mask_rcnn_keras_mask_rcnn_keras_cpu"), (xfail_issue_36465, "test_MSFT_opset9_LSTM_Seq_lens_unpacked_model_cpu"), ] @@ -162,6 +159,8 @@ if len(zoo_models) > 0: (xfail_issue_38084, "test_onnx_model_zoo_vision_object_detection_segmentation_mask_rcnn_model_MaskRCNN_10_mask_rcnn_R_50_FPN_1x_cpu"), (xfail_issue_38090, "test_onnx_model_zoo_vision_object_detection_segmentation_ssd_model_ssd_10_model_cpu"), (xfail_issue_38084, "test_onnx_model_zoo_vision_object_detection_segmentation_faster_rcnn_model_FasterRCNN_10_faster_rcnn_R_50_FPN_1x_cpu"), + (xfail_issue_41815, "test_onnx_model_zoo_vision_object_detection_segmentation_yolov3_model_yolov3_10_yolov3_yolov3_cpu"), + (xfail_issue_41815, "test_onnx_model_zoo_vision_object_detection_segmentation_tiny_yolov3_model_tiny_yolov3_11_yolov3_tiny_cpu"), # Model MSFT (xfail_issue_36533, "test_MSFT_opset10_tf_inception_v2_model_cpu"), @@ -187,6 +186,9 @@ if len(zoo_models) > 0: (xfail_issue_39669, "test_MSFT_opset9_cgan_cgan_cpu"), (xfail_issue_34323, "test_MSFT_opset10_BERT_Squad_bertsquad10_cpu"), + + (xfail_issue_41815, "test_MSFT_opset11_tinyyolov3_yolov3_tiny_cpu"), + (xfail_issue_41815, "test_MSFT_opset10_yolov3_yolov3_cpu") ] for test_case in import_xfail_list + execution_xfail_list: xfail, test_name = test_case diff --git a/ngraph/test/models/onnx/loop_2d_add.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add.prototxt similarity index 81% rename from ngraph/test/models/onnx/loop_2d_add.prototxt rename to ngraph/test/models/onnx/loop/loop_2d_add.prototxt index 2cc761ccb69..3b0a0a8b966 100644 --- a/ngraph/test/models/onnx/loop_2d_add.prototxt +++ b/ngraph/test/models/onnx/loop/loop_2d_add.prototxt @@ -20,7 +20,7 @@ graph { op_type: "Add" } node { - input: "cond" + input: "cond_in" output: "cond_out" name: "cond_identity" op_type: "Identity" @@ -46,15 +46,12 @@ graph { tensor_type { elem_type: 7 shape { - dim { - dim_value: 1 - } } } } } input { - name: "cond" + name: "cond_in" type { tensor_type { elem_type: 9 @@ -95,12 +92,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } } } } @@ -111,12 +102,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } } } } @@ -153,12 +138,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } } } } @@ -169,12 +148,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 3 - } - dim { - dim_value: 2 - } } } } diff --git a/ngraph/test/models/onnx/loop/loop_2d_add_cond_and_trip_count_as_inputs.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add_cond_and_trip_count_as_inputs.prototxt new file mode 100644 index 00000000000..9882c0eddd6 --- /dev/null +++ b/ngraph/test/models/onnx/loop/loop_2d_add_cond_and_trip_count_as_inputs.prototxt @@ -0,0 +1,163 @@ +ir_version: 6 +producer_name: "nGraph ONNX Importer" +graph { + name: "basic loop" + node { + input: "trip_count" + input: "cond_in" + input: "a_init" + output: "a_final" + output: "a_values" + op_type: "Loop" + attribute { + name: "body" + g { + node { + input: "a_in" + input: "b" + output: "current_a" + name: "loop_body_add" + op_type: "Add" + } + node { + input: "i" + input: "threshold" + output: "cond_out" + name: "condition_calc" + op_type: "Less" + } + node { + input: "current_a" + output: "a_out" + name: "output_accumulator" + op_type: "Identity" + } + name: "simple add" + initializer { + dims: 1 + dims: 2 + data_type: 1 + float_data: 1 + float_data: 1 + name: "b" + } + input { + name: "i" + type { + tensor_type { + elem_type: 7 + } + } + } + input { + name: "cond" + type { + tensor_type { + elem_type: 9 + } + } + } + input { + name: "a_in" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "cond_out" + type { + tensor_type { + elem_type: 9 + } + } + } + output { + name: "current_a" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "a_out" + type { + tensor_type { + elem_type: 1 + } + } + } + } + type: GRAPH + } + } + initializer { + dims: 1 + data_type: 7 + int64_data: 5 + name: "threshold" + } + input { + name: "trip_count" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "cond_in" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "a_init" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "a_final" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "a_values" + type { + tensor_type { + elem_type: 1 + } + } + } +} +opset_import { + version: 11 +} diff --git a/ngraph/test/models/onnx/loop_2d_add_const_cond.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add_const_cond.prototxt similarity index 78% rename from ngraph/test/models/onnx/loop_2d_add_const_cond.prototxt rename to ngraph/test/models/onnx/loop/loop_2d_add_const_cond.prototxt index d256bfa8459..c6780118825 100644 --- a/ngraph/test/models/onnx/loop_2d_add_const_cond.prototxt +++ b/ngraph/test/models/onnx/loop/loop_2d_add_const_cond.prototxt @@ -46,9 +46,6 @@ graph { tensor_type { elem_type: 7 shape { - dim { - dim_value: 1 - } } } } @@ -84,8 +81,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -94,14 +89,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -110,14 +97,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -158,14 +137,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -174,14 +145,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 3 - } - dim { - dim_value: 2 - } - } } } } diff --git a/ngraph/test/models/onnx/loop/loop_2d_add_const_no_identity_termination_cond.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add_const_no_identity_termination_cond.prototxt new file mode 100644 index 00000000000..41ea4ffd3d9 --- /dev/null +++ b/ngraph/test/models/onnx/loop/loop_2d_add_const_no_identity_termination_cond.prototxt @@ -0,0 +1,149 @@ +ir_version: 6 +producer_name: "nGraph ONNX Importer" +graph { + name: "basic loop" + node { + input: "trip_count" + input: "cond_in" + input: "a_init" + output: "a_final" + output: "a_values" + op_type: "Loop" + attribute { + name: "body" + g { + node { + input: "a_in" + input: "b" + output: "current_a" + name: "loop_body_add" + op_type: "Add" + } + node { + input: "i" + input: "threshold" + output: "cond_out" + name: "condition_calc" + op_type: "Less" + } + node { + input: "current_a" + output: "a_out" + name: "output_accumulator" + op_type: "Identity" + } + name: "simple add" + initializer { + dims: 1 + dims: 2 + data_type: 1 + float_data: 1 + float_data: 1 + name: "b" + } + input { + name: "i" + type { + tensor_type { + elem_type: 7 + } + } + } + input { + name: "cond" + type { + tensor_type { + elem_type: 9 + } + } + } + input { + name: "a_in" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "cond_out" + type { + tensor_type { + elem_type: 9 + } + } + } + output { + name: "current_a" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "a_out" + type { + tensor_type { + elem_type: 1 + } + } + } + } + type: GRAPH + } + } + initializer { + dims: 1 + data_type: 7 + int64_data: 10 + name: "trip_count" + } + initializer { + dims: 1 + data_type: 7 + int64_data: 3 + name: "threshold" + } + initializer { + dims: 1 + data_type: 9 + int32_data: 00000001 + name: "cond_in" + } + input { + name: "a_init" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "a_final" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "a_values" + type { + tensor_type { + elem_type: 1 + } + } + } +} +opset_import { + version: 11 +} diff --git a/ngraph/test/models/onnx/loop_2d_add_incorrect_access_body_scope.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add_incorrect_access_body_scope.prototxt similarity index 72% rename from ngraph/test/models/onnx/loop_2d_add_incorrect_access_body_scope.prototxt rename to ngraph/test/models/onnx/loop/loop_2d_add_incorrect_access_body_scope.prototxt index 95c1eff7ebc..bfab6ea5853 100644 --- a/ngraph/test/models/onnx/loop_2d_add_incorrect_access_body_scope.prototxt +++ b/ngraph/test/models/onnx/loop/loop_2d_add_incorrect_access_body_scope.prototxt @@ -54,11 +54,6 @@ graph { type { tensor_type { elem_type: 7 - shape { - dim { - dim_value: 1 - } - } } } } @@ -67,8 +62,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -77,14 +70,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -93,8 +78,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -103,14 +86,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -119,14 +94,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -161,14 +128,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -177,14 +136,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 3 - } - dim { - dim_value: 2 - } - } } } } diff --git a/ngraph/test/models/onnx/loop_2d_add_initializer_from_parent_scope.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add_initializer_from_parent_scope.prototxt similarity index 77% rename from ngraph/test/models/onnx/loop_2d_add_initializer_from_parent_scope.prototxt rename to ngraph/test/models/onnx/loop/loop_2d_add_initializer_from_parent_scope.prototxt index 3de6f8f0413..8fdfe21b09c 100644 --- a/ngraph/test/models/onnx/loop_2d_add_initializer_from_parent_scope.prototxt +++ b/ngraph/test/models/onnx/loop/loop_2d_add_initializer_from_parent_scope.prototxt @@ -50,8 +50,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -76,8 +74,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -86,14 +82,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -102,14 +90,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -127,8 +107,8 @@ graph { dims: 1 dims: 2 data_type: 1 - float_data: 1 - float_data: 1 + float_data: 2 + float_data: 2 name: "b" } input { @@ -152,14 +132,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -168,14 +140,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 3 - } - dim { - dim_value: 2 - } - } } } } diff --git a/ngraph/test/models/onnx/loop_2d_add_no_identity_cond.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add_no_identity_termination_cond.prototxt similarity index 80% rename from ngraph/test/models/onnx/loop_2d_add_no_identity_cond.prototxt rename to ngraph/test/models/onnx/loop/loop_2d_add_no_identity_termination_cond.prototxt index cbb8a777ad6..edd40668d2d 100644 --- a/ngraph/test/models/onnx/loop_2d_add_no_identity_cond.prototxt +++ b/ngraph/test/models/onnx/loop/loop_2d_add_no_identity_termination_cond.prototxt @@ -3,8 +3,8 @@ producer_name: "nGraph ONNX Importer" graph { name: "basic loop" node { - input: "trip_count" input: "" + input: "cond_in" input: "a_init" output: "a_final" output: "a_values" @@ -20,10 +20,11 @@ graph { op_type: "Add" } node { - input: "cond" + input: "i" + input: "threshold" output: "cond_out" - name: "cond_identity" - op_type: "Not" + name: "condition_calc" + op_type: "Less" } node { input: "current_a" @@ -58,8 +59,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -84,8 +83,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -95,12 +92,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } } } } @@ -111,12 +102,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } } } } @@ -128,8 +113,21 @@ graph { initializer { dims: 1 data_type: 7 - int64_data: 3 - name: "trip_count" + int64_data: 5 + name: "threshold" + } + input { + name: "cond_in" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } } input { name: "a_init" @@ -153,12 +151,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } } } } @@ -169,12 +161,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 3 - } - dim { - dim_value: 2 - } } } } diff --git a/ngraph/test/models/onnx/loop_2d_add_input_from_parent_scope.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add_no_identity_termination_cond_false.prototxt similarity index 73% rename from ngraph/test/models/onnx/loop_2d_add_input_from_parent_scope.prototxt rename to ngraph/test/models/onnx/loop/loop_2d_add_no_identity_termination_cond_false.prototxt index 298215b9b13..8bd963d07cb 100644 --- a/ngraph/test/models/onnx/loop_2d_add_input_from_parent_scope.prototxt +++ b/ngraph/test/models/onnx/loop/loop_2d_add_no_identity_termination_cond_false.prototxt @@ -3,8 +3,8 @@ producer_name: "nGraph ONNX Importer" graph { name: "basic loop" node { - input: "trip_count" input: "" + input: "cond_in" input: "a_init" output: "a_final" output: "a_values" @@ -12,19 +12,19 @@ graph { attribute { name: "body" g { - name: "simple add" node { input: "a_in" - input: "a_init" + input: "b" output: "current_a" name: "loop_body_add" op_type: "Add" } node { - input: "cond" + input: "i" + input: "threshold" output: "cond_out" - name: "cond_identity" - op_type: "Identity" + name: "condition_calc" + op_type: "Less" } node { input: "current_a" @@ -32,16 +32,20 @@ graph { name: "output_accumulator" op_type: "Identity" } + name: "simple add" + initializer { + dims: 1 + dims: 2 + data_type: 1 + float_data: 1 + float_data: 1 + name: "b" + } input { name: "i" type { tensor_type { elem_type: 7 - shape { - dim { - dim_value: 1 - } - } } } } @@ -50,8 +54,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -76,8 +78,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -87,12 +87,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } } } } @@ -103,12 +97,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } } } } @@ -120,8 +108,14 @@ graph { initializer { dims: 1 data_type: 7 - int64_data: 3 - name: "trip_count" + int64_data: 5 + name: "threshold" + } + initializer { + dims: 1 + data_type: 9 + int32_data: 0 + name: "cond_in" } input { name: "a_init" @@ -145,12 +139,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } } } } @@ -161,12 +149,6 @@ graph { tensor_type { elem_type: 1 shape { - dim { - dim_value: 3 - } - dim { - dim_value: 2 - } } } } diff --git a/ngraph/test/models/onnx/loop_2d_add_node_from_parent_scope.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add_node_from_parent_scope.prototxt similarity index 68% rename from ngraph/test/models/onnx/loop_2d_add_node_from_parent_scope.prototxt rename to ngraph/test/models/onnx/loop/loop_2d_add_node_from_parent_scope.prototxt index 11bcdc0a668..d98cd7fa87f 100644 --- a/ngraph/test/models/onnx/loop_2d_add_node_from_parent_scope.prototxt +++ b/ngraph/test/models/onnx/loop/loop_2d_add_node_from_parent_scope.prototxt @@ -3,7 +3,7 @@ producer_name: "nGraph ONNX Importer" graph { name: "basic loop" node { - input: "a_init" + input: "scale" input: "scale" name: "mul_node" op_type: "Mul" @@ -22,7 +22,7 @@ graph { name: "simple add" node { input: "b" - input: "a_init" + input: "a_in" output: "current_a" name: "loop_body_add" op_type: "Add" @@ -57,8 +57,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -67,14 +65,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -83,8 +73,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -93,14 +81,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -109,14 +89,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -158,14 +130,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -174,30 +138,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 3 - } - dim { - dim_value: 2 - } - } - } - } - } - output { - name: "b" - type { - tensor_type { - elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } diff --git a/ngraph/test/models/onnx/loop_2d_add_the_same_name.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add_the_same_name.prototxt similarity index 78% rename from ngraph/test/models/onnx/loop_2d_add_the_same_name.prototxt rename to ngraph/test/models/onnx/loop/loop_2d_add_the_same_name.prototxt index ee39b985022..343c56c666a 100644 --- a/ngraph/test/models/onnx/loop_2d_add_the_same_name.prototxt +++ b/ngraph/test/models/onnx/loop/loop_2d_add_the_same_name.prototxt @@ -12,6 +12,7 @@ graph { attribute { name: "body" g { + name: "simple add" node { input: "a_in" input: "b" @@ -31,15 +32,6 @@ graph { name: "output_accumulator" op_type: "Identity" } - name: "simple add" - initializer { - dims: 1 - dims: 2 - data_type: 1 - float_data: 1 - float_data: 1 - name: "b" - } input { name: "i" type { @@ -58,8 +50,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -84,8 +74,6 @@ graph { type { tensor_type { elem_type: 9 - shape { - } } } } @@ -94,14 +82,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -110,17 +90,17 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } + initializer { + dims: 1 + dims: 2 + data_type: 1 + float_data: 1 + float_data: 1 + name: "b" + } } type: GRAPH } @@ -133,11 +113,10 @@ graph { } initializer { dims: 1 - dims: 3 + dims: 2 data_type: 1 - float_data: 1 - float_data: 1 - float_data: 1 + float_data: 2 + float_data: 2 name: "b" } input { @@ -161,14 +140,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 1 - } - dim { - dim_value: 2 - } - } } } } @@ -177,14 +148,6 @@ graph { type { tensor_type { elem_type: 1 - shape { - dim { - dim_value: 3 - } - dim { - dim_value: 2 - } - } } } } diff --git a/ngraph/test/models/onnx/loop/loop_2d_add_trip_count_and_cond_skipped.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add_trip_count_and_cond_skipped.prototxt new file mode 100644 index 00000000000..7b750ece3c1 --- /dev/null +++ b/ngraph/test/models/onnx/loop/loop_2d_add_trip_count_and_cond_skipped.prototxt @@ -0,0 +1,138 @@ +ir_version: 6 +producer_name: "nGraph ONNX Importer" +graph { + name: "basic loop" + node { + input: "" + input: "" + input: "a_init" + output: "a_final" + output: "a_values" + op_type: "Loop" + attribute { + name: "body" + g { + node { + input: "a_in" + input: "b" + output: "current_a" + name: "loop_body_add" + op_type: "Add" + } + node { + input: "cond" + output: "cond_out" + name: "cond_identity" + op_type: "Identity" + } + node { + input: "current_a" + output: "a_out" + name: "output_accumulator" + op_type: "Identity" + } + name: "simple add" + initializer { + dims: 1 + dims: 2 + data_type: 1 + float_data: 1 + float_data: 1 + name: "b" + } + input { + name: "i" + type { + tensor_type { + elem_type: 7 + } + } + } + input { + name: "cond" + type { + tensor_type { + elem_type: 9 + } + } + } + input { + name: "a_in" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "cond_out" + type { + tensor_type { + elem_type: 9 + } + } + } + output { + name: "current_a" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "a_out" + type { + tensor_type { + elem_type: 1 + } + } + } + } + type: GRAPH + } + } + input { + name: "a_init" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "a_final" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "a_values" + type { + tensor_type { + elem_type: 1 + } + } + } +} +opset_import { + version: 11 +} diff --git a/ngraph/test/models/onnx/loop/loop_2d_add_trip_count_dynamic.prototxt b/ngraph/test/models/onnx/loop/loop_2d_add_trip_count_dynamic.prototxt new file mode 100644 index 00000000000..ad6cd5868ce --- /dev/null +++ b/ngraph/test/models/onnx/loop/loop_2d_add_trip_count_dynamic.prototxt @@ -0,0 +1,149 @@ +ir_version: 6 +producer_name: "nGraph ONNX Importer" +graph { + name: "basic loop" + node { + input: "trip_count" + input: "" + input: "a_init" + output: "a_final" + output: "a_values" + op_type: "Loop" + attribute { + name: "body" + g { + node { + input: "a_in" + input: "b" + output: "current_a" + name: "loop_body_add" + op_type: "Add" + } + node { + input: "cond" + output: "cond_out" + name: "cond_identity" + op_type: "Identity" + } + node { + input: "current_a" + output: "a_out" + name: "output_accumulator" + op_type: "Identity" + } + name: "simple add" + initializer { + dims: 1 + dims: 2 + data_type: 1 + float_data: 1 + float_data: 1 + name: "b" + } + input { + name: "i" + type { + tensor_type { + elem_type: 7 + } + } + } + input { + name: "cond" + type { + tensor_type { + elem_type: 9 + } + } + } + input { + name: "a_in" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "cond_out" + type { + tensor_type { + elem_type: 9 + } + } + } + output { + name: "current_a" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "a_out" + type { + tensor_type { + elem_type: 1 + } + } + } + } + type: GRAPH + } + } + initializer { + dims: 1 + data_type: 9 + int32_data: 00000001 + name: "cond_in" + } + input { + name: "trip_count" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "a_init" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + dim { + dim_value: 2 + } + } + } + } + } + output { + name: "a_final" + type { + tensor_type { + elem_type: 1 + } + } + } + output { + name: "a_values" + type { + tensor_type { + elem_type: 1 + } + } + } +} +opset_import { + version: 11 +} diff --git a/ngraph/test/models/onnx/loop/loop_concat_values.prototxt b/ngraph/test/models/onnx/loop/loop_concat_values.prototxt new file mode 100644 index 00000000000..9f5f4dd4b75 --- /dev/null +++ b/ngraph/test/models/onnx/loop/loop_concat_values.prototxt @@ -0,0 +1,157 @@ +ir_version: 7 +producer_name: "nGraph ONNX Importer" +graph { + node { + input: "iter_count_init" + input: "cond_init" + input: "seq_init" + output: "seq_final" + output: "seq_final_scan" + op_type: "Loop" + attribute { + name: "body" + g { + node { + input: "cond_in" + output: "cond_out" + op_type: "Identity" + } + node { + input: "iter_count" + output: "to_concat" + op_type: "Unsqueeze" + attribute { + name: "axes" + ints: 0 + type: INTS + } + } + node { + input: "seq_in" + input: "to_concat" + output: "seq_out" + op_type: "Concat" + attribute { + name: "axis" + i: 0 + type: INT + } + } + node { + input: "seq_out" + output: "seq_final_out" + op_type: "Identity" + } + name: "loop_body" + input { + name: "iter_count" + type { + tensor_type { + elem_type: 7 + shape { + } + } + } + } + input { + name: "cond_in" + type { + tensor_type { + elem_type: 9 + shape { + } + } + } + } + input { + name: "seq_in" + type { + tensor_type { + elem_type: 7 + } + } + } + output { + name: "cond_out" + type { + tensor_type { + elem_type: 9 + shape { + } + } + } + } + output { + name: "seq_out" + type { + tensor_type { + elem_type: 7 + } + } + } + output { + name: "seq_final_out" + type { + tensor_type { + elem_type: 7 + } + } + } + } + type: GRAPH + } + } + name: "Slice in Loop" + input { + name: "iter_count_init" + type { + tensor_type { + elem_type: 7 + shape { + } + } + } + } + input { + name: "cond_init" + type { + tensor_type { + elem_type: 9 + shape { + } + } + } + } + input { + name: "seq_init" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "seq_final" + type { + tensor_type { + elem_type: 7 + } + } + } + output { + name: "seq_final_scan" + type { + tensor_type { + elem_type: 7 + } + } + } +} +opset_import { + version: 12 +} diff --git a/ngraph/test/models/onnx/loop/loop_infinite.prototxt b/ngraph/test/models/onnx/loop/loop_infinite.prototxt new file mode 100644 index 00000000000..67f1d16b954 --- /dev/null +++ b/ngraph/test/models/onnx/loop/loop_infinite.prototxt @@ -0,0 +1,202 @@ +ir_version: 7 +producer_name: "nGraph ONNX Importer" +graph { + node { + input: "trip_count" + input: "cond" + input: "fake" + output: "out_final" + name: "loop" + op_type: "Loop" + attribute { + name: "body" + g { + node { + input: "cond_in" + output: "cond_out" + name: "cond_in_identity" + op_type: "Identity" + } + node { + input: "outer_scope_var" + output: "loop_var_0_out" + name: "loop_var_out" + op_type: "Identity" + } + name: "Infinite Loop subgraph" + input { + name: "iter_num_in" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "cond_in" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "outer_scope_var" + type { + tensor_type { + elem_type: 1 + shape { + dim { + } + } + } + } + } + output { + name: "cond_out" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "loop_var_0_out" + type { + tensor_type { + elem_type: 1 + shape { + dim { + } + } + } + } + } + value_info { + name: "outer_scope_var" + type { + tensor_type { + elem_type: 1 + shape { + dim { + } + } + } + } + } + } + type: GRAPH + } + doc_string: "Loop node" + } + node { + input: "outer_scope_var" + output: "outer_scope_var_out" + name: "cast" + op_type: "Cast" + attribute { + name: "to" + i: 7 + type: INT + } + } + name: "test" + doc_string: "" + input { + name: "trip_count" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "cond" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "fake" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "outer_scope_var" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "outer_scope_var_out" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "out_final" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + } + } + } + } +} +opset_import { + domain: "" + version: 8 +} diff --git a/ngraph/test/models/onnx/loop/loop_no_variadic_inputs_and_outputs.prototxt b/ngraph/test/models/onnx/loop/loop_no_variadic_inputs_and_outputs.prototxt new file mode 100644 index 00000000000..7948abab9b1 --- /dev/null +++ b/ngraph/test/models/onnx/loop/loop_no_variadic_inputs_and_outputs.prototxt @@ -0,0 +1,123 @@ +ir_version: 7 +graph { + node { + input: "trip_count" + input: "cond" + output: "loop_scan_out" + name: "node1" + op_type: "Loop" + attribute { + name: "body" + g { + node { + input: "cond_in" + output: "cond_out" + name: "cond_in_identity" + op_type: "Identity" + } + name: "Loop opset 11 op body graph" + initializer { + data_type: 1 + float_data: 1 + name: "constant_out" + } + input { + name: "iter_num_in" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "cond_in" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "cond_out" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "constant_out" + type { + tensor_type { + elem_type: 1 + shape { + } + } + } + } + } + type: GRAPH + } + doc_string: "Loop" + } + name: "test" + doc_string: "" + input { + name: "trip_count" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "cond" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "loop_scan_out" + type { + tensor_type { + elem_type: 1 + shape { + dim { + dim_value: 1 + } + } + } + } + } +} +opset_import { + domain: "" + version: 11 +} diff --git a/ngraph/test/models/onnx/loop/loop_pow.prototxt b/ngraph/test/models/onnx/loop/loop_pow.prototxt new file mode 100644 index 00000000000..34d4a02698d --- /dev/null +++ b/ngraph/test/models/onnx/loop/loop_pow.prototxt @@ -0,0 +1,175 @@ +ir_version: 6 +producer_name: "nGraph ONNX Importer" +graph { + name: "power calculation" + node { + input: "trip_count" + input: "cond" + input: "pow_init" + output: "pow_final" + output: "pow_scans" + op_type: "Loop" + attribute { + name: "body" + g { + name: "pow calculation subgraph" + node { + input: "i" + input: "i" + output: "pow" + name: "power calc" + op_type: "Mul" + } + node { + input: "cond_in" + output: "cond_out" + name: "cond_identity" + op_type: "Identity" + } + node { + input: "pow" + output: "pow_scan" + name: "output_accumulator" + op_type: "Identity" + } + input { + name: "i" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "cond_in" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "pow_in" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "cond_out" + type { + tensor_type { + elem_type: 9 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "pow" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "pow_scan" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + } + type: GRAPH + } + } + initializer { + dims: 1 + data_type: 9 + int32_data: 00000001 + name: "cond" + } + input { + name: "trip_count" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + input { + name: "pow_init" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "pow_final" + type { + tensor_type { + elem_type: 7 + shape { + dim { + dim_value: 1 + } + } + } + } + } + output { + name: "pow_scans" + type { + tensor_type { + elem_type: 7 + shape { + } + } + } + } +} +opset_import { + version: 11 +} diff --git a/ngraph/test/models/onnx/loop_scalars_add.prototxt b/ngraph/test/models/onnx/loop/loop_scalars_add.prototxt similarity index 100% rename from ngraph/test/models/onnx/loop_scalars_add.prototxt rename to ngraph/test/models/onnx/loop/loop_scalars_add.prototxt diff --git a/ngraph/test/onnx/onnx_import_controlflow.in.cpp b/ngraph/test/onnx/onnx_import_controlflow.in.cpp index a5b6b1c36ce..23e4e721c35 100644 --- a/ngraph/test/onnx/onnx_import_controlflow.in.cpp +++ b/ngraph/test/onnx/onnx_import_controlflow.in.cpp @@ -33,13 +33,19 @@ static std::string s_manifest = "${MANIFEST}"; using TestEngine = test::ENGINE_CLASS_NAME(${BACKEND_NAME}); -NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_check_model) -{ - // The model contains a loop which has statically set iterations count equal 3. - // In the loop body there is just simple add operation. - const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add.prototxt")); +// ~~~~~~~~TERMINATION CONDITION/TRIP COUNT COMBINATIONS TESTS:~~~~~~~~ +// input (trip_count, "") // Note this is analogous to a for loop +// int trip_count = ... +// for (int i=0; i < trip_count; ++i) { +// cond = ...; // ignored +// } +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add) +{ + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/loop/loop_2d_add.prototxt")); + + // Shape inference tests const auto& parameters = function->get_parameters(); EXPECT_EQ(parameters.size(), 1); EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32); @@ -54,90 +60,129 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_check_model) EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32); EXPECT_TRUE(function->get_output_partial_shape(1).is_static()); EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2})); + + auto test_case = test::TestCase(function); + // a_init + test_case.add_input({0.f, 0.f}); + + test_case.add_expected_output(Shape{1, 2}, {3.f, 3.f}); + test_case.add_expected_output(Shape{3, 2}, {1.f, 1.f, 2.f, 2.f, 3.f, 3.f}); + test_case.run(); } -NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_scalars_check_model) +// input ("", cond) // Note this is analogous to a while loop +// bool cond = ...; +// for (int i=0; cond; ++i) { +// cond = ...; +// } +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_no_identity_termination_cond) { - const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/loop_scalars_add.prototxt")); + const auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/loop/loop_2d_add_no_identity_termination_cond.prototxt")); - const auto& parameters = function->get_parameters(); - EXPECT_EQ(parameters.size(), 1); - EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32); - EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static()); - EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{})); + auto test_case = test::TestCase(function); + // termination condition + test_case.add_input({true}); + // a_init + test_case.add_input({0.f, 0.f}); - const auto& results = function->get_results(); - EXPECT_EQ(results.size(), 2); - EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(0).is_static()); - EXPECT_EQ(function->get_output_shape(0), (Shape{})); - EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(1).is_static()); - EXPECT_EQ(function->get_output_shape(1), (Shape{3})); + test_case.add_expected_output(Shape{1, 2}, {6.f, 6.f}); + test_case.add_expected_output(Shape{5, 2}, + {1.f, 1.f, 2.f, 2.f, 3.f, 3.f, 4.f, 4.f, 5.f, 5.f}); + test_case.run(); } +// cond = false +// input ("", cond) // Note this is analogous to a while loop +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_no_identity_termination_cond_false) +{ + const auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/loop/loop_2d_add_no_identity_termination_cond_false.prototxt")); + + auto test_case = test::TestCase(function); + // a_init + test_case.add_input({3.f, 4.f}); + + test_case.add_expected_output(Shape{1, 2}, {3.f, 4.f}); + test_case.add_expected_output(Shape{1, 2}, {3.f, 4.f}); + test_case.run(); +} + +// input ("", 1) // Note this is analogous to a do-while loop +// bool cond = true +// for (int i=0; cond; ++i) { +// cond = ...; +// } +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_const_no_identity_termination_cond) +{ + const auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/loop/loop_2d_add_const_no_identity_termination_cond.prototxt")); + + auto test_case = test::TestCase(function); + // a_init + test_case.add_input({0.f, 0.f}); + + test_case.add_expected_output(Shape{1, 2}, {3.f, 3.f}); + test_case.add_expected_output(Shape{3, 2}, {1.f, 1.f, 2.f, 2.f, 3.f, 3.f}); + test_case.run(); +} + +// input (trip_count, cond) +// int trip_count = ...; +// bool cond = ...; +// for (int i=0; i < trip_count && cond; ++i) { +// cond = ...; +// } +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_both_cond_and_trip_count_as_inputs) +{ + const auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/loop/loop_2d_add_cond_and_trip_count_as_inputs.prototxt")); + + auto test_case = test::TestCase(function); + // trip count + test_case.add_input({10}); + + // termination condition + test_case.add_input({true}); + + // a_init + test_case.add_input({0.f, 0.f}); + + test_case.add_expected_output(Shape{1, 2}, {5.f, 5.f}); + test_case.add_expected_output(Shape{5, 2}, + {1.f, 1.f, 2.f, 2.f, 3.f, 3.f, 4.f, 4.f, 5.f, 5.f}); + test_case.run(); +} + +// ~~~~~~~~SCOPES VISIBILITY TESTS:~~~~~~~~ + NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_initializer_from_parent_scope) { const auto function = onnx_import::import_onnx_model(file_util::path_join( - SERIALIZED_ZOO, "onnx/loop_2d_add_initializer_from_parent_scope.prototxt")); + SERIALIZED_ZOO, "onnx/loop/loop_2d_add_initializer_from_parent_scope.prototxt")); - const auto& parameters = function->get_parameters(); - EXPECT_EQ(parameters.size(), 1); - EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32); - EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static()); - EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{1, 2})); + auto test_case = test::TestCase(function); - const auto& results = function->get_results(); - EXPECT_EQ(results.size(), 2); - EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(0).is_static()); - EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2})); - EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(1).is_static()); - EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2})); -} + // a_init + test_case.add_input({0.f, 0.f}); -NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_input_from_parent_scope) -{ - const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add_input_from_parent_scope.prototxt")); - - const auto& parameters = function->get_parameters(); - EXPECT_EQ(parameters.size(), 1); - EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32); - EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static()); - EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{1, 2})); - - const auto& results = function->get_results(); - EXPECT_EQ(results.size(), 2); - EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(0).is_static()); - EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2})); - EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(1).is_static()); - EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2})); + test_case.add_expected_output(Shape{1, 2}, {6.f, 6.f}); + test_case.add_expected_output(Shape{3, 2}, {2.f, 2.f, 4.f, 4.f, 6.f, 6.f}); + test_case.run(); } NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_node_from_parent_scope) { - const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add_node_from_parent_scope.prototxt")); + const auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/loop/loop_2d_add_node_from_parent_scope.prototxt")); - const auto& parameters = function->get_parameters(); - EXPECT_EQ(parameters.size(), 1); - EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32); - EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static()); - EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{1, 2})); + auto test_case = test::TestCase(function); + // a_init + test_case.add_input({0.f, 0.f}); - const auto& results = function->get_results(); - EXPECT_EQ(results.size(), 3); - EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(0).is_static()); - EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2})); - EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(1).is_static()); - EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2})); + test_case.add_expected_output(Shape{1, 2}, {12.f, 12.f}); + test_case.add_expected_output(Shape{3, 2}, {4.f, 4.f, 8.f, 8.f, 12.f, 12.f}); + test_case.run(); } NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_value_access_to_body_scope_exception) @@ -145,7 +190,7 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_value_access_to_body_scop try { const auto function = onnx_import::import_onnx_model(file_util::path_join( - SERIALIZED_ZOO, "onnx/loop_2d_add_incorrect_access_body_scope.prototxt")); + SERIALIZED_ZOO, "onnx/loop/loop_2d_add_incorrect_access_body_scope.prototxt")); FAIL() << "Incorrect access to body scope not detected"; } catch (const ngraph_error& e) @@ -163,75 +208,9 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_value_access_to_body_scop NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_add_value_the_same_node_from_parent_and_subgraph) { const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add_the_same_name.prototxt")); - - const auto& parameters = function->get_parameters(); - EXPECT_EQ(parameters.size(), 1); - EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32); - EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static()); - EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{1, 2})); - - const auto& results = function->get_results(); - EXPECT_EQ(results.size(), 2); - EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(0).is_static()); - EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2})); - EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(1).is_static()); - EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2})); -} - -NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_exception_if_no_identity_cond) -{ - try - { - const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add_no_identity_cond.prototxt")); - FAIL() << "Not supported termination loop condition exception not thrown"; - } - catch (const ngraph_error& e) - { - EXPECT_HAS_SUBSTRING( - e.what(), - std::string( - "Given termination loop condition input is not supported by Loop operator")); - } - catch (...) - { - FAIL() << "Deduced type check failed for unexpected reason"; - } -} - -NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_const_cond) -{ - const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add_const_cond.prototxt")); - - const auto& parameters = function->get_parameters(); - EXPECT_EQ(parameters.size(), 1); - EXPECT_EQ(parameters.at(0)->get_element_type(), ngraph::element::f32); - EXPECT_TRUE(parameters.at(0)->get_partial_shape().is_static()); - EXPECT_EQ(parameters.at(0)->get_partial_shape().to_shape(), (Shape{1, 2})); - - const auto& results = function->get_results(); - EXPECT_EQ(results.size(), 2); - EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(0).is_static()); - EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2})); - EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32); - EXPECT_TRUE(function->get_output_partial_shape(1).is_static()); - EXPECT_EQ(function->get_output_shape(1), (Shape{3, 2})); -} - -NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_execution) -{ - // The model contains a loop which has statically set iterations count equal 3. - // In the loop body there is just simple add operation. - const auto function = onnx_import::import_onnx_model( - file_util::path_join(SERIALIZED_ZOO, "onnx/loop_2d_add.prototxt")); + file_util::path_join(SERIALIZED_ZOO, "onnx/loop/loop_2d_add_the_same_name.prototxt")); auto test_case = test::TestCase(function); - // a_init test_case.add_input({0.f, 0.f}); @@ -239,3 +218,148 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_execution) test_case.add_expected_output(Shape{3, 2}, {1.f, 1.f, 2.f, 2.f, 3.f, 3.f}); test_case.run(); } + +// ~~~~~~~~STATIC/DYNAMIC/CONSTANT INPUTS TESTS:~~~~~~~~ + +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_scalars) +{ + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/loop/loop_scalars_add.prototxt")); + + auto test_case = test::TestCase(function); + // a_init + test_case.add_input({0.f}); + + test_case.add_expected_output(Shape{}, {3.f}); + test_case.add_expected_output(Shape{3}, {1.f, 2.f, 3.f}); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_const_cond) +{ + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/loop/loop_2d_add_const_cond.prototxt")); + + auto test_case = test::TestCase(function); + // a_init + test_case.add_input({0.f, 0.f}); + + test_case.add_expected_output(Shape{1, 2}, {3.f, 3.f}); + test_case.add_expected_output(Shape{3, 2}, {1.f, 1.f, 2.f, 2.f, 3.f, 3.f}); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_trip_count_dynamic) +{ + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/loop/loop_2d_add_trip_count_dynamic.prototxt")); + + auto test_case = test::TestCase(function); + // trip count + test_case.add_input({3}); + // a_init + test_case.add_input({0.f, 0.f}); + + test_case.add_expected_output(Shape{1, 2}, {3.f, 3.f}); + test_case.add_expected_output(Shape{3, 2}, {1.f, 1.f, 2.f, 2.f, 3.f, 3.f}); + test_case.run(); +} + +// ~~~~~~~~ADDITIONAL TESTS:~~~~~~~~ + +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_concat_values) +{ + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/loop/loop_concat_values.prototxt")); + + auto test_case = test::TestCase(function); + // trip_count + test_case.add_input({5}); + // init condition + test_case.add_input({true}); + // seq_init + test_case.add_input({0}); + + // trip_count is concatenated during Loop iterations + test_case.add_expected_output(Shape{6}, {0, 1, 2, 3, 4, 5}); + test_case.add_expected_output( + Shape{2 + 3 + 4 + 5 + 6}, {0, 1, 0, 1, 2, 0, 1, 2, 3, 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, 5}); + test_case.run(); +} + +// infinitive loop shape inference +// input ("", ""): +// for (int i=0; ; ++i) { +// cond = ... // Note this value is ignored, but is required in the body +// } +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_trip_count_and_cond_skipped_shape_inference) +{ + const auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/loop/loop_2d_add_trip_count_and_cond_skipped.prototxt")); + + const auto& results = function->get_results(); + EXPECT_EQ(results.size(), 2); + EXPECT_EQ(function->get_output_element_type(0), ngraph::element::f32); + EXPECT_TRUE(function->get_output_partial_shape(0).is_static()); + EXPECT_EQ(function->get_output_shape(0), (Shape{1, 2})); + EXPECT_EQ(function->get_output_element_type(1), ngraph::element::f32); + // scan_outputs shape is not know if trip_count and termination condition is not determined + EXPECT_TRUE(function->get_output_partial_shape(1).rank().is_dynamic()); +} + +// infinitive loop execution +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_infinite) +{ + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/loop/loop_infinite.prototxt")); + + auto test_case = test::TestCase(function); + // trip_count + test_case.add_input({std::numeric_limits::max()}); + // init condition + test_case.add_input({true}); + // fake + test_case.add_input({0.f}); + // outer_scope + test_case.add_input({3.f}); + + // final value not changed + test_case.add_expected_output(Shape{1}, {0.f}); + // outer_scope passed as scan output + test_case.add_expected_output(Shape{1}, {3.f}); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_no_variadic_inputs_and_outputs) +{ + const auto function = onnx_import::import_onnx_model(file_util::path_join( + SERIALIZED_ZOO, "onnx/loop/loop_no_variadic_inputs_and_outputs.prototxt")); + + auto test_case = test::TestCase(function); + // trip_count + test_case.add_input({1}); + // init condition + test_case.add_input({true}); + + // loop_scan_out + test_case.add_expected_output(Shape{1}, {1.f}); + test_case.run(); +} + +NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_power) +{ + const auto function = onnx_import::import_onnx_model( + file_util::path_join(SERIALIZED_ZOO, "onnx/loop/loop_pow.prototxt")); + + auto test_case = test::TestCase(function); + // trip_count + test_case.add_input({5}); + // pow init + test_case.add_input({5}); + + // pow_final + test_case.add_expected_output(Shape{1}, {16}); + // pow_scans + test_case.add_expected_output(Shape{5}, {0, 1, 4, 9, 16}); + test_case.run(); +} diff --git a/ngraph/test/runtime/ie/unit_test.manifest b/ngraph/test/runtime/ie/unit_test.manifest index 439fc78ccc7..de833110138 100644 --- a/ngraph/test/runtime/ie/unit_test.manifest +++ b/ngraph/test/runtime/ie/unit_test.manifest @@ -1476,16 +1476,30 @@ IE_GPU.builder_opset1_collapse_dyn_shape IE_GPU.onnx_model_fake_quantize_const_inputs_infer IE_GPU.onnx_model_fake_quantize_nonconst_inputs_infer -# ONNX Loop -onnx_controlflow_loop_2d_add_execution +# No Constant/Identity termination condition output body is not supported by current nG Loop +# is_termination_condition_always_true returns false +onnx_controlflow_loop_2d_no_identity_termination_cond +onnx_controlflow_loop_2d_const_no_identity_termination_cond +onnx_controlflow_loop_2d_both_cond_and_trip_count_as_inputs -# ONNX Loop - tests disabled temporarily -onnx_controlflow_loop_2d_add_check_model -onnx_controlflow_loop_scalars_check_model +#dynamic trip count +onnx_controlflow_loop_2d_trip_count_dynamic + +# Input body shape is changed during Loop iterations +# Exception is throw during Loop shape inference +# Is it expected? +onnx_controlflow_loop_concat_values + +# Infinitive Loop is not supported +onnx_controlflow_loop_infinite + +# Loop is not supported yet by IE backend +onnx_controlflow_loop_2d_add +onnx_controlflow_loop_2d_no_identity_termination_cond_false onnx_controlflow_loop_add_initializer_from_parent_scope -onnx_controlflow_loop_add_input_from_parent_scope onnx_controlflow_loop_add_node_from_parent_scope -onnx_controlflow_loop_add_value_access_to_body_scope_exception onnx_controlflow_loop_add_value_the_same_node_from_parent_and_subgraph -onnx_controlflow_loop_2d_add_exception_if_no_identity_cond +onnx_controlflow_loop_scalars onnx_controlflow_loop_2d_add_const_cond +onnx_controlflow_loop_no_variadic_inputs_and_outputs +onnx_controlflow_loop_power diff --git a/ngraph/test/runtime/interpreter/unit_test.manifest b/ngraph/test/runtime/interpreter/unit_test.manifest index d6dca8a86c2..489cf3c0d59 100644 --- a/ngraph/test/runtime/interpreter/unit_test.manifest +++ b/ngraph/test/runtime/interpreter/unit_test.manifest @@ -18,20 +18,6 @@ INTERPRETER.onnx_resize10_down_scales_const_nearest # Failed in MacOS: INTERPRETER.onnx_resize11_sizes_nearest_asymmetric_floor -# ONNX Loop -onnx_controlflow_loop_2d_add_execution - -# ONNX Loop - tests disabled temporarily -onnx_controlflow_loop_2d_add_check_model -onnx_controlflow_loop_scalars_check_model -onnx_controlflow_loop_add_initializer_from_parent_scope -onnx_controlflow_loop_add_input_from_parent_scope -onnx_controlflow_loop_add_node_from_parent_scope -onnx_controlflow_loop_add_value_access_to_body_scope_exception -onnx_controlflow_loop_add_value_the_same_node_from_parent_and_subgraph -onnx_controlflow_loop_2d_add_exception_if_no_identity_cond -onnx_controlflow_loop_2d_add_const_cond - # Disabled tests for disabled reference implementations INTERPRETER.onnx_model_qlinear_matmul_3d INTERPRETER.onnx_dyn_shapes_expand_uint16_dyn_shape @@ -141,3 +127,30 @@ INTERPRETER.ctc_greedy_decoder_f16 # LogSoftmax's reference implementation doesn't handle scalar input properly onnx_model_logsoftmax_0D +# No Constant/Identity termination condition output body is not supported by current nG Loop +# is_termination_condition_always_true returns false +onnx_controlflow_loop_2d_no_identity_termination_cond +onnx_controlflow_loop_2d_const_no_identity_termination_cond +onnx_controlflow_loop_2d_both_cond_and_trip_count_as_inputs + +#dynamic trip count +onnx_controlflow_loop_2d_trip_count_dynamic + +# Input body shape is changed during Loop iterations +# Exception is throw during Loop shape inference +# Is it expected? +onnx_controlflow_loop_concat_values + +# Infinitive Loop is not supported +onnx_controlflow_loop_infinite + +# Loop is not supported yet by INTERPRETER backend +onnx_controlflow_loop_2d_add +onnx_controlflow_loop_2d_no_identity_termination_cond_false +onnx_controlflow_loop_add_initializer_from_parent_scope +onnx_controlflow_loop_add_node_from_parent_scope +onnx_controlflow_loop_add_value_the_same_node_from_parent_and_subgraph +onnx_controlflow_loop_scalars +onnx_controlflow_loop_2d_add_const_cond +onnx_controlflow_loop_no_variadic_inputs_and_outputs +onnx_controlflow_loop_power