* 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 <ivan.tikhonov@intel.com>
This commit is contained in:
Mateusz Bencer 2020-10-29 07:51:51 +01:00 committed by GitHub
parent c95d8e242d
commit 53b865eb58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 1773 additions and 607 deletions

View File

@ -19,6 +19,7 @@
#include <memory>
#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<ngraph::Node>& loop_cond,
const Output<ngraph::Node>& body_cond)
bool is_termination_condition_always_true(
const Output<ngraph::Node>& 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<default_opset::Constant>(
loop_cond.get_node_shared_ptr())
->cast_vector<bool>()
.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<default_opset::LogicalOr>(body_cond.get_node_shared_ptr()))
if (is_type<default_opset::LogicalOr>(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<ngraph::Node> trip_count = ng_inputs.at(0);
const Output<ngraph::Node> 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<Subgraph>("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<ngraph::Node> 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<ngraph::Node>
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<default_opset::Constant>(
ng_inputs.at(1).get_node_shared_ptr());
if (term_cond_const->cast_vector<bool>()[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<default_opset::Unsqueeze>(
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<ngraph::Function>(graph_outputs, graph_inputs);
auto tensor_iterator = std::make_shared<ngraph::op::TensorIterator>();
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::Range>(
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<ngraph::Function>(body_outputs, body_params);
auto loop = std::make_shared<default_opset::Loop>(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;

View File

@ -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);

View File

@ -139,6 +139,16 @@ xfail_issue_38714 = xfail_test(reason="RuntimeError: While validating ONNX node
"While validating node 'v1::<name> (sizes[0]:i64{4},"
"Convert_29306[0]:f32{4}) -> (dynamic?)' with friendly_name '<name>':"
"Argument element types are inconsistent.")
xfail_issue_41813 = xfail_test(reason="RuntimeError: While validating ONNX node"
" '<Node(Loop): generic_loop_Loop__69>'"
"While validating ONNX node '<Node(Resize): Resize__143>':"
"vector::_M_range_check: __n (which is 2) >= this->size() (which is 2")
xfail_issue_41814 = xfail_test(reason="RuntimeError: While validating ONNX node '<Node(Loop):"
" generic_loop_Loop__121>':"
"While validating ONNX node '<Node(TopK):"
" map_1/while/select_bboxes/sort_bboxes_10/TopKV2>':"
"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 '<Node(OneHot): y>':"
"While validating node 'v1::OneHot OneHot_<number>"
"(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."
"<PartialShape: <value>>, <PartialShape: <value>>)")
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},")

View File

@ -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

View File

@ -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
}
}
}
}

View File

@ -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
}

View File

@ -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
}
}
}
}
}

View File

@ -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
}

View File

@ -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
}
}
}
}
}

View File

@ -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
}
}
}
}
}

View File

@ -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
}
}
}
}

View File

@ -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
}
}
}
}

View File

@ -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
}
}
}
}
}

View File

@ -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
}
}
}
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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<TestEngine>(function);
// a_init
test_case.add_input<float>({0.f, 0.f});
test_case.add_expected_output<float>(Shape{1, 2}, {3.f, 3.f});
test_case.add_expected_output<float>(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<TestEngine>(function);
// termination condition
test_case.add_input<bool>({true});
// a_init
test_case.add_input<float>({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<float>(Shape{1, 2}, {6.f, 6.f});
test_case.add_expected_output<float>(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<TestEngine>(function);
// a_init
test_case.add_input<float>({3.f, 4.f});
test_case.add_expected_output<float>(Shape{1, 2}, {3.f, 4.f});
test_case.add_expected_output<float>(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<TestEngine>(function);
// a_init
test_case.add_input<float>({0.f, 0.f});
test_case.add_expected_output<float>(Shape{1, 2}, {3.f, 3.f});
test_case.add_expected_output<float>(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<TestEngine>(function);
// trip count
test_case.add_input<int64_t>({10});
// termination condition
test_case.add_input<bool>({true});
// a_init
test_case.add_input<float>({0.f, 0.f});
test_case.add_expected_output<float>(Shape{1, 2}, {5.f, 5.f});
test_case.add_expected_output<float>(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<TestEngine>(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<float>({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<float>(Shape{1, 2}, {6.f, 6.f});
test_case.add_expected_output<float>(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<TestEngine>(function);
// a_init
test_case.add_input<float>({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<float>(Shape{1, 2}, {12.f, 12.f});
test_case.add_expected_output<float>(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<TestEngine>(function);
// a_init
test_case.add_input<float>({0.f, 0.f});
@ -239,3 +218,148 @@ NGRAPH_TEST(${BACKEND_NAME}, onnx_controlflow_loop_2d_add_execution)
test_case.add_expected_output<float>(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<TestEngine>(function);
// a_init
test_case.add_input<float>({0.f});
test_case.add_expected_output<float>(Shape{}, {3.f});
test_case.add_expected_output<float>(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<TestEngine>(function);
// a_init
test_case.add_input<float>({0.f, 0.f});
test_case.add_expected_output<float>(Shape{1, 2}, {3.f, 3.f});
test_case.add_expected_output<float>(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<TestEngine>(function);
// trip count
test_case.add_input<int64_t>({3});
// a_init
test_case.add_input<float>({0.f, 0.f});
test_case.add_expected_output<float>(Shape{1, 2}, {3.f, 3.f});
test_case.add_expected_output<float>(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<TestEngine>(function);
// trip_count
test_case.add_input<int64_t>({5});
// init condition
test_case.add_input<bool>({true});
// seq_init
test_case.add_input<float>({0});
// trip_count is concatenated during Loop iterations
test_case.add_expected_output<int64_t>(Shape{6}, {0, 1, 2, 3, 4, 5});
test_case.add_expected_output<int64_t>(
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<TestEngine>(function);
// trip_count
test_case.add_input<int64_t>({std::numeric_limits<int64_t>::max()});
// init condition
test_case.add_input<bool>({true});
// fake
test_case.add_input<float>({0.f});
// outer_scope
test_case.add_input<float>({3.f});
// final value not changed
test_case.add_expected_output<float>(Shape{1}, {0.f});
// outer_scope passed as scan output
test_case.add_expected_output<float>(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<TestEngine>(function);
// trip_count
test_case.add_input<int64_t>({1});
// init condition
test_case.add_input<bool>({true});
// loop_scan_out
test_case.add_expected_output<float>(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<TestEngine>(function);
// trip_count
test_case.add_input<int64_t>({5});
// pow init
test_case.add_input<int64_t>({5});
// pow_final
test_case.add_expected_output<int64_t>(Shape{1}, {16});
// pow_scans
test_case.add_expected_output<int64_t>(Shape{5}, {0, 1, 4, 9, 16});
test_case.run();
}

View File

@ -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

View File

@ -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