diff --git a/src/plugins/intel_cpu/src/cpu_shape.h b/src/plugins/intel_cpu/src/cpu_shape.h index 9fbc0a55616..0d6cc341443 100644 --- a/src/plugins/intel_cpu/src/cpu_shape.h +++ b/src/plugins/intel_cpu/src/cpu_shape.h @@ -17,11 +17,11 @@ class Shape { public: Shape() = default; - explicit Shape(const ngraph::PartialShape& shape) { + explicit Shape(const ov::PartialShape& shape) { minDims = shape.get_min_shape(); - std::transform(minDims.begin(), minDims.end(), minDims.begin(), [](Dim x){ return ngraph::Interval::s_max == x ? UNDEFINED_DIM : x;}); + std::transform(minDims.begin(), minDims.end(), minDims.begin(), [](Dim x){ return ov::Interval::s_max == x ? UNDEFINED_DIM : x;}); maxDims = shape.get_max_shape(); - std::transform(maxDims.begin(), maxDims.end(), maxDims.begin(), [](Dim x){ return ngraph::Interval::s_max == x ? UNDEFINED_DIM : x;}); + std::transform(maxDims.begin(), maxDims.end(), maxDims.begin(), [](Dim x){ return ov::Interval::s_max == x ? UNDEFINED_DIM : x;}); type = shape.is_static() ? ShapeType::Static : ShapeType::Dynamic; initDims(); @@ -29,7 +29,7 @@ public: hasZeroDimensions = std::any_of(dims.begin(), dims.end(), [](size_t dim) { return dim == 0; } ); } - explicit Shape(const InferenceEngine::SizeVector& shape) { + explicit Shape(const VectorDims& shape) { minDims = shape; maxDims = shape; type = ShapeType::Static; @@ -39,6 +39,30 @@ public: hasZeroDimensions = std::any_of(dims.begin(), dims.end(), [](size_t dim) { return dim == 0; } ); } + Shape(const VectorDims& minVals, const VectorDims& maxVals) { + minDims = minVals; + maxDims = maxVals; + type = minVals == maxVals ? ShapeType::Static : ShapeType::Dynamic; + + initDims(); + + hasZeroDimensions = std::any_of(dims.begin(), dims.end(), [](size_t dim) { return dim == 0; } ); + } + + Shape(const std::initializer_list& shape) { + minDims.reserve(shape.size()); + maxDims.reserve(shape.size()); + type = ShapeType::Static; + for (auto dim : shape) { + minDims.push_back(dim); + maxDims.push_back(dim); + } + + initDims(); + + hasZeroDimensions = std::any_of(dims.begin(), dims.end(), [](size_t dim) { return dim == 0; } ); + } + /** * @brief * for static shape @@ -132,8 +156,8 @@ public: return size; } - ngraph::PartialShape toPartialShape() const { - using ngraph::Dimension; + ov::PartialShape toPartialShape() const { + using ov::Dimension; std::vector nGraphDims; nGraphDims.reserve(minDims.size()); for (int i = 0; i < minDims.size(); i++) { @@ -141,7 +165,7 @@ public: Dimension::value_type maxDim = Shape::UNDEFINED_DIM == maxDims[i] ? -1 : maxDims[i]; nGraphDims.emplace_back(minDim, maxDim); } - return ngraph::PartialShape(nGraphDims); + return ov::PartialShape(nGraphDims); } bool isCompatible(const VectorDims& vecDims) const; diff --git a/src/plugins/intel_cpu/src/mkldnn_graph_optimizer.cpp b/src/plugins/intel_cpu/src/mkldnn_graph_optimizer.cpp index 937a143f82b..568c61d7f9f 100644 --- a/src/plugins/intel_cpu/src/mkldnn_graph_optimizer.cpp +++ b/src/plugins/intel_cpu/src/mkldnn_graph_optimizer.cpp @@ -2022,10 +2022,11 @@ void MKLDNNGraphOptimizer::reshapeRnnSeq(MKLDNNGraph &graph) { } auto childrenEdges = parentNode->getChildEdgesAtPort(0); - std::vector origShape = static_cast>(parentNode->getOutputShapeAtPort(0).toPartialShape()); - origShape.erase(origShape.begin() + 1); - const auto newShape = Shape(origShape); - parentNode->outputShapes[0] = newShape; + auto minDims = parentNode->getOutputShapeAtPort(0).getMinDims(); + auto maxDims = parentNode->getOutputShapeAtPort(0).getMaxDims(); + minDims.erase(minDims.begin() + 1); + maxDims.erase(maxDims.begin() + 1); + parentNode->outputShapes[0] = {minDims, maxDims}; for (size_t j = 0; j < childrenEdges.size(); j++) { auto edge = childrenEdges[j]; diff --git a/src/plugins/intel_cpu/src/mkldnn_node.cpp b/src/plugins/intel_cpu/src/mkldnn_node.cpp index 00250a8c635..473408571cf 100644 --- a/src/plugins/intel_cpu/src/mkldnn_node.cpp +++ b/src/plugins/intel_cpu/src/mkldnn_node.cpp @@ -648,8 +648,7 @@ void MKLDNNNode::filterSupportedPrimitiveDescriptors() { } void MKLDNNNode::initDescriptor(const NodeConfig& config) { - auto* selectedPD = getSelectedPrimitiveDescriptor(); - if (!selectedPD) { + if (!getSelectedPrimitiveDescriptor()) { return; } std::vector inDescs; @@ -662,6 +661,7 @@ void MKLDNNNode::initDescriptor(const NodeConfig& config) { AttrPtr attr = initPrimitiveAttr(); + auto* selectedPD = getSelectedPrimitiveDescriptor(); NodeConfig rightConfig = selectedPD->getConfig(); size_t selected_count = 0; for (size_t j = 0; j < descs.size(); j++) { @@ -1376,8 +1376,9 @@ bool MKLDNNNode::hasEmptyOutputTensors() const { bool MKLDNNNode::inputShapesDefined() const { for (size_t i = 0; i < getParentEdges().size(); i++) { - if (!getParentEdgesAtPort(i)[0]->getMemory().getDesc().isDefined()) + if (!getParentEdgesAtPort(i)[0]->getMemory().getDesc().isDefined()) { return false; + } } return true; } diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_broadcast_node.h b/src/plugins/intel_cpu/src/nodes/mkldnn_broadcast_node.h index 93cbddb0b45..14d374ba8a0 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_broadcast_node.h +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_broadcast_node.h @@ -39,7 +39,7 @@ private: NUMPY, EXPLICIT }; - AutoBroadcastType broadcastType; + AutoBroadcastType broadcastType = NUMPY; static constexpr size_t INPUT_DATA_IDX = 0; static constexpr size_t TARGET_SHAPE_IDX = 1; diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_conv_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_conv_node.cpp index c0ab2af45a1..f0b7fcd412d 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_conv_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_conv_node.cpp @@ -907,7 +907,6 @@ std::shared_ptr MKLDNNConvolutionNode::createMkldnnConvDesc(co const mkldnn::memory::desc& wghDesc, const mkldnn::memory::desc& dstDesc, const mkldnn::memory::desc& biasDesc) { - std::shared_ptr dnnlConvDesc; auto alg = isWinograd() ? mkldnn::algorithm::convolution_winograd : mkldnn::algorithm::convolution_direct; if (withBiases) { @@ -931,11 +930,11 @@ void MKLDNNConvolutionNode::prepareParams() { auto wghMemPtr = getParentEdgesAtPort(1)[0]->getMemoryPtr(); auto dstMemPtr = getChildEdgesAtPort(0)[0]->getMemoryPtr(); if (!dstMemPtr || !dstMemPtr->GetPrimitivePtr()) - IE_THROW() << "Destination memory didn't allocate."; + IE_THROW() << "Destination memory was not allocated."; if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr()) - IE_THROW() << "Input memory didn't allocate."; + IE_THROW() << "Input memory was not allocated."; if (!wghMemPtr || !wghMemPtr->GetPrimitivePtr()) - IE_THROW() << "Weight memory didn't allocate."; + IE_THROW() << "Weight memory was not allocated."; MKLDNNMemoryPtr biasMemPtr = nullptr; if (withBiases) { biasMemPtr = getParentEdgesAtPort(2)[0]->getMemoryPtr(); diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_rnn.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_rnn.cpp index 85d7e0083d3..013b7da8e00 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_rnn.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_rnn.cpp @@ -16,74 +16,76 @@ #include #include +#define THROW_ERROR IE_THROW() << getTypeStr() << " node with name '" << getName() << "' " + using namespace mkldnn; using namespace InferenceEngine; namespace MKLDNNPlugin { -static rnn_direction ieDirection2dnnl(const std::shared_ptr& op) { - ngraph::op::RecurrentSequenceDirection direction = ngraph::op::RecurrentSequenceDirection::FORWARD; - if (op->get_type_info() == ngraph::op::v5::GRUSequence::get_type_info_static()) { - direction = ngraph::as_type_ptr(op)->get_direction(); - } else if (op->get_type_info() == ngraph::op::v0::LSTMSequence::get_type_info_static()) { - direction = ngraph::as_type_ptr(op)->get_direction(); - } else if (op->get_type_info() == ngraph::op::v5::LSTMSequence::get_type_info_static()) { - direction = ngraph::as_type_ptr(op)->get_direction(); - } else if (op->get_type_info() == ngraph::op::v5::RNNSequence::get_type_info_static()) { - direction = ngraph::as_type_ptr(op)->get_direction(); +static rnn_direction ieDirection2dnnl(const std::shared_ptr& op) { + ov::op::RecurrentSequenceDirection direction = ov::op::RecurrentSequenceDirection::FORWARD; + if (ov::is_type(op)) { + direction = ov::as_type_ptr(op)->get_direction(); + } else if (ov::is_type(op)) { + direction = ov::as_type_ptr(op)->get_direction(); + } else if (ov::is_type(op)) { + direction = ov::as_type_ptr(op)->get_direction(); + } else if (ov::is_type(op)) { + direction = ov::as_type_ptr(op)->get_direction(); } - return direction == ngraph::op::RecurrentSequenceDirection::FORWARD ? rnn_direction::unidirectional_left2right - : direction == ngraph::op::RecurrentSequenceDirection::REVERSE ? rnn_direction::unidirectional_right2left - : direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL ? rnn_direction::bidirectional_concat + return direction == ov::op::RecurrentSequenceDirection::FORWARD ? rnn_direction::unidirectional_left2right + : direction == ov::op::RecurrentSequenceDirection::REVERSE ? rnn_direction::unidirectional_right2left + : direction == ov::op::RecurrentSequenceDirection::BIDIRECTIONAL ? rnn_direction::bidirectional_concat : rnn_direction::unidirectional; } -static mkldnn::algorithm ie2dnnl(std::string act_type) { +static mkldnn::algorithm ie2dnnl(const std::string& act_type) { return act_type == "sigmoid" ? mkldnn::algorithm::eltwise_logistic : act_type == "tanh" ? mkldnn::algorithm::eltwise_tanh : act_type == "relu" ? mkldnn::algorithm::eltwise_relu : mkldnn::algorithm::undef; } -static mkldnn::algorithm ie2dnnl(const std::shared_ptr& op) { +static mkldnn::algorithm ie2dnnl(const std::shared_ptr& op) { if (one_of(op->get_type_info(), - ngraph::op::v3::GRUCell::get_type_info_static(), - ngraph::op::v5::GRUSequence::get_type_info_static())) { - auto gruCellOp = ngraph::as_type_ptr(op); - auto gruSeqOp = ngraph::as_type_ptr(op); + ov::op::v3::GRUCell::get_type_info_static(), + ov::op::v5::GRUSequence::get_type_info_static())) { + auto gruCellOp = ov::as_type_ptr(op); + auto gruSeqOp = ov::as_type_ptr(op); if ((gruCellOp && gruCellOp->get_linear_before_reset()) || (gruSeqOp && gruSeqOp->get_linear_before_reset())) return mkldnn::algorithm::lbr_gru; else return mkldnn::algorithm::vanilla_gru; } else if (one_of(op->get_type_info(), - ngraph::op::v0::LSTMCell::get_type_info_static(), - ngraph::op::v4::LSTMCell::get_type_info_static(), - ngraph::op::v0::LSTMSequence::get_type_info_static(), - ngraph::op::v5::LSTMSequence::get_type_info_static())) { + ov::op::v0::LSTMCell::get_type_info_static(), + ov::op::v4::LSTMCell::get_type_info_static(), + ov::op::v0::LSTMSequence::get_type_info_static(), + ov::op::v5::LSTMSequence::get_type_info_static())) { return mkldnn::algorithm::vanilla_lstm; } else if (one_of(op->get_type_info(), - ngraph::op::v0::RNNCell::get_type_info_static(), - ngraph::op::v5::RNNSequence::get_type_info_static())) { + ov::op::v0::RNNCell::get_type_info_static(), + ov::op::v5::RNNSequence::get_type_info_static())) { return mkldnn::algorithm::vanilla_rnn; } else { - IE_THROW() << "Unsupported cell type"; + IE_THROW() << "Operation " << op->get_type_name() << " with name '" << op->get_friendly_name() << "' has unsupported cell type."; } } -inline size_t gatesCount(mkldnn::algorithm alg) { +inline size_t gatesCount(const algorithm& alg) { switch (alg) { - case mkldnn::algorithm::vanilla_rnn: return 1; - case mkldnn::algorithm::vanilla_gru: - case mkldnn::algorithm::lbr_gru: return 3; - case mkldnn::algorithm::vanilla_lstm: return 4; + case algorithm::vanilla_rnn: return 1; + case algorithm::vanilla_gru: + case algorithm::lbr_gru: return 3; + case algorithm::vanilla_lstm: return 4; default: IE_THROW() << "Unsupported cell type"; return 0; } } -inline size_t statesCount(mkldnn::algorithm alg) { +inline size_t statesCount(const mkldnn::algorithm& alg) { switch (alg) { case mkldnn::algorithm::vanilla_rnn: case mkldnn::algorithm::vanilla_gru: @@ -95,97 +97,87 @@ inline size_t statesCount(mkldnn::algorithm alg) { } } -inline bool haveCellState(mkldnn::algorithm alg) { +inline bool haveCellState(const mkldnn::algorithm& alg) { return alg == mkldnn::algorithm::vanilla_lstm; } -const std::map MKLDNNRNN::weightsByLayerPrec { +const std::map MKLDNNRNN::weightsByLayerPrec { // layer precision, weights precision - {InferenceEngine::Precision::FP32, InferenceEngine::Precision::FP32}, - {InferenceEngine::Precision::BF16, InferenceEngine::Precision::BF16}, + {Precision::FP32, Precision::FP32}, + {Precision::BF16, Precision::BF16}, // FP16 and U8 are not supported yet - // {InferenceEngine::Precision::FP16, InferenceEngine::Precision::FP16}, - // {InferenceEngine::Precision::U8, InferenceEngine::Precision::I8}, + // {Precision::FP16, Precision::FP16}, + // {Precision::U8, Precision::I8}, }; -bool MKLDNNRNN::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { +bool MKLDNNRNN::isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept { try { - if (isDynamicNgraphNode(op)) { - errorMessage = "Doesn't support op with dynamic shapes"; - return false; - } - if (!one_of(op->get_type_info(), - ngraph::op::v3::GRUCell::get_type_info_static(), - ngraph::op::v0::LSTMCell::get_type_info_static(), - ngraph::op::v4::LSTMCell::get_type_info_static(), - ngraph::op::v0::RNNCell::get_type_info_static(), - ngraph::op::v5::GRUSequence::get_type_info_static(), - ngraph::op::v0::LSTMSequence::get_type_info_static(), - ngraph::op::v5::LSTMSequence::get_type_info_static(), - ngraph::op::v5::RNNSequence::get_type_info_static())) { - errorMessage = "Unsupported RNN operation."; + ov::op::v3::GRUCell::get_type_info_static(), + ov::op::v0::LSTMCell::get_type_info_static(), + ov::op::v4::LSTMCell::get_type_info_static(), + ov::op::v0::RNNCell::get_type_info_static(), + ov::op::v5::GRUSequence::get_type_info_static(), + ov::op::v0::LSTMSequence::get_type_info_static(), + ov::op::v5::LSTMSequence::get_type_info_static(), + ov::op::v5::RNNSequence::get_type_info_static())) { + errorMessage = "Unsupported sequence operation."; return false; } - if (one_of(op->get_type_info(), ngraph::op::v0::RNNCell::get_type_info_static(), ngraph::op::v3::GRUCell::get_type_info_static())) { - if (op->get_input_size() != 5) { - errorMessage = "Node expects 5 inputs. Actual: " + std::to_string(op->get_input_size()); - return false; - } - if (op->get_input_node_ptr(2)->get_type_info() != ngraph::op::v0::Constant::get_type_info_static() || - op->get_input_node_ptr(3)->get_type_info() != ngraph::op::v0::Constant::get_type_info_static() || - op->get_input_node_ptr(4)->get_type_info() != ngraph::op::v0::Constant::get_type_info_static()) { + if (one_of(op->get_type_info(), ov::op::v0::RNNCell::get_type_info_static(), ov::op::v3::GRUCell::get_type_info_static())) { + // Plug-in does not support dynamism on weights. + if (!ov::is_type(op->get_input_node_ptr(2)) || + !ov::is_type(op->get_input_node_ptr(3)) || + (op->get_input_size() > 4 && !ov::is_type(op->get_input_node_ptr(4)))) { errorMessage = "Node expects constants as W, R, B inputs."; return false; } } else if (one_of(op->get_type_info(), - ngraph::op::v0::LSTMCell::get_type_info_static(), - ngraph::op::v4::LSTMCell::get_type_info_static(), - ngraph::op::v5::GRUSequence::get_type_info_static(), - ngraph::op::v5::RNNSequence::get_type_info_static())) { - if (op->get_input_size() != 6) { - errorMessage = "Node expects 6 inputs. Actual: " + std::to_string(op->get_input_size()); - return false; - } - if (op->get_input_node_ptr(3)->get_type_info() != ngraph::op::v0::Constant::get_type_info_static() || - op->get_input_node_ptr(4)->get_type_info() != ngraph::op::v0::Constant::get_type_info_static() || - op->get_input_node_ptr(5)->get_type_info() != ngraph::op::v0::Constant::get_type_info_static()) { + ov::op::v0::LSTMCell::get_type_info_static(), + ov::op::v4::LSTMCell::get_type_info_static(), + ov::op::v5::GRUSequence::get_type_info_static(), + ov::op::v5::RNNSequence::get_type_info_static())) { + // Plug-in does not support dynamism on weights. + if (!ov::is_type(op->get_input_node_ptr(3)) || + !ov::is_type(op->get_input_node_ptr(4)) || + (op->get_input_size() > 5 && !ov::is_type(op->get_input_node_ptr(5)))) { errorMessage = "Node expects constants as W, R, B inputs."; return false; } } else if (one_of(op->get_type_info(), - ngraph::op::v0::LSTMSequence::get_type_info_static(), - ngraph::op::v5::LSTMSequence::get_type_info_static())) { + ov::op::v0::LSTMSequence::get_type_info_static(), + ov::op::v5::LSTMSequence::get_type_info_static())) { if (op->get_input_size() != 7) { errorMessage = "Node expects 7 inputs. Actual: " + std::to_string(op->get_input_size()); return false; } - if (op->get_input_node_ptr(4)->get_type_info() != ngraph::op::v0::Constant::get_type_info_static() || - op->get_input_node_ptr(5)->get_type_info() != ngraph::op::v0::Constant::get_type_info_static() || - op->get_input_node_ptr(6)->get_type_info() != ngraph::op::v0::Constant::get_type_info_static()) { + // Plug-in does not support dynamism on weights. + if (!ov::is_type(op->get_input_node_ptr(4)) || + !ov::is_type(op->get_input_node_ptr(5)) || + !ov::is_type(op->get_input_node_ptr(6))) { errorMessage = "Node expects constants as W, R, B inputs."; return false; } } - auto rnnCellBase = std::dynamic_pointer_cast(op); - if (rnnCellBase && rnnCellBase->get_clip() != 0.0f) { + auto rnnCellBase = ov::as_type_ptr(op); + if (rnnCellBase && rnnCellBase->get_clip() != 0.f) { errorMessage = "Clipping is not supported for RNN primitive."; return false; } - ngraph::op::RecurrentSequenceDirection direction = ngraph::op::RecurrentSequenceDirection::FORWARD; - if (op->get_type_info() == ngraph::op::v5::GRUSequence::get_type_info_static()) { - direction = ngraph::as_type_ptr(op)->get_direction(); - } else if (op->get_type_info() == ngraph::op::v0::LSTMSequence::get_type_info_static()) { - direction = ngraph::as_type_ptr(op)->get_direction(); - } else if (op->get_type_info() == ngraph::op::v5::LSTMSequence::get_type_info_static()) { - direction = ngraph::as_type_ptr(op)->get_direction(); - } else if (op->get_type_info() == ngraph::op::v5::RNNSequence::get_type_info_static()) { - direction = ngraph::as_type_ptr(op)->get_direction(); + ov::op::RecurrentSequenceDirection direction = ov::op::RecurrentSequenceDirection::FORWARD; + if (ov::is_type(op)) { + direction = ov::as_type_ptr(op)->get_direction(); + } else if (ov::is_type(op)) { + direction = ov::as_type_ptr(op)->get_direction(); + } else if (ov::is_type(op)) { + direction = ov::as_type_ptr(op)->get_direction(); + } else if (ov::is_type(op)) { + direction = ov::as_type_ptr(op)->get_direction(); } - if (!one_of(direction, ngraph::op::RecurrentSequenceDirection::FORWARD, ngraph::op::RecurrentSequenceDirection::REVERSE)) { + if (!one_of(direction, ov::op::RecurrentSequenceDirection::FORWARD, ov::op::RecurrentSequenceDirection::REVERSE)) { errorMessage = "Unsupported sequence direction."; return false; } @@ -195,8 +187,13 @@ bool MKLDNNRNN::isSupportedOperation(const std::shared_ptr& return true; } -MKLDNNRNN::MKLDNNRNN(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache) : +MKLDNNRNN::MKLDNNRNN(const std::shared_ptr& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache) : MKLDNNNode(op, eng, cache) { + std::string errorMessage; + if (!isSupportedOperation(op, errorMessage)) { + IE_THROW(NotImplemented) << errorMessage; + } + internalBlobDesc.emplace_back([&](primitive_desc_iterator& primitive_desc_it, size_t idx) -> DnnlMemoryDescPtr { return MKLDNNExtensionUtils::makeDescriptor(primitive_desc_it.weights_desc(0)); }); @@ -207,37 +204,56 @@ MKLDNNRNN::MKLDNNRNN(const std::shared_ptr& op, const mkldnn::engi return MKLDNNExtensionUtils::makeDescriptor(primitive_desc_it.weights_desc(2)); }); - std::string errorMessage; - if (!isSupportedOperation(op, errorMessage)) { - IE_THROW(NotImplemented) << errorMessage; - } - is_cell = one_of(op->get_type_info(), - ngraph::op::v0::RNNCell::get_type_info_static(), - ngraph::op::v3::GRUCell::get_type_info_static(), - ngraph::op::v0::LSTMCell::get_type_info_static(), - ngraph::op::v4::LSTMCell::get_type_info_static()); + ov::op::v0::RNNCell::get_type_info_static(), + ov::op::v3::GRUCell::get_type_info_static(), + ov::op::v0::LSTMCell::get_type_info_static(), + ov::op::v4::LSTMCell::get_type_info_static()); if (one_of(op->get_type_info(), - ngraph::op::v0::RNNCell::get_type_info_static(), - ngraph::op::v3::GRUCell::get_type_info_static())) { + ov::op::v0::RNNCell::get_type_info_static(), + ov::op::v3::GRUCell::get_type_info_static())) { wIdx = 2; rIdx = 3; bIdx = 4; } else if (one_of(op->get_type_info(), - ngraph::op::v5::RNNSequence::get_type_info_static(), - ngraph::op::v0::LSTMCell::get_type_info_static(), - ngraph::op::v4::LSTMCell::get_type_info_static(), - ngraph::op::v5::GRUSequence::get_type_info_static())) { + ov::op::v5::RNNSequence::get_type_info_static(), + ov::op::v0::LSTMCell::get_type_info_static(), + ov::op::v4::LSTMCell::get_type_info_static(), + ov::op::v5::GRUSequence::get_type_info_static())) { wIdx = 3; rIdx = 4; bIdx = 5; } else if (one_of(op->get_type_info(), - ngraph::op::v0::LSTMSequence::get_type_info_static(), - ngraph::op::v5::LSTMSequence::get_type_info_static())) { + ov::op::v0::LSTMSequence::get_type_info_static(), + ov::op::v5::LSTMSequence::get_type_info_static())) { wIdx = 4; rIdx = 5; bIdx = 6; } - if (is_cell) - initCell(op); - else - initSeq(op); + auto rnnCellBase = std::dynamic_pointer_cast(op); + if (!rnnCellBase) + THROW_ERROR << "does not have original layer for RNNCell."; + + cell_type = ie2dnnl(op); + cell_act = mkldnn::algorithm::undef; + if (!rnnCellBase->get_activations().empty()) + cell_act = ie2dnnl(rnnCellBase->get_activations()[0]); // Works only for RNN with one gate + + G = gatesCount(cell_type); + Gb = (cell_type != mkldnn::algorithm::lbr_gru) ? G : G + 1; + S = statesCount(cell_type); + SC = rnnCellBase->get_hidden_size(); + N = {getInputShapeAtPort(0).getMinDims()[0], getInputShapeAtPort(0).getMaxDims()[0]}; + + if (is_cell) { + initCell(); + } else { + direction = ieDirection2dnnl(op); + + nativeOrder = false; + const auto& rtInfo = op->get_rt_info(); + if (rtInfo.count("seqAxis")) { + nativeOrder = rtInfo.at("seqAxis").as() == 0; + } + + initSequence(); + } } bool MKLDNNRNN::created() const { @@ -248,248 +264,215 @@ void MKLDNNRNN::getSupportedDescriptors() { if (is_cell) fillCellDesc(); else - fillSeqDesc(); + fillSequenceDesc(); } -void MKLDNNRNN::initCell(const std::shared_ptr& op) { - auto rnnCellBase = std::dynamic_pointer_cast(op); - if (!rnnCellBase) - IE_THROW() << "No original layer for RNNCell."; +void MKLDNNRNN::initCell() { + if (getInputShapeAtPort(0).getRank() != 2lu || getInputShapeAtPort(1).getRank() != 2lu) + THROW_ERROR << "has incorrect input ranks. Data rank: " << getInputShapeAtPort(0).getRank() << + "; Hidden state rank: " << getInputShapeAtPort(1).getRank(); - cell_type = ie2dnnl(op); - cell_act = ie2dnnl(rnnCellBase->get_activations()[0]); // Works only for RNN with one gate + T = {1, 1}; + if (cell_type == algorithm::vanilla_lstm) + DC = getInputShapeAtPort(3).getDims()[1]; + else + DC = getInputShapeAtPort(2).getDims()[1]; - auto in_data_dims = op->get_input_shape(0); - auto in_h_state_dims = op->get_input_shape(1); - auto out_h_state_dims = op->get_output_shape(0); + // Expected shapes. + const Shape shapeD{{N.minVal, DC}, {N.maxVal, DC}}, shapeS{{N.minVal, SC}, {N.maxVal, SC}}; - if (in_data_dims.size() != 2 || in_h_state_dims.size() != 2) - IE_THROW() << "Incorrect shape of input/output ports for layer " << getName(); - - G = gatesCount(cell_type); - S = statesCount(cell_type); - T = 1; - N = in_data_dims[0]; - DC = in_data_dims[1]; - SC = in_h_state_dims[1]; - - Gb = (cell_type != mkldnn::algorithm::lbr_gru) ? G : G + 1; - - // Expected shapes - VectorDims D_shape {N, DC}, S_shape {N, SC}, S_4D_shape {L, D, N, SC}; - - if (in_data_dims != D_shape - || in_h_state_dims != S_shape - || out_h_state_dims != S_shape) - IE_THROW() << "Incorrect shape of input/output ports for layer " << getName(); + if ((getInputShapeAtPort(0).isStatic() && getInputShapeAtPort(0) != shapeD) || + (getInputShapeAtPort(1).isStatic() && getInputShapeAtPort(1) != shapeS) || + (getOutputShapeAtPort(0) != shapeS)) { + THROW_ERROR << "has incorrect input/output shapes. Data shape: " << getInputShapeAtPort(0).toString() << + "; Hidden state input: " << getInputShapeAtPort(1).toString() << "; Hidden state output: " << getOutputShapeAtPort(0).toString(); + } if (S == 2) { - auto in_c_state_dims = op->get_input_shape(2); - auto out_c_state_dims = op->get_output_shape(1); - - if (in_c_state_dims != S_shape - || out_c_state_dims != S_shape) - IE_THROW() << "Incorrect shape of input/output ports for layer " << getName(); + if ((getInputShapeAtPort(2).isStatic() && getInputShapeAtPort(2) != shapeS) || (getOutputShapeAtPort(1) != shapeS)) + THROW_ERROR << "has incorrect input/output shapes. Cell state input: " << getInputShapeAtPort(2).toString() << + "; Cell state output: " << getOutputShapeAtPort(1).toString(); } } void MKLDNNRNN::fillCellDesc() { - runtimePrecision = getOriginalInputPrecisionAtPort(0); - auto dataType = MKLDNNExtensionUtils::IEPrecisionToDataType(runtimePrecision); - - Shape S_4D_shape(VectorDims{L, D, N, SC}); + const auto dataType = MKLDNNExtensionUtils::IEPrecisionToDataType(getOriginalInputPrecisionAtPort(0)); + const Shape shapeS_4D = MemoryDescUtils::makeDummyShape({{L, D, N.minVal, SC}, {L, D, N.maxVal, SC}}), + inShape = MemoryDescUtils::makeDummyShape({{T.minVal, N.minVal, DC}, {T.maxVal, N.maxVal, DC}}), + outShape = MemoryDescUtils::makeDummyShape({{T.minVal, N.minVal, SC}, {T.maxVal, N.maxVal, SC}}); // layer input plus states - in_data_d.reserve(S + 1); - out_data_d.reserve(S + 1); + inDataDescs.reserve(S + 1); + outDataDescs.reserve(S + 1); - // Shapes and Attributes are correct. Can start internal stuff initialization. - in_data_d.emplace_back(Shape(VectorDims{T, N, DC}), dataType, memory::format_tag::tnc); - out_data_d.emplace_back(Shape(VectorDims{T, N, SC}), dataType, memory::format_tag::tnc); + inDataDescs.emplace_back(inShape, dataType, memory::format_tag::tnc); + outDataDescs.emplace_back(outShape, dataType, memory::format_tag::tnc); - in_data_d.emplace_back(S_4D_shape, dataType, memory::format_tag::ldnc); - out_data_d.emplace_back(S_4D_shape, dataType, memory::format_tag::ldnc); + inDataDescs.emplace_back(shapeS_4D, dataType, memory::format_tag::ldnc); + outDataDescs.emplace_back(shapeS_4D, dataType, memory::format_tag::ldnc); if (haveCellState(cell_type)) { - in_data_d.emplace_back(S_4D_shape, memory::data_type::f32, memory::format_tag::ldnc); - out_data_d.emplace_back(S_4D_shape, memory::data_type::f32, memory::format_tag::ldnc); + inDataDescs.emplace_back(shapeS_4D, memory::data_type::f32, memory::format_tag::ldnc); + outDataDescs.emplace_back(shapeS_4D, memory::data_type::f32, memory::format_tag::ldnc); } copyWeightsData(); - // Expected shapes - Shape D_shape(VectorDims{N, DC}), S_shape(VectorDims{N, SC}), WShape(VectorDims{SC * G, DC}), RShape(VectorDims{SC * G, SC}), BShape(VectorDims{SC * Gb}); - std::vector in_candidate, out_candidate; - in_candidate.reserve(6); + // Expected shapes. + Shape shapeD{{N.minVal, DC}, {N.maxVal, DC}}, shapeS{{N.minVal, SC}, {N.maxVal, SC}}, + WShape{SC * G, DC}, RShape{SC * G, SC}, BShape{SC * Gb}; + std::vector inCandidate, outCandidate; + inCandidate.reserve(6); - in_candidate.emplace_back(std::make_shared(D_shape, dataType, memory::format_tag::nc)); - in_candidate.emplace_back(std::make_shared(S_shape, dataType, memory::format_tag::nc)); - out_candidate.emplace_back(std::make_shared(S_shape, dataType, memory::format_tag::nc)); + inCandidate.emplace_back(std::make_shared(shapeD, dataType, memory::format_tag::nc)); + inCandidate.emplace_back(std::make_shared(shapeS, dataType, memory::format_tag::nc)); + outCandidate.emplace_back(std::make_shared(shapeS, dataType, memory::format_tag::nc)); if (haveCellState(cell_type)) { - in_candidate.emplace_back(std::make_shared(S_shape, memory::data_type::f32, memory::format_tag::nc)); - out_candidate.emplace_back(std::make_shared(S_shape, memory::data_type::f32, memory::format_tag::nc)); + inCandidate.emplace_back(std::make_shared(shapeS, memory::data_type::f32, memory::format_tag::nc)); + outCandidate.emplace_back(std::make_shared(shapeS, memory::data_type::f32, memory::format_tag::nc)); } if (one_of(cell_type, mkldnn::algorithm::vanilla_rnn, mkldnn::algorithm::vanilla_gru, mkldnn::algorithm::lbr_gru, mkldnn::algorithm::vanilla_lstm)) { - in_candidate.emplace_back(std::make_shared(WShape, memory::data_type::f32, memory::format_tag::nc)); - in_candidate.emplace_back(std::make_shared(RShape, memory::data_type::f32, memory::format_tag::nc)); - in_candidate.emplace_back(std::make_shared(BShape, memory::data_type::f32, memory::format_tag::x)); + inCandidate.emplace_back(std::make_shared(WShape, memory::data_type::f32, memory::format_tag::nc)); + inCandidate.emplace_back(std::make_shared(RShape, memory::data_type::f32, memory::format_tag::nc)); + inCandidate.emplace_back(std::make_shared(BShape, memory::data_type::f32, memory::format_tag::x)); } - createDescriptor(in_candidate, out_candidate); + createDescriptor(inCandidate, outCandidate); } -void MKLDNNRNN::initSeq(const std::shared_ptr& op) { - auto rnnCellBase = std::dynamic_pointer_cast(op); - if (!rnnCellBase) - IE_THROW() << "No original layer for RNNCell."; +void MKLDNNRNN::initSequence() { + const auto& inDataShape = getInputShapeAtPort(0); + const auto& outDataShape = getOutputShapeAtPort(0); - cell_type = ie2dnnl(op); - cell_act = mkldnn::algorithm::undef; - if (!rnnCellBase->get_activations().empty()) - cell_act = ie2dnnl(rnnCellBase->get_activations()[0]); // Works only for RNN with one gate + if (inDataShape.getRank() != 3lu || outDataShape.getRank() != 4lu) + THROW_ERROR << "has incorrect input/output shapes. Input data shape: " << inDataShape.toString() << + " Output shape: " << outDataShape.toString(); - direction = ieDirection2dnnl(op); + if (!one_of(getOriginalInputsNumber(), 6, 7)) + THROW_ERROR << "has incorrect number of input ports: " << getOriginalInputsNumber(); + if (!one_of(getOriginalOutputsNumber(), 2, 3)) + THROW_ERROR << "has incorrect number of output ports: " << getOriginalOutputsNumber(); - if (!one_of(op->get_input_size(), 6, 7)) - IE_THROW() << "Incorrect number of input ports for layer " << getName(); - if (!one_of(op->get_output_size(), 2, 3)) - IE_THROW() << "Incorrect number of output ports for layer " << getName(); - - in_data_dims = op->get_input_shape(0); - out_data_dims = op->get_output_shape(0); - - if (in_data_dims.size() != 3 || out_data_dims.size() != 4) - IE_THROW() << "Incorrect shape of input/output ports for layer " << getName(); - - N = op->get_input_shape(1)[0]; - nativeOrder = false; - const auto rtInfo = op->get_rt_info(); - - if (rtInfo.count("seqAxis")) { - nativeOrder = rtInfo.at("seqAxis").as() == 0; - } - out_data_dims.erase(out_data_dims.begin() + 1); - - std::swap(in_data_dims[0], in_data_dims[1]); - std::swap(out_data_dims[0], out_data_dims[1]); - - G = gatesCount(cell_type); - S = statesCount(cell_type); - T = in_data_dims[0]; - DC = in_data_dims[2]; - SC = rnnCellBase->get_hidden_size(); - - Gb = (cell_type != mkldnn::algorithm::lbr_gru) ? G : G + 1; + T = {inDataShape.getMinDims()[1], inDataShape.getMaxDims()[1]}; + if (cell_type == algorithm::vanilla_lstm) + DC = getInputShapeAtPort(4).getDims()[2]; + else + DC = getInputShapeAtPort(3).getDims()[2]; // layer input plus states - in_data_d.reserve(S + 1); - out_data_d.reserve(S + 1); + inDataDescs.reserve(S + 1); + outDataDescs.reserve(S + 1); } -void MKLDNNRNN::fillSeqDesc() { - runtimePrecision = getOriginalInputPrecisionAtPort(0); - auto dataType = MKLDNNExtensionUtils::IEPrecisionToDataType(runtimePrecision); - - Shape S_4D_shape(VectorDims{L, D, N, SC}); +void MKLDNNRNN::fillSequenceDesc() { + const auto dataType = MKLDNNExtensionUtils::IEPrecisionToDataType(getOriginalInputPrecisionAtPort(0)); + const Shape shapeS_4D = MemoryDescUtils::makeDummyShape({{L, D, N.minVal, SC}, {L, D, N.maxVal, SC}}), + inShape = MemoryDescUtils::makeDummyShape({{T.minVal, N.minVal, DC}, {T.maxVal, N.maxVal, DC}}), + outShape = MemoryDescUtils::makeDummyShape({{T.minVal, N.minVal, SC}, {T.maxVal, N.maxVal, SC}}), + shapeNDSC {{N.minVal, D, SC}, {N.maxVal, D, SC}}, + shapeNTSC {{N.minVal, T.minVal, SC}, {N.maxVal, T.maxVal, SC}}, + shapeNTDC {{N.minVal, T.minVal, DC}, {N.maxVal, T.maxVal, DC}}; // Try to create descriptor and corresponding configuration - in_data_d.emplace_back(Shape(VectorDims{in_data_dims}), dataType, memory::format_tag::tnc); - out_data_d.emplace_back(Shape(VectorDims{out_data_dims}), dataType, memory::format_tag::tnc); + inDataDescs.emplace_back(inShape, dataType, memory::format_tag::tnc); + outDataDescs.emplace_back(outShape, dataType, memory::format_tag::tnc); - in_data_d.emplace_back(S_4D_shape, dataType, memory::format_tag::ldnc); - out_data_d.emplace_back(S_4D_shape, dataType, memory::format_tag::ldnc); + inDataDescs.emplace_back(shapeS_4D, dataType, memory::format_tag::ldnc); + outDataDescs.emplace_back(shapeS_4D, dataType, memory::format_tag::ldnc); if (haveCellState(cell_type)) { - in_data_d.emplace_back(S_4D_shape, memory::data_type::f32, memory::format_tag::ldnc); - out_data_d.emplace_back(S_4D_shape, memory::data_type::f32, memory::format_tag::ldnc); + inDataDescs.emplace_back(shapeS_4D, memory::data_type::f32, memory::format_tag::ldnc); + outDataDescs.emplace_back(shapeS_4D, memory::data_type::f32, memory::format_tag::ldnc); } copyWeightsData(); - std::vector in_candidate; - in_candidate.reserve(7); + std::vector inCandidate; + inCandidate.reserve(7); if (nativeOrder) - in_candidate.emplace_back(std::make_shared(inputShapes[RNNInOutKind::Layer], dataType, memory::format_tag::tnc)); - else if (N == 1) - // WA to avoid reorder before sequence for some models - in_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, T, DC}), dataType, memory::format_tag::tnc)); + inCandidate.emplace_back(std::make_shared(inputShapes[RNNInOutKind::Layer], dataType, memory::format_tag::tnc)); + else if (N.isStatic() && N.maxVal == 1) + // WA to avoid reorder before sequence for some models. + inCandidate.emplace_back(std::make_shared(shapeNTDC, dataType, memory::format_tag::tnc)); else - in_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, T, DC}), dataType, memory::format_tag::ntc)); + inCandidate.emplace_back(std::make_shared(shapeNTDC, dataType, memory::format_tag::ntc)); - // initial hidden state - // WA to avoid reorder before + // Initial hidden state. + // WA to avoid reorder before. if (D == 1) - in_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, D, SC}), dataType, memory::format_tag::tnc)); + inCandidate.emplace_back(std::make_shared(shapeNDSC, dataType, memory::format_tag::tnc)); else - in_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, D, SC}), dataType, memory::format_tag::ntc)); + inCandidate.emplace_back(std::make_shared(shapeNDSC, dataType, memory::format_tag::ntc)); // initial cell state if (haveCellState(cell_type)) { if (D == 1) - in_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, D, SC}), memory::data_type::f32, memory::format_tag::tnc)); + inCandidate.emplace_back(std::make_shared(shapeNDSC, memory::data_type::f32, memory::format_tag::tnc)); else - in_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, D, SC}), memory::data_type::f32, memory::format_tag::ntc)); + inCandidate.emplace_back(std::make_shared(shapeNDSC, memory::data_type::f32, memory::format_tag::ntc)); } - in_candidate.emplace_back(std::make_shared(Shape(VectorDims{N}), memory::data_type::s32, memory::format_tag::x)); // sequence lengths - in_candidate.emplace_back(std::make_shared(Shape(VectorDims{D, G * SC, DC}), memory::data_type::f32, memory::format_tag::ntc)); // W - in_candidate.emplace_back(std::make_shared(Shape(VectorDims{D, G * SC, SC}), memory::data_type::f32, memory::format_tag::ntc)); // R - in_candidate.emplace_back(std::make_shared(Shape(VectorDims{D, Gb * SC}), memory::data_type::f32, memory::format_tag::nc)); // B + inCandidate.emplace_back(std::make_shared(Shape{VectorDims{N.minVal}, VectorDims{N.maxVal}}, + memory::data_type::s32, memory::format_tag::x)); // sequence lengths + inCandidate.emplace_back(std::make_shared(Shape{D, G * SC, DC}, memory::data_type::f32, memory::format_tag::ntc)); // W + inCandidate.emplace_back(std::make_shared(Shape{D, G * SC, SC}, memory::data_type::f32, memory::format_tag::ntc)); // R + inCandidate.emplace_back(std::make_shared(Shape{D, Gb * SC}, memory::data_type::f32, memory::format_tag::nc)); // B - std::vector out_candidate; - out_candidate.reserve(3); + std::vector outCandidate; + outCandidate.reserve(3); if (nativeOrder) { - out_candidate.emplace_back(std::make_shared(out_data_d[RNNInOutKind::Layer])); - } else if (N == 1) { + outCandidate.emplace_back(std::make_shared(outDataDescs[RNNInOutKind::Layer])); + } else if (N.isStatic() && N.maxVal == 1) { // WA to avoid reorder after sequence for some models - out_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, T, SC}), dataType, memory::format_tag::tnc)); + outCandidate.emplace_back(std::make_shared(shapeNTSC, dataType, memory::format_tag::tnc)); } else { - out_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, T, SC}), dataType, memory::format_tag::ntc)); + outCandidate.emplace_back(std::make_shared(shapeNTSC, dataType, memory::format_tag::ntc)); } // WA to avoid reorder after if (D == 1) - out_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, D, SC}), dataType, memory::format_tag::tnc)); + outCandidate.emplace_back(std::make_shared(shapeNDSC, dataType, memory::format_tag::tnc)); else - out_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, D, SC}), dataType, memory::format_tag::ntc)); + outCandidate.emplace_back(std::make_shared(shapeNDSC, dataType, memory::format_tag::ntc)); if (haveCellState(cell_type)) { if (D == 1) - out_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, D, SC}), memory::data_type::f32, memory::format_tag::tnc)); + outCandidate.emplace_back(std::make_shared(shapeNDSC, memory::data_type::f32, memory::format_tag::tnc)); else - out_candidate.emplace_back(std::make_shared(Shape(VectorDims{N, D, SC}), memory::data_type::f32, memory::format_tag::ntc)); + outCandidate.emplace_back(std::make_shared(shapeNDSC, memory::data_type::f32, memory::format_tag::ntc)); } - createDescriptor(in_candidate, out_candidate); + createDescriptor(inCandidate, outCandidate); } bool MKLDNNRNN::verifyWeightsPrecision(const Precision &layerPrec, const Precision &weightsPrec) { if (!weightsByLayerPrec.count(layerPrec)) - IE_THROW() << "Unsupported layer precision " << layerPrec; + THROW_ERROR << "has unsupported layer precision " << layerPrec; return weightsPrec == weightsByLayerPrec.at(layerPrec); } template void MKLDNNRNN::fillWeights(const int *gate_map, const size_t wIdx, const size_t rIdx) { - const auto weightPrec = getOriginalInputPrecisionAtPort(wIdx); - if (!verifyWeightsPrecision(runtimePrecision, weightPrec) && runtimePrecision != Precision::BF16 && weightPrec != Precision::FP32) { - IE_THROW() << "Doesn't support combination of weights precision: " << weightPrec << " and runtime precision: " << runtimePrecision; + const auto& dataPrecision = getOriginalInputPrecisionAtPort(0); + const auto& weightPrec = getOriginalInputPrecisionAtPort(wIdx); + if (!verifyWeightsPrecision(dataPrecision, weightPrec) && dataPrecision != Precision::BF16 && weightPrec != Precision::FP32) { + THROW_ERROR << "doesn't support combination of weights precision: " << weightPrec << " and runtime precision: " << dataPrecision; } // create weight blobs (data and state part) - InferenceEngine::SizeVector dims_w = { L, D, DC, G, SC }; - InferenceEngine::TensorDesc w_data_desc(runtimePrecision, dims_w, getWeightsLayoutByDims(dims_w, false)); - Blob::Ptr w_data_mem = InferenceEngine::make_shared_blob(w_data_desc); + const VectorDims dims_w = { L, D, DC, G, SC }; + TensorDesc w_data_desc(dataPrecision, dims_w, getWeightsLayoutByDims(dims_w, false)); + Blob::Ptr w_data_mem = make_shared_blob(w_data_desc); w_data_mem->allocate(); auto w_ptr = static_cast(w_data_mem->buffer()); if (w_ptr == nullptr) IE_THROW(NotAllocated) << "Internal blob was not allocated for node " << getName() << "."; - InferenceEngine::SizeVector dims_s = { L, D, SC, G, SC }; - InferenceEngine::TensorDesc w_state_desc(runtimePrecision, dims_s, getWeightsLayoutByDims(dims_s, false)); - Blob::Ptr w_state_mem = InferenceEngine::make_shared_blob(w_state_desc); + const VectorDims dims_s = { L, D, SC, G, SC }; + TensorDesc w_state_desc(dataPrecision, dims_s, getWeightsLayoutByDims(dims_s, false)); + Blob::Ptr w_state_mem = make_shared_blob(w_state_desc); w_state_mem->allocate(); auto r_ptr = static_cast(w_state_mem->buffer()); if (r_ptr == nullptr) @@ -508,8 +491,8 @@ void MKLDNNRNN::fillWeights(const int *gate_map, const size_t wIdx, const size_t auto ie_w_ptr = ie_w_vec.data(); auto ie_r_ptr = ie_r_vec.data(); - cpu_convert(wConstBlob->GetPtr(), ie_w_ptr, weightPrec, runtimePrecision, ie_w_vec_size); - cpu_convert(rConstBlob->GetPtr(), ie_r_ptr, weightPrec, runtimePrecision, ie_r_vec_size); + cpu_convert(wConstBlob->GetPtr(), ie_w_ptr, weightPrec, dataPrecision, ie_w_vec_size); + cpu_convert(rConstBlob->GetPtr(), ie_r_ptr, weightPrec, dataPrecision, ie_r_vec_size); const int step = SC * G; @@ -535,17 +518,17 @@ void MKLDNNRNN::fillWeights(const int *gate_map, const size_t wIdx, const size_t internalBlobs.push_back(w_state_mem); } -template +template void MKLDNNRNN::fillBiases(const int *gate_map) { using dataType = typename PrecisionTrait::value_type; if (getOriginalInputPrecisionAtPort(bIdx) != Precision::FP32) { - IE_THROW() << "Doesn't support bias precision: " << getOriginalInputPrecisionAtPort(bIdx); + THROW_ERROR << "doesn't support bias precision: " << getOriginalInputPrecisionAtPort(bIdx); } - InferenceEngine::SizeVector dims_b = { L, D, Gb, SC }; - InferenceEngine::TensorDesc w_bias_data_desc(Prec, dims_b, getWeightsLayoutByDims(dims_b, false)); - Blob::Ptr w_bias_data_mem = InferenceEngine::make_shared_blob(w_bias_data_desc); + VectorDims dims_b = { L, D, Gb, SC }; + TensorDesc w_bias_data_desc(Prec, dims_b, getWeightsLayoutByDims(dims_b, false)); + Blob::Ptr w_bias_data_mem = make_shared_blob(w_bias_data_desc); w_bias_data_mem->allocate(); auto b_ptr = static_cast(w_bias_data_mem->buffer()); if (b_ptr == nullptr) @@ -600,107 +583,124 @@ void MKLDNNRNN::copyWeightsData() { if (cell_type == mkldnn::algorithm::vanilla_lstm) { gate_map = gate_map_lstm; if (G > gate_map_lstm_size) { - IE_THROW() << "G isn't equal to the size of gate_map"; + THROW_ERROR << ". G isn't equal to the size of gate_map."; } } else if (cell_type == mkldnn::algorithm::vanilla_gru) { gate_map = gate_map_gru; if (G > gate_map_gru_size) { - IE_THROW() << "G isn't equal to the size of gate_map"; + THROW_ERROR << ". G isn't equal to the size of gate_map"; } } else if (cell_type == mkldnn::algorithm::lbr_gru) { gate_map = gate_map_gru; if (G > gate_map_gru_size) { - IE_THROW() << "G isn't equal to the size of gate_map"; + THROW_ERROR << ". G isn't equal to the size of gate_map."; } } else if (cell_type == mkldnn::algorithm::vanilla_rnn) { gate_map = gate_map_rnn; if (G > gate_map_rnn_size) { - IE_THROW() << "G isn't equal to the size of gate_map"; + THROW_ERROR << ". G isn't equal to the size of gate_map."; } } else { gate_map = gate_map_gru; if (G > gate_map_gru_size) { - IE_THROW() << "G isn't equal to the size of gate_map"; + THROW_ERROR << ". G isn't equal to the size of gate_map."; } } - if (runtimePrecision == Precision::BF16) { + const auto& dataPrecision = getOriginalInputPrecisionAtPort(0); + if (dataPrecision == Precision::BF16) { fillWeights(gate_map, wIdx, rIdx); - } else if (runtimePrecision == Precision::FP32) { + } else if (dataPrecision == Precision::FP32) { // WA To avoid different weights layer and iter formats in FP32 case - if (T != 1 || N < 16) - w_format = mkldnn::memory::format_tag::ldigo; + if (T.minVal > 1 || N.maxVal < optimalBatchSize) + wFormat = mkldnn::memory::format_tag::ldigo; fillWeights(gate_map, wIdx, rIdx); } else {// TODO FP16 and INT8 support - IE_THROW() << "Unsupported data type"; + THROW_ERROR << "has unsupported data type: " << dataPrecision; } - if (runtimePrecision == Precision::BF16 || runtimePrecision == Precision::FP32) + if (dataPrecision == Precision::BF16 || dataPrecision == Precision::FP32) fillBiases(gate_map); } -void MKLDNNRNN::createDescriptor(const std::vector &inputDesc, - const std::vector &outputDesc) { - auto dataType = MKLDNNExtensionUtils::IEPrecisionToDataType(runtimePrecision); - auto weightsDims = MKLDNNExtensionUtils::convertToDnnlDims(VectorDims{ L, D, DC, G, SC }); - mkldnn::memory::desc w_data_d(weightsDims, dataType, w_format); - auto statesDims = MKLDNNExtensionUtils::convertToDnnlDims(VectorDims{ L, D, SC, G, SC }); - mkldnn::memory::desc w_state_d(statesDims, dataType, w_format); - auto biasDims = MKLDNNExtensionUtils::convertToDnnlDims(VectorDims{ L, D, Gb, SC }); - mkldnn::memory::desc w_bias_d(biasDims, memory::data_type::f32, memory::format_tag::ldgo); + +void MKLDNNRNN::fillDescs() { + descs.clear(); switch (cell_type) { case mkldnn::algorithm::vanilla_rnn: { - MKLDNNDescriptor desc(std::shared_ptr( - new vanilla_rnn_forward::desc(prop_kind::forward_scoring, cell_act, direction, - /* In Data */ in_data_d[RNNInOutKind::Layer].getDnnlDesc(), - /* In State */ in_data_d[RNNInOutKind::HiddenState].getDnnlDesc(), - /* Weights data */ w_data_d, - /* Weights state */ w_state_d, - /* Bias */ w_bias_d, - /* Out Data */ out_data_d[RNNInOutKind::Layer].getDnnlDesc(), - /* Out State */ out_data_d[RNNInOutKind::HiddenState].getDnnlDesc()))); + MKLDNNDescriptor desc(std::make_shared( + prop_kind::forward_scoring, + cell_act, + direction, + /* In Data */ inDataDescs[RNNInOutKind::Layer].getDnnlDesc(), + /* In State */ inDataDescs[RNNInOutKind::HiddenState].getDnnlDesc(), + /* Weights data */ wDescs[0], + /* Weights state */ wDescs[1], + /* Bias */ wDescs[2], + /* Out Data */ outDataDescs[RNNInOutKind::Layer].getDnnlDesc(), + /* Out State */ outDataDescs[RNNInOutKind::HiddenState].getDnnlDesc())); descs.push_back(desc); } break; case mkldnn::algorithm::vanilla_gru: { - MKLDNNDescriptor desc(std::shared_ptr( - new gru_forward::desc(prop_kind::forward_scoring, direction, - /* In Data */ in_data_d[RNNInOutKind::Layer].getDnnlDesc(), - /* In State */ in_data_d[RNNInOutKind::HiddenState].getDnnlDesc(), - /* Weights data */ w_data_d, - /* Weights state */ w_state_d, - /* Bias */ w_bias_d, - /* Out Data */ out_data_d[RNNInOutKind::Layer].getDnnlDesc(), - /* Out State */ out_data_d[RNNInOutKind::HiddenState].getDnnlDesc()))); + MKLDNNDescriptor desc(std::make_shared( + prop_kind::forward_scoring, + direction, + /* In Data */ inDataDescs[RNNInOutKind::Layer].getDnnlDesc(), + /* In State */ inDataDescs[RNNInOutKind::HiddenState].getDnnlDesc(), + /* Weights data */ wDescs[0], + /* Weights state */ wDescs[1], + /* Bias */ wDescs[2], + /* Out Data */ outDataDescs[RNNInOutKind::Layer].getDnnlDesc(), + /* Out State */ outDataDescs[RNNInOutKind::HiddenState].getDnnlDesc())); descs.push_back(desc); } break; case mkldnn::algorithm::lbr_gru: { - MKLDNNDescriptor desc(std::shared_ptr( - new lbr_gru_forward::desc(prop_kind::forward_scoring, direction, - /* In Data */ in_data_d[RNNInOutKind::Layer].getDnnlDesc(), - /* In State */ in_data_d[RNNInOutKind::HiddenState].getDnnlDesc(), - /* Weights data */ w_data_d, - /* Weights state */ w_state_d, - /* Bias */ w_bias_d, - /* Out Data */ out_data_d[RNNInOutKind::Layer].getDnnlDesc(), - /* Out State */ out_data_d[RNNInOutKind::HiddenState].getDnnlDesc()))); + MKLDNNDescriptor desc(std::make_shared( + prop_kind::forward_scoring, + direction, + /* In Data */ inDataDescs[RNNInOutKind::Layer].getDnnlDesc(), + /* In State */ inDataDescs[RNNInOutKind::HiddenState].getDnnlDesc(), + /* Weights data */ wDescs[0], + /* Weights state */ wDescs[1], + /* Bias */ wDescs[2], + /* Out Data */ outDataDescs[RNNInOutKind::Layer].getDnnlDesc(), + /* Out State */ outDataDescs[RNNInOutKind::HiddenState].getDnnlDesc())); descs.push_back(desc); } break; case mkldnn::algorithm::vanilla_lstm: { - MKLDNNDescriptor desc(std::shared_ptr( - new lstm_forward::desc(prop_kind::forward_scoring, direction, - /* In Data */ in_data_d[RNNInOutKind::Layer].getDnnlDesc(), - /* In State */ in_data_d[RNNInOutKind::HiddenState].getDnnlDesc(), - /* In State C */ in_data_d[RNNInOutKind::CellState].getDnnlDesc(), - /* Weights data */ w_data_d, - /* Weights state */ w_state_d, - /* Bias */ w_bias_d, - /* Out Data */ out_data_d[RNNInOutKind::Layer].getDnnlDesc(), - /* Out State */ out_data_d[RNNInOutKind::HiddenState].getDnnlDesc(), - /* Out State C */ out_data_d[RNNInOutKind::CellState].getDnnlDesc()))); + MKLDNNDescriptor desc(std::make_shared( + prop_kind::forward_scoring, + direction, + /* In Data */ inDataDescs[RNNInOutKind::Layer].getDnnlDesc(), + /* In State */ inDataDescs[RNNInOutKind::HiddenState].getDnnlDesc(), + /* In State C */ inDataDescs[RNNInOutKind::CellState].getDnnlDesc(), + /* Weights data */ wDescs[0], + /* Weights state */ wDescs[1], + /* Bias */ wDescs[2], + /* Out Data */ outDataDescs[RNNInOutKind::Layer].getDnnlDesc(), + /* Out State */ outDataDescs[RNNInOutKind::HiddenState].getDnnlDesc(), + /* Out State C */ outDataDescs[RNNInOutKind::CellState].getDnnlDesc())); descs.push_back(desc); } break; default: - IE_THROW() << "Unknown cell type"; + THROW_ERROR << "has unknown cell type."; + } +} + +void MKLDNNRNN::createDescriptor(const std::vector &inputDesc, + const std::vector &outputDesc) { + if (descs.empty()) { + wDescs.resize(3); + const auto& dataPrecision = getOriginalInputPrecisionAtPort(0); + auto dataType = MKLDNNExtensionUtils::IEPrecisionToDataType(dataPrecision); + auto weightsDims = MKLDNNExtensionUtils::convertToDnnlDims(VectorDims{ L, D, DC, G, SC }); + wDescs[0] = mkldnn::memory::desc(weightsDims, dataType, wFormat); + auto statesDims = MKLDNNExtensionUtils::convertToDnnlDims(VectorDims{ L, D, SC, G, SC }); + wDescs[1] = mkldnn::memory::desc(statesDims, dataType, wFormat); + auto biasDims = MKLDNNExtensionUtils::convertToDnnlDims(VectorDims{ L, D, Gb, SC }); + wDescs[2] = mkldnn::memory::desc(biasDims, memory::data_type::f32, memory::format_tag::ldgo); + + fillDescs(); } // Fill supported config @@ -725,21 +725,71 @@ void MKLDNNRNN::createDescriptor(const std::vector &inputDesc, supportedPrimitiveDescriptors.emplace_back(config, ref_any); } -void MKLDNNRNN::createPrimitive() { +void MKLDNNRNN::prepareParams() { + for (size_t i = 0; i < wIdx; i++) { + auto memPtr = getParentEdgesAtPort(i).front()->getMemoryPtr(); + if (!memPtr || !memPtr->GetPrimitivePtr()) + THROW_ERROR << "has uninitialized memory at port " << i; + } + + const auto& dataPrecision = getOriginalInputPrecisionAtPort(0); + const auto dataType = MKLDNNExtensionUtils::IEPrecisionToDataType(dataPrecision); + + auto dataMemPtr = getParentEdgesAtPort(0).front()->getMemoryPtr(); + const size_t B = dataMemPtr->GetShape().getStaticDims()[0]; + const size_t SL = is_cell ? 1lu : dataMemPtr->GetShape().getStaticDims()[1]; + const Shape shapeS_4D{L, D, B, SC}; + + inDataDescs[0] = DnnlBlockedMemoryDesc({SL, B, DC}, dataType, memory::format_tag::tnc); + outDataDescs[0] = DnnlBlockedMemoryDesc({SL, B, SC}, dataType, memory::format_tag::tnc); + + inDataDescs[1] = DnnlBlockedMemoryDesc(shapeS_4D, dataType, memory::format_tag::ldnc); + outDataDescs[1] = DnnlBlockedMemoryDesc(shapeS_4D, dataType, memory::format_tag::ldnc); + + if (haveCellState(cell_type)) { + inDataDescs[2] = DnnlBlockedMemoryDesc(shapeS_4D, memory::data_type::f32, memory::format_tag::ldnc); + outDataDescs[2] = DnnlBlockedMemoryDesc(shapeS_4D, memory::data_type::f32, memory::format_tag::ldnc); + } + + bool wFormatWasChanged = false; + // WA To avoid different weights layer and iter formats in FP32 case. + if (dataPrecision == Precision::FP32) { + if (SL != 1 || B < optimalBatchSize) { + if (wFormat != mkldnn::memory::format_tag::ldigo) { + wFormat = mkldnn::memory::format_tag::ldigo; + wFormatWasChanged = true; + } + } else if (wFormat != mkldnn::memory::format_tag::any) { + wFormat = mkldnn::memory::format_tag::any; + wFormatWasChanged = true; + } + } + if (wFormatWasChanged) { + auto weightsDims = MKLDNNExtensionUtils::convertToDnnlDims(VectorDims{ L, D, DC, G, SC }); + wDescs[0] = mkldnn::memory::desc(weightsDims, dataType, wFormat); + auto statesDims = MKLDNNExtensionUtils::convertToDnnlDims(VectorDims{ L, D, SC, G, SC }); + wDescs[1] = mkldnn::memory::desc(statesDims, dataType, wFormat); + } + + fillDescs(); if (cell_type == mkldnn::algorithm::vanilla_rnn) { - auto prim_desc = createPrimitiveDescriptor(); - prim.reset(new vanilla_rnn_forward(prim_desc)); + std::shared_ptr desc = descs[0]; + prim.reset(new vanilla_rnn_forward(vanilla_rnn_forward::primitive_desc(*desc, getEngine()))); } else if (cell_type == mkldnn::algorithm::vanilla_gru) { - auto prim_desc = createPrimitiveDescriptor(); - prim.reset(new gru_forward(prim_desc)); + std::shared_ptr desc = descs[0]; + prim.reset(new gru_forward(gru_forward::primitive_desc(*desc, getEngine()))); } else if (cell_type == mkldnn::algorithm::lbr_gru) { - auto prim_desc = createPrimitiveDescriptor(); - prim.reset(new lbr_gru_forward(prim_desc)); + std::shared_ptr desc = descs[0]; + prim.reset(new lbr_gru_forward(lbr_gru_forward::primitive_desc(*desc, getEngine()))); } else if (cell_type == mkldnn::algorithm::vanilla_lstm) { - auto prim_desc = createPrimitiveDescriptor(); - prim.reset(new lstm_forward(prim_desc)); - } else { - IE_THROW() << "Unknown cell type"; + std::shared_ptr desc = descs[0]; + prim.reset(new lstm_forward(lstm_forward::primitive_desc(*desc, getEngine()))); + } + + if (!wasMemoryPrepared || wFormatWasChanged) { + auto itpd = descs[0].createPrimitiveDescriptorIterator(getEngine(), mkldnn::primitive_attr()); + prepareMemory(itpd); + wasMemoryPrepared = true; } } @@ -755,7 +805,7 @@ std::shared_ptr MKLDNNRNN::getDstMemDesc(mkldnn::primitive_desc_iter void MKLDNNRNN::execute(mkldnn::stream strm) { if (!prim) - IE_THROW() << "No initialized primitive to execute"; + THROW_ERROR << "does not have initialized primitive to execute."; const auto src_data_mem = getParentEdgeAt(0)->getMemoryPtr(); const auto dst_data_mem = getChildEdgeAt(0)->getMemoryPtr(); @@ -794,6 +844,37 @@ void MKLDNNRNN::execute(mkldnn::stream strm) { (*prim).execute(strm, args); } +void MKLDNNRNN::executeDynamicImpl(mkldnn::stream strm) { + execute(strm); +} + +std::vector MKLDNNRNN::shapeInfer() const { + if ((is_cell && DC != getParentEdgesAtPort(0)[0]->getMemory().getDesc().getShape().getStaticDims()[1]) || + (!is_cell && DC != getParentEdgesAtPort(0)[0]->getMemory().getDesc().getShape().getStaticDims()[2])) + THROW_ERROR << "has incorrect input size value in the first input."; + + auto originOutputShapes = MKLDNNNode::shapeInfer(); + + // Graph optimizer makes the same optimization. So this is required to make shapes compatible. + if (!hasNativeOrder() && originOutputShapes[0].size() == 4lu && originOutputShapes[0][1] == 1lu) { + originOutputShapes[0].erase(originOutputShapes[0].begin() + 1); + } + return originOutputShapes; +} + +void MKLDNNRNN::cleanup() { + if (!isDynamicNode()) { + internalBlobs.clear(); + } + + for (auto it : fusedWith) { + it->cleanup(); + } + + for (auto it : mergedWith) { + it->cleanup(); + } +} } // namespace MKLDNNPlugin REG_MKLDNN_PRIM_FOR(MKLDNNRNN, RNNCell); diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_rnn.h b/src/plugins/intel_cpu/src/nodes/mkldnn_rnn.h index 2b6d24afaf8..0be942b3dc3 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_rnn.h +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_rnn.h @@ -5,10 +5,10 @@ #pragma once #include + #include #include #include -#include "memory_desc/dnnl_blocked_memory_desc.h" namespace MKLDNNPlugin { @@ -18,7 +18,6 @@ public: static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; void getSupportedDescriptors() override; - void createPrimitive() override; std::shared_ptr getSrcMemDesc(mkldnn::primitive_desc_iterator& primitive_desc_it, size_t idx) override; std::shared_ptr getDstMemDesc(mkldnn::primitive_desc_iterator& primitive_desc_it, size_t idx) override; bool created() const override; @@ -31,11 +30,19 @@ public: return nativeOrder; } + void cleanup() override; + +protected: + std::vector shapeInfer() const override; + void prepareParams() override; + void executeDynamicImpl(mkldnn::stream strm) override; + private: - void initCell(const std::shared_ptr& op); - void initSeq(const std::shared_ptr& op); + void initCell(); + void initSequence(); void fillCellDesc(); - void fillSeqDesc(); + void fillSequenceDesc(); + void fillDescs(); bool verifyWeightsPrecision(const InferenceEngine::Precision& layerPrec, const InferenceEngine::Precision& weightsPrec); @@ -46,8 +53,6 @@ private: void copyWeightsData(); -private: - InferenceEngine::Precision runtimePrecision; /** Specify mode Cell or Seq. true - Cell, false - Seq */ bool is_cell = false; @@ -64,11 +69,26 @@ private: mkldnn::algorithm cell_act = mkldnn::algorithm::eltwise_tanh; /** Weights data and state memory format: ldigo or any */ - mkldnn::memory::format_tag w_format = mkldnn::memory::format_tag::any; + mkldnn::memory::format_tag wFormat = mkldnn::memory::format_tag::any; + struct Interval { + Interval() = default; + + Interval(Dim min, Dim max) { + minVal = min; + maxVal = max; + } + + bool isStatic() { + return minVal == maxVal; + } + + Dim minVal = 0; + Dim maxVal = 0; + }; // Internal attributes - size_t N = 0; /**< Batch value */ - size_t T = 0; /**< Sequence value */ + Interval N; /**< Batch value */ + Interval T; /**< Sequence value */ size_t DC = 0; /**< Input data channel size */ size_t SC = 0; /**< State channel size value */ size_t G = 0; /**< Gate size. LSTM - 4, GRU - 3, RNN - 1 */ @@ -77,8 +97,9 @@ private: const size_t L = 1; /**< What is it??. Constant for mkldnn impl */ const size_t D = 1; /**< Num of direction. 1 or 2 */ - std::vector in_data_d; - std::vector out_data_d; + std::vector inDataDescs; + std::vector outDataDescs; + std::vector wDescs; enum RNNInOutKind { Layer = 0, @@ -86,14 +107,16 @@ private: CellState = 2 }; - std::vector in_data_dims; - std::vector out_data_dims; - size_t wIdx = 0; size_t rIdx = 0; size_t bIdx = 0; static const std::map weightsByLayerPrec; + + static constexpr size_t optimalBatchSize = 16lu; + static constexpr size_t batchDimDummyValue = 64lu; + + bool wasMemoryPrepared = false; }; } // namespace MKLDNNPlugin diff --git a/src/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp b/src/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp index bd8d9b8f37a..d5f4d0d7eb5 100644 --- a/src/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp +++ b/src/tests/functional/plugin/cpu/shared_tests_instances/skip_tests_config.cpp @@ -71,6 +71,10 @@ std::vector disabledTestPatterns() { R"(.*NonZeroLayerTest.*)", // TODO: 69084 Not constant Axis input produces dynamic output shape. R"(.*GatherLayerTestCPU.*constAx=False.*)", + // TODO: 74601. RNN, GRU, LSTM Sequences batch 1 tests failure. + R"(.*smoke_dynamic_BatchSizeOne.*Sequence.*)", + // TODO: 74961. Enforce precision via inType and outType does not work properly. + R"(.*(RNN|GRU|LSTM).*ENFORCE_BF16=YES.*)", // Not expected behavior R"(.*Behavior.*InferRequestIOBBlobSetLayoutTest.*layout=(95|OIHW).*)", R"(.*Behavior.*InferRequestIOBBlobSetLayoutTest.*layout=(95|OIHW).*)", diff --git a/src/tests/functional/plugin/cpu/single_layer_tests/gru_cell.cpp b/src/tests/functional/plugin/cpu/single_layer_tests/gru_cell.cpp index 9eea07dc591..b4a16dca6cd 100644 --- a/src/tests/functional/plugin/cpu/single_layer_tests/gru_cell.cpp +++ b/src/tests/functional/plugin/cpu/single_layer_tests/gru_cell.cpp @@ -2,38 +2,64 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/op/gru_cell.hpp" -#include +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "ngraph_functions/builders.hpp" #include "test_utils/cpu_test_utils.hpp" -#include "transformations/op_conversions/gru_cell_decomposition.hpp" -using namespace InferenceEngine; using namespace CPUTestUtils; +using namespace ov::test; namespace CPULayerTestsDefinitions { -using GRUCellCpuSpecificParams = typename std::tuple>; +using GRUCellCpuSpecificParams = typename std::tuple< + std::vector, // Shapes + bool, // Using decompose to sub-ops transformation + std::vector, // Activations + float, // Clip + bool, // Linear before reset + ElementType, // Network precision + CPUSpecificParams, // CPU specific params + std::map // Additional config +>; class GRUCellCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, - public CPUTestsBase { + virtual public ov::test::SubgraphBaseTest, public CPUTestsBase { public: static std::string getTestCaseName(const testing::TestParamInfo &obj) { + std::vector inputShapes; + bool decompose, linearBeforeReset; + std::vector activations; + float clip = 0.f; + ElementType netPrecision; CPUSpecificParams cpuParams; - LayerTestsDefinitions::GRUCellParams basicParamsSet; std::map additionalConfig; - std::tie(basicParamsSet, cpuParams, additionalConfig) = obj.param; + std::tie(inputShapes, decompose, activations, clip, linearBeforeReset, netPrecision, cpuParams, additionalConfig) = obj.param; std::ostringstream result; - result << LayerTestsDefinitions::GRUCellTest::getTestCaseName( - testing::TestParamInfo(basicParamsSet, 0)); + result << "IS=("; + for (const auto& shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result << ")_TS="; + for (size_t i = 0lu; i < inputShapes.front().second.size(); i++) { + result << "{"; + for (size_t j = 0lu; j < inputShapes.size(); j++) { + result << CommonTestUtils::vec2str(inputShapes[j].second[i]) << (j < inputShapes.size() - 1 ? "_" : ""); + } + result << "}_"; + } + result << "decompose=" << decompose << "_"; + result << "activations=" << CommonTestUtils::vec2str(activations) << "_"; + result << "clip=" << clip << "_"; + result << "linear=" << linearBeforeReset << "_"; + result << "netPrec=" << netPrecision << "_"; result << CPUTestsBase::getTestCaseName(cpuParams); if (!additionalConfig.empty()) { result << "_PluginConf"; for (auto &item : additionalConfig) { - if (item.second == PluginConfigParams::YES) + if (item.second == InferenceEngine::PluginConfigParams::YES) result << "_" << item.first << "=" << item.second; } } @@ -42,94 +68,116 @@ public: protected: void SetUp() override { + std::vector inputShapes; + bool decompose, linearBeforeReset; + std::vector activations; + float clip = 0.f; + ElementType netPrecision; CPUSpecificParams cpuParams; - LayerTestsDefinitions::GRUCellParams basicParamsSet; std::map additionalConfig; - bool should_decompose; - size_t batch; - size_t hidden_size; - size_t input_size; - std::vector activations; - std::vector activations_alpha; - std::vector activations_beta; - float clip; - bool linear_before_reset; - InferenceEngine::Precision netPrecision; - - std::tie(basicParamsSet, cpuParams, additionalConfig) = this->GetParam(); + std::tie(inputShapes, decompose, activations, clip, linearBeforeReset, netPrecision, cpuParams, additionalConfig) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - std::tie(should_decompose, batch, hidden_size, input_size, activations, clip, linear_before_reset, netPrecision, targetDevice) = basicParamsSet; + targetDevice = CommonTestUtils::DEVICE_CPU; - std::vector> inputShapes = { - {{batch, input_size}, - {batch, hidden_size}, - {3 * hidden_size, input_size}, - {3 * hidden_size, hidden_size}, - {(linear_before_reset ? 4 : 3) * hidden_size}}, - }; + init_input_shapes(inputShapes); + + const size_t hiddenSize = targetStaticShapes.front()[1][1]; + const size_t inputSize = targetStaticShapes.front()[0][1]; configuration.insert(additionalConfig.begin(), additionalConfig.end()); - if (additionalConfig[PluginConfigParams::KEY_ENFORCE_BF16] == PluginConfigParams::YES) { - inPrc = outPrc = Precision::BF16; + if (additionalConfig[InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16] == InferenceEngine::PluginConfigParams::YES) { + inType = outType = ElementType::bf16; } else { - inPrc = outPrc = netPrecision; + inType = outType = netPrecision; } + selectedType = makeSelectedTypeStr(selectedType, outType); - selectedType += "_"; - selectedType += outPrc.name(); + auto params = ngraph::builder::makeDynamicParams(netPrecision, inputDynamicShapes); + std::vector WRB = {{3 * hiddenSize, inputSize}, {3 * hiddenSize, hiddenSize}, {(linearBeforeReset ? 4 : 3) * hiddenSize}}; + auto gruCellOp = ngraph::builder::makeGRU( + ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)), WRB, hiddenSize, activations, {}, {}, clip, linearBeforeReset); - auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(Precision::FP32); - auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1]}); - std::vector WRB = {inputShapes[2], inputShapes[3], inputShapes[4]}; - auto gru_cell = ngraph::builder::makeGRU( - ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)), WRB, hidden_size, activations, {}, {}, clip, linear_before_reset); - ngraph::ResultVector results{std::make_shared(gru_cell->output(0))}; - - function = makeNgraphFunction(ngPrc, params, gru_cell, "gru_cell"); + function = makeNgraphFunction(netPrecision, params, gruCellOp, "GRUCell"); } }; TEST_P(GRUCellCPUTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() - Run(); + run(); CheckPluginRelatedResults(executableNetwork, "RNNCell"); } namespace { /* CPU PARAMS */ std::vector> additionalConfig - = {{{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO}}, - {{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::YES}}}; + = {{{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::NO}}, + {{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::YES}}}; CPUSpecificParams cpuParams{{nc, nc}, {nc}, {"ref_any"}, "ref_any"}; -std::vector should_decompose{false}; -std::vector batch{1, 5}; -std::vector hidden_size{1, 10}; -std::vector input_size{1, 30}; +std::vector shouldDecompose{false}; // oneDNN supports only sigmoid-tanh std::vector> activations = {{"sigmoid", "tanh"}}; // oneDNN supports only zero clip std::vector clip = {0.f}; -std::vector linear_before_reset = {true, false}; -std::vector netPrecisions = {InferenceEngine::Precision::FP32}; +std::vector linearBeforeReset = {true, false}; +std::vector netPrecisions = { ElementType::f32 }; -INSTANTIATE_TEST_SUITE_P(smoke_GRUCellCPU, - GRUCellCPUTest, - ::testing::Combine(::testing::Combine(::testing::ValuesIn(should_decompose), - ::testing::ValuesIn(batch), - ::testing::ValuesIn(hidden_size), - ::testing::ValuesIn(input_size), - ::testing::ValuesIn(activations), - ::testing::ValuesIn(clip), - ::testing::ValuesIn(linear_before_reset), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::Values(cpuParams), - ::testing::ValuesIn(additionalConfig)), - GRUCellCPUTest::getTestCaseName); +const std::vector> staticShapes = { + { { {}, { {1, 1} } }, // Static shapes + { {}, { {1, 1} } } }, + { { {}, { {1, 1} } }, // Static shapes + { {}, { {1, 10} } } }, + { { {}, { {1, 30} } }, // Static shapes + { {}, { {1, 10} } } }, + { { {}, { {1, 30} } }, // Static shapes + { {}, { {1, 1} } } }, + { { {}, { {3, 1} } }, // Static shapes + { {}, { {3, 1} } } }, + { { {}, { {5, 1} } }, // Static shapes + { {}, { {5, 1} } } }, + { { {}, { {5, 30} } }, // Static shapes + { {}, { {5, 10} } } } +}; + +INSTANTIATE_TEST_SUITE_P(smoke_static, GRUCellCPUTest, + ::testing::Combine(::testing::ValuesIn(staticShapes), + ::testing::ValuesIn(shouldDecompose), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(linearBeforeReset), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::ValuesIn(additionalConfig)), + GRUCellCPUTest::getTestCaseName); + +const std::vector> dynamicShapes = { + { { { {-1}, 1 }, // Dynamic shape 0 + { {1, 1}, {3, 1}, {5, 1} } }, // Target shapes + { { {-1}, 1 }, // Dynamic shape 1 + { {1, 1}, {3, 1}, {5, 1} } } }, // Target shapes + { { { {1, 10}, 30 }, // Dynamic shape 0 + { {2, 30}, {5, 30}, {8, 30} } }, // Target shapes + { { {1, 10}, 10 }, // Dynamic shape 1 + { {2, 10}, {5, 10}, {8, 10} } } }, // Target shapes + { { { {1, 10}, {25, 35} }, // Dynamic shape 0 + { {2, 30}, {5, 30}, {8, 30} } }, // Target shapes + { { {1, 10}, -1 }, // Dynamic shape 1 + { {2, 10}, {5, 10}, {8, 10} } } } // Target shapes +}; + +INSTANTIATE_TEST_SUITE_P(smoke_dynamic, GRUCellCPUTest, + ::testing::Combine(::testing::ValuesIn(dynamicShapes), + ::testing::ValuesIn(shouldDecompose), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(linearBeforeReset), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::ValuesIn(additionalConfig)), + GRUCellCPUTest::getTestCaseName); } // namespace } // namespace CPULayerTestsDefinitions diff --git a/src/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp b/src/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp index dc5c35b72dd..760f6557757 100644 --- a/src/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp +++ b/src/tests/functional/plugin/cpu/single_layer_tests/gru_sequence.cpp @@ -2,38 +2,70 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "shared_test_classes/single_layer/gru_sequence.hpp" -#include "ngraph/pass/visualize_tree.hpp" +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "ngraph_functions/builders.hpp" #include "test_utils/cpu_test_utils.hpp" #include "transformations/op_conversions/bidirectional_sequences_decomposition.hpp" #include "transformations/op_conversions/convert_sequences_to_tensor_iterator.hpp" -using namespace InferenceEngine; using namespace CPUTestUtils; +using namespace ov::test; namespace CPULayerTestsDefinitions { -using GRUSequenceCpuSpecificParams = typename std::tuple>; +using GRUSequenceCpuSpecificParams = typename std::tuple< + std::vector, // Shapes + ngraph::helpers::SequenceTestsMode, // Pure Sequence or TensorIterator + std::vector, // Activations + float, // Clip + bool, // Linear_before_reset + ov::op::RecurrentSequenceDirection, // Direction + ElementType, // Network precision + CPUSpecificParams, // CPU specific params + std::map // Additional config +>; class GRUSequenceCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, - public CPUTestsBase { + virtual public ov::test::SubgraphBaseTest, public CPUTestsBase { public: static std::string getTestCaseName(const testing::TestParamInfo &obj) { + std::vector inputShapes; + ngraph::helpers::SequenceTestsMode seqMode; + std::vector activations; + float clip; + bool linearBeforeRest; + ov::op::RecurrentSequenceDirection direction; + ElementType netPrecision; CPUSpecificParams cpuParams; - LayerTestsDefinitions::GRUSequenceParams basicParamsSet; std::map additionalConfig; - std::tie(basicParamsSet, cpuParams, additionalConfig) = obj.param; - std::ostringstream result; + std::tie(inputShapes, seqMode, activations, clip, linearBeforeRest, direction, netPrecision, cpuParams, additionalConfig) = obj.param; - result << LayerTestsDefinitions::GRUSequenceTest::getTestCaseName(testing::TestParamInfo(basicParamsSet, 0)); + std::ostringstream result; + result << "IS=("; + for (const auto& shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result << ")_TS="; + for (size_t i = 0lu; i < inputShapes.front().second.size(); i++) { + result << "{"; + for (size_t j = 0lu; j < inputShapes.size(); j++) { + result << CommonTestUtils::vec2str(inputShapes[j].second[i]) << (j < inputShapes.size() - 1 ? "_" : ""); + } + result << "}_"; + } + result << "seqMode=" << seqMode << "_"; + result << "activations=" << CommonTestUtils::vec2str(activations) << "_"; + result << "clip=" << clip << "_"; + result << "linear=" << linearBeforeRest << "_"; + result << "direction=" << direction << "_"; + result << "netPrec=" << netPrecision << "_"; result << CPUTestsBase::getTestCaseName(cpuParams); if (!additionalConfig.empty()) { result << "_PluginConf"; for (auto &item : additionalConfig) { - if (item.second == PluginConfigParams::YES) + if (item.second == InferenceEngine::PluginConfigParams::YES) result << "_" << item.first << "=" << item.second; } } @@ -42,92 +74,90 @@ public: protected: void SetUp() override { - LayerTestsDefinitions::GRUSequenceParams basicParamsSet; + std::vector inputShapes; + ngraph::helpers::SequenceTestsMode seqMode; + std::vector activations; + float clip; + bool linearBeforeReset; + ov::op::RecurrentSequenceDirection direction; + ElementType netPrecision; CPUSpecificParams cpuParams; std::map additionalConfig; - size_t seq_lengths; - size_t batch; - size_t hidden_size; - size_t input_size = 10; - std::vector activations; - std::vector activations_alpha; - std::vector activations_beta; - float clip; - bool linear_before_reset; - ngraph::op::RecurrentSequenceDirection direction; - InferenceEngine::Precision netPrecision; - - std::tie(basicParamsSet, cpuParams, additionalConfig) = this->GetParam(); + std::tie(inputShapes, seqMode, activations, clip, linearBeforeReset, direction, netPrecision, cpuParams, additionalConfig) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - std::tie(m_mode, seq_lengths, batch, hidden_size, activations, clip, linear_before_reset, direction, netPrecision, targetDevice) = basicParamsSet; + targetDevice = CommonTestUtils::DEVICE_CPU; - size_t num_directions = direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; - std::vector> inputShapes = { - {{batch, seq_lengths, input_size}, - {batch, num_directions, hidden_size}, - {batch}, - {num_directions, 3 * hidden_size, input_size}, - {num_directions, 3 * hidden_size, hidden_size}, - {num_directions, (linear_before_reset ? 4 : 3) * hidden_size}}, - }; + init_input_shapes(inputShapes); + if (inputDynamicShapes.size() == 2 && inputDynamicShapes[0][0].is_dynamic() && inputDynamicShapes[1][0].is_dynamic()) + throw std::runtime_error("Invalid test case. If 3rd input is constant, batch dimension must be static."); - // method MKLDNNMemoryDesc::isSame can't correct compute layout for tensor with strides = 1 + // Method MKLDNNMemoryDesc::isSame can't correct compute layout for tensor with strides = 1 // returned output format always tnc - if (inFmts.size() == 2 && ngraph::shape_size(inputShapes[1]) == 1) { + if (inFmts.size() == 2 && (inputDynamicShapes[0][0].is_static() && inputDynamicShapes[0][0].get_length() == 1 || + inputDynamicShapes[1].is_static() && ov::shape_size(inputDynamicShapes[1].to_shape()) == 1)) { inFmts[1] = tnc; } configuration.insert(additionalConfig.begin(), additionalConfig.end()); - if (additionalConfig[PluginConfigParams::KEY_ENFORCE_BF16] == PluginConfigParams::YES) { - inPrc = outPrc = Precision::BF16; + const size_t hiddenSize = targetStaticShapes.front()[1][2]; + const size_t inputSize = targetStaticShapes.front()[0][2]; + const size_t numDirections = direction == ov::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; + + // 3rd input type must be an integer, thus it cannot be forced to BF16. + if (additionalConfig[InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16] == InferenceEngine::PluginConfigParams::YES) { + if (inputDynamicShapes.size() > 2) + throw std::runtime_error("Invalid test case. Cannot enforce integer input to BF16."); + inType = outType = ElementType::bf16; } else { - inPrc = outPrc = netPrecision; + outType = netPrecision; + } + selectedType = makeSelectedTypeStr(selectedType, outType); + + auto params = ngraph::builder::makeDynamicParams(netPrecision, inputDynamicShapes); + const size_t batchSize = inputDynamicShapes[0][0].is_static() ? inputDynamicShapes[0][0].get_length() : + inputDynamicShapes[1][0].is_static() ? inputDynamicShapes[1][0].get_length() : + inputDynamicShapes.size() > 2 && inputDynamicShapes[2][0].is_static() ? inputDynamicShapes[2][0].get_length() : + 1lu; + if (inputDynamicShapes.size() > 2) { + if (!inputDynamicShapes[2].is_dynamic() && + seqMode != ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM && + seqMode != ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM) { + params.pop_back(); + } else { + params[2]->set_element_type(ElementType::i64); + } } - selectedType += "_"; - selectedType += outPrc.name(); - - m_max_seq_len = seq_lengths; - auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(Precision::FP32); - 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) { - 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); - } - std::vector WRB = {inputShapes[3], inputShapes[4], inputShapes[5], inputShapes[2]}; - auto gru_sequence = ngraph::builder::makeGRU(ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)), + std::vector WRB = {{numDirections, 3 * hiddenSize, inputSize}, {numDirections, 3 * hiddenSize, hiddenSize}, + {numDirections, (linearBeforeReset ? 4 : 3) * hiddenSize}, {batchSize}}; + auto gruSequenceOp = ngraph::builder::makeGRU(ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)), WRB, - hidden_size, + hiddenSize, activations, {}, {}, clip, - linear_before_reset, + linearBeforeReset, true, direction, - m_mode); + seqMode); // method MKLDNNMemoryDesc::isSame can't correct compute layout for tensor with strides = 1 // returned output format always tnc - if (ngraph::shape_size(gru_sequence->get_output_shape(0)) == 1) { + if (gruSequenceOp->get_output_partial_shape(0).is_static() && ov::shape_size(gruSequenceOp->get_output_shape(0)) == 1) { outFmts[0] = tnc; - } else if (ngraph::shape_size(gru_sequence->get_output_shape(1)) == 1 || - gru_sequence->get_output_shape(0)[0] == 1) { + } else if (gruSequenceOp->get_output_partial_shape(1).is_static() && ov::shape_size(gruSequenceOp->get_output_shape(1)) == 1 || + gruSequenceOp->get_output_partial_shape(0)[0].is_static() && gruSequenceOp->get_output_partial_shape(0)[0].get_length() == 1) { outFmts[1] = tnc; } - ngraph::ResultVector results{std::make_shared(gru_sequence->output(0)), - std::make_shared(gru_sequence->output(1))}; + function = makeNgraphFunction(netPrecision, params, gruSequenceOp, "gruSequenceOp"); - function = makeNgraphFunction(ngPrc, params, gru_sequence, "gru_sequence"); - - if (m_mode != ngraph::helpers::SequenceTestsMode::PURE_SEQ) { - ngraph::pass::Manager manager; - if (direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL) + if (seqMode != ngraph::helpers::SequenceTestsMode::PURE_SEQ) { + ov::pass::Manager manager; + if (direction == ov::op::RecurrentSequenceDirection::BIDIRECTIONAL) manager.register_pass(); manager.register_pass(); manager.run_passes(function); @@ -139,80 +169,196 @@ protected: } } - void GenerateInputs() override { - for (const auto &input : executableNetwork.GetInputsInfo()) { - const auto &info = input.second; - auto blob = GenerateInput(*info); - if (input.first == "seq_lengths") { - blob = FuncTestUtils::createAndFillBlob(info->getTensorDesc(), m_max_seq_len, 0); - } - inputs.push_back(blob); + void generate_inputs(const std::vector& targetInputStaticShapes) override { + SubgraphBaseTest::generate_inputs(targetInputStaticShapes); + + const size_t batchSize = targetInputStaticShapes[0][0]; + const int64_t maxSeqLen = targetInputStaticShapes[0][1]; + const auto& funcInputs = function->inputs(); + if (funcInputs.size() > 2) { + const auto& seqLenInput = inputs.find(funcInputs[2].get_node_shared_ptr()); + if (seqLenInput == inputs.end()) + throw std::runtime_error("Could not find Sequence length input."); + + auto lenData = seqLenInput->second.data::value_type>(); + std::fill(lenData, lenData + batchSize, maxSeqLen); } } - -private: - ngraph::helpers::SequenceTestsMode m_mode; - int64_t m_max_seq_len = 0; }; TEST_P(GRUSequenceCPUTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() - Run(); + run(); CheckPluginRelatedResults(executableNetwork, "RNNSeq"); } namespace { /* CPU PARAMS */ std::vector> additionalConfig - = {{{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO}}, {{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::YES}}}; + = {{{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::NO}}, + {{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::YES}}}; CPUSpecificParams cpuParams{{ntc, tnc}, {ntc, tnc}, {"ref_any"}, "ref_any"}; CPUSpecificParams cpuParamsBatchSizeOne{{tnc, ntc}, {tnc, ntc}, {"ref_any"}, "ref_any"};; std::vector mode{ngraph::helpers::SequenceTestsMode::PURE_SEQ}; // output values increase rapidly without clip, so use only seq_lengths = 2 -std::vector seq_lengths_zero_clip{2}; -std::vector batch{10}; -std::vector batch_size_one{1}; -std::vector hidden_size{1, 10}; std::vector> activations = {{"sigmoid", "tanh"}}; -std::vector linear_before_reset = {true, false}; +std::vector linearBeforeReset = {true, false}; std::vector clip{0.f}; -std::vector direction = {ngraph::op::RecurrentSequenceDirection::FORWARD}; +std::vector direction = {ov::op::RecurrentSequenceDirection::FORWARD}; -std::vector netPrecisions = {InferenceEngine::Precision::FP32}; +std::vector netPrecisions = { ElementType::f32 }; -INSTANTIATE_TEST_SUITE_P(smoke_GRUSequenceCPU, - GRUSequenceCPUTest, - ::testing::Combine(::testing::Combine(::testing::ValuesIn(mode), - ::testing::ValuesIn(seq_lengths_zero_clip), - ::testing::ValuesIn(batch), - ::testing::ValuesIn(hidden_size), - ::testing::ValuesIn(activations), - ::testing::ValuesIn(clip), - ::testing::ValuesIn(linear_before_reset), - ::testing::ValuesIn(direction), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::Values(cpuParams), - ::testing::ValuesIn(additionalConfig)), - GRUSequenceCPUTest::getTestCaseName); +const std::vector> staticShapes = { + { { {}, { {10, 2, 10} } }, // #0. Static shapes + { {}, { {10, 1, 1} } }, + { {}, { {10} } } }, + { { {}, { {10, 2, 10} } }, // #1. Static shapes + { {}, { {10, 1, 10} } }, + { {}, { {10} } } }, + { { {}, { {1, 2, 10} } }, // #2. Static shapes + { {}, { {1, 1, 1} } }, + { {}, { {1} } } }, + { { {}, { {1, 2, 10} } }, // #3. Static shapes + { {}, { {1, 1, 10} } }, + { {}, { {1} } } }, + { { {}, { {10, 2, 10} } }, // #4. Static shapes + { {}, { {10, 1, 1} } } }, + { { {}, { {10, 2, 10} } }, // #5. Static shapes + { {}, { {10, 1, 10} } } } +}; -INSTANTIATE_TEST_SUITE_P(smoke_GRUSequenceCPUBatchSizeOne, - GRUSequenceCPUTest, - ::testing::Combine(::testing::Combine(::testing::ValuesIn(mode), - ::testing::ValuesIn(seq_lengths_zero_clip), - ::testing::ValuesIn(batch_size_one), - ::testing::ValuesIn(hidden_size), - ::testing::ValuesIn(activations), - ::testing::ValuesIn(clip), - ::testing::ValuesIn(linear_before_reset), - ::testing::ValuesIn(direction), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::Values(cpuParamsBatchSizeOne), - ::testing::ValuesIn(additionalConfig)), - GRUSequenceCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_static, GRUSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{staticShapes[0], staticShapes[1]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(linearBeforeReset), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(std::map{})), + GRUSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_static_BatchSizeOne, GRUSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{staticShapes[3]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(linearBeforeReset), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParamsBatchSizeOne), + ::testing::Values(std::map{})), + GRUSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(nightly_static_bf16, GRUSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{staticShapes[4], staticShapes[5]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(linearBeforeReset), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(additionalConfig[1])), + GRUSequenceCPUTest::getTestCaseName); + +const std::vector> dynamicShapes = { + { { {-1, {1, 5}, 10}, // #0. Dynamic shape 0 + { {10, 2, 10}, {8, 3, 10}, {5, 4, 10} } }, // Target shapes + { {{0, 15}, 1, 1}, // Dynamic shape 1 + { {10, 1, 1}, {8, 1, 1}, {5, 1, 1} } }, // Target shapes + { {{0, 12}}, // Dynamic shape 2 + { {10}, {8}, {5} } } }, // Target shapes + { { {{0, 11}, -1, 10}, // #1. Dynamic shape 0 + { {10, 2, 10}, {3, 4, 10}, {5, 5, 10} } }, // Target shapes + { {-1, 1, 10}, // Dynamic shape 1 + { {10, 1, 10}, {3, 1, 10}, {5, 1, 10} } }, // Target shapes + { {-1}, // Dynamic shape 2 + { {10}, {3}, {5} } } }, // Target shapes + { { {{0, 11}, -1, {7, 11}}, // #2. Dynamic shape 0 + { {10, 2, 10}, {3, 4, 10}, {5, 5, 10} } }, // Target shapes + { {-1, 1, {8, 12}}, // Dynamic shape 1 + { {10, 1, 10}, {3, 1, 10}, {5, 1, 10} } }, // Target shapes + { {-1}, // Dynamic shape 2 + { {10}, {3}, {5} } } }, // Target shapes + { { {-1, {0, 7}, 10}, // #3. Dynamic shape 0 + { {1, 2, 10}, {1, 3, 10}, {1, 6, 10} } }, // Target shapes + { {-1, 1, 1}, // Dynamic shape 1 + { {1, 1, 1}, {1, 1, 1}, {1, 1, 1} } }, // Target shapes + { {-1}, // Dynamic shape 2 + { {1}, {1}, {1} } } }, // Target shapes + { { {1, -1, 10}, // #4. Dynamic shape 0 + { {1, 2, 10}, {1, 4, 10}, {1, 8, 10} } }, // Target shapes + { {1, 1, 10}, // Dynamic shape 1 + { {1, 1, 10}, {1, 1, 10}, {1, 1, 10} } }, // Target shapes + { {1}, // Dynamic shape 2 + { {1}, {1}, {1} } } }, // Target shapes + { { {-1, -1, -1}, // #5. Dynamic shape 0 + { {1, 2, 10}, {1, 4, 10}, {1, 8, 10} } }, // Target shapes + { {-1, -1, -1}, // Dynamic shape 1 + { {1, 1, 10}, {1, 1, 10}, {1, 1, 10} } }, // Target shapes + { {-1}, // Dynamic shape 2 + { {1}, {1}, {1} } } }, // Target shapes + { { {2, {1, 5}, 10}, // #6. Dynamic shape 0 + { {10, 2, 10}, {2, 3, 10}, {2, 4, 10} } }, // Target shapes + { {2, 1, 1}, // Dynamic shape 1 + { {2, 1, 1}, {2, 1, 1}, {2, 1, 1} } } }, // Target shapes + { { {5, -1, 10}, // #7. Dynamic shape 0 + { {5, 2, 10}, {5, 4, 10}, {5, 5, 10} } }, // Target shapes + { {5, 1, 10}, // Dynamic shape 1 + { {5, 1, 10}, {5, 1, 10}, {5, 1, 10} } } } // Target shapes +}; + +INSTANTIATE_TEST_SUITE_P(smoke_dynamic, GRUSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{dynamicShapes[0], dynamicShapes[1], dynamicShapes[2]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(linearBeforeReset), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(std::map{})), + GRUSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_dynamic_BatchSizeOne, GRUSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{dynamicShapes[4]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(linearBeforeReset), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParamsBatchSizeOne), + ::testing::Values(std::map{})), + GRUSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(nightly_dynamic, GRUSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{dynamicShapes[5]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(linearBeforeReset), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(std::map{})), + GRUSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(nightly_dynamic_bf16, GRUSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{dynamicShapes[6], dynamicShapes[7]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(linearBeforeReset), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(additionalConfig[1])), + GRUSequenceCPUTest::getTestCaseName); } // namespace } // namespace CPULayerTestsDefinitions diff --git a/src/tests/functional/plugin/cpu/single_layer_tests/lstm_cell.cpp b/src/tests/functional/plugin/cpu/single_layer_tests/lstm_cell.cpp index c0fce294005..cc59cd489e5 100644 --- a/src/tests/functional/plugin/cpu/single_layer_tests/lstm_cell.cpp +++ b/src/tests/functional/plugin/cpu/single_layer_tests/lstm_cell.cpp @@ -2,38 +2,62 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/op/lstm_cell.hpp" -#include +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "ngraph_functions/builders.hpp" #include "test_utils/cpu_test_utils.hpp" -#include "transformations/op_conversions/lstm_cell_decomposition.hpp" -using namespace InferenceEngine; using namespace CPUTestUtils; +using namespace ov::test; namespace CPULayerTestsDefinitions { -using LSTMCellCpuSpecificParams = typename std::tuple>; +using LSTMCellCpuSpecificParams = typename std::tuple< + std::vector, // Shapes + bool, // using decompose to sub-ops transformation + std::vector, // activations + float, // clip + ElementType, // Network precision + CPUSpecificParams, // CPU specific params + std::map // Additional config +>; class LSTMCellLayerCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, - public CPUTestsBase { + virtual public ov::test::SubgraphBaseTest, public CPUTestsBase { public: static std::string getTestCaseName(const testing::TestParamInfo& obj) { + std::vector inputShapes; + bool decompose; + std::vector activations; + float clip = 0.f; + ElementType netPrecision; CPUSpecificParams cpuParams; - LayerTestsDefinitions::LSTMCellParams basicParamsSet; std::map additionalConfig; - std::tie(basicParamsSet, cpuParams, additionalConfig) = obj.param; - std::ostringstream result; + std::tie(inputShapes, decompose, activations, clip, netPrecision, cpuParams, additionalConfig) = obj.param; - result << LayerTestsDefinitions::LSTMCellTest::getTestCaseName(testing::TestParamInfo( - basicParamsSet, 0)); + std::ostringstream result; + result << "IS=("; + for (const auto& shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result << ")_TS="; + for (size_t i = 0lu; i < inputShapes.front().second.size(); i++) { + result << "{"; + for (size_t j = 0lu; j < inputShapes.size(); j++) { + result << CommonTestUtils::vec2str(inputShapes[j].second[i]) << (j < inputShapes.size() - 1 ? "_" : ""); + } + result << "}_"; + } + result << "decompose=" << decompose << "_"; + result << "activations=" << CommonTestUtils::vec2str(activations) << "_"; + result << "clip=" << clip << "_"; + result << "netPrec=" << netPrecision << "_"; result << CPUTestsBase::getTestCaseName(cpuParams); if (!additionalConfig.empty()) { result << "_PluginConf"; for (auto& item : additionalConfig) { - if (item.second == PluginConfigParams::YES) + if (item.second == InferenceEngine::PluginConfigParams::YES) result << "_" << item.first << "=" << item.second; } } @@ -42,91 +66,118 @@ public: protected: void SetUp() override { - LayerTestsDefinitions::LSTMCellParams basicParamsSet; + std::vector inputShapes; + bool decompose; + std::vector activations; + float clip = 0.f; + ElementType netPrecision; CPUSpecificParams cpuParams; std::map additionalConfig; + abs_threshold = 0.05; - bool should_decompose; - size_t batch; - size_t hidden_size; - size_t input_size; - std::vector activations; - std::vector activations_alpha; - std::vector activations_beta; - float clip; - InferenceEngine::Precision netPrecision; - threshold = 0.05; - - std::tie(basicParamsSet, cpuParams, additionalConfig) = this->GetParam(); + std::tie(inputShapes, decompose, activations, clip, netPrecision, cpuParams, additionalConfig) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - std::tie(should_decompose, batch, hidden_size, input_size, activations, clip, netPrecision, targetDevice) = basicParamsSet; + targetDevice = CommonTestUtils::DEVICE_CPU; - std::vector> inputShapes = { - {{batch, input_size}, {batch, hidden_size}, {batch, hidden_size}, {4 * hidden_size, input_size}, {4 * hidden_size, hidden_size}, {4 * hidden_size}}, - }; + init_input_shapes(inputShapes); configuration.insert(additionalConfig.begin(), additionalConfig.end()); - if (additionalConfig[PluginConfigParams::KEY_ENFORCE_BF16] == PluginConfigParams::YES) { - inPrc = outPrc = Precision::BF16; + const size_t hiddenSize = targetStaticShapes.front()[1][1]; + const size_t inputSize = targetStaticShapes.front()[0][1]; + + if (additionalConfig[InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16] == InferenceEngine::PluginConfigParams::YES) { + inType = outType = ElementType::bf16; } else { - inPrc = outPrc = netPrecision; + inType = outType = netPrecision; } + selectedType = makeSelectedTypeStr(selectedType, outType); - selectedType += "_"; - selectedType += outPrc.name(); + auto params = ngraph::builder::makeDynamicParams(netPrecision, inputDynamicShapes); + auto paramsOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)); + std::vector WRB = {{4 * hiddenSize, inputSize}, {4 * hiddenSize, hiddenSize}, {4 * hiddenSize}}; + auto lstmCellOp = ngraph::builder::makeLSTM(paramsOuts, WRB, hiddenSize, activations, {}, {}, clip); - auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(Precision::FP32); - auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1], inputShapes[2]}); - std::vector WRB = {inputShapes[3], inputShapes[4], inputShapes[5]}; - - auto lstm_cell = ngraph::builder::makeLSTM( - ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)), WRB, hidden_size, activations, {}, {}, clip); - - ngraph::ResultVector results{std::make_shared(lstm_cell->output(0)), - std::make_shared(lstm_cell->output(1))}; - - function = makeNgraphFunction(ngPrc, params, lstm_cell, "lstm_cell"); + function = makeNgraphFunction(netPrecision, params, lstmCellOp, "LSTMCell"); } }; TEST_P(LSTMCellLayerCPUTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() - Run(); + run(); CheckPluginRelatedResults(executableNetwork, "RNNCell"); } namespace { /* CPU PARAMS */ std::vector> additionalConfig - = {{{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::YES}}, - {{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO}}}; + = {{{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::YES}}, + {{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::NO}}}; CPUSpecificParams cpuParams{{nc, nc, nc}, {nc}, {"ref_any"}, "ref_any"}; std::vector should_decompose{false}; -std::vector batch{5}; -std::vector hidden_size{1, 10}; -std::vector input_size{1, 30}; // oneDNN supports only sigmoid-tanh-tanh std::vector> activations = {{"sigmoid", "tanh", "tanh"}}; // oneDNN supports only zero clip std::vector clip{0.f}; -std::vector netPrecisions = {InferenceEngine::Precision::FP32, InferenceEngine::Precision::BF16}; +std::vector netPrecisions = { ElementType::f32 }; -INSTANTIATE_TEST_SUITE_P(smoke_LSTMCellCPU, - LSTMCellLayerCPUTest, - ::testing::Combine(::testing::Combine(::testing::ValuesIn(should_decompose), - ::testing::ValuesIn(batch), - ::testing::ValuesIn(hidden_size), - ::testing::ValuesIn(input_size), - ::testing::ValuesIn(activations), - ::testing::ValuesIn(clip), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::Values(cpuParams), - ::testing::ValuesIn(additionalConfig)), - LSTMCellLayerCPUTest::getTestCaseName); +const std::vector> staticShapes = { + { { {}, { {1, 1} } }, // Static shapes + { {}, { {1, 1} } }, + { {}, { {1, 1} } } }, + { { {}, { {1, 30} } }, // Static shapes + { {}, { {1, 10} } }, + { {}, { {1, 10} } } }, + { { {}, { {5, 1} } }, // Static shapes + { {}, { {5, 1} } }, + { {}, { {5, 1} } } }, + { { {}, { {5, 30} } }, // Static shapes + { {}, { {5, 10} } }, + { {}, { {5, 10} } } } +}; + +INSTANTIATE_TEST_SUITE_P(smoke_static, LSTMCellLayerCPUTest, + ::testing::Combine(::testing::ValuesIn(staticShapes), + ::testing::ValuesIn(should_decompose), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::ValuesIn(additionalConfig)), + LSTMCellLayerCPUTest::getTestCaseName); + +const std::vector> dynamicShapes = { + { { { -1, 1 }, // Dynamic shape 0 + { {1, 1}, {3, 1}, {5, 1} } }, // Target shapes + { { -1, 1 }, // Dynamic shape 1 + { {1, 1}, {3, 1}, {5, 1} } }, // Target shapes + { { -1, 1 }, // Dynamic shape 2 + { {1, 1}, {3, 1}, {5, 1} } } }, // Target shapes + { { { {1, 20}, 30 }, // Dynamic shape 0 + { {2, 30}, {5, 30}, {8, 30} } }, // Target shapes + { { {1, 20}, 10 }, // Dynamic shape 1 + { {2, 10}, {5, 10}, {8, 10} } }, // Target shapes + { { {1, 20}, 10 }, // Dynamic shape 2 + { {2, 10}, {5, 10}, {8, 10} } } }, // Target shapes + { { { {1, 20}, {28, 32} }, // Dynamic shape 0 + { {2, 30}, {5, 30}, {8, 30} } }, // Target shapes + { { {1, 20}, {8, 12} }, // Dynamic shape 1 + { {2, 10}, {5, 10}, {8, 10} } }, // Target shapes + { { {1, 20}, -1 }, // Dynamic shape 2 + { {2, 10}, {5, 10}, {8, 10} } } } // Target shapes +}; + +INSTANTIATE_TEST_SUITE_P(smoke_dynamic, LSTMCellLayerCPUTest, + ::testing::Combine(::testing::ValuesIn(dynamicShapes), + ::testing::ValuesIn(should_decompose), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::ValuesIn(additionalConfig)), + LSTMCellLayerCPUTest::getTestCaseName); } // namespace } // namespace CPULayerTestsDefinitions diff --git a/src/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp b/src/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp index 4077e4755c3..e171459072c 100644 --- a/src/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp +++ b/src/tests/functional/plugin/cpu/single_layer_tests/lstm_sequence.cpp @@ -2,39 +2,67 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "shared_test_classes/single_layer/lstm_sequence.hpp" -#include "ngraph/pass/visualize_tree.hpp" +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "ngraph_functions/builders.hpp" #include "test_utils/cpu_test_utils.hpp" #include "transformations/op_conversions/bidirectional_sequences_decomposition.hpp" #include "transformations/op_conversions/convert_sequences_to_tensor_iterator.hpp" -using namespace InferenceEngine; using namespace CPUTestUtils; +using namespace ov::test; namespace CPULayerTestsDefinitions { -using LSTMSequenceCpuSpecificParams = typename std::tuple>; +using LSTMSequenceCpuSpecificParams = typename std::tuple< + std::vector, // Shapes + ngraph::helpers::SequenceTestsMode, // Pure Sequence or TensorIterator + std::vector, // Activations + float, // Clip + ngraph::op::RecurrentSequenceDirection, // Direction + ElementType, // Network precision + CPUSpecificParams, // CPU specific params + std::map // Additional config +>; class LSTMSequenceCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, - public CPUTestsBase { + virtual public ov::test::SubgraphBaseTest, public CPUTestsBase { public: static std::string getTestCaseName(const testing::TestParamInfo &obj) { + std::vector inputShapes; + ngraph::helpers::SequenceTestsMode seqMode; + std::vector activations; + float clip; + ov::op::RecurrentSequenceDirection direction; + ElementType netPrecision; CPUSpecificParams cpuParams; - LayerTestsDefinitions::LSTMSequenceParams basicParamsSet; std::map additionalConfig; - std::tie(basicParamsSet, cpuParams, additionalConfig) = obj.param; - std::ostringstream result; + std::tie(inputShapes, seqMode, activations, clip, direction, netPrecision, cpuParams, additionalConfig) = obj.param; - result << LayerTestsDefinitions::LSTMSequenceTest::getTestCaseName( - testing::TestParamInfo(basicParamsSet, 0)); + std::ostringstream result; + result << "IS=("; + for (const auto& shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result << ")_TS="; + for (size_t i = 0lu; i < inputShapes.front().second.size(); i++) { + result << "{"; + for (size_t j = 0lu; j < inputShapes.size(); j++) { + result << CommonTestUtils::vec2str(inputShapes[j].second[i]) << (j < inputShapes.size() - 1 ? "_" : ""); + } + result << "}_"; + } + result << "seqMode=" << seqMode << "_"; + result << "activations=" << CommonTestUtils::vec2str(activations) << "_"; + result << "clip=" << clip << "_"; + result << "direction=" << direction << "_"; + result << "netPrec=" << netPrecision << "_"; result << CPUTestsBase::getTestCaseName(cpuParams); if (!additionalConfig.empty()) { result << "_PluginConf"; for (auto &item : additionalConfig) { - if (item.second == PluginConfigParams::YES) + if (item.second == InferenceEngine::PluginConfigParams::YES) result << "_" << item.first << "=" << item.second; } } @@ -43,42 +71,33 @@ public: protected: void SetUp() override { - LayerTestsDefinitions::LSTMSequenceParams basicParamsSet; + std::vector inputShapes; + ngraph::helpers::SequenceTestsMode seqMode; + std::vector activations; + float clip; + ov::op::RecurrentSequenceDirection direction; + ElementType netPrecision; CPUSpecificParams cpuParams; std::map additionalConfig; - size_t seq_lengths; - size_t batch; - size_t hidden_size; - size_t input_size; - std::vector activations; - std::vector activations_alpha; - std::vector activations_beta; - float clip; - ngraph::op::RecurrentSequenceDirection direction; - InferenceEngine::Precision netPrecision; - - std::tie(basicParamsSet, cpuParams, additionalConfig) = this->GetParam(); + std::tie(inputShapes, seqMode, activations, clip, direction, netPrecision, cpuParams, additionalConfig) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - std::tie(m_mode, seq_lengths, batch, hidden_size, input_size, activations, clip, direction, netPrecision, targetDevice) = basicParamsSet; + targetDevice = CommonTestUtils::DEVICE_CPU; - size_t num_directions = direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; - m_max_seq_len = seq_lengths; - std::vector> inputShapes = { - {{batch, seq_lengths, input_size}, - {batch, num_directions, hidden_size}, - {batch, num_directions, hidden_size}, - {batch}, - {num_directions, 4 * hidden_size, input_size}, - {num_directions, 4 * hidden_size, hidden_size}, - {num_directions, 4 * hidden_size}}, - }; + init_input_shapes(inputShapes); + if (inputDynamicShapes.size() == 3 && inputDynamicShapes[0][0].is_dynamic() && + inputDynamicShapes[1][0].is_dynamic() && inputDynamicShapes[2][0].is_dynamic()) + throw std::runtime_error("Invalid test case. If 4th input is constant, batch dimension must be static."); + + const size_t inputSize = targetStaticShapes.front()[0][2]; + const size_t hiddenSize = targetStaticShapes.front()[1][2]; + const size_t numDirections = direction == ov::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; // method MKLDNNMemoryDesc::isSame can't correct compute layout for tensor with strides = 1 // returned output format always tnc if (inFmts.size() >= 3) { for (size_t i = 1; i < 3; i++) { - if (ngraph::shape_size(inputShapes[i]) == 1) { + if (inputDynamicShapes[i].is_static() && ov::shape_size(inputDynamicShapes[i].to_shape()) == 1) { inFmts[i] = tnc; } } @@ -86,54 +105,60 @@ protected: configuration.insert(additionalConfig.begin(), additionalConfig.end()); - if (additionalConfig[PluginConfigParams::KEY_ENFORCE_BF16] == PluginConfigParams::YES) { - inPrc = outPrc = Precision::BF16; + // 4th input type must be integer, thus it cannot be forced to BF16. + if (additionalConfig[InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16] == InferenceEngine::PluginConfigParams::YES) { + if (inputDynamicShapes.size() > 3) + throw std::runtime_error("Invalid test case. Cannot enforce integer input to BF16."); + inType = outType = ElementType::bf16; } else { - inPrc = outPrc = netPrecision; + outType = netPrecision; + } + selectedType = makeSelectedTypeStr(selectedType, outType); + + auto params = ngraph::builder::makeDynamicParams(netPrecision, inputDynamicShapes); + const size_t batchSize = inputDynamicShapes[0][0].is_static() ? inputDynamicShapes[0][0].get_length() : + inputDynamicShapes[1][0].is_static() ? inputDynamicShapes[1][0].get_length() : + inputDynamicShapes[2][0].is_static() ? inputDynamicShapes[2][0].get_length() : + inputDynamicShapes.size() > 3 && inputDynamicShapes[3][0].is_static() ? inputDynamicShapes[3][0].get_length() : + 1lu; + if (inputDynamicShapes.size() > 3) { + if (!inputDynamicShapes[3].is_dynamic() && + seqMode != ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM && + seqMode != ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM) { + params.pop_back(); + } else { + params[3]->set_element_type(ElementType::i64); + } } - selectedType += "_"; - selectedType += outPrc.name(); - - auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(Precision::FP32); - 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); - 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)), + std::vector WRB = {{numDirections, 4 * hiddenSize, inputSize}, {numDirections, 4 * hiddenSize, hiddenSize}, + {numDirections, 4 * hiddenSize}, {batchSize}}; + auto lstmSequenceOp = ngraph::builder::makeLSTM(ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)), WRB, - hidden_size, + hiddenSize, activations, {}, {}, clip, true, direction, - m_mode); + seqMode); // method MKLDNNMemoryDesc::isSame can't correct compute layout for tensor with strides = 1 // returned output format always tnc if (outFmts.size() >= 3) { for (size_t i = 1; i < 3; i++) { - if (ngraph::shape_size(lstm_sequence->get_output_shape(i)) == 1 || - lstm_sequence->get_output_shape(0) == ngraph::Shape{1, 1, 2, 10}) { + if (lstmSequenceOp->get_output_partial_shape(i).is_static() && ov::shape_size(lstmSequenceOp->get_output_shape(i)) == 1 || + lstmSequenceOp->get_output_partial_shape(0).is_static() && lstmSequenceOp->get_output_shape(0) == ov::Shape{1, 1, 2, 10}) { outFmts[i] = tnc; } } } - 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 = makeNgraphFunction(netPrecision, params, lstmSequenceOp, "lstmSequenceOp"); - function = makeNgraphFunction(ngPrc, params, lstm_sequence, "lstm_sequence"); - - if (m_mode != ngraph::helpers::SequenceTestsMode::PURE_SEQ) { - ngraph::pass::Manager manager; + if (seqMode != ngraph::helpers::SequenceTestsMode::PURE_SEQ) { + ov::pass::Manager manager; if (direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL) manager.register_pass(); manager.register_pass(); @@ -146,82 +171,202 @@ protected: } } - void GenerateInputs() override { - for (const auto &input : executableNetwork.GetInputsInfo()) { - const auto &info = input.second; - auto blob = GenerateInput(*info); - if (input.first == "seq_lengths") { - blob = FuncTestUtils::createAndFillBlob(info->getTensorDesc(), m_max_seq_len, 0); - } + void generate_inputs(const std::vector& targetInputStaticShapes) override { + SubgraphBaseTest::generate_inputs(targetInputStaticShapes); - inputs.push_back(blob); + const size_t batchSize = targetInputStaticShapes[0][0]; + const int64_t maxSeqLen = targetInputStaticShapes[0][1]; + const auto& funcInputs = function->inputs(); + if (funcInputs.size() > 3) { + const auto& seqLenInput = inputs.find(funcInputs[3].get_node_shared_ptr()); + if (seqLenInput == inputs.end()) + throw std::runtime_error("Could not find Sequence length input."); + + auto lenData = seqLenInput->second.data::value_type>(); + std::fill(lenData, lenData + batchSize, maxSeqLen); } } - -private: - ngraph::helpers::SequenceTestsMode m_mode; - int64_t m_max_seq_len = 0; }; TEST_P(LSTMSequenceCPUTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() - Run(); + run(); CheckPluginRelatedResults(executableNetwork, "RNNSeq"); } namespace { /* CPU PARAMS */ std::vector> additionalConfig - = {{{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO}}, - {{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::YES}}}; + = {{{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::NO}}, + {{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::YES}}}; CPUSpecificParams cpuParams{{ntc, tnc, tnc}, {ntc, tnc, tnc}, {"ref_any"}, "ref_any"}; CPUSpecificParams cpuParamsBatchSizeOne{{tnc, ntc, ntc}, {tnc, ntc, ntc}, {"ref_any"}, "ref_any"}; std::vector mode{ngraph::helpers::SequenceTestsMode::PURE_SEQ}; -std::vector seq_lengths_zero_clip{2}; -std::vector batch_size_one{1}; -std::vector batch{10}; -std::vector hidden_size{1, 10}; -std::vector input_size{10}; // oneDNN supports only sigmoid-tanh-tanh std::vector> activations = {{"sigmoid", "tanh", "tanh"}}; // oneDNN supports only zero clip std::vector clip{0.f}; -std::vector direction = {ngraph::op::RecurrentSequenceDirection::FORWARD}; -std::vector netPrecisions = {InferenceEngine::Precision::FP32}; +std::vector direction = {ov::op::RecurrentSequenceDirection::FORWARD}; -INSTANTIATE_TEST_SUITE_P(smoke_LSTMSequenceCPU, - LSTMSequenceCPUTest, - ::testing::Combine(::testing::Combine(::testing::ValuesIn(mode), - ::testing::ValuesIn(seq_lengths_zero_clip), - ::testing::ValuesIn(batch), - ::testing::ValuesIn(hidden_size), - ::testing::ValuesIn(input_size), - ::testing::ValuesIn(activations), - ::testing::ValuesIn(clip), - ::testing::ValuesIn(direction), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::Values(cpuParams), - ::testing::ValuesIn(additionalConfig)), - LSTMSequenceCPUTest::getTestCaseName); +std::vector netPrecisions = { ElementType::f32 }; -INSTANTIATE_TEST_SUITE_P(smoke_LSTMSequenceCPUbatchSizeOne, - LSTMSequenceCPUTest, - ::testing::Combine(::testing::Combine(::testing::ValuesIn(mode), - ::testing::ValuesIn(seq_lengths_zero_clip), - ::testing::ValuesIn(batch_size_one), - ::testing::ValuesIn(hidden_size), - ::testing::ValuesIn(input_size), - ::testing::ValuesIn(activations), - ::testing::ValuesIn(clip), - ::testing::ValuesIn(direction), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::Values(cpuParamsBatchSizeOne), - ::testing::ValuesIn(additionalConfig)), - LSTMSequenceCPUTest::getTestCaseName); +const std::vector> staticShapes = { + { { {}, { {10, 2, 10} } }, // Static shapes + { {}, { {10, 1, 1} } }, + { {}, { {10, 1, 1} } }, + { {}, { {10} } } }, + { { {}, { {10, 2, 10} } }, // Static shapes + { {}, { {10, 1, 10} } }, + { {}, { {10, 1, 10} } }, + { {}, { {10} } } }, + { { {}, { {1, 2, 10} } }, // Static shapes + { {}, { {1, 1, 1} } }, + { {}, { {1, 1, 1} } }, + { {}, { {1} } } }, + { { {}, { {1, 2, 10} } }, // Static shapes + { {}, { {1, 1, 10} } }, + { {}, { {1, 1, 10} } }, + { {}, { {1} } } }, + { { {}, { {1, 2, 10} } }, // Static shapes + { {}, { {1, 1, 10} } }, + { {}, { {1, 1, 10} } } } +}; + +INSTANTIATE_TEST_SUITE_P(smoke_static, LSTMSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{staticShapes[0], staticShapes[1]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(std::map{})), + LSTMSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_static_BatchSizeOne, LSTMSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{staticShapes[3]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParamsBatchSizeOne), + ::testing::Values(std::map{})), + LSTMSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(nightly_static_bf16, LSTMSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{staticShapes[4]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(additionalConfig[1])), + LSTMSequenceCPUTest::getTestCaseName); + +const std::vector> dynamicShapes = { + { { {-1, {1, 5}, 10}, // #0. Dynamic shape 0 + { {10, 2, 10}, {8, 3, 10}, {5, 4, 10} } }, // Target shapes + { {{0, 15}, 1, 1}, // Dynamic shape 1 + { {10, 1, 1}, {8, 1, 1}, {5, 1, 1} } }, // Target shapes + { {{0, 15}, 1, 1}, // Dynamic shape 2 + { {10, 1, 1}, {8, 1, 1}, {5, 1, 1} } }, // Target shapes + { {{0, 12}}, // Dynamic shape 3 + { {10}, {8}, {5} } } }, // Target shapes + { { {{0, 11}, -1, 10}, // #1. Dynamic shape 0 + { {10, 2, 10}, {3, 4, 10}, {5, 5, 10} } }, // Target shapes + { {-1, 1, 10}, // Dynamic shape 1 + { {10, 1, 10}, {3, 1, 10}, {5, 1, 10} } }, // Target shapes + { {-1, 1, 10}, // Dynamic shape 2 + { {10, 1, 10}, {3, 1, 10}, {5, 1, 10} } }, // Target shapes + { {-1}, // Dynamic shape 3 + { {10}, {3}, {5} } } }, // Target shapes + { { {{0, 11}, -1, {5, 15}}, // #2. Dynamic shape 0 + { {10, 2, 10}, {3, 4, 10}, {5, 5, 10} } }, // Target shapes + { {-1, 1, -1}, // Dynamic shape 1 + { {10, 1, 10}, {3, 1, 10}, {5, 1, 10} } }, // Target shapes + { {-1, 1, -1}, // Dynamic shape 2 + { {10, 1, 10}, {3, 1, 10}, {5, 1, 10} } }, // Target shapes + { {-1}, // Dynamic shape 3 + { {10}, {3}, {5} } } }, // Target shapes + { { {-1, {0, 7}, 10}, // #3. Dynamic shape 0 + { {1, 2, 10}, {1, 3, 10}, {1, 6, 10} } }, // Target shapes + { {-1, 1, 1}, // Dynamic shape 1 + { {1, 1, 1}, {1, 1, 1}, {1, 1, 1} } }, // Target shapes + { {-1, 1, 1}, // Dynamic shape 2 + { {1, 1, 1}, {1, 1, 1}, {1, 1, 1} } }, // Target shapes + { {-1}, // Dynamic shape 3 + { {1}, {1}, {1} } } }, // Target shapes + { { {1, -1, 10}, // #4. Dynamic shape 0 + { {1, 2, 10}, {1, 4, 10}, {1, 8, 10} } }, // Target shapes + { {1, 1, 10}, // Dynamic shape 1 + { {1, 1, 10}, {1, 1, 10}, {1, 1, 10} } }, // Target shapes + { {1, 1, 10}, // Dynamic shape 2 + { {1, 1, 10}, {1, 1, 10}, {1, 1, 10} } }, // Target shapes + { {1}, // Dynamic shape 3 + { {1}, {1}, {1} } } }, // Target shapes + { { {-1, -1, -1}, // #5. Dynamic shape 0 + { {1, 2, 10}, {1, 4, 10}, {1, 8, 10} } }, // Target shapes + { {-1, -1, -1}, // Dynamic shape 1 + { {1, 1, 10}, {1, 1, 10}, {1, 1, 10} } }, // Target shapes + { {-1, -1, -1}, // Dynamic shape 2 + { {1, 1, 10}, {1, 1, 10}, {1, 1, 10} } }, // Target shapes + { {-1}, // Dynamic shape 3 + { {1}, {1}, {1} } } }, // Target shapes + { { {3, -1, {0, 12}}, // #6. Dynamic shape 0 + { {3, 2, 10}, {3, 4, 10}, {3, 5, 10} } }, // Target shapes + { {3, -1, {0, 12}}, // Dynamic shape 1 + { {3, 1, 10}, {3, 1, 10}, {3, 1, 10} } }, // Target shapes + { {3, -1, {0, 12}}, // Dynamic shape 2 + { {3, 1, 10}, {3, 1, 10}, {3, 1, 10} } } } // Target shapes +}; + +INSTANTIATE_TEST_SUITE_P(smoke_dynamic, LSTMSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{dynamicShapes[0], dynamicShapes[1], dynamicShapes[2]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(std::map{})), + LSTMSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_dynamic_BatchSizeOne, LSTMSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{dynamicShapes[4]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParamsBatchSizeOne), + ::testing::Values(std::map{})), + LSTMSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(nightly_dynamic, LSTMSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{dynamicShapes[5]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(std::map{})), + LSTMSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(nightly_dynamic_bf16, LSTMSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{dynamicShapes[6]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(additionalConfig[1])), + LSTMSequenceCPUTest::getTestCaseName); } // namespace } // namespace CPULayerTestsDefinitions diff --git a/src/tests/functional/plugin/cpu/single_layer_tests/rnn_cell.cpp b/src/tests/functional/plugin/cpu/single_layer_tests/rnn_cell.cpp index c81a856c3ec..a049f68904d 100644 --- a/src/tests/functional/plugin/cpu/single_layer_tests/rnn_cell.cpp +++ b/src/tests/functional/plugin/cpu/single_layer_tests/rnn_cell.cpp @@ -2,37 +2,59 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "ngraph/op/rnn_cell.hpp" -#include +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "ngraph_functions/builders.hpp" #include "test_utils/cpu_test_utils.hpp" -using namespace InferenceEngine; using namespace CPUTestUtils; +using namespace ov::test; namespace CPULayerTestsDefinitions { -using RNNCellCpuSpecificParams = typename std::tuple>; +using RNNCellCPUParams = typename std::tuple< + std::vector, // Shapes + std::vector, // Activations + float, // Clip + ElementType, // Network precision + CPUSpecificParams, // CPU specific params + std::map // Additional config +>; -class RNNCellCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, - public CPUTestsBase { +class RNNCellCPUTest : public testing::WithParamInterface, + virtual public ov::test::SubgraphBaseTest, public CPUTestsBase { public: - static std::string getTestCaseName(const testing::TestParamInfo &obj) { + static std::string getTestCaseName(const testing::TestParamInfo &obj) { + std::vector inputShapes; + std::vector activations; + float clip = 0.f; + ElementType netPrecision; CPUSpecificParams cpuParams; - LayerTestsDefinitions::RNNCellParams basicParamsSet; std::map additionalConfig; - std::tie(basicParamsSet, cpuParams, additionalConfig) = obj.param; + std::tie(inputShapes, activations, clip, netPrecision, cpuParams, additionalConfig) = obj.param; std::ostringstream result; - result << LayerTestsDefinitions::RNNCellTest::getTestCaseName( - testing::TestParamInfo(basicParamsSet, 0)); + result << "IS=("; + for (const auto& shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result << ")_TS="; + for (size_t i = 0lu; i < inputShapes.front().second.size(); i++) { + result << "{"; + for (size_t j = 0lu; j < inputShapes.size(); j++) { + result << CommonTestUtils::vec2str(inputShapes[j].second[i]) << (j < inputShapes.size() - 1 ? "_" : ""); + } + result << "}_"; + } + result << "activations=" << CommonTestUtils::vec2str(activations) << "_"; + result << "clip=" << clip << "_"; + result << "netPrec=" << netPrecision << "_"; result << CPUTestsBase::getTestCaseName(cpuParams); if (!additionalConfig.empty()) { result << "_PluginConf"; for (auto &item : additionalConfig) { - if (item.second == PluginConfigParams::YES) + if (item.second == InferenceEngine::PluginConfigParams::YES) result << "_" << item.first << "=" << item.second; } } @@ -42,83 +64,102 @@ public: protected: void SetUp() override { + std::vector inputShapes; + std::vector activations; + float clip = 0.f; + ElementType netPrecision; CPUSpecificParams cpuParams; - LayerTestsDefinitions::RNNCellParams basicParamsSet; std::map additionalConfig; - bool should_decompose; - size_t batch; - size_t hidden_size; - size_t input_size; - std::vector activations; - std::vector activations_alpha; - std::vector activations_beta; - float clip; - InferenceEngine::Precision netPrecision; - - std::tie(basicParamsSet, cpuParams, additionalConfig) = this->GetParam(); + std::tie(inputShapes, activations, clip, netPrecision, cpuParams, additionalConfig) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - std::tie(should_decompose, batch, hidden_size, input_size, activations, clip, netPrecision, targetDevice) = basicParamsSet; + targetDevice = CommonTestUtils::DEVICE_CPU; - std::vector> inputShapes = {{batch, input_size}, {batch, hidden_size}, - {hidden_size, input_size}, {hidden_size, hidden_size}, {hidden_size}}; + init_input_shapes(inputShapes); + + const size_t hiddenSize = targetStaticShapes.front()[1][1]; + const size_t inputSize = targetStaticShapes.front()[0][1]; configuration.insert(additionalConfig.begin(), additionalConfig.end()); - if (additionalConfig[PluginConfigParams::KEY_ENFORCE_BF16] == PluginConfigParams::YES) { - inPrc = outPrc = Precision::BF16; + if (additionalConfig[InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16] == InferenceEngine::PluginConfigParams::YES) { + inType = outType = ElementType::bf16; } else { - inPrc = outPrc = netPrecision; + inType = outType = netPrecision; } + selectedType = makeSelectedTypeStr(selectedType, outType); - selectedType += "_"; - selectedType += outPrc.name(); + auto params = ngraph::builder::makeDynamicParams(netPrecision, inputDynamicShapes); + auto paramsOuts = ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)); + std::vector WRB = {{hiddenSize, inputSize}, {hiddenSize, hiddenSize}, {hiddenSize}}; + auto rnnCellOp = ngraph::builder::makeRNN(paramsOuts, WRB, hiddenSize, activations, {}, {}, clip); - auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(Precision::FP32); - auto params = ngraph::builder::makeParams(ngPrc, {inputShapes[0], inputShapes[1]}); - std::vector WRB = {inputShapes[2], inputShapes[3], inputShapes[4]}; - auto rnn_cell = ngraph::builder::makeRNN( - ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)), - WRB, hidden_size, activations, {}, {}, clip); - ngraph::ResultVector results{std::make_shared(rnn_cell)}; - function = makeNgraphFunction(ngPrc, params, rnn_cell, "rnn_cell"); + function = makeNgraphFunction(netPrecision, params, rnnCellOp, "RNNCellCPU"); } }; TEST_P(RNNCellCPUTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() - Run(); + run(); CheckPluginRelatedResults(executableNetwork, "RNNCell"); } namespace { /* CPU PARAMS */ -std::vector> additionalConfig - = {{{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO}}, {{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::YES}}}; +std::vector> additionalConfig = { + {{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::NO}}, + {{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::YES}} +}; CPUSpecificParams cpuParams{{nc, nc}, {nc}, {"ref_any"}, "ref_any"}; -std::vector should_decompose{false}; -std::vector batch{1, 5}; -std::vector hidden_size{1, 10}; -std::vector input_size{1, 30}; std::vector> activations = {{"relu"}, {"sigmoid"}, {"tanh"}}; // oneDNN supports only zero clip std::vector clip = {0.f}; -std::vector netPrecisions = {InferenceEngine::Precision::FP32}; +std::vector netPrecisions = { ElementType::f32 }; -INSTANTIATE_TEST_SUITE_P(smoke_RNNCellCPU, - RNNCellCPUTest, - ::testing::Combine(::testing::Combine(::testing::ValuesIn(should_decompose), - ::testing::ValuesIn(batch), - ::testing::ValuesIn(hidden_size), - ::testing::ValuesIn(input_size), - ::testing::ValuesIn(activations), - ::testing::ValuesIn(clip), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::Values(cpuParams), - ::testing::ValuesIn(additionalConfig)), - RNNCellCPUTest::getTestCaseName); +const std::vector> staticShapes = { + { { {}, { {1, 1} } }, // Static shapes + { {}, { {1, 1} } } }, + { { {}, { {1, 30} } }, // Static shapes + { {}, { {1, 10} } } }, + { { {}, { {5, 1} } }, // Static shapes + { {}, { {5, 1} } } }, + { { {}, { {5, 30} } }, // Static shapes + { {}, { {5, 10} } } } +}; + +INSTANTIATE_TEST_SUITE_P(smoke_static, RNNCellCPUTest, + ::testing::Combine(::testing::ValuesIn(staticShapes), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::ValuesIn(additionalConfig)), + RNNCellCPUTest::getTestCaseName); + +const std::vector> dynamicShapes = { + { { { {-1}, 1 }, // Dynamic shape 0 + { {1, 1}, {3, 1}, {5, 1} } }, // Target shapes + { { {-1}, 1 }, // Dynamic shape 1 + { {1, 1}, {3, 1}, {5, 1} } } }, // Target shapes + { { { {1, 10}, 30 }, // Dynamic shape 0 + { {2, 30}, {5, 30}, {8, 30} } }, // Target shapes + { { {1, 10}, 10 }, // Dynamic shape 1 + { {2, 10}, {5, 10}, {8, 10} } } }, // Target shapes + { { { {1, 10}, -1 }, // Dynamic shape 0 + { {2, 30}, {5, 30}, {8, 30} } }, // Target shapes + { { {1, 10}, {1, 11} }, // Dynamic shape 1 + { {2, 10}, {5, 10}, {8, 10} } } } // Target shapes +}; + +INSTANTIATE_TEST_SUITE_P(smoke_dynamic, RNNCellCPUTest, + ::testing::Combine(::testing::ValuesIn(dynamicShapes), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::ValuesIn(additionalConfig)), + RNNCellCPUTest::getTestCaseName); } // namespace } // namespace CPULayerTestsDefinitions diff --git a/src/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp b/src/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp index 80834bc9c44..d1aecb67c44 100644 --- a/src/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp +++ b/src/tests/functional/plugin/cpu/single_layer_tests/rnn_sequence.cpp @@ -2,38 +2,67 @@ // SPDX-License-Identifier: Apache-2.0 // -#include "shared_test_classes/single_layer/rnn_sequence.hpp" -#include "ngraph/pass/visualize_tree.hpp" +#include "shared_test_classes/base/ov_subgraph.hpp" +#include "ngraph_functions/builders.hpp" #include "test_utils/cpu_test_utils.hpp" #include "transformations/op_conversions/bidirectional_sequences_decomposition.hpp" #include "transformations/op_conversions/convert_sequences_to_tensor_iterator.hpp" -using namespace InferenceEngine; using namespace CPUTestUtils; +using namespace ov::test; namespace CPULayerTestsDefinitions { -using RNNSequenceCpuSpecificParams = typename std::tuple>; +using RNNSequenceCpuSpecificParams = typename std::tuple< + std::vector, // Shapes + ngraph::helpers::SequenceTestsMode, // Pure Sequence or TensorIterator + std::vector, // Activations + float, // Clip + ov::op::RecurrentSequenceDirection, // Direction + ElementType, // Network precision + CPUSpecificParams, // CPU specific params + std::map // Additional config +>; class RNNSequenceCPUTest : public testing::WithParamInterface, - virtual public LayerTestsUtils::LayerTestsCommon, - public CPUTestsBase { + virtual public SubgraphBaseTest, public CPUTestsBase { public: static std::string getTestCaseName(const testing::TestParamInfo &obj) { + std::vector inputShapes; + ngraph::helpers::SequenceTestsMode seqMode; + std::vector activations; + float clip; + ov::op::RecurrentSequenceDirection direction; + ElementType netPrecision; CPUSpecificParams cpuParams; - LayerTestsDefinitions::RNNSequenceParams basicParamsSet; std::map additionalConfig; - std::tie(basicParamsSet, cpuParams, additionalConfig) = obj.param; - std::ostringstream result; + std::tie(inputShapes, seqMode, activations, clip, direction, netPrecision, cpuParams, additionalConfig) = obj.param; - result << LayerTestsDefinitions::RNNSequenceTest::getTestCaseName(testing::TestParamInfo(basicParamsSet, 0)); + std::ostringstream result; + result << "IS=("; + for (const auto& shape : inputShapes) { + result << CommonTestUtils::partialShape2str({shape.first}) << "_"; + } + result << ")_TS="; + for (size_t i = 0lu; i < inputShapes.front().second.size(); i++) { + result << "{"; + for (size_t j = 0lu; j < inputShapes.size(); j++) { + result << CommonTestUtils::vec2str(inputShapes[j].second[i]) << (j < inputShapes.size() - 1 ? "_" : ""); + } + result << "}_"; + } + result << "seqMode=" << seqMode << "_"; + result << "activations=" << CommonTestUtils::vec2str(activations) << "_"; + result << "clip=" << clip << "_"; + result << "direction=" << direction << "_"; + result << "netPrec=" << netPrecision << "_"; result << CPUTestsBase::getTestCaseName(cpuParams); if (!additionalConfig.empty()) { result << "_PluginConf"; for (auto &item : additionalConfig) { - if (item.second == PluginConfigParams::YES) + if (item.second == InferenceEngine::PluginConfigParams::YES) result << "_" << item.first << "=" << item.second; } } @@ -42,72 +71,71 @@ public: protected: void SetUp() override { - LayerTestsDefinitions::RNNSequenceParams basicParamsSet; + std::vector inputShapes; + ngraph::helpers::SequenceTestsMode seqMode; + std::vector activations; + float clip; + ov::op::RecurrentSequenceDirection direction; + ElementType netPrecision; CPUSpecificParams cpuParams; std::map additionalConfig; - size_t seq_lengths; - size_t batch; - size_t hidden_size; - size_t input_size; - std::vector activations; - std::vector activations_alpha; - std::vector activations_beta; - float clip; - ngraph::op::RecurrentSequenceDirection direction; - InferenceEngine::Precision netPrecision; - - std::tie(basicParamsSet, cpuParams, additionalConfig) = this->GetParam(); + std::tie(inputShapes, seqMode, activations, clip, direction, netPrecision, cpuParams, additionalConfig) = this->GetParam(); std::tie(inFmts, outFmts, priority, selectedType) = cpuParams; - std::tie(m_mode, seq_lengths, batch, hidden_size, input_size, activations, clip, direction, netPrecision, targetDevice) = basicParamsSet; + targetDevice = CommonTestUtils::DEVICE_CPU; - size_t num_directions = direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; - std::vector> inputShapes = { - {{batch, seq_lengths, input_size}, - {batch, num_directions, hidden_size}, - {batch}, - {num_directions, hidden_size, input_size}, - {num_directions, hidden_size, hidden_size}, - {num_directions, hidden_size}}, - }; + init_input_shapes(inputShapes); + if (inputDynamicShapes.size() == 2 && inputDynamicShapes[0][0].is_dynamic() && inputDynamicShapes[1][0].is_dynamic()) + throw std::runtime_error("Invalid test case. If 3rd input is constant, batch dimension must be static."); + + const size_t hiddenSize = targetStaticShapes.front()[1][2]; + const size_t inputSize = targetStaticShapes.front()[0][2]; + const size_t numDirections = direction == ov::op::RecurrentSequenceDirection::BIDIRECTIONAL ? 2 : 1; configuration.insert(additionalConfig.begin(), additionalConfig.end()); - if (additionalConfig[PluginConfigParams::KEY_ENFORCE_BF16] == PluginConfigParams::YES) { - inPrc = outPrc = Precision::BF16; + // 3rd input type must be integer, thus it cannot be forced to BF16. + if (additionalConfig[InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16] == InferenceEngine::PluginConfigParams::YES) { + if (inputDynamicShapes.size() > 2) + throw std::runtime_error("Invalid test case. Cannot enforce integer input to BF16."); + inType = outType = ElementType::bf16; } else { - inPrc = outPrc = netPrecision; + outType = netPrecision; + } + selectedType = makeSelectedTypeStr(selectedType, outType); + + auto params = ngraph::builder::makeDynamicParams(netPrecision, inputDynamicShapes); + const size_t batchSize = inputDynamicShapes[0][0].is_static() ? inputDynamicShapes[0][0].get_length() : + inputDynamicShapes[1][0].is_static() ? inputDynamicShapes[1][0].get_length() : + inputDynamicShapes.size() > 2 && inputDynamicShapes[2][0].is_static() ? inputDynamicShapes[2][0].get_length() : + 1lu; + if (inputDynamicShapes.size() > 2) { + if (!inputDynamicShapes[2].is_dynamic() && + seqMode != ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_PARAM && + seqMode != ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_RAND_SEQ_LEN_PARAM) { + params.pop_back(); + } else { + params[2]->set_element_type(ElementType::i64); + } } - selectedType += "_"; - selectedType += outPrc.name(); - - m_max_seq_len = seq_lengths; - auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(Precision::FP32); - 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) { - 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); - } - std::vector WRB = {inputShapes[3], inputShapes[4], inputShapes[5], inputShapes[2]}; + std::vector WRB = {{numDirections, hiddenSize, inputSize}, {numDirections, hiddenSize, hiddenSize}, {numDirections, hiddenSize}, + {batchSize}}; auto rnn_sequence = ngraph::builder::makeRNN(ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)), WRB, - hidden_size, + hiddenSize, activations, {}, {}, clip, true, direction, - m_mode); - ngraph::ResultVector results{std::make_shared(rnn_sequence->output(0)), - std::make_shared(rnn_sequence->output(1))}; - function = makeNgraphFunction(ngPrc, params, rnn_sequence, "rnn_sequence"); - if (m_mode != ngraph::helpers::SequenceTestsMode::PURE_SEQ) { + seqMode); + function = makeNgraphFunction(netPrecision, params, rnn_sequence, "rnnSequence"); + + if (seqMode != ngraph::helpers::SequenceTestsMode::PURE_SEQ) { ngraph::pass::Manager manager; - if (direction == ngraph::op::RecurrentSequenceDirection::BIDIRECTIONAL) + if (direction == ov::op::RecurrentSequenceDirection::BIDIRECTIONAL) manager.register_pass(); manager.register_pass(); manager.run_passes(function); @@ -119,84 +147,176 @@ protected: } } - void GenerateInputs() override { - for (const auto &input : executableNetwork.GetInputsInfo()) { - const auto &info = input.second; - auto blob = GenerateInput(*info); - if (input.first == "seq_lengths") { - blob = FuncTestUtils::createAndFillBlob(info->getTensorDesc(), m_max_seq_len, 0); - } + void generate_inputs(const std::vector& targetInputStaticShapes) override { + SubgraphBaseTest::generate_inputs(targetInputStaticShapes); - inputs.push_back(blob); + const size_t batchSize = targetInputStaticShapes[0][0]; + const int64_t maxSeqLen = targetInputStaticShapes[0][1]; + const auto& funcInputs = function->inputs(); + if (funcInputs.size() > 2) { + const auto& seqLenInput = inputs.find(funcInputs[2].get_node_shared_ptr()); + if (seqLenInput == inputs.end()) + throw std::runtime_error("Could not find Sequence length input."); + + auto lenData = seqLenInput->second.data::value_type>(); + std::fill(lenData, lenData + batchSize, maxSeqLen); } } - -private: - ngraph::helpers::SequenceTestsMode m_mode; - int64_t m_max_seq_len = 0; }; TEST_P(RNNSequenceCPUTest, CompareWithRefs) { SKIP_IF_CURRENT_TEST_IS_DISABLED() - Run(); + run(); CheckPluginRelatedResults(executableNetwork, "RNNSeq"); } namespace { /* CPU PARAMS */ std::vector> additionalConfig - = {{{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO}}, {{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::YES}}}; + = {{{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::NO}}, + {{InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16, InferenceEngine::PluginConfigParams::YES}}}; CPUSpecificParams cpuParams{{ntc, tnc}, {ntc, tnc}, {"ref_any"}, "ref_any"}; CPUSpecificParams cpuParamsBatchSizeOne{{tnc, ntc}, {tnc, tnc}, {"ref_any"}, "ref_any"}; std::vector mode{ngraph::helpers::SequenceTestsMode::PURE_SEQ}; // output values increase rapidly without clip, so use only seq_lengths = 2 -std::vector seq_lengths_zero_clip{2}; -std::vector batch{10}; -std::vector batch_size_one{1}; -std::vector hidden_size{10}; -// std::vector hidden_size{1, 10}; -std::vector input_size{10}; +std::vector seq_lengths_zero_clip{ 2 }; std::vector> activations = {{"relu"}, {"sigmoid"}, {"tanh"}}; // oneDNN supports only zero clip std::vector clip{0.f}; -std::vector direction{ngraph::op::RecurrentSequenceDirection::FORWARD}; +std::vector direction{ov::op::RecurrentSequenceDirection::FORWARD}; -std::vector netPrecisions = {InferenceEngine::Precision::FP32}; +std::vector netPrecisions = { ElementType::f32 }; -INSTANTIATE_TEST_SUITE_P(smoke_RNNSequenceCPU, - RNNSequenceCPUTest, - ::testing::Combine(::testing::Combine(::testing::ValuesIn(mode), - ::testing::ValuesIn(seq_lengths_zero_clip), - ::testing::ValuesIn(batch), - ::testing::ValuesIn(hidden_size), - ::testing::ValuesIn(input_size), - ::testing::ValuesIn(activations), - ::testing::ValuesIn(clip), - ::testing::ValuesIn(direction), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::Values(cpuParams), - ::testing::ValuesIn(additionalConfig)), - RNNSequenceCPUTest::getTestCaseName); +const std::vector> staticShapes = { + { { {}, { {10, 2, 10} } }, // Static shapes + { {}, { {10, 1, 1} } }, + { {}, { {10} } } }, + { { {}, { {10, 2, 10} } }, // Static shapes + { {}, { {10, 1, 10} } }, + { {}, { {10} } } }, + { { {}, { {1, 2, 10} } }, // Static shapes + { {}, { {1, 1, 1} } }, + { {}, { {1} } } }, + { { {}, { {1, 2, 10} } }, // Static shapes + { {}, { {1, 1, 10} } }, + { {}, { {1} } } } +}; -INSTANTIATE_TEST_SUITE_P(smoke_RNNSequenceCPUBatchSizeOne, - RNNSequenceCPUTest, - ::testing::Combine(::testing::Combine(::testing::ValuesIn(mode), - ::testing::ValuesIn(seq_lengths_zero_clip), - ::testing::ValuesIn(batch_size_one), - ::testing::ValuesIn(hidden_size), - ::testing::ValuesIn(input_size), - ::testing::ValuesIn(activations), - ::testing::ValuesIn(clip), - ::testing::ValuesIn(direction), - ::testing::ValuesIn(netPrecisions), - ::testing::Values(CommonTestUtils::DEVICE_CPU)), - ::testing::Values(cpuParamsBatchSizeOne), - ::testing::ValuesIn(additionalConfig)), - RNNSequenceCPUTest::getTestCaseName); +INSTANTIATE_TEST_SUITE_P(smoke_static, RNNSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{staticShapes[0], staticShapes[1]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(std::map{})), + RNNSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_static_BatchSizeOne, RNNSequenceCPUTest, + ::testing::Combine(::testing::Values(staticShapes[3]), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParamsBatchSizeOne), + ::testing::Values(std::map{})), + RNNSequenceCPUTest::getTestCaseName); + +const std::vector> dynamicShapes = { + { { {-1, {1, 5}, 10}, // #0. Dynamic shape 0 + { {10, 2, 10}, {8, 3, 10}, {5, 4, 10} } }, // Target shapes + { {{0, 15}, 1, 1}, // Dynamic shape 1 + { {10, 1, 1}, {8, 1, 1}, {5, 1, 1} } }, // Target shapes + { {{0, 12}}, // Dynamic shape 2 + { {10}, {8}, {5} } } }, // Target shapes + { { {{0, 11}, -1, 10}, // #1. Dynamic shape 0 + { {10, 2, 10}, {3, 4, 10}, {5, 5, 10} } }, // Target shapes + { {-1, 1, 10}, // Dynamic shape 1 + { {10, 1, 10}, {3, 1, 10}, {5, 1, 10} } }, // Target shapes + { {-1}, // Dynamic shape 2 + { {10}, {3}, {5} } } }, // Target shapes + { { {{0, 11}, -1, {5, 15}}, // #2. Dynamic shape 0 + { {10, 2, 10}, {3, 4, 10}, {5, 5, 10} } }, // Target shapes + { {-1, -1, {8, 11}}, // Dynamic shape 1 + { {10, 1, 10}, {3, 1, 10}, {5, 1, 10} } }, // Target shapes + { {-1}, // Dynamic shape 2 + { {10}, {3}, {5} } } }, // Target shapes + { { {-1, {0, 7}, 10}, // #3. Dynamic shape 0 + { {1, 2, 10}, {1, 3, 10}, {1, 6, 10} } }, // Target shapes + { {-1, 1, 1}, // Dynamic shape 1 + { {1, 1, 1}, {1, 1, 1}, {1, 1, 1} } }, // Target shapes + { {-1}, // Dynamic shape 2 + { {1}, {1}, {1} } } }, // Target shapes + { { {1, -1, 10}, // #4. Dynamic shape 0 + { {1, 2, 10}, {1, 4, 10}, {1, 8, 10} } }, // Target shapes + { {1, 1, 10}, // Dynamic shape 1 + { {1, 1, 10}, {1, 1, 10}, {1, 1, 10} } }, // Target shapes + { {1}, // Dynamic shape 2 + { {1}, {1}, {1} } } }, // Target shapes + { { {-1, -1, -1}, // #5. Dynamic shape 0 + { {1, 2, 10}, {1, 4, 10}, {1, 8, 10} } }, // Target shapes + { {-1, -1, -1}, // Dynamic shape 1 + { {1, 1, 10}, {1, 1, 10}, {1, 1, 10} } }, // Target shapes + { {-1}, // Dynamic shape 2 + { {1}, {1}, {1} } } }, // Target shapes + { { {-1, {1, 5}, 10}, // #6. Dynamic shape 0 + { {10, 2, 10}, {8, 3, 10}, {5, 4, 10} } }, // Target shapes + { {{0, 15}, 1, 1}, // Dynamic shape 1 + { {10, 1, 1}, {8, 1, 1}, {5, 1, 1} } } }, // Target shapes + { { {{0, 11}, -1, 10}, // #7. Dynamic shape 0 + { {10, 2, 10}, {3, 4, 10}, {5, 5, 10} } }, // Target shapes + { {-1, 1, 10}, // Dynamic shape 1 + { {10, 1, 10}, {3, 1, 10}, {5, 1, 10} } } } // Target shapes +}; + +INSTANTIATE_TEST_SUITE_P(smoke_dynamic, RNNSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn(std::vector>{dynamicShapes[0], dynamicShapes[1], dynamicShapes[2]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParams), + ::testing::Values(std::map{})), + RNNSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(smoke_dynamic_BatchSizeOne, RNNSequenceCPUTest, + ::testing::Combine(::testing::Values(dynamicShapes[4]), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParamsBatchSizeOne), + ::testing::Values(std::map{})), + RNNSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(nightly_dynamic, RNNSequenceCPUTest, + ::testing::Combine(::testing::Values(dynamicShapes[5]), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParamsBatchSizeOne), + ::testing::Values(std::map{})), + RNNSequenceCPUTest::getTestCaseName); + +INSTANTIATE_TEST_SUITE_P(nightly_dynamic_bf16, RNNSequenceCPUTest, + ::testing::Combine(::testing::ValuesIn({dynamicShapes[6], dynamicShapes[7]}), + ::testing::ValuesIn(mode), + ::testing::ValuesIn(activations), + ::testing::ValuesIn(clip), + ::testing::ValuesIn(direction), + ::testing::ValuesIn(netPrecisions), + ::testing::Values(cpuParamsBatchSizeOne), + ::testing::Values(additionalConfig[1])), + RNNSequenceCPUTest::getTestCaseName); } // namespace } // namespace CPULayerTestsDefinitions diff --git a/src/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp b/src/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp index 5f2484b73a5..02137f785ee 100644 --- a/src/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp +++ b/src/tests/ngraph_helpers/ngraph_functions/src/gru_cell.cpp @@ -10,8 +10,8 @@ namespace ngraph { namespace builder { -std::shared_ptr makeGRU(const OutputVector& in, - const std::vector& constants, +std::shared_ptr makeGRU(const OutputVector& in, + const std::vector& constants, std::size_t hidden_size, const std::vector& activations, const std::vector& activations_alpha, @@ -19,46 +19,51 @@ std::shared_ptr makeGRU(const OutputVector& in, float clip, bool linear_before_reset, bool make_sequence, - ngraph::op::RecurrentSequenceDirection direction, + ov::op::RecurrentSequenceDirection direction, ngraph::helpers::SequenceTestsMode mode) { std::vector empty; auto W = ngraph::builder::makeConstant(in[0].get_element_type(), constants[0], empty, true); auto R = ngraph::builder::makeConstant(in[0].get_element_type(), constants[1], empty, true); auto B = ngraph::builder::makeConstant(in[0].get_element_type(), constants[2], empty, true); if (!make_sequence) { - return std::make_shared(in[0], in[1], W, R, B, hidden_size, activations, + return std::make_shared(in[0], in[1], W, R, B, hidden_size, activations, activations_alpha, activations_beta, clip, linear_before_reset); } else { - std::shared_ptr seq_lengths; - switch (mode) { - case ngraph::helpers::SequenceTestsMode::PURE_SEQ: - case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: { - std::vector lengths(in[0].get_shape()[0], in[0].get_shape()[1]); - 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::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, - static_cast(in[0].get_shape()[1]), 0.f); + if (in.size() > 2 && in[2].get_partial_shape().is_dynamic()) { + return std::make_shared(in[0], in[1], in[2], W, R, B, hidden_size, direction, + activations, activations_alpha, activations_beta, clip, linear_before_reset); + } else { + std::shared_ptr seq_lengths; + switch (mode) { + case ngraph::helpers::SequenceTestsMode::PURE_SEQ: + case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: { + std::vector lengths(in[0].get_partial_shape()[0].get_min_length(), in[0].get_partial_shape()[1].get_min_length()); + seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, false); + break; } - break; + 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, + static_cast(in[0].get_shape()[1]), 0.f); + } + 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::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; + } + default: + throw std::runtime_error("Incorrect mode for creation of Sequence operation"); } - 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::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; - } - default: - throw std::runtime_error("Incorrect mode for creation of Sequence operation"); + return std::make_shared(in[0], in[1], seq_lengths, W, R, B, hidden_size, direction, + activations, activations_alpha, activations_beta, clip, linear_before_reset); } - return std::make_shared(in[0], in[1], seq_lengths, W, R, B, hidden_size, direction, - activations, activations_alpha, activations_beta, clip, linear_before_reset); } } } // namespace builder diff --git a/src/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp b/src/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp index 8a8865643c3..a9c4c9c9d0d 100644 --- a/src/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp +++ b/src/tests/ngraph_helpers/ngraph_functions/src/lstm_cell.cpp @@ -10,53 +10,58 @@ namespace ngraph { namespace builder { -std::shared_ptr makeLSTM(const std::vector>& in, - const std::vector& constants, +std::shared_ptr makeLSTM(const std::vector>& in, + const std::vector& constants, std::size_t hidden_size, const std::vector& activations, const std::vector& activations_alpha, const std::vector& activations_beta, float clip, bool make_sequence, - ngraph::op::RecurrentSequenceDirection direction, + ov::op::RecurrentSequenceDirection direction, ngraph::helpers::SequenceTestsMode mode) { std::vector empty; auto W = ngraph::builder::makeConstant(in[0].get_element_type(), constants[0], empty, true); auto R = ngraph::builder::makeConstant(in[0].get_element_type(), constants[1], empty, true); auto B = ngraph::builder::makeConstant(in[0].get_element_type(), constants[2], empty, true); if (!make_sequence) { - return std::make_shared(in[0], in[1], in[2], W, R, B, hidden_size, activations, + return std::make_shared(in[0], in[1], in[2], W, R, B, hidden_size, activations, activations_alpha, activations_beta, clip); } else { - std::shared_ptr seq_lengths; - switch (mode) { - case ngraph::helpers::SequenceTestsMode::PURE_SEQ: - case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: { - std::vector lengths(in[0].get_shape()[0], in[0].get_shape()[1]); - 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::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, - static_cast(in[0].get_shape()[1]), 0.f); + if (in.size() > 3 && in[3].get_partial_shape().is_dynamic()) { + return std::make_shared(in[0], in[1], in[2], in[3], W, R, B, hidden_size, direction, + activations_alpha, activations_beta, activations, clip); + } else { + std::shared_ptr seq_lengths; + switch (mode) { + case ngraph::helpers::SequenceTestsMode::PURE_SEQ: + case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: { + std::vector lengths(in[0].get_partial_shape()[0].get_min_length(), in[0].get_partial_shape()[1].get_min_length()); + seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, false); + break; } - break; + 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, + static_cast(in[0].get_shape()[1]), 0.f); + } + 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 + seq_lengths = in.at(3).get_node_shared_ptr(); + break; + } + default: + throw std::runtime_error("Incorrect mode for creation of Sequence operation"); } - 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 - seq_lengths = in.at(3).get_node_shared_ptr(); - break; - } - default: - throw std::runtime_error("Incorrect mode for creation of Sequence operation"); + return std::make_shared(in[0], in[1], in[2], seq_lengths, W, R, B, hidden_size, direction, + activations_alpha, activations_beta, activations, clip); } - return std::make_shared(in[0], in[1], in[2], seq_lengths, W, R, B, hidden_size, direction, - activations_alpha, activations_beta, activations, clip); } } } // namespace builder diff --git a/src/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp b/src/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp index 55b1b661c2b..6f319645bc4 100644 --- a/src/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp +++ b/src/tests/ngraph_helpers/ngraph_functions/src/rnn_cell.cpp @@ -10,53 +10,58 @@ namespace ngraph { namespace builder { -std::shared_ptr makeRNN(const OutputVector& in, - const std::vector& constants, +std::shared_ptr makeRNN(const OutputVector& in, + const std::vector& constants, std::size_t hidden_size, const std::vector& activations, const std::vector& activations_alpha, const std::vector& activations_beta, float clip, bool make_sequence, - ngraph::op::RecurrentSequenceDirection direction, + ov::op::RecurrentSequenceDirection direction, ngraph::helpers::SequenceTestsMode mode) { std::vector empty; auto W = ngraph::builder::makeConstant(in[0].get_element_type(), constants[0], empty, true); auto R = ngraph::builder::makeConstant(in[0].get_element_type(), constants[1], empty, true); auto B = ngraph::builder::makeConstant(in[0].get_element_type(), constants[2], empty, true); if (!make_sequence) { - return std::make_shared(in[0], in[1], W, R, B, hidden_size, activations, + return std::make_shared(in[0], in[1], W, R, B, hidden_size, activations, activations_alpha, activations_beta, clip); } else { - std::shared_ptr seq_lengths; - switch (mode) { - case ngraph::helpers::SequenceTestsMode::PURE_SEQ: - case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: { - std::vector lengths(in[0].get_shape()[0], in[0].get_shape()[1]); - 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::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, - static_cast(in[0].get_shape()[1]), 0.f); + if (in.size() > 2 && in[2].get_partial_shape().is_dynamic()) { + return std::make_shared(in[0], in[1], in[2], W, R, B, hidden_size, direction, + activations, activations_alpha, activations_beta, clip); + } else { + std::shared_ptr seq_lengths; + switch (mode) { + case ngraph::helpers::SequenceTestsMode::PURE_SEQ: + case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: { + std::vector lengths(in[0].get_partial_shape()[0].get_min_length(), in[0].get_partial_shape()[1].get_min_length()); + seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, false); + break; } - break; + 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, + static_cast(in[0].get_shape()[1]), 0.f); + } + 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::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; + } + default: + throw std::runtime_error("Incorrect mode for creation of Sequence operation"); } - 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::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; - } - default: - throw std::runtime_error("Incorrect mode for creation of Sequence operation"); + return std::make_shared(in[0], in[1], seq_lengths, W, R, B, hidden_size, direction, + activations, activations_alpha, activations_beta, clip); } - return std::make_shared(in[0], in[1], seq_lengths, W, R, B, hidden_size, direction, - activations, activations_alpha, activations_beta, clip); } } } // namespace builder