diff --git a/inference-engine/src/cldnn_engine/cldnn_engine.cpp b/inference-engine/src/cldnn_engine/cldnn_engine.cpp index 6d8b9512197..55d612a13e4 100644 --- a/inference-engine/src/cldnn_engine/cldnn_engine.cpp +++ b/inference-engine/src/cldnn_engine/cldnn_engine.cpp @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -221,31 +221,56 @@ InferenceEngine::CNNNetwork clDNNEngine::CloneAndTransformNetwork(const Inferenc }); auto isCellPrimitiveSupported = [](const_node_ptr &node) -> bool { - if (std::dynamic_pointer_cast(node) || std::dynamic_pointer_cast(node)) { + if (std::dynamic_pointer_cast(node)) { return false; - } else if (std::dynamic_pointer_cast(node) || - std::dynamic_pointer_cast(node)) { + } else if (std::dynamic_pointer_cast(node)) { return false; - } else if (const auto &lstm_cell = std::dynamic_pointer_cast(node)) { + } else if (const auto &lstm_cell = std::dynamic_pointer_cast(node)) { return lstm_cell->get_clip() == 0.0f && lstm_cell->get_activations() == std::vector{"sigmoid", "tanh", "tanh"}; - } else if (const auto &lstm_cell_v1 = std::dynamic_pointer_cast(node)) { + } else if (const auto &lstm_cell_v1 = std::dynamic_pointer_cast(node)) { return lstm_cell_v1->get_clip() == 0.0f && lstm_cell_v1->get_activations() == std::vector{"sigmoid", "tanh", "tanh"}; - } else if (const auto &lstm_sequence = std::dynamic_pointer_cast(node)) { - return lstm_sequence->get_clip() == 0.0f && lstm_sequence->get_activations() == std::vector{"sigmoid", "tanh", "tanh"}; } return false; }; - pass_config->set_callback bool { + const auto& data = node->input(0); + const auto& data_pshape = data.get_partial_shape(); + if (data_pshape.rank().is_static() && data_pshape.rank().get_length() > 1 && !data_pshape[1].is_static()) + return false; + auto max_seq_len = data.get_shape().at(1); + if (std::dynamic_pointer_cast(node)) { + return false; + } else if (std::dynamic_pointer_cast(node)) { + return false; + } else if (const auto &lstm_seq = std::dynamic_pointer_cast(node)) { + return lstm_seq->get_clip() == 0.0f && + lstm_seq->get_activations() == std::vector{"sigmoid", "tanh", "tanh"} && + !ngraph::op::util::is_seq_len_provided(lstm_seq->get_input_node_shared_ptr(3), + max_seq_len); + } + return false; + }; + + pass_config->set_callback( [isCellPrimitiveSupported](const_node_ptr &node) -> bool { return isCellPrimitiveSupported(node); }); + pass_config->set_callback( + [isSequencePrimitiveSupported](const_node_ptr &node) -> bool { + return isSequencePrimitiveSupported(node); + }); + pass_config->set_callback( diff --git a/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_sequences_to_sequences_ie.cpp b/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_sequences_to_sequences_ie.cpp index 7aa5ebd8503..934fc8b8742 100644 --- a/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_sequences_to_sequences_ie.cpp +++ b/inference-engine/src/legacy_api/src/transformations/convert_opset1_to_legacy/convert_sequences_to_sequences_ie.cpp @@ -116,6 +116,7 @@ ngraph::pass::ConvertLSTMSequenceMatcher::ConvertLSTMSequenceMatcher() { if (lstm_target_inputs.empty()) return false; auto transpose_after = lstm_target_inputs.begin()->get_node()->shared_from_this(); + unsqueeze_1->set_friendly_name(transpose_after->get_friendly_name()); ngraph::replace_node(transpose_after, unsqueeze_1); ngraph::replace_node(lstm_sequence, {lstm_sequence_ie->output(0), unsqueeze_2->output(0), unsqueeze_3->output(0)}); } @@ -186,6 +187,7 @@ ngraph::pass::ConvertGRUSequenceMatcher::ConvertGRUSequenceMatcher() { if (gru_target_inputs.empty()) return false; auto transpose_after = gru_target_inputs.begin()->get_node()->shared_from_this(); + unsqueeze_1->set_friendly_name(transpose_after->get_friendly_name()); ngraph::replace_node(transpose_after, unsqueeze_1); ngraph::replace_node(gru_sequence, {gru_sequence_ie->output(0), unsqueeze_2->output(0)}); } @@ -257,6 +259,7 @@ ngraph::pass::ConvertRNNSequenceMatcher::ConvertRNNSequenceMatcher() { if (rnn_target_inputs.empty()) return false; auto transpose_after = rnn_target_inputs.begin()->get_node()->shared_from_this(); + unsqueeze_1->set_friendly_name(transpose_after->get_friendly_name()); ngraph::replace_node(transpose_after, unsqueeze_1); ngraph::replace_node(rnn_sequence, {rnn_sequence_ie->output(0), unsqueeze_2->output(0)}); } diff --git a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp index efdc6e20667..d93fcef53d0 100644 --- a/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp +++ b/inference-engine/src/mkldnn_plugin/mkldnn_plugin.cpp @@ -68,6 +68,7 @@ #include #include #include +#include #include #include @@ -196,6 +197,42 @@ static void Transformation(CNNNetwork& clonedNetwork, const Config& conf) { return false; }; + // Sequences supported by the plugin shouldn't be converted to TensorIterator. + // sequence_length input is not supported in all Sequences, so if is_seq_len_provided() == true, we + // should always convert to TensorIterator. + // RNN/GRU/LSTM Sequences are supported with clip == 0, and with default activations. + auto isSequencePrimitiveSupported = [](const_node_ptr &node) -> bool { + const auto& data = node->input(0); + const auto& data_pshape = data.get_partial_shape(); + if (data_pshape.rank().is_static() && data_pshape.rank().get_length() > 1 && !data_pshape[1].is_static()) + return false; + auto max_seq_len = data.get_shape().at(1); + if (const auto &rnn_seq = std::dynamic_pointer_cast(node)) { + return rnn_seq->get_clip() == 0.0f && + !ngraph::op::util::is_seq_len_provided(rnn_seq->get_input_node_shared_ptr(2), + max_seq_len); + } else if (const auto &gru_seq = std::dynamic_pointer_cast( + node)) { + return gru_seq->get_clip() == 0.0f && + gru_seq->get_activations() == std::vector{"sigmoid", "tanh"} && + !ngraph::op::util::is_seq_len_provided(gru_seq->get_input_node_shared_ptr(2), + max_seq_len); + } else if (const auto &lstm_seq = std::dynamic_pointer_cast( + node)) { + return lstm_seq->get_clip() == 0.0f && + lstm_seq->get_activations() == std::vector{"sigmoid", "tanh", "tanh"} && + !ngraph::op::util::is_seq_len_provided(lstm_seq->get_input_node_shared_ptr(3), + max_seq_len); + } + return false; + }; + + pass_config->set_callback( + [isSequencePrimitiveSupported](const_node_ptr &node) -> bool { + return isSequencePrimitiveSupported(node); + }); + pass_config->set_callback( [isCellPrimitiveSupported](const_node_ptr &node) -> bool { diff --git a/inference-engine/src/transformations/include/transformations/utils/utils.hpp b/inference-engine/src/transformations/include/transformations/utils/utils.hpp index 8ce82397bf4..9a4016dfbb7 100644 --- a/inference-engine/src/transformations/include/transformations/utils/utils.hpp +++ b/inference-engine/src/transformations/include/transformations/utils/utils.hpp @@ -1,4 +1,4 @@ -// Copyright (C) 2018-2020 Intel Corporation +// Copyright (C) 2018-2021 Intel Corporation // SPDX-License-Identifier: Apache-2.0 // @@ -104,6 +104,9 @@ TRANSFORMATIONS_API bool check_for_broadcast(const ngraph::Shape &ref_shape, con TRANSFORMATIONS_API std::shared_ptr activation(const std::string& activation_name, const ngraph::Output& apply_to); +TRANSFORMATIONS_API bool is_seq_len_provided(const std::shared_ptr &seq_len_input, int64_t max_seq_len); + + template Output eltwise_fold(const Output & input0, const Output & input1) { auto eltwise = std::make_shared(input0, input1); diff --git a/inference-engine/src/transformations/src/transformations/op_conversions/convert_sequences_to_tensor_iterator.cpp b/inference-engine/src/transformations/src/transformations/op_conversions/convert_sequences_to_tensor_iterator.cpp index 4319bfa2fa6..fbebf7c3baf 100644 --- a/inference-engine/src/transformations/src/transformations/op_conversions/convert_sequences_to_tensor_iterator.cpp +++ b/inference-engine/src/transformations/src/transformations/op_conversions/convert_sequences_to_tensor_iterator.cpp @@ -70,18 +70,6 @@ namespace { } return squeezed_nodes; } - - bool should_enable_mask(const ngraph::Output &seq_lengths, int64_t max_seq_len) { - // disable the mask if all values of seq_lengths input are equal to max_seq_len (X_shape[1]) - if (const auto &seq_len_const = std::dynamic_pointer_cast( - seq_lengths.get_node_shared_ptr())) { - const auto &seq_len_values = seq_len_const->cast_vector(); - return std::any_of(seq_len_values.begin(), seq_len_values.end(), [max_seq_len](const int64_t val) { - return val != max_seq_len; - }); - } - return true; - } } // namespace ngraph::pass::ConvertRNNSequenceToTensorIterator::ConvertRNNSequenceToTensorIterator() { @@ -93,12 +81,12 @@ ngraph::pass::ConvertRNNSequenceToTensorIterator::ConvertRNNSequenceToTensorIter pattern::any_input(), pattern::any_input(), pattern::any_input()}); - ngraph::matcher_pass_callback callback = [](ngraph::pattern::Matcher &m) { + ngraph::matcher_pass_callback callback = [this](ngraph::pattern::Matcher &m) { auto sequence = std::dynamic_pointer_cast(m.get_match_root()); // Bidirectional Sequence op should be decomposed to Reverse + Forward // (e.g. apply BidirectionalRNNSequenceDecomposition transformation before this one) - if (!sequence || sequence->get_direction() == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL) { + if (!sequence || sequence->get_direction() == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL || transformation_callback(sequence)) { return false; } @@ -113,7 +101,7 @@ ngraph::pass::ConvertRNNSequenceToTensorIterator::ConvertRNNSequenceToTensorIter auto tensor_iterator = std::make_shared(); auto max_seq_len = X.get_shape().at(1); - bool enable_mask = should_enable_mask(seq_lengths, max_seq_len); + bool enable_mask = ngraph::op::util::is_seq_len_provided(seq_lengths.get_node_shared_ptr(), max_seq_len); std::shared_ptr reverse_seq_before; if (is_reverse && enable_mask) { @@ -252,12 +240,12 @@ ngraph::pass::ConvertGRUSequenceToTensorIterator::ConvertGRUSequenceToTensorIter pattern::any_input(), pattern::any_input(), pattern::any_input()}); - ngraph::matcher_pass_callback callback = [](ngraph::pattern::Matcher &m) { + ngraph::matcher_pass_callback callback = [this](ngraph::pattern::Matcher &m) { auto sequence = std::dynamic_pointer_cast(m.get_match_root()); // Bidirectional Sequence op should be decomposed to Reverse + Forward // (e.g. apply BidirectionalRNNSequenceDecomposition transformation before this one) - if (!sequence || sequence->get_direction() == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL) { + if (!sequence || sequence->get_direction() == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL || transformation_callback(sequence)) { return false; } @@ -272,7 +260,7 @@ ngraph::pass::ConvertGRUSequenceToTensorIterator::ConvertGRUSequenceToTensorIter auto tensor_iterator = std::make_shared(); auto max_seq_len = X.get_shape().at(1); - bool enable_mask = should_enable_mask(seq_lengths, max_seq_len); + bool enable_mask = ngraph::op::util::is_seq_len_provided(seq_lengths.get_node_shared_ptr(), max_seq_len); std::shared_ptr reverse_seq_before; if (is_reverse && enable_mask) { @@ -412,12 +400,12 @@ ngraph::pass::ConvertLSTMSequenceToTensorIterator::ConvertLSTMSequenceToTensorIt pattern::any_input(), pattern::any_input(), pattern::any_input()}); - ngraph::matcher_pass_callback callback = [](ngraph::pattern::Matcher &m) { + ngraph::matcher_pass_callback callback = [this](ngraph::pattern::Matcher &m) { auto sequence = std::dynamic_pointer_cast(m.get_match_root()); // Bidirectional Sequence op should be decomposed to Reverse + Forward // (e.g. apply BidirectionalRNNSequenceDecomposition transformation before this one) - if (!sequence || sequence->get_direction() == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL) { + if (!sequence || sequence->get_direction() == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL || transformation_callback(sequence)) { return false; } @@ -433,7 +421,7 @@ ngraph::pass::ConvertLSTMSequenceToTensorIterator::ConvertLSTMSequenceToTensorIt auto tensor_iterator = std::make_shared(); auto max_seq_len = X.get_shape().at(1); - bool enable_mask = should_enable_mask(seq_lengths, max_seq_len); + bool enable_mask = ngraph::op::util::is_seq_len_provided(seq_lengths.get_node_shared_ptr(), max_seq_len); std::shared_ptr reverse_seq_before; if (is_reverse && enable_mask) { diff --git a/inference-engine/src/transformations/src/transformations/utils/utils.cpp b/inference-engine/src/transformations/src/transformations/utils/utils.cpp index 75655f0122c..180f247927b 100644 --- a/inference-engine/src/transformations/src/transformations/utils/utils.cpp +++ b/inference-engine/src/transformations/src/transformations/utils/utils.cpp @@ -120,6 +120,16 @@ std::shared_ptr activation(const std::string& activation_name, con } } +bool is_seq_len_provided(const std::shared_ptr &seq_len_input, int64_t max_seq_len) { + if (const auto &seq_len_const = std::dynamic_pointer_cast(seq_len_input)) { + const auto &seq_len_values = seq_len_const->cast_vector(); + return std::any_of(seq_len_values.begin(), seq_len_values.end(), [max_seq_len](const int64_t val) { + return val != max_seq_len; + }); + } + return true; +} + } // namespace util } // namespace op } // namespace ngraph diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp index 01b4133d070..070ab298c18 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp @@ -13,6 +13,8 @@ namespace { std::vector mode{ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::PURE_SEQ}; // output values increase rapidly without clip, so use only seq_lenghts = 2 std::vector seq_lengths_zero_clip{2}; diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp index c6988625d75..91bd76a3045 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp @@ -13,7 +13,9 @@ namespace { std::vector mode{ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM, - ngraph::helpers::SequenceTestsMode::PURE_SEQ}; + ngraph::helpers::SequenceTestsMode::PURE_SEQ, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM}; // output values increase rapidly without clip, so use only seq_lenghts = 2 std::vector seq_lengths_zero_clip{2}; std::vector seq_lengths_clip_non_zero{20}; diff --git a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp index 94be74518b5..c0bfb34b45a 100644 --- a/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp +++ b/inference-engine/tests/functional/plugin/cpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp @@ -13,6 +13,8 @@ namespace { std::vector mode{ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::PURE_SEQ}; // output values increase rapidly without clip, so use only seq_lenghts = 2 std::vector seq_lengths_zero_clip{2}; diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp index 96403998752..8265c4b0c65 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/gru_sequence.cpp @@ -13,6 +13,8 @@ namespace { std::vector mode{ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM, ngraph::helpers::SequenceTestsMode::PURE_SEQ}; // output values increase rapidly without clip, so use only seq_lenghts = 2 std::vector seq_lengths_zero_clip{2}; diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp index fa293441e7b..a42d34a9fa9 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/lstm_sequence.cpp @@ -13,6 +13,8 @@ namespace { std::vector mode{ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM, ngraph::helpers::SequenceTestsMode::PURE_SEQ}; // output values increase rapidly without clip, so use only seq_lenghts = 2 std::vector seq_lengths_zero_clip{2}; diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp index e965d12ca7b..2e07945d622 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/single_layer_tests/rnn_sequence.cpp @@ -13,6 +13,8 @@ namespace { std::vector mode{ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST, ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST, + ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM, ngraph::helpers::SequenceTestsMode::PURE_SEQ}; // output values increase rapidly without clip, so use only seq_lenghts = 2 std::vector seq_lengths_zero_clip{2}; diff --git a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp index 804cfe13cab..add13ad377c 100644 --- a/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp +++ b/inference-engine/tests/functional/plugin/gpu/shared_tests_instances/skip_tests_config.cpp @@ -48,7 +48,7 @@ std::vector disabledTestPatterns() { // Need to update activation primitive to support any broadcastable constant to enable these cases. R"(.*ActivationParamLayerTest.*)", // Unknown issues - R"(.*(LSTMSequence).*mode=CONVERT_TO_TI_RAND_SEQ_LEN.*)", + R"(.*(LSTMSequence).*mode=.*_RAND_SEQ_LEN_CONST.*)", R"(.*(smoke_DetectionOutput3In).*)", R"(.*(smoke_DetectionOutput5In).*)", // TODO: Issue: 47773 diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp index 960bcb5b3c3..a324ab846dc 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/gru_sequence.cpp @@ -44,6 +44,7 @@ namespace LayerTestsDefinitions { } void GRUSequenceTest::SetUp() { + using namespace ngraph::helpers; size_t seq_lenghts; size_t batch; size_t hidden_size; @@ -66,8 +67,9 @@ namespace LayerTestsDefinitions { m_max_seq_len = seq_lenghts; auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1]}); - if (m_mode == ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM || - m_mode == ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM) { + if (m_mode == SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM || + m_mode == SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM || + m_mode == SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM) { auto seq_lengths = ngraph::builder::makeParams(ngraph::element::i64, {inputShapes[2]}).at(0); seq_lengths->set_friendly_name("seq_lengths"); params.push_back(seq_lengths); @@ -79,16 +81,19 @@ namespace LayerTestsDefinitions { ngraph::ResultVector results{std::make_shared(gru_sequence->output(0)), std::make_shared(gru_sequence->output(1))}; function = std::make_shared(results, params, "gru_sequence"); - if (m_mode != ngraph::helpers::SequenceTestsMode::PURE_SEQ) { + bool is_pure_sequence = (m_mode == SequenceTestsMode::PURE_SEQ || + m_mode == SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM || + m_mode == SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST); + if (!is_pure_sequence) { ngraph::pass::Manager manager; if (direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL) manager.register_pass(); manager.register_pass(); manager.run_passes(function); - bool ti_found = ngraph::helpers::is_tensor_iterator_exist(function); + bool ti_found = is_tensor_iterator_exist(function); EXPECT_EQ(ti_found, true); } else { - bool ti_found = ngraph::helpers::is_tensor_iterator_exist(function); + bool ti_found = is_tensor_iterator_exist(function); EXPECT_EQ(ti_found, false); } } diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/lstm_sequence.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/lstm_sequence.cpp index 6c7b5b77264..1c94b172713 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/lstm_sequence.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/lstm_sequence.cpp @@ -44,6 +44,8 @@ namespace LayerTestsDefinitions { } void LSTMSequenceTest::SetUp() { + using namespace ngraph::helpers; + using namespace ngraph::builder; size_t seq_lenghts; size_t batch; @@ -64,33 +66,36 @@ namespace LayerTestsDefinitions { {batch}, {num_directions, 4 * hidden_size, input_size}, {num_directions, 4 * hidden_size, hidden_size}, {num_directions, 4 * hidden_size}}, }; auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); - auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1], inputShapes[2]}); - if (m_mode == ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM || - m_mode == ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM) { - auto seq_lengths = ngraph::builder::makeParams(ngraph::element::i64, {inputShapes[3]}).at(0); + auto params = makeParams(ngPrc, {inputShapes[0], inputShapes[1], inputShapes[2]}); + if (m_mode == SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM || + m_mode == SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM || + m_mode == SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM) { + auto seq_lengths = makeParams(ngraph::element::i64, {inputShapes[3]}).at(0); seq_lengths->set_friendly_name("seq_lengths"); params.push_back(seq_lengths); } std::vector WRB = {inputShapes[4], inputShapes[5], inputShapes[6], inputShapes[3]}; - auto lstm_sequence = ngraph::builder::makeLSTM(ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)), - WRB, hidden_size, activations, {}, {}, clip, true, direction, - m_mode); + auto lstm_sequence = makeLSTM(convert2OutputVector(castOps2Nodes(params)), WRB, hidden_size, activations, + {}, {}, clip, true, direction, m_mode); ngraph::ResultVector results{std::make_shared(lstm_sequence->output(0)), std::make_shared(lstm_sequence->output(1)), std::make_shared(lstm_sequence->output(2))}; function = std::make_shared(results, params, "lstm_sequence"); - if (m_mode != ngraph::helpers::SequenceTestsMode::PURE_SEQ) { + bool is_pure_sequence = (m_mode == SequenceTestsMode::PURE_SEQ || + m_mode == SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM || + m_mode == SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST); + if (!is_pure_sequence) { ngraph::pass::Manager manager; if (direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL) manager.register_pass(); manager.register_pass(); manager.run_passes(function); - bool ti_found = ngraph::helpers::is_tensor_iterator_exist(function); + bool ti_found = is_tensor_iterator_exist(function); EXPECT_EQ(ti_found, true); } else { - bool ti_found = ngraph::helpers::is_tensor_iterator_exist(function); + bool ti_found = is_tensor_iterator_exist(function); EXPECT_EQ(ti_found, false); - } + } } void LSTMSequenceTest::GenerateInputs() { diff --git a/inference-engine/tests/functional/shared_test_classes/src/single_layer/rnn_sequence.cpp b/inference-engine/tests/functional/shared_test_classes/src/single_layer/rnn_sequence.cpp index 9efb562dc0a..ddf0fcdbfbb 100644 --- a/inference-engine/tests/functional/shared_test_classes/src/single_layer/rnn_sequence.cpp +++ b/inference-engine/tests/functional/shared_test_classes/src/single_layer/rnn_sequence.cpp @@ -43,6 +43,7 @@ namespace LayerTestsDefinitions { } void RNNSequenceTest::SetUp() { + using namespace ngraph::helpers; size_t seq_lenghts; size_t batch; size_t hidden_size; @@ -64,8 +65,9 @@ namespace LayerTestsDefinitions { m_max_seq_len = seq_lenghts; auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision); auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1]}); - if (m_mode == ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM || - m_mode == ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM) { + if (m_mode == SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM || + m_mode == SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM || + m_mode == SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM) { auto seq_lengths = ngraph::builder::makeParams(ngraph::element::i64, {inputShapes[2]}).at(0); seq_lengths->set_friendly_name("seq_lengths"); params.push_back(seq_lengths); @@ -77,7 +79,10 @@ namespace LayerTestsDefinitions { ngraph::ResultVector results{std::make_shared(rnn_sequence->output(0)), std::make_shared(rnn_sequence->output(1))}; function = std::make_shared(results, params, "rnn_sequence"); - if (m_mode != ngraph::helpers::SequenceTestsMode::PURE_SEQ) { + bool is_pure_sequence = (m_mode == SequenceTestsMode::PURE_SEQ || + m_mode == SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM || + m_mode == SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST); + if (!is_pure_sequence) { ngraph::pass::Manager manager; if (direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL) manager.register_pass(); diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/ngraph_helpers.hpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/ngraph_helpers.hpp index 4430441a8ce..5ccb03307f8 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/ngraph_helpers.hpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/include/ngraph_functions/utils/ngraph_helpers.hpp @@ -198,6 +198,8 @@ enum class TensorIteratorBody { enum class SequenceTestsMode { PURE_SEQ, + PURE_SEQ_RAND_SEQ_LEN_CONST, + PURE_SEQ_RAND_SEQ_LEN_PARAM, CONVERT_TO_TI_MAX_SEQ_LEN_CONST, CONVERT_TO_TI_MAX_SEQ_LEN_PARAM, CONVERT_TO_TI_RAND_SEQ_LEN_CONST, diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp index 1b69aaa5d35..12a4a44273f 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp @@ -38,7 +38,8 @@ std::shared_ptr makeGRU(const OutputVector& in, seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, false); break; } - case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST: { + case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST: + case ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST: { for (size_t i = 0; i <= in[0].get_shape().at(0); ++i) { std::vector lengths; seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true, @@ -47,7 +48,8 @@ std::shared_ptr makeGRU(const OutputVector& in, break; } case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM: - case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM: { + case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM: + case ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM: { // Seq_lengths should be as a Parameter node for these two modes seq_lengths = in.at(2).get_node_shared_ptr(); break; diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp index 4053563f380..b61506e9c7e 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp @@ -36,7 +36,8 @@ std::shared_ptr makeLSTM(const std::vector>& seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, false); break; } - case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST: { + case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST: + case ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST: { for (size_t i = 0; i <= in[0].get_shape().at(0); ++i) { std::vector lengths; seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true, @@ -44,6 +45,7 @@ std::shared_ptr makeLSTM(const std::vector>& } break; } + case ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM: case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM: case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM: { // Seq_lengths should be as a Parameter node for these two modes diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp index 480a0ae9995..453e6ab28ef 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp @@ -36,7 +36,8 @@ std::shared_ptr makeRNN(const OutputVector& in, seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, false); break; } - case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST: { + case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_CONST: + case ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST: { for (size_t i = 0; i <= in[0].get_shape().at(0); ++i) { std::vector lengths; seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true, @@ -45,7 +46,8 @@ std::shared_ptr makeRNN(const OutputVector& in, break; } case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM: - case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM: { + case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM: + case ngraph::helpers::SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM: { // Seq_lengths should be as a Parameter node for these two modes seq_lengths = in.at(2).get_node_shared_ptr(); break; diff --git a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/utils/ngraph_helpers.cpp b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/utils/ngraph_helpers.cpp index 85e4033e836..2cc38f6b9e2 100644 --- a/inference-engine/tests/ngraph_helpers/ngraph_functions/src/utils/ngraph_helpers.cpp +++ b/inference-engine/tests/ngraph_helpers/ngraph_functions/src/utils/ngraph_helpers.cpp @@ -943,6 +943,12 @@ std::ostream& operator<<(std::ostream & os, SequenceTestsMode type) { case SequenceTestsMode::PURE_SEQ: os << "PURE_SEQ"; break; + case SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_CONST: + os << "PURE_SEQ_RAND_SEQ_LEN_CONST"; + break; + case SequenceTestsMode::PURE_SEQ_RAND_SEQ_LEN_PARAM: + os << "PURE_SEQ_RAND_SEQ_LEN_PARAM"; + break; case SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM: os << "CONVERT_TO_TI_RAND_SEQ_LEN_PARAM"; break; diff --git a/ngraph/core/reference/include/ngraph/runtime/reference/sequences.hpp b/ngraph/core/reference/include/ngraph/runtime/reference/sequences.hpp index 046097cf2b4..c3b93fb7290 100644 --- a/ngraph/core/reference/include/ngraph/runtime/reference/sequences.hpp +++ b/ngraph/core/reference/include/ngraph/runtime/reference/sequences.hpp @@ -191,17 +191,18 @@ namespace ngraph size_t part_size_single_batch = part_shape_size / batch * sizeof(T); for (int i = 0; i < batch; ++i) { + auto shift = i * part_size_single_batch; if ((time_step + 1) > seq_len_values[i]) { continue; } - std::memcpy(h_list[time_step].data() + i * part_size_single_batch, - outputs[1] + i * part_size_single_batch, + std::memcpy(h_list[time_step].data() + shift, + outputs[1] + shift, part_size_single_batch); if (type == CellType::LSTM) { - std::memcpy(c_list[time_step].data() + i * part_size_single_batch, - outputs[2] + i * part_size_single_batch, + std::memcpy(c_list[time_step].data() + shift, + outputs[2] + shift, part_size_single_batch); } } @@ -220,16 +221,27 @@ namespace ngraph { for (int i = 0; i < batch; ++i) { - std::memcpy(outputs[1] + i * part_size_single_batch, - h_list[seq_len_values[i] - 1].data() + - i * part_size_single_batch, - part_size_single_batch); - if (type == CellType::LSTM) + auto idx = seq_len_values[i] - 1; + auto shift = i * part_size_single_batch; + if (idx >= 0 && idx < h_list.size()) { - std::memcpy(outputs[2] + i * part_size_single_batch, - c_list[seq_len_values[i] - 1].data() + - i * part_size_single_batch, + std::memcpy(outputs[1] + shift, + h_list[idx].data() + shift, part_size_single_batch); + if (type == CellType::LSTM) + { + std::memcpy(outputs[2] + shift, + c_list[idx].data() + shift, + part_size_single_batch); + } + } + else + { + std::memset(outputs[1] + shift, 0, part_size_single_batch); + if (type == CellType::LSTM) + { + std::memset(outputs[2] + shift, 0, part_size_single_batch); + } } } }