[CPU] Dynamic shapes. RNN node. (#9002)

This commit is contained in:
Nikolay Shchegolev 2022-01-11 18:17:35 +03:00 committed by GitHub
parent 02cabcda3c
commit 62e8923605
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 1704 additions and 1005 deletions

View File

@ -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<Dim>& 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<Dimension> 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;

View File

@ -2022,10 +2022,11 @@ void MKLDNNGraphOptimizer::reshapeRnnSeq(MKLDNNGraph &graph) {
}
auto childrenEdges = parentNode->getChildEdgesAtPort(0);
std::vector<ov::Dimension> origShape = static_cast<std::vector<ov::Dimension>>(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];

View File

@ -648,8 +648,7 @@ void MKLDNNNode::filterSupportedPrimitiveDescriptors() {
}
void MKLDNNNode::initDescriptor(const NodeConfig& config) {
auto* selectedPD = getSelectedPrimitiveDescriptor();
if (!selectedPD) {
if (!getSelectedPrimitiveDescriptor()) {
return;
}
std::vector<MemoryDescPtr> 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;
}

View File

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

View File

@ -907,7 +907,6 @@ std::shared_ptr<MKLDNNDescriptor> MKLDNNConvolutionNode::createMkldnnConvDesc(co
const mkldnn::memory::desc& wghDesc,
const mkldnn::memory::desc& dstDesc,
const mkldnn::memory::desc& biasDesc) {
std::shared_ptr<mkldnn::convolution_forward::desc> 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();

File diff suppressed because it is too large Load Diff

View File

@ -5,10 +5,10 @@
#pragma once
#include <mkldnn_node.h>
#include <string>
#include <memory>
#include <vector>
#include "memory_desc/dnnl_blocked_memory_desc.h"
namespace MKLDNNPlugin {
@ -18,7 +18,6 @@ public:
static bool isSupportedOperation(const std::shared_ptr<const ngraph::Node>& op, std::string& errorMessage) noexcept;
void getSupportedDescriptors() override;
void createPrimitive() override;
std::shared_ptr<MemoryDesc> getSrcMemDesc(mkldnn::primitive_desc_iterator& primitive_desc_it, size_t idx) override;
std::shared_ptr<MemoryDesc> 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<VectorDims> shapeInfer() const override;
void prepareParams() override;
void executeDynamicImpl(mkldnn::stream strm) override;
private:
void initCell(const std::shared_ptr<ngraph::Node>& op);
void initSeq(const std::shared_ptr<ngraph::Node>& 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<DnnlBlockedMemoryDesc> in_data_d;
std::vector<DnnlBlockedMemoryDesc> out_data_d;
std::vector<DnnlBlockedMemoryDesc> inDataDescs;
std::vector<DnnlBlockedMemoryDesc> outDataDescs;
std::vector<mkldnn::memory::desc> wDescs;
enum RNNInOutKind {
Layer = 0,
@ -86,14 +107,16 @@ private:
CellState = 2
};
std::vector<size_t > in_data_dims;
std::vector<size_t > out_data_dims;
size_t wIdx = 0;
size_t rIdx = 0;
size_t bIdx = 0;
static const std::map<InferenceEngine::Precision, InferenceEngine::Precision> weightsByLayerPrec;
static constexpr size_t optimalBatchSize = 16lu;
static constexpr size_t batchDimDummyValue = 64lu;
bool wasMemoryPrepared = false;
};
} // namespace MKLDNNPlugin

View File

@ -71,6 +71,10 @@ std::vector<std::string> 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).*)",

View File

@ -2,38 +2,64 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "ngraph/op/gru_cell.hpp"
#include <shared_test_classes/single_layer/gru_cell.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/gru_cell_decomposition.hpp"
using namespace InferenceEngine;
using namespace CPUTestUtils;
using namespace ov::test;
namespace CPULayerTestsDefinitions {
using GRUCellCpuSpecificParams = typename std::tuple<LayerTestsDefinitions::GRUCellParams, CPUSpecificParams, std::map<std::string, std::string>>;
using GRUCellCpuSpecificParams = typename std::tuple<
std::vector<InputShape>, // Shapes
bool, // Using decompose to sub-ops transformation
std::vector<std::string>, // Activations
float, // Clip
bool, // Linear before reset
ElementType, // Network precision
CPUSpecificParams, // CPU specific params
std::map<std::string, std::string> // Additional config
>;
class GRUCellCPUTest : public testing::WithParamInterface<GRUCellCpuSpecificParams>,
virtual public LayerTestsUtils::LayerTestsCommon,
public CPUTestsBase {
virtual public ov::test::SubgraphBaseTest, public CPUTestsBase {
public:
static std::string getTestCaseName(const testing::TestParamInfo<GRUCellCpuSpecificParams> &obj) {
std::vector<InputShape> inputShapes;
bool decompose, linearBeforeReset;
std::vector<std::string> activations;
float clip = 0.f;
ElementType netPrecision;
CPUSpecificParams cpuParams;
LayerTestsDefinitions::GRUCellParams basicParamsSet;
std::map<std::string, std::string> 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<LayerTestsDefinitions::GRUCellParams>(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<InputShape> inputShapes;
bool decompose, linearBeforeReset;
std::vector<std::string> activations;
float clip = 0.f;
ElementType netPrecision;
CPUSpecificParams cpuParams;
LayerTestsDefinitions::GRUCellParams basicParamsSet;
std::map<std::string, std::string> additionalConfig;
bool should_decompose;
size_t batch;
size_t hidden_size;
size_t input_size;
std::vector<std::string> activations;
std::vector<float> activations_alpha;
std::vector<float> 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<std::vector<size_t>> 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<ngraph::Shape> 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<ngraph::Shape> 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<ngraph::opset1::Result>(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<std::map<std::string, std::string>> 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<bool> should_decompose{false};
std::vector<size_t> batch{1, 5};
std::vector<size_t> hidden_size{1, 10};
std::vector<size_t> input_size{1, 30};
std::vector<bool> shouldDecompose{false};
// oneDNN supports only sigmoid-tanh
std::vector<std::vector<std::string>> activations = {{"sigmoid", "tanh"}};
// oneDNN supports only zero clip
std::vector<float> clip = {0.f};
std::vector<bool> linear_before_reset = {true, false};
std::vector<InferenceEngine::Precision> netPrecisions = {InferenceEngine::Precision::FP32};
std::vector<bool> linearBeforeReset = {true, false};
std::vector<ElementType> 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<std::vector<ov::test::InputShape>> 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<std::vector<ov::test::InputShape>> 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

View File

@ -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<LayerTestsDefinitions::GRUSequenceParams, CPUSpecificParams, std::map<std::string, std::string>>;
using GRUSequenceCpuSpecificParams = typename std::tuple<
std::vector<InputShape>, // Shapes
ngraph::helpers::SequenceTestsMode, // Pure Sequence or TensorIterator
std::vector<std::string>, // Activations
float, // Clip
bool, // Linear_before_reset
ov::op::RecurrentSequenceDirection, // Direction
ElementType, // Network precision
CPUSpecificParams, // CPU specific params
std::map<std::string, std::string> // Additional config
>;
class GRUSequenceCPUTest : public testing::WithParamInterface<GRUSequenceCpuSpecificParams>,
virtual public LayerTestsUtils::LayerTestsCommon,
public CPUTestsBase {
virtual public ov::test::SubgraphBaseTest, public CPUTestsBase {
public:
static std::string getTestCaseName(const testing::TestParamInfo<GRUSequenceCpuSpecificParams> &obj) {
std::vector<InputShape> inputShapes;
ngraph::helpers::SequenceTestsMode seqMode;
std::vector<std::string> activations;
float clip;
bool linearBeforeRest;
ov::op::RecurrentSequenceDirection direction;
ElementType netPrecision;
CPUSpecificParams cpuParams;
LayerTestsDefinitions::GRUSequenceParams basicParamsSet;
std::map<std::string, std::string> 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<LayerTestsDefinitions::GRUSequenceParams>(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<InputShape> inputShapes;
ngraph::helpers::SequenceTestsMode seqMode;
std::vector<std::string> activations;
float clip;
bool linearBeforeReset;
ov::op::RecurrentSequenceDirection direction;
ElementType netPrecision;
CPUSpecificParams cpuParams;
std::map<std::string, std::string> additionalConfig;
size_t seq_lengths;
size_t batch;
size_t hidden_size;
size_t input_size = 10;
std::vector<std::string> activations;
std::vector<float> activations_alpha;
std::vector<float> 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<std::vector<size_t>> 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<ngraph::Shape> WRB = {inputShapes[3], inputShapes[4], inputShapes[5], inputShapes[2]};
auto gru_sequence = ngraph::builder::makeGRU(ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)),
std::vector<ov::Shape> 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<ngraph::opset1::Result>(gru_sequence->output(0)),
std::make_shared<ngraph::opset1::Result>(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<ngraph::pass::BidirectionalGRUSequenceDecomposition>();
manager.register_pass<ngraph::pass::ConvertGRUSequenceToTensorIterator>();
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<ov::Shape>& 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<ov::element_type_traits<ElementType::i64>::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<std::map<std::string, std::string>> 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<ngraph::helpers::SequenceTestsMode> mode{ngraph::helpers::SequenceTestsMode::PURE_SEQ};
// output values increase rapidly without clip, so use only seq_lengths = 2
std::vector<size_t> seq_lengths_zero_clip{2};
std::vector<size_t> batch{10};
std::vector<size_t> batch_size_one{1};
std::vector<size_t> hidden_size{1, 10};
std::vector<std::vector<std::string>> activations = {{"sigmoid", "tanh"}};
std::vector<bool> linear_before_reset = {true, false};
std::vector<bool> linearBeforeReset = {true, false};
std::vector<float> clip{0.f};
std::vector<ngraph::op::RecurrentSequenceDirection> direction = {ngraph::op::RecurrentSequenceDirection::FORWARD};
std::vector<ov::op::RecurrentSequenceDirection> direction = {ov::op::RecurrentSequenceDirection::FORWARD};
std::vector<InferenceEngine::Precision> netPrecisions = {InferenceEngine::Precision::FP32};
std::vector<ElementType> 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<std::vector<InputShape>> 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<std::vector<InputShape>>{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<std::string, std::string>{})),
GRUSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_static_BatchSizeOne, GRUSequenceCPUTest,
::testing::Combine(::testing::ValuesIn(std::vector<std::vector<InputShape>>{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<std::string, std::string>{})),
GRUSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(nightly_static_bf16, GRUSequenceCPUTest,
::testing::Combine(::testing::ValuesIn(std::vector<std::vector<InputShape>>{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<std::vector<InputShape>> 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<std::vector<InputShape>>{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<std::string, std::string>{})),
GRUSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_dynamic_BatchSizeOne, GRUSequenceCPUTest,
::testing::Combine(::testing::ValuesIn(std::vector<std::vector<InputShape>>{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<std::string, std::string>{})),
GRUSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(nightly_dynamic, GRUSequenceCPUTest,
::testing::Combine(::testing::ValuesIn(std::vector<std::vector<InputShape>>{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<std::string, std::string>{})),
GRUSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(nightly_dynamic_bf16, GRUSequenceCPUTest,
::testing::Combine(::testing::ValuesIn(std::vector<std::vector<InputShape>>{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

View File

@ -2,38 +2,62 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "ngraph/op/lstm_cell.hpp"
#include <shared_test_classes/single_layer/lstm_cell.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/lstm_cell_decomposition.hpp"
using namespace InferenceEngine;
using namespace CPUTestUtils;
using namespace ov::test;
namespace CPULayerTestsDefinitions {
using LSTMCellCpuSpecificParams = typename std::tuple<LayerTestsDefinitions::LSTMCellParams, CPUSpecificParams, std::map<std::string, std::string>>;
using LSTMCellCpuSpecificParams = typename std::tuple<
std::vector<InputShape>, // Shapes
bool, // using decompose to sub-ops transformation
std::vector<std::string>, // activations
float, // clip
ElementType, // Network precision
CPUSpecificParams, // CPU specific params
std::map<std::string, std::string> // Additional config
>;
class LSTMCellLayerCPUTest : public testing::WithParamInterface<LSTMCellCpuSpecificParams>,
virtual public LayerTestsUtils::LayerTestsCommon,
public CPUTestsBase {
virtual public ov::test::SubgraphBaseTest, public CPUTestsBase {
public:
static std::string getTestCaseName(const testing::TestParamInfo<LSTMCellCpuSpecificParams>& obj) {
std::vector<InputShape> inputShapes;
bool decompose;
std::vector<std::string> activations;
float clip = 0.f;
ElementType netPrecision;
CPUSpecificParams cpuParams;
LayerTestsDefinitions::LSTMCellParams basicParamsSet;
std::map<std::string, std::string> 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<LayerTestsDefinitions::LSTMCellParams>(
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<InputShape> inputShapes;
bool decompose;
std::vector<std::string> activations;
float clip = 0.f;
ElementType netPrecision;
CPUSpecificParams cpuParams;
std::map<std::string, std::string> additionalConfig;
abs_threshold = 0.05;
bool should_decompose;
size_t batch;
size_t hidden_size;
size_t input_size;
std::vector<std::string> activations;
std::vector<float> activations_alpha;
std::vector<float> 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<std::vector<size_t>> 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<ov::op::v0::Parameter>(params));
std::vector<ngraph::Shape> 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<ngraph::Shape> 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<ngraph::opset1::Result>(lstm_cell->output(0)),
std::make_shared<ngraph::opset1::Result>(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<std::map<std::string, std::string>> 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<bool> should_decompose{false};
std::vector<size_t> batch{5};
std::vector<size_t> hidden_size{1, 10};
std::vector<size_t> input_size{1, 30};
// oneDNN supports only sigmoid-tanh-tanh
std::vector<std::vector<std::string>> activations = {{"sigmoid", "tanh", "tanh"}};
// oneDNN supports only zero clip
std::vector<float> clip{0.f};
std::vector<InferenceEngine::Precision> netPrecisions = {InferenceEngine::Precision::FP32, InferenceEngine::Precision::BF16};
std::vector<ElementType> 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<std::vector<ov::test::InputShape>> 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<std::vector<ov::test::InputShape>> 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

View File

@ -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<LayerTestsDefinitions::LSTMSequenceParams, CPUSpecificParams, std::map<std::string, std::string>>;
using LSTMSequenceCpuSpecificParams = typename std::tuple<
std::vector<InputShape>, // Shapes
ngraph::helpers::SequenceTestsMode, // Pure Sequence or TensorIterator
std::vector<std::string>, // Activations
float, // Clip
ngraph::op::RecurrentSequenceDirection, // Direction
ElementType, // Network precision
CPUSpecificParams, // CPU specific params
std::map<std::string, std::string> // Additional config
>;
class LSTMSequenceCPUTest : public testing::WithParamInterface<LSTMSequenceCpuSpecificParams>,
virtual public LayerTestsUtils::LayerTestsCommon,
public CPUTestsBase {
virtual public ov::test::SubgraphBaseTest, public CPUTestsBase {
public:
static std::string getTestCaseName(const testing::TestParamInfo<LSTMSequenceCpuSpecificParams> &obj) {
std::vector<InputShape> inputShapes;
ngraph::helpers::SequenceTestsMode seqMode;
std::vector<std::string> activations;
float clip;
ov::op::RecurrentSequenceDirection direction;
ElementType netPrecision;
CPUSpecificParams cpuParams;
LayerTestsDefinitions::LSTMSequenceParams basicParamsSet;
std::map<std::string, std::string> 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<LayerTestsDefinitions::LSTMSequenceParams>(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<InputShape> inputShapes;
ngraph::helpers::SequenceTestsMode seqMode;
std::vector<std::string> activations;
float clip;
ov::op::RecurrentSequenceDirection direction;
ElementType netPrecision;
CPUSpecificParams cpuParams;
std::map<std::string, std::string> additionalConfig;
size_t seq_lengths;
size_t batch;
size_t hidden_size;
size_t input_size;
std::vector<std::string> activations;
std::vector<float> activations_alpha;
std::vector<float> 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<std::vector<size_t>> 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<ngraph::Shape> WRB = {inputShapes[4], inputShapes[5], inputShapes[6], inputShapes[3]};
auto lstm_sequence = ngraph::builder::makeLSTM(ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)),
std::vector<ov::Shape> 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<ngraph::opset1::Result>(lstm_sequence->output(0)),
std::make_shared<ngraph::opset1::Result>(lstm_sequence->output(1)),
std::make_shared<ngraph::opset1::Result>(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<ngraph::pass::BidirectionalLSTMSequenceDecomposition>();
manager.register_pass<ngraph::pass::ConvertLSTMSequenceToTensorIterator>();
@ -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<ov::Shape>& 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<ov::element_type_traits<ElementType::i64>::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<std::map<std::string, std::string>> 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<ngraph::helpers::SequenceTestsMode> mode{ngraph::helpers::SequenceTestsMode::PURE_SEQ};
std::vector<size_t> seq_lengths_zero_clip{2};
std::vector<size_t> batch_size_one{1};
std::vector<size_t> batch{10};
std::vector<size_t> hidden_size{1, 10};
std::vector<size_t> input_size{10};
// oneDNN supports only sigmoid-tanh-tanh
std::vector<std::vector<std::string>> activations = {{"sigmoid", "tanh", "tanh"}};
// oneDNN supports only zero clip
std::vector<float> clip{0.f};
std::vector<ngraph::op::RecurrentSequenceDirection> direction = {ngraph::op::RecurrentSequenceDirection::FORWARD};
std::vector<InferenceEngine::Precision> netPrecisions = {InferenceEngine::Precision::FP32};
std::vector<ov::op::RecurrentSequenceDirection> 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<ElementType> 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<std::vector<InputShape>> 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<std::vector<InputShape>>{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<std::string, std::string>{})),
LSTMSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_static_BatchSizeOne, LSTMSequenceCPUTest,
::testing::Combine(::testing::ValuesIn(std::vector<std::vector<InputShape>>{staticShapes[3]}),
::testing::ValuesIn(mode),
::testing::ValuesIn(activations),
::testing::ValuesIn(clip),
::testing::ValuesIn(direction),
::testing::ValuesIn(netPrecisions),
::testing::Values(cpuParamsBatchSizeOne),
::testing::Values(std::map<std::string, std::string>{})),
LSTMSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(nightly_static_bf16, LSTMSequenceCPUTest,
::testing::Combine(::testing::ValuesIn(std::vector<std::vector<InputShape>>{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<std::vector<InputShape>> 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<std::vector<InputShape>>{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<std::string, std::string>{})),
LSTMSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_dynamic_BatchSizeOne, LSTMSequenceCPUTest,
::testing::Combine(::testing::ValuesIn(std::vector<std::vector<InputShape>>{dynamicShapes[4]}),
::testing::ValuesIn(mode),
::testing::ValuesIn(activations),
::testing::ValuesIn(clip),
::testing::ValuesIn(direction),
::testing::ValuesIn(netPrecisions),
::testing::Values(cpuParamsBatchSizeOne),
::testing::Values(std::map<std::string, std::string>{})),
LSTMSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(nightly_dynamic, LSTMSequenceCPUTest,
::testing::Combine(::testing::ValuesIn(std::vector<std::vector<InputShape>>{dynamicShapes[5]}),
::testing::ValuesIn(mode),
::testing::ValuesIn(activations),
::testing::ValuesIn(clip),
::testing::ValuesIn(direction),
::testing::ValuesIn(netPrecisions),
::testing::Values(cpuParams),
::testing::Values(std::map<std::string, std::string>{})),
LSTMSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(nightly_dynamic_bf16, LSTMSequenceCPUTest,
::testing::Combine(::testing::ValuesIn(std::vector<std::vector<InputShape>>{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

View File

@ -2,37 +2,59 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "ngraph/op/rnn_cell.hpp"
#include <shared_test_classes/single_layer/rnn_cell.hpp>
#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<LayerTestsDefinitions::RNNCellParams, CPUSpecificParams, std::map<std::string, std::string>>;
using RNNCellCPUParams = typename std::tuple<
std::vector<InputShape>, // Shapes
std::vector<std::string>, // Activations
float, // Clip
ElementType, // Network precision
CPUSpecificParams, // CPU specific params
std::map<std::string, std::string> // Additional config
>;
class RNNCellCPUTest : public testing::WithParamInterface<RNNCellCpuSpecificParams>,
virtual public LayerTestsUtils::LayerTestsCommon,
public CPUTestsBase {
class RNNCellCPUTest : public testing::WithParamInterface<RNNCellCPUParams>,
virtual public ov::test::SubgraphBaseTest, public CPUTestsBase {
public:
static std::string getTestCaseName(const testing::TestParamInfo<RNNCellCpuSpecificParams> &obj) {
static std::string getTestCaseName(const testing::TestParamInfo<RNNCellCPUParams> &obj) {
std::vector<InputShape> inputShapes;
std::vector<std::string> activations;
float clip = 0.f;
ElementType netPrecision;
CPUSpecificParams cpuParams;
LayerTestsDefinitions::RNNCellParams basicParamsSet;
std::map<std::string, std::string> 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<LayerTestsDefinitions::RNNCellParams>(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<InputShape> inputShapes;
std::vector<std::string> activations;
float clip = 0.f;
ElementType netPrecision;
CPUSpecificParams cpuParams;
LayerTestsDefinitions::RNNCellParams basicParamsSet;
std::map<std::string, std::string> additionalConfig;
bool should_decompose;
size_t batch;
size_t hidden_size;
size_t input_size;
std::vector<std::string> activations;
std::vector<float> activations_alpha;
std::vector<float> 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<std::vector<size_t>> 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<ov::op::v0::Parameter>(params));
std::vector<ov::Shape> 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<ngraph::Shape> 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<ngraph::opset1::Result>(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<std::map<std::string, std::string>> additionalConfig
= {{{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::NO}}, {{PluginConfigParams::KEY_ENFORCE_BF16, PluginConfigParams::YES}}};
std::vector<std::map<std::string, std::string>> 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<bool> should_decompose{false};
std::vector<size_t> batch{1, 5};
std::vector<size_t> hidden_size{1, 10};
std::vector<size_t> input_size{1, 30};
std::vector<std::vector<std::string>> activations = {{"relu"}, {"sigmoid"}, {"tanh"}};
// oneDNN supports only zero clip
std::vector<float> clip = {0.f};
std::vector<InferenceEngine::Precision> netPrecisions = {InferenceEngine::Precision::FP32};
std::vector<ElementType> 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<std::vector<ov::test::InputShape>> 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<std::vector<ov::test::InputShape>> 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

View File

@ -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<LayerTestsDefinitions::RNNSequenceParams, CPUSpecificParams, std::map<std::string, std::string>>;
using RNNSequenceCpuSpecificParams = typename std::tuple<
std::vector<InputShape>, // Shapes
ngraph::helpers::SequenceTestsMode, // Pure Sequence or TensorIterator
std::vector<std::string>, // Activations
float, // Clip
ov::op::RecurrentSequenceDirection, // Direction
ElementType, // Network precision
CPUSpecificParams, // CPU specific params
std::map<std::string, std::string> // Additional config
>;
class RNNSequenceCPUTest : public testing::WithParamInterface<RNNSequenceCpuSpecificParams>,
virtual public LayerTestsUtils::LayerTestsCommon,
public CPUTestsBase {
virtual public SubgraphBaseTest, public CPUTestsBase {
public:
static std::string getTestCaseName(const testing::TestParamInfo<RNNSequenceCpuSpecificParams> &obj) {
std::vector<InputShape> inputShapes;
ngraph::helpers::SequenceTestsMode seqMode;
std::vector<std::string> activations;
float clip;
ov::op::RecurrentSequenceDirection direction;
ElementType netPrecision;
CPUSpecificParams cpuParams;
LayerTestsDefinitions::RNNSequenceParams basicParamsSet;
std::map<std::string, std::string> 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<LayerTestsDefinitions::RNNSequenceParams>(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<InputShape> inputShapes;
ngraph::helpers::SequenceTestsMode seqMode;
std::vector<std::string> activations;
float clip;
ov::op::RecurrentSequenceDirection direction;
ElementType netPrecision;
CPUSpecificParams cpuParams;
std::map<std::string, std::string> additionalConfig;
size_t seq_lengths;
size_t batch;
size_t hidden_size;
size_t input_size;
std::vector<std::string> activations;
std::vector<float> activations_alpha;
std::vector<float> 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<std::vector<size_t>> 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<ngraph::Shape> WRB = {inputShapes[3], inputShapes[4], inputShapes[5], inputShapes[2]};
std::vector<ov::Shape> 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<ngraph::opset1::Result>(rnn_sequence->output(0)),
std::make_shared<ngraph::opset1::Result>(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<ngraph::pass::BidirectionalRNNSequenceDecomposition>();
manager.register_pass<ngraph::pass::ConvertRNNSequenceToTensorIterator>();
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<ov::Shape>& 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<ov::element_type_traits<ElementType::i64>::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<std::map<std::string, std::string>> 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<ngraph::helpers::SequenceTestsMode> mode{ngraph::helpers::SequenceTestsMode::PURE_SEQ};
// output values increase rapidly without clip, so use only seq_lengths = 2
std::vector<size_t> seq_lengths_zero_clip{2};
std::vector<size_t> batch{10};
std::vector<size_t> batch_size_one{1};
std::vector<size_t> hidden_size{10};
// std::vector<size_t> hidden_size{1, 10};
std::vector<size_t> input_size{10};
std::vector<size_t> seq_lengths_zero_clip{ 2 };
std::vector<std::vector<std::string>> activations = {{"relu"}, {"sigmoid"}, {"tanh"}};
// oneDNN supports only zero clip
std::vector<float> clip{0.f};
std::vector<ngraph::op::RecurrentSequenceDirection> direction{ngraph::op::RecurrentSequenceDirection::FORWARD};
std::vector<ov::op::RecurrentSequenceDirection> direction{ov::op::RecurrentSequenceDirection::FORWARD};
std::vector<InferenceEngine::Precision> netPrecisions = {InferenceEngine::Precision::FP32};
std::vector<ElementType> 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<std::vector<InputShape>> 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<std::vector<InputShape>>{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<std::string, std::string>{})),
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<std::string, std::string>{})),
RNNSequenceCPUTest::getTestCaseName);
const std::vector<std::vector<InputShape>> 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<std::vector<InputShape>>{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<std::string, std::string>{})),
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<std::string, std::string>{})),
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<std::string, std::string>{})),
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

View File

@ -10,8 +10,8 @@
namespace ngraph {
namespace builder {
std::shared_ptr<ngraph::Node> makeGRU(const OutputVector& in,
const std::vector<ngraph::Shape>& constants,
std::shared_ptr<ov::Node> makeGRU(const OutputVector& in,
const std::vector<ov::Shape>& constants,
std::size_t hidden_size,
const std::vector<std::string>& activations,
const std::vector<float>& activations_alpha,
@ -19,46 +19,51 @@ std::shared_ptr<ngraph::Node> 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<float> 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<ngraph::opset4::GRUCell>(in[0], in[1], W, R, B, hidden_size, activations,
return std::make_shared<ov::op::v3::GRUCell>(in[0], in[1], W, R, B, hidden_size, activations,
activations_alpha, activations_beta, clip,
linear_before_reset);
} else {
std::shared_ptr<Node> seq_lengths;
switch (mode) {
case ngraph::helpers::SequenceTestsMode::PURE_SEQ:
case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: {
std::vector<float> 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<float> lengths;
seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true,
static_cast<float>(in[0].get_shape()[1]), 0.f);
if (in.size() > 2 && in[2].get_partial_shape().is_dynamic()) {
return std::make_shared<ov::op::v5::GRUSequence>(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<Node> seq_lengths;
switch (mode) {
case ngraph::helpers::SequenceTestsMode::PURE_SEQ:
case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: {
std::vector<float> 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<float> lengths;
seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true,
static_cast<float>(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<ov::op::v5::GRUSequence>(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<ngraph::opset5::GRUSequence>(in[0], in[1], seq_lengths, W, R, B, hidden_size, direction,
activations, activations_alpha, activations_beta, clip, linear_before_reset);
}
}
} // namespace builder

View File

@ -10,53 +10,58 @@
namespace ngraph {
namespace builder {
std::shared_ptr<ngraph::Node> makeLSTM(const std::vector<ngraph::Output<Node>>& in,
const std::vector<ngraph::Shape>& constants,
std::shared_ptr<ov::Node> makeLSTM(const std::vector<ov::Output<Node>>& in,
const std::vector<ov::Shape>& constants,
std::size_t hidden_size,
const std::vector<std::string>& activations,
const std::vector<float>& activations_alpha,
const std::vector<float>& activations_beta,
float clip,
bool make_sequence,
ngraph::op::RecurrentSequenceDirection direction,
ov::op::RecurrentSequenceDirection direction,
ngraph::helpers::SequenceTestsMode mode) {
std::vector<float> 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<ngraph::opset4::LSTMCell>(in[0], in[1], in[2], W, R, B, hidden_size, activations,
return std::make_shared<ov::op::v4::LSTMCell>(in[0], in[1], in[2], W, R, B, hidden_size, activations,
activations_alpha, activations_beta, clip);
} else {
std::shared_ptr<Node> seq_lengths;
switch (mode) {
case ngraph::helpers::SequenceTestsMode::PURE_SEQ:
case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: {
std::vector<float> 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<float> lengths;
seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true,
static_cast<float>(in[0].get_shape()[1]), 0.f);
if (in.size() > 3 && in[3].get_partial_shape().is_dynamic()) {
return std::make_shared<ov::op::v5::LSTMSequence>(in[0], in[1], in[2], in[3], W, R, B, hidden_size, direction,
activations_alpha, activations_beta, activations, clip);
} else {
std::shared_ptr<Node> seq_lengths;
switch (mode) {
case ngraph::helpers::SequenceTestsMode::PURE_SEQ:
case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: {
std::vector<float> 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<float> lengths;
seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true,
static_cast<float>(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<ov::op::v5::LSTMSequence>(in[0], in[1], in[2], seq_lengths, W, R, B, hidden_size, direction,
activations_alpha, activations_beta, activations, clip);
}
return std::make_shared<ngraph::opset5::LSTMSequence>(in[0], in[1], in[2], seq_lengths, W, R, B, hidden_size, direction,
activations_alpha, activations_beta, activations, clip);
}
}
} // namespace builder

View File

@ -10,53 +10,58 @@
namespace ngraph {
namespace builder {
std::shared_ptr<ngraph::Node> makeRNN(const OutputVector& in,
const std::vector<ngraph::Shape>& constants,
std::shared_ptr<ov::Node> makeRNN(const OutputVector& in,
const std::vector<ov::Shape>& constants,
std::size_t hidden_size,
const std::vector<std::string>& activations,
const std::vector<float>& activations_alpha,
const std::vector<float>& activations_beta,
float clip,
bool make_sequence,
ngraph::op::RecurrentSequenceDirection direction,
ov::op::RecurrentSequenceDirection direction,
ngraph::helpers::SequenceTestsMode mode) {
std::vector<float> 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<ngraph::opset4::RNNCell>(in[0], in[1], W, R, B, hidden_size, activations,
return std::make_shared<ov::op::v0::RNNCell>(in[0], in[1], W, R, B, hidden_size, activations,
activations_alpha, activations_beta, clip);
} else {
std::shared_ptr<Node> seq_lengths;
switch (mode) {
case ngraph::helpers::SequenceTestsMode::PURE_SEQ:
case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: {
std::vector<float> 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<float> lengths;
seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true,
static_cast<float>(in[0].get_shape()[1]), 0.f);
if (in.size() > 2 && in[2].get_partial_shape().is_dynamic()) {
return std::make_shared<ov::op::v5::RNNSequence>(in[0], in[1], in[2], W, R, B, hidden_size, direction,
activations, activations_alpha, activations_beta, clip);
} else {
std::shared_ptr<Node> seq_lengths;
switch (mode) {
case ngraph::helpers::SequenceTestsMode::PURE_SEQ:
case ngraph::helpers::SequenceTestsMode::CONVERT_TO_TI_MAX_SEQ_LEN_CONST: {
std::vector<float> 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<float> lengths;
seq_lengths = ngraph::builder::makeConstant(element::i64, constants[3], lengths, true,
static_cast<float>(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<ov::op::v5::RNNSequence>(in[0], in[1], seq_lengths, W, R, B, hidden_size, direction,
activations, activations_alpha, activations_beta, clip);
}
return std::make_shared<ngraph::opset5::RNNSequence>(in[0], in[1], seq_lengths, W, R, B, hidden_size, direction,
activations, activations_alpha, activations_beta, clip);
}
}
} // namespace builder