[CPU] add support for internal ops augrucell and augrusequence (#12647)

* [cpu] enable augru.

* initiate opset_private_tbl.hpp for private ops.

* fix ngraph_functions target_linker.

* temporaliy disable a failure test.
This commit is contained in:
cecilia peng authored and GitHub committed 2022-11-09 05:58:04 +03:00
1 parent 4d1de75b24
commit 3bdb9cae54
16 files changed
+918 -13

No files matched your search

@@ -0,0 +1,11 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#ifndef _OPENVINO_OP_REG
# warning "_OPENVINO_OP_REG not defined"
# define _OPENVINO_OP_REG(x, y)
#endif
_OPENVINO_OP_REG(AUGRUCell, ov::op::internal)
_OPENVINO_OP_REG(AUGRUSequence, ov::op::internal)
+2
View File
@@ -94,9 +94,11 @@ const InferenceEngine::details::caseless_unordered_map<std::string, Type> type_t
{ "Transpose", Type::Transpose },
{ "LSTMCell", Type::RNNCell },
{ "GRUCell", Type::RNNCell },
{ "AUGRUCell", Type::RNNCell },
{ "RNNCell", Type::RNNCell },
{ "LSTMSequence", Type::RNNSeq },
{ "GRUSequence", Type::RNNSeq },
{ "AUGRUSequence", Type::RNNSeq },
{ "RNNSequence", Type::RNNSeq },
{ "FakeQuantize", Type::FakeQuantize },
{ "BinaryConvolution", Type::BinaryConvolution },
@@ -169,6 +169,30 @@ DnnlDesriptor::operator std::shared_ptr<dnnl::lbr_gru_forward::desc>() {
return typeDesc->getPtr();
}
DnnlDesriptor::DnnlDesriptor(std::shared_ptr<dnnl::augru_forward::desc> desc) {
this->desc.reset(new DescFwdImpl<dnnl::augru_forward::desc>(desc));
}
DnnlDesriptor::operator std::shared_ptr<dnnl::augru_forward::desc>() {
auto typeDesc = std::dynamic_pointer_cast<DescFwdImpl<dnnl::augru_forward::desc>>(desc);
if (typeDesc == nullptr) {
IE_THROW() << "Cannot cast descriptor!";
}
return typeDesc->getPtr();
}
DnnlDesriptor::DnnlDesriptor(std::shared_ptr<dnnl::lbr_augru_forward::desc> desc) {
this->desc.reset(new DescFwdImpl<dnnl::lbr_augru_forward::desc>(desc));
}
DnnlDesriptor::operator std::shared_ptr<dnnl::lbr_augru_forward::desc>() {
auto typeDesc = std::dynamic_pointer_cast<DescFwdImpl<dnnl::lbr_augru_forward::desc>>(desc);
if (typeDesc == nullptr) {
IE_THROW() << "Cannot cast descriptor!";
}
return typeDesc->getPtr();
}
DnnlDesriptor::DnnlDesriptor(std::shared_ptr<dnnl::eltwise_forward::desc> desc) {
this->desc.reset(new DescFwdImpl<dnnl::eltwise_forward::desc>(desc));
}
@@ -49,6 +49,12 @@ public:
explicit DnnlDesriptor(std::shared_ptr<dnnl::lbr_gru_forward::desc> desc);
operator std::shared_ptr<dnnl::lbr_gru_forward::desc>();
explicit DnnlDesriptor(std::shared_ptr<dnnl::augru_forward::desc> desc);
operator std::shared_ptr<dnnl::augru_forward::desc>();
explicit DnnlDesriptor(std::shared_ptr<dnnl::lbr_augru_forward::desc> desc);
operator std::shared_ptr<dnnl::lbr_augru_forward::desc>();
explicit DnnlDesriptor(std::shared_ptr<dnnl::eltwise_forward::desc> desc);
operator std::shared_ptr<dnnl::eltwise_forward::desc>();
+118 -11
View File
@@ -12,6 +12,9 @@
#include "memory_desc/dnnl_blocked_memory_desc.h"
#include <common/primitive_hashing_utils.hpp>
#include "ngraph_ops/augru_cell.hpp"
#include "ngraph_ops/augru_sequence.hpp"
#include <ngraph/node.hpp>
#include <string>
@@ -61,6 +64,16 @@ static dnnl::algorithm ie2dnnl(const std::shared_ptr<const ov::Node>& op) {
return dnnl::algorithm::lbr_gru;
else
return dnnl::algorithm::vanilla_gru;
} else if (one_of(op->get_type_info(),
ov::op::internal::AUGRUCell::get_type_info_static(),
ov::op::internal::AUGRUSequence::get_type_info_static())) {
auto gruCellOp = ov::as_type_ptr<const ov::op::internal::AUGRUCell>(op);
auto gruSeqOp = ov::as_type_ptr<const ov::op::internal::AUGRUSequence>(op);
if ((gruCellOp && gruCellOp->get_linear_before_reset()) ||
(gruSeqOp && gruSeqOp->get_linear_before_reset()))
return dnnl::algorithm::lbr_augru;
else
return dnnl::algorithm::vanilla_augru;
} else if (one_of(op->get_type_info(),
ov::op::v0::LSTMCell::get_type_info_static(),
ov::op::v4::LSTMCell::get_type_info_static(),
@@ -80,6 +93,8 @@ inline size_t gatesCount(const algorithm& alg) {
switch (alg) {
case algorithm::vanilla_rnn: return 1;
case algorithm::vanilla_gru:
case algorithm::vanilla_augru:
case algorithm::lbr_augru:
case algorithm::lbr_gru: return 3;
case algorithm::vanilla_lstm: return 4;
default:
@@ -92,6 +107,8 @@ inline size_t statesCount(const dnnl::algorithm& alg) {
switch (alg) {
case dnnl::algorithm::vanilla_rnn:
case dnnl::algorithm::vanilla_gru:
case dnnl::algorithm::vanilla_augru:
case dnnl::algorithm::lbr_augru:
case dnnl::algorithm::lbr_gru: return 1;
case dnnl::algorithm::vanilla_lstm: return 2;
default:
@@ -103,6 +120,9 @@ inline size_t statesCount(const dnnl::algorithm& alg) {
inline bool haveCellState(const dnnl::algorithm& alg) {
return alg == dnnl::algorithm::vanilla_lstm;
}
inline bool haveAttention(const dnnl::algorithm& alg) {
return alg == dnnl::algorithm::vanilla_augru || alg == dnnl::algorithm::lbr_augru;
}
const std::map<Precision, Precision> RNN::weightsByLayerPrec {
// layer precision, weights precision
@@ -177,6 +197,8 @@ bool RNN::isSupportedOperation(const std::shared_ptr<const ov::Node>& op, std::s
try {
if (!one_of(op->get_type_info(),
ov::op::v3::GRUCell::get_type_info_static(),
ov::op::internal::AUGRUCell::get_type_info_static(),
ov::op::internal::AUGRUSequence::get_type_info_static(),
ov::op::v0::LSTMCell::get_type_info_static(),
ov::op::v4::LSTMCell::get_type_info_static(),
ov::op::v0::RNNCell::get_type_info_static(),
@@ -257,21 +279,28 @@ RNN::RNN(const std::shared_ptr<ov::Node>& op, const dnnl::engine& eng, WeightsSh
IE_THROW(NotImplemented) << errorMessage;
}
is_augru = one_of(op->get_type_info(),
ov::op::internal::AUGRUCell::get_type_info_static(),
ov::op::internal::AUGRUSequence::get_type_info_static());
is_cell = one_of(op->get_type_info(),
ov::op::v0::RNNCell::get_type_info_static(),
ov::op::v3::GRUCell::get_type_info_static(),
ov::op::internal::AUGRUCell::get_type_info_static(),
ov::op::v0::LSTMCell::get_type_info_static(),
ov::op::v4::LSTMCell::get_type_info_static());
if (one_of(op->get_type_info(),
ov::op::v0::RNNCell::get_type_info_static(),
ov::op::v3::GRUCell::get_type_info_static())) {
ov::op::v3::GRUCell::get_type_info_static(),
ov::op::internal::AUGRUCell::get_type_info_static())) {
wIdx = 2; rIdx = 3; bIdx = 4;
} else if (one_of(op->get_type_info(),
ov::op::v5::RNNSequence::get_type_info_static(),
ov::op::v0::LSTMCell::get_type_info_static(),
ov::op::v4::LSTMCell::get_type_info_static(),
ov::op::v5::GRUSequence::get_type_info_static())) {
ov::op::v5::GRUSequence::get_type_info_static(),
ov::op::internal::AUGRUSequence::get_type_info_static())) {
wIdx = 3; rIdx = 4; bIdx = 5;
} else if (one_of(op->get_type_info(),
ov::op::v0::LSTMSequence::get_type_info_static(),
@@ -323,6 +352,8 @@ void RNN::initCell() {
if (getInputShapeAtPort(0).getRank() != 2lu || getInputShapeAtPort(1).getRank() != 2lu)
THROW_ERROR << "has incorrect input ranks. Data rank: " << getInputShapeAtPort(0).getRank() <<
"; Hidden state rank: " << getInputShapeAtPort(1).getRank();
if (is_augru && getInputShapeAtPort(5).getRank() != 2lu)
THROW_ERROR << "has incorrect input ranks. Attention rank: " << getInputShapeAtPort(2).getRank();
T = {1, 1};
if (cell_type == algorithm::vanilla_lstm)
@@ -345,6 +376,13 @@ void RNN::initCell() {
THROW_ERROR << "has incorrect input/output shapes. Cell state input: " << getInputShapeAtPort(2).toString() <<
"; Cell state output: " << getOutputShapeAtPort(1).toString();
}
if (is_augru) {
const Shape shapeA{{N.minVal, 1}, {N.maxVal, 1}};
if (getInputShapeAtPort(5).isStatic() && getInputShapeAtPort(5) != shapeA) {
THROW_ERROR << "has incorrect input shapes. Attention shape: " << getInputShapeAtPort(5).toString();
}
}
}
void RNN::fillCellDesc() {
@@ -354,7 +392,11 @@ void RNN::fillCellDesc() {
outShape = MemoryDescUtils::makeDummyShape({{T.minVal, N.minVal, SC}, {T.maxVal, N.maxVal, SC}});
// layer input plus states
inDataDescs.reserve(S + 1);
if (haveAttention(cell_type)) {
inDataDescs.reserve(S + 2);
} else {
inDataDescs.reserve(S + 1);
}
outDataDescs.reserve(S + 1);
inDataDescs.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(inShape, dataType, memory::format_tag::tnc));
@@ -368,6 +410,11 @@ void RNN::fillCellDesc() {
outDataDescs.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(shapeS_4D, memory::data_type::f32, memory::format_tag::ldnc));
}
if (haveAttention(cell_type)) {
const Shape attnShape = MemoryDescUtils::makeDummyShape({{T.minVal, N.minVal, 1}, {T.maxVal, N.maxVal, 1}});
inDataDescs.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(attnShape, dataType, memory::format_tag::tnc));
}
copyWeightsData();
// Expected shapes.
@@ -384,10 +431,15 @@ void RNN::fillCellDesc() {
inCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(shapeS, memory::data_type::f32, memory::format_tag::nc));
outCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(shapeS, memory::data_type::f32, memory::format_tag::nc));
}
if (one_of(cell_type, dnnl::algorithm::vanilla_rnn, dnnl::algorithm::vanilla_gru, dnnl::algorithm::lbr_gru, dnnl::algorithm::vanilla_lstm)) {
inCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(WShape, memory::data_type::f32, memory::format_tag::nc));
inCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(RShape, memory::data_type::f32, memory::format_tag::nc));
inCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(BShape, memory::data_type::f32, memory::format_tag::x));
inCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(WShape, memory::data_type::f32, memory::format_tag::nc));
inCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(RShape, memory::data_type::f32, memory::format_tag::nc));
inCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(BShape, memory::data_type::f32, memory::format_tag::x));
// note: the order matters. attention is the last input of augru.
if (haveAttention(cell_type)) {
Shape shapeAttn{{N.minVal, 1}, {N.maxVal, 1}};
inCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(shapeAttn, dataType, memory::format_tag::nc));
}
createDescriptor(inCandidate, outCandidate);
@@ -413,7 +465,11 @@ void RNN::initSequence() {
DC = getInputShapeAtPort(3).getDims()[2];
// layer input plus states
inDataDescs.reserve(S + 1);
if (haveAttention(cell_type)) {
inDataDescs.reserve(S + 2);
} else {
inDataDescs.reserve(S + 1);
}
outDataDescs.reserve(S + 1);
}
@@ -437,6 +493,10 @@ void RNN::fillSequenceDesc() {
inDataDescs.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(shapeS_4D, memory::data_type::f32, memory::format_tag::ldnc));
outDataDescs.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(shapeS_4D, memory::data_type::f32, memory::format_tag::ldnc));
}
if (haveAttention(cell_type)) {
const Shape attnShape = MemoryDescUtils::makeDummyShape({{T.minVal, N.minVal, 1}, {T.maxVal, N.maxVal, 1}});
inDataDescs.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(attnShape, dataType, memory::format_tag::tnc));
}
copyWeightsData();
@@ -472,6 +532,12 @@ void RNN::fillSequenceDesc() {
inCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(Shape{D, G * SC, SC}, memory::data_type::f32, memory::format_tag::ntc)); // R
inCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(Shape{D, Gb * SC}, memory::data_type::f32, memory::format_tag::nc)); // B
// note: the order matters. attention is the last input of augru.
if (haveAttention(cell_type)) {
Shape shapeAttn{{N.minVal, T.minVal, 1}, {N.maxVal, T.maxVal, 1}};
inCandidate.emplace_back(std::make_shared<DnnlBlockedMemoryDesc>(shapeAttn, dataType, memory::format_tag::ntc));
}
std::vector<MemoryDescPtr> outCandidate;
outCandidate.reserve(3);
@@ -637,12 +703,12 @@ void RNN::copyWeightsData() {
if (G > gate_map_lstm_size) {
THROW_ERROR << ". G isn't equal to the size of gate_map.";
}
} else if (cell_type == dnnl::algorithm::vanilla_gru) {
} else if (cell_type == dnnl::algorithm::vanilla_gru || cell_type == dnnl::algorithm::vanilla_augru) {
gate_map = gate_map_gru;
if (G > gate_map_gru_size) {
THROW_ERROR << ". G isn't equal to the size of gate_map";
}
} else if (cell_type == dnnl::algorithm::lbr_gru) {
} else if (cell_type == dnnl::algorithm::lbr_gru || cell_type == dnnl::algorithm::lbr_augru) {
gate_map = gate_map_gru;
if (G > gate_map_gru_size) {
THROW_ERROR << ". G isn't equal to the size of gate_map.";
@@ -734,6 +800,34 @@ void RNN::fillDescs() {
/* Out State C */ outDataDescs[RNNInOutKind::CellState]->getDnnlDesc()));
descs.push_back(desc);
} break;
case dnnl::algorithm::vanilla_augru: {
DnnlDesriptor desc(std::make_shared<augru_forward::desc>(
prop_kind::forward_scoring,
direction,
/* In Data */ inDataDescs[RNNInOutKind::Layer]->getDnnlDesc(),
/* In State */ inDataDescs[RNNInOutKind::HiddenState]->getDnnlDesc(),
/* In Attention */ inDataDescs[RNNInOutKind::Attention]->getDnnlDesc(),
/* Weights data */ wDescs[0],
/* Weights state */ wDescs[1],
/* Bias */ wDescs[2],
/* Out Data */ outDataDescs[RNNInOutKind::Layer]->getDnnlDesc(),
/* Out State */ outDataDescs[RNNInOutKind::HiddenState]->getDnnlDesc()));
descs.push_back(desc);
} break;
case dnnl::algorithm::lbr_augru: {
DnnlDesriptor desc(std::make_shared<lbr_augru_forward::desc>(
prop_kind::forward_scoring,
direction,
/* In Data */ inDataDescs[RNNInOutKind::Layer]->getDnnlDesc(),
/* In State */ inDataDescs[RNNInOutKind::HiddenState]->getDnnlDesc(),
/* In Attention */ inDataDescs[RNNInOutKind::Attention]->getDnnlDesc(),
/* Weights data */ wDescs[0],
/* Weights state */ wDescs[1],
/* Bias */ wDescs[2],
/* Out Data */ outDataDescs[RNNInOutKind::Layer]->getDnnlDesc(),
/* Out State */ outDataDescs[RNNInOutKind::HiddenState]->getDnnlDesc()));
descs.push_back(desc);
} break;
default:
THROW_ERROR << "has unknown cell type.";
}
@@ -803,9 +897,12 @@ void RNN::prepareParams() {
outDataDescs[2] = std::make_shared<DnnlBlockedMemoryDesc>(shapeS_4D, memory::data_type::f32, memory::format_tag::ldnc);
}
if (haveAttention(cell_type)) {
inDataDescs[2] = std::make_shared<DnnlBlockedMemoryDesc>(Shape{SL, B, 1}, dataType, memory::format_tag::tnc);
}
bool wFormatWasChanged = false;
// WA To avoid different weights layer and iter formats in FP32 case.
if (SL != 1 || B < optimalBatchSize) {
if ((dataPrecision == Precision::FP32) && (SL != 1 || B < optimalBatchSize)) {
if (wFormat != dnnl::memory::format_tag::ldigo) {
wFormat = dnnl::memory::format_tag::ldigo;
wFormatWasChanged = true;
@@ -840,6 +937,12 @@ void RNN::prepareParams() {
} else if (key.cellType == dnnl::algorithm::vanilla_lstm) {
std::shared_ptr<lstm_forward::desc> desc = descs[0];
return std::make_shared<lstm_forward>(lstm_forward::primitive_desc(*desc, attr, getEngine()));
} else if (key.cellType == dnnl::algorithm::vanilla_augru) {
std::shared_ptr<augru_forward::desc> desc = descs[0];
return std::make_shared<augru_forward>(augru_forward::primitive_desc(*desc, attr, getEngine()));
} else if (key.cellType == dnnl::algorithm::lbr_augru) {
std::shared_ptr<lbr_augru_forward::desc> desc = descs[0];
return std::make_shared<lbr_augru_forward>(lbr_augru_forward::primitive_desc(*desc, attr, getEngine()));
} else {
return nullptr;
}
@@ -909,6 +1012,10 @@ void RNN::execute(dnnl::stream strm) {
for (size_t s = 0; s < S; s++) {
args[state_i_tags[s]] = getParentEdgeAt(s+1)->getMemoryPtr()->GetPrimitive();
}
if (is_augru) {
const auto atten_port = is_cell ? 5 : 6;
args[DNNL_ARG_AUGRU_ATTENTION] = getParentEdgeAt(atten_port)->getMemoryPtr()->GetPrimitive();
}
if (is_cell) {
for (size_t s = 0; s < S; s++) {
+4 -1
View File
@@ -59,6 +59,8 @@ private:
/** Specify mode Cell or Seq. true - Cell, false - Seq */
bool is_cell = false;
bool is_augru = false;
/** Native order if [batch, seq, data], other case is [seq, batch, data] */
bool nativeOrder = true;
@@ -107,7 +109,8 @@ private:
enum RNNInOutKind {
Layer = 0,
HiddenState = 1,
CellState = 2
CellState = 2,
Attention = 2
};
size_t wIdx = 0;
+13
View File
@@ -101,6 +101,9 @@
#include <ngraph/pass/manager.hpp>
#include <ngraph/graph_util.hpp>
#include "ngraph_ops/augru_cell.hpp"
#include "ngraph_ops/augru_sequence.hpp"
#include <transformations/common_optimizations/lin_op_sequence_fusion.hpp>
#include <transformations/low_precision/disable_convert_constant_folding_on_const_path.hpp>
@@ -355,6 +358,10 @@ static void TransformationUpToCPUSpecificOpSet(std::shared_ptr<ngraph::Function>
node)) {
return gru_cell->get_clip() == 0.0f
&& gru_cell->get_activations() == std::vector<std::string>{"sigmoid", "tanh"};
} else if (const auto &augru_cell = std::dynamic_pointer_cast<const ov::op::internal::AUGRUCell>(
node)) {
return augru_cell->get_clip() == 0.0f
&& augru_cell->get_activations() == std::vector<std::string>{"sigmoid", "tanh"};
} else if (const auto &lstm_cell = std::dynamic_pointer_cast<const ngraph::opset4::LSTMCell>(
node)) {
return lstm_cell->get_clip() == 0.0f &&
@@ -391,6 +398,12 @@ static void TransformationUpToCPUSpecificOpSet(std::shared_ptr<ngraph::Function>
gru_seq->get_activations() == std::vector<std::string>{"sigmoid", "tanh"} &&
!ngraph::op::util::is_seq_len_provided(gru_seq->get_input_node_shared_ptr(2),
max_seq_len);
} else if (const auto &augru_seq = std::dynamic_pointer_cast<const ov::op::internal::AUGRUSequence>(
node)) {
return augru_seq->get_clip() == 0.0f &&
augru_seq->get_activations() == std::vector<std::string>{"sigmoid", "tanh"} &&
!ngraph::op::util::is_seq_len_provided(augru_seq->get_input_node_shared_ptr(2),
max_seq_len);
} else if (const auto &lstm_seq = std::dynamic_pointer_cast<const ngraph::opset6::LSTMSequence>(
node)) {
return lstm_seq->get_clip() == 0.0f &&
@@ -164,6 +164,9 @@ std::vector<std::string> disabledTestPatterns() {
// is shared across plugins
// passed local test and cpu has specific test cases with nms9 to cover
R"(smoke_NmsLayerTest.*)",
// Issue: 95915
R"(smoke_dynamic/AUGRUCellCPUTest.CompareWithRefs/IS=\(\{\?\.1\}_\{\?\.1\}_\{\?\.1\}_\)_TS=\{\(1\.1\)_\(1\.1\)_\(1\.1\)\}_\{\(3\.1\)_\(3\.1\)_\(3\.1\)\}_\{\(5\.1\)_\(5\.1\)_\(5\.1\)\}_decompose=0_activations=\(sigmoid\.tanh\)_clip=0_linear=0_netPrec=f32__inFmts=nc\.nc_outFmts=nc_primitive=ref_any_PluginConf_ENFORCE_BF16=YES)", // NOLINT
R"(smoke_dynamic/GRUCellCPUTest.CompareWithRefs/IS=\(\{\?\.1\}_\{\?\.1\}_\)_TS=\{\(1\.1\)_\(1\.1\)\}_\{\(3\.1\)_\(3\.1\)\}_\{\(5\.1\)_\(5\.1\)\}_decompose=0_activations=\(sigmoid\.tanh\)_clip=0_linear=0_netPrec=f32__inFmts=nc\.nc_outFmts=nc_primitive=ref_any_PluginConf_ENFORCE_BF16=YES)", // NOLINT
// 94982. FP32->I32 conversion issue in the reference implementation. There can be some garbage in the rest of float values like 0.333333745.
// The kernel does not have such garbage. The diff 0.000000745 is taken into account in calculations and affects further type conversion.
// Reorder->GridSample->Reorder also does not work here. Potential fix is to use nearest conversion instead of truncation.
@@ -0,0 +1,205 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "shared_test_classes/base/ov_subgraph.hpp"
#include "ngraph_functions/builders.hpp"
#include "test_utils/cpu_test_utils.hpp"
using namespace CPUTestUtils;
using namespace ov::test;
namespace CPULayerTestsDefinitions {
using AUGRUCellCpuSpecificParams = 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 AUGRUCellCPUTest : public testing::WithParamInterface<AUGRUCellCpuSpecificParams>,
virtual public ov::test::SubgraphBaseTest, public CPUTestsBase {
public:
static std::string getTestCaseName(const testing::TestParamInfo<AUGRUCellCpuSpecificParams> &obj) {
std::vector<InputShape> inputShapes;
bool decompose, linearBeforeReset;
std::vector<std::string> activations;
float clip = 0.f;
ElementType netPrecision;
CPUSpecificParams cpuParams;
std::map<std::string, std::string> additionalConfig;
std::tie(inputShapes, decompose, activations, clip, linearBeforeReset, netPrecision, cpuParams, additionalConfig) = obj.param;
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 << "linear=" << linearBeforeReset << "_";
result << "netPrec=" << netPrecision << "_";
result << CPUTestsBase::getTestCaseName(cpuParams);
if (!additionalConfig.empty()) {
result << "_PluginConf";
for (auto &item : additionalConfig) {
if (item.second == InferenceEngine::PluginConfigParams::YES)
result << "_" << item.first << "=" << item.second;
}
}
return result.str();
}
protected:
void SetUp() override {
std::vector<InputShape> inputShapes;
bool decompose, linearBeforeReset;
std::vector<std::string> activations;
float clip = 0.f;
ElementType netPrecision;
CPUSpecificParams cpuParams;
std::map<std::string, std::string> additionalConfig;
std::tie(inputShapes, decompose, activations, clip, linearBeforeReset, netPrecision, cpuParams, additionalConfig) = this->GetParam();
std::tie(inFmts, outFmts, priority, selectedType) = cpuParams;
targetDevice = CommonTestUtils::DEVICE_CPU;
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[InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16] == InferenceEngine::PluginConfigParams::YES) {
selectedType = makeSelectedTypeStr(selectedType, ElementType::bf16);
} else {
selectedType = makeSelectedTypeStr(selectedType, netPrecision);
}
auto params = ngraph::builder::makeDynamicParams(netPrecision, inputDynamicShapes);
std::vector<ngraph::Shape> WRB = {{3 * hiddenSize, inputSize}, {3 * hiddenSize, hiddenSize}, {(linearBeforeReset ? 4 : 3) * hiddenSize}};
auto augruCellOp = ngraph::builder::makeAUGRU(
ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)), WRB, hiddenSize/*, activations, {}, {}, clip, linearBeforeReset*/);
function = makeNgraphFunction(netPrecision, params, augruCellOp, "AUGRUCell");
ov::pass::Serialize serializer("AUGRUCell.xml", "AUGRUCell.bin");
serializer.run_on_model(function);
std::cout << "Saved subgraph IR." << std::endl;
}
};
TEST_P(AUGRUCellCPUTest, CompareWithRefs) {
SKIP_IF_CURRENT_TEST_IS_DISABLED()
run();
CheckPluginRelatedResults(compiledModel, "RNNCell");
}
namespace {
/* CPU PARAMS */
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> 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};
// dev_api::augrucell does not support lbr so far.
std::vector<bool> linearBeforeReset = {false};
std::vector<ElementType> netPrecisions = { ElementType::f32 };
const std::vector<std::vector<ov::test::InputShape>> staticShapes = {
{ { {}, { {1, 1} } }, // Static shapes
{ {}, { {1, 1} } },
{ {}, { {1, 1} } } },
{ { {}, { {1, 1} } }, // Static shapes
{ {}, { {1, 10} } },
{ {}, { {1, 1} } } },
{ { {}, { {1, 30} } }, // Static shapes
{ {}, { {1, 10} } },
{ {}, { {1, 1} } } },
{ { {}, { {1, 30} } }, // Static shapes
{ {}, { {1, 1} } },
{ {}, { {1, 1} } } },
{ { {}, { {3, 1} } }, // Static shapes
{ {}, { {3, 1} } },
{ {}, { {3, 1} } } },
{ { {}, { {5, 1} } }, // Static shapes
{ {}, { {5, 1} } },
{ {}, { {5, 1} } } },
{ { {}, { {5, 30} } }, // Static shapes
{ {}, { {5, 10} } },
{ {}, { {5, 1} } } }
};
INSTANTIATE_TEST_SUITE_P(smoke_static, AUGRUCellCPUTest,
::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)),
AUGRUCellCPUTest::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, 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 2
{ {2, 1}, {5, 1}, {8, 1} } } }, // 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
{ { {1, 10}, 1 }, // Dynamic shape 2
{ {2, 1}, {5, 1}, {8, 1} } } }, // Target shapes
{ { { {1, 10}, {25, 35} }, // Dynamic shape 0
{ {2, 30}, {5, 30}, {8, 30}, {2, 30}, {5, 30}, {8, 30} } }, // Target shapes
{ { {1, 10}, -1 }, // Dynamic shape 1
{ {2, 10}, {5, 10}, {8, 10}, {2, 10}, {5, 10}, {8, 10} } }, // Target shapes
{ { {1, 10}, 1 }, // Dynamic shape 2
{ {2, 1}, {5, 1}, {8, 1}, {2, 1}, {5, 1}, {8, 1} } } } // Target shapes
};
INSTANTIATE_TEST_SUITE_P(smoke_dynamic, AUGRUCellCPUTest,
::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)),
AUGRUCellCPUTest::getTestCaseName);
} // namespace
} // namespace CPULayerTestsDefinitions
@@ -0,0 +1,391 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#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 CPUTestUtils;
using namespace ov::test;
namespace CPULayerTestsDefinitions {
using AUGRUSequenceCpuSpecificParams = 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 AUGRUSequenceCPUTest : public testing::WithParamInterface<AUGRUSequenceCpuSpecificParams>,
virtual public ov::test::SubgraphBaseTest, public CPUTestsBase {
public:
static std::string getTestCaseName(const testing::TestParamInfo<AUGRUSequenceCpuSpecificParams> &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;
std::map<std::string, std::string> additionalConfig;
std::tie(inputShapes, seqMode, activations, clip, linearBeforeRest, direction, netPrecision, cpuParams, additionalConfig) = obj.param;
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 == InferenceEngine::PluginConfigParams::YES)
result << "_" << item.first << "=" << item.second;
}
}
return result.str();
}
protected:
void SetUp() override {
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;
std::tie(inputShapes, seqMode, activations, clip, linearBeforeReset, direction, netPrecision, cpuParams, additionalConfig) = this->GetParam();
std::tie(inFmts, outFmts, priority, selectedType) = cpuParams;
targetDevice = CommonTestUtils::DEVICE_CPU;
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 MemoryDesc::isSame can't correct compute layout for tensor with strides = 1
// returned output format always tnc
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());
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;
if (additionalConfig[InferenceEngine::PluginConfigParams::KEY_ENFORCE_BF16] == InferenceEngine::PluginConfigParams::YES) {
selectedType = makeSelectedTypeStr(selectedType, ElementType::bf16);
} else {
selectedType = makeSelectedTypeStr(selectedType, netPrecision);
}
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;
/**
* There are 2 options to paramter "in" when "make_sequence" is true.
* 0 1 2 3
* X init_hidden_state attention seq_length
* or,
* 0 1 2
* X init_hidden_state attention
*
*/
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);
}
}
std::vector<ov::Shape> WRB = {{numDirections, 3 * hiddenSize, inputSize}, {numDirections, 3 * hiddenSize, hiddenSize},
{numDirections, (linearBeforeReset ? 4 : 3) * hiddenSize}, {batchSize}};
auto augruSequenceOp = ngraph::builder::makeAUGRU(ngraph::helpers::convert2OutputVector(ngraph::helpers::castOps2Nodes(params)),
WRB,
hiddenSize,
true,
direction,
seqMode);
// method MemoryDesc::isSame can't correct compute layout for tensor with strides = 1
// returned output format always tnc
if (augruSequenceOp->get_output_partial_shape(0).is_static() && ov::shape_size(augruSequenceOp->get_output_shape(0)) == 1) {
outFmts[0] = tnc;
} else if (augruSequenceOp->get_output_partial_shape(1).is_static() && ov::shape_size(augruSequenceOp->get_output_shape(1)) == 1 ||
augruSequenceOp->get_output_partial_shape(0)[0].is_static() && augruSequenceOp->get_output_partial_shape(0)[0].get_length() == 1) {
outFmts[1] = tnc;
}
function = makeNgraphFunction(netPrecision, params, augruSequenceOp, "augruSequenceOp");
if (seqMode != ngraph::helpers::SequenceTestsMode::PURE_SEQ) {
// TODO: ConvertAUGRUSequenceToTensorIterator
throw std::runtime_error("ConvertAUGRUSequenceToTensorIterator not implemented yet.");
} else {
bool ti_found = ngraph::helpers::is_tensor_iterator_exist(function);
EXPECT_EQ(ti_found, false);
}
}
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() > 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);
}
}
};
TEST_P(AUGRUSequenceCPUTest, CompareWithRefs) {
SKIP_IF_CURRENT_TEST_IS_DISABLED()
run();
CheckPluginRelatedResults(compiledModel, "RNNSeq");
}
namespace {
/* CPU PARAMS */
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{{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<std::vector<std::string>> activations = {{"sigmoid", "tanh"}};
// dev_api::augrucell does not support lbr so far.
std::vector<bool> linearBeforeReset = {false};
std::vector<float> clip{0.f};
// dev_api::augrusequence only supports forward so far.
std::vector<ov::op::RecurrentSequenceDirection> direction = {ov::op::RecurrentSequenceDirection::FORWARD};
std::vector<ElementType> netPrecisions = { ElementType::f32 };
const std::vector<std::vector<InputShape>> staticShapes = {
{ { {}, { {10, 2, 10} } }, // #0. Static shapes
{ {}, { {10, 1, 1} } },
{ {}, { {10, 2, 1} } },
{ {}, { {10} } } },
{ { {}, { {10, 2, 10} } }, // #1. Static shapes
{ {}, { {10, 1, 10} } },
{ {}, { {10, 2, 1} } },
{ {}, { {10} } } },
{ { {}, { {1, 2, 10} } }, // #2. Static shapes
{ {}, { {1, 1, 1} } },
{ {}, { {1, 2, 1} } },
{ {}, { {1} } } },
{ { {}, { {1, 2, 10} } }, // #3. Static shapes
{ {}, { {1, 1, 10} } },
{ {}, { {1, 2, 1} } },
{ {}, { {1} } } },
{ { {}, { {10, 2, 10} } }, // #4. Static shapes
{ {}, { {10, 1, 1} } },
{ {}, { {10, 2, 1} } } },
{ { {}, { {10, 2, 10} } }, // #5. Static shapes
{ {}, { {10, 1, 10} } },
{ {}, { {10, 2, 1} } } }
};
INSTANTIATE_TEST_SUITE_P(smoke_static, AUGRUSequenceCPUTest,
::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>{})),
AUGRUSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_static_BatchSizeOne, AUGRUSequenceCPUTest,
::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>{})),
AUGRUSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(nightly_static_bf16, AUGRUSequenceCPUTest,
::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])),
AUGRUSequenceCPUTest::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
{ {-1, {1, 5}, 1}, // Dynamic shape 2
{ {10, 2, 1}, {8, 3, 1}, {5, 4, 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
{ {{0, 11}, -1, 1}, // Dynamic shape 3
{ {10, 2, 1}, {3, 4, 1}, {5, 5, 1} } }, // 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
{ {{0, 11}, -1, 1}, // Dynamic shape 3
{ {10, 2, 1}, {3, 4, 1}, {5, 5, 1} } } , // 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, {0, 7}, 1}, // Dynamic shape 3
{ {1, 2, 1}, {1, 3, 1}, {1, 6, 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, -1, 1}, // Dynamic shape 0
{ {1, 2, 1}, {1, 4, 1}, {1, 8, 1} } }, // 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, -1, -1}, // Dynamic shape 0
{ {1, 2, 1}, {1, 4, 1}, {1, 8, 1} } }, // Target shapes
{ {-1}, // Dynamic shape 2
{ {1}, {1}, {1} } } }, // Target shapes
{ { {2, {1, 5}, 10}, // #6. Dynamic shape 0
{ {2, 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
{ {2, {1, 5}, 1}, // Dynamic shape 2
{ {2, 2, 1}, {2, 3, 1}, {2, 4, 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
{ {5, -1, 1}, // Dynamic shape 0
{ {5, 2, 1}, {5, 4, 1}, {5, 5, 1} } } }, // Target shapes
{ { {{0, 11}, -1, {7, 11}}, // #8. Dynamic shape 0
{ {10, 2, 10}, {3, 4, 10}, {5, 5, 10}, {10, 2, 10}, {5, 5, 10} } }, // Target shapes
{ {-1, 1, {8, 12}}, // Dynamic shape 1
{ {10, 1, 10}, {3, 1, 10}, {5, 1, 10}, {10, 1, 10}, {5, 1, 10} } }, // Target shapes
{ {{0, 11}, -1, 1}, // Dynamic shape 3
{ {10, 2, 1}, {3, 4, 1}, {5, 5, 1}, {10, 2, 1}, {5, 5, 1} } }, // Target shapes
{ {-1}, // Dynamic shape 2
{ {10}, {3}, {5}, {10}, {5} } } } // Target shapes
};
INSTANTIATE_TEST_SUITE_P(smoke_dynamic, AUGRUSequenceCPUTest,
::testing::Combine(::testing::ValuesIn({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>{})),
AUGRUSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_dynamic_BatchSizeOne, AUGRUSequenceCPUTest,
::testing::Combine(::testing::ValuesIn({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>{})),
AUGRUSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(nightly_dynamic, AUGRUSequenceCPUTest,
::testing::Combine(::testing::ValuesIn({dynamicShapes[5], dynamicShapes[8]}),
::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>{})),
AUGRUSequenceCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(nightly_dynamic_bf16, AUGRUSequenceCPUTest,
::testing::Combine(::testing::ValuesIn({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])),
AUGRUSequenceCPUTest::getTestCaseName);
} // namespace
} // namespace CPULayerTestsDefinitions
@@ -166,6 +166,7 @@ void SubgraphBaseTest::compare(const std::vector<ov::Tensor>& expected,
}
}
auto it = compareMap.find(inputNode->get_type_info());
ASSERT_NE(it, compareMap.end());
it->second(inputNode, i, expected[j], actual[j], abs_threshold, rel_threshold);
}
}
@@ -232,6 +233,7 @@ void SubgraphBaseTest::generate_inputs(const std::vector<ov::Shape>& targetInput
}
}
auto it = inputMap.find(nodePtr->get_type_info());
ASSERT_NE(it, inputMap.end());
for (size_t port = 0; port < nodePtr->get_input_size(); ++port) {
if (nodePtr->get_input_node_ptr(port)->shared_from_this() == inputNode->shared_from_this()) {
inputs.insert({param, it->second(nodePtr, port, param->get_element_type(), *itTargetShape++)});
@@ -3,6 +3,8 @@
//
#include "ngraph/ops.hpp"
#include "ngraph_ops/augru_cell.hpp"
#include "ngraph_ops/augru_sequence.hpp"
#include "shared_test_classes/base/layer_test_utils.hpp"
#include "shared_test_classes/base/utils/compare_results.hpp"
@@ -79,6 +81,7 @@ CompareMap getCompareMap() {
#include "openvino/opsets/opset9_tbl.hpp"
#include "openvino/opsets/opset10_tbl.hpp"
#include "ngraph_ops/opset_private_tbl.hpp"
#undef _OPENVINO_OP_REG
};
return compareMap;
@@ -4,6 +4,8 @@
#include <shared_test_classes/base/ov_subgraph.hpp>
#include "ngraph/ops.hpp"
#include "ngraph_ops/augru_cell.hpp"
#include "ngraph_ops/augru_sequence.hpp"
#include <common_test_utils/ov_tensor_utils.hpp>
@@ -656,6 +658,54 @@ ov::runtime::Tensor generate(const std::shared_ptr<ngraph::op::v9::NonMaxSuppres
}
}
ov::runtime::Tensor generate(const std::shared_ptr<ov::op::internal::AUGRUSequence>& node,
size_t port,
const ov::element::Type& elemType,
const ov::Shape& targetShape) {
if (port == 6) {
ov::runtime::Tensor tensor = ov::runtime::Tensor(elemType, targetShape);
const size_t range = 1;
const size_t startFrom = 0;
const size_t k = 1000;
const int seed = 1;
std::default_random_engine random(seed);
std::uniform_int_distribution<int32_t> distribution(k * startFrom, k * (startFrom + range));
auto *dataPtr = tensor.data<float>();
for (size_t i = 0; i < tensor.get_size(); i++) {
auto value = static_cast<float>(distribution(random));
dataPtr[i] = value / static_cast<float>(k);
}
return tensor;
}
return generate(std::dynamic_pointer_cast<ov::Node>(node), port, elemType, targetShape);
}
ov::runtime::Tensor generate(const std::shared_ptr<ov::op::internal::AUGRUCell>& node,
size_t port,
const ov::element::Type& elemType,
const ov::Shape& targetShape) {
if (port == 5) {
ov::runtime::Tensor tensor = ov::runtime::Tensor(elemType, targetShape);
const size_t range = 1;
const size_t startFrom = 0;
const size_t k = 1000;
const int seed = 1;
std::default_random_engine random(seed);
std::uniform_int_distribution<int32_t> distribution(k * startFrom, k * (startFrom + range));
auto *dataPtr = tensor.data<float>();
for (size_t i = 0; i < tensor.get_size(); i++) {
auto value = static_cast<float>(distribution(random));
dataPtr[i] = value / static_cast<float>(k);
}
return tensor;
}
return generate(std::dynamic_pointer_cast<ov::Node>(node), port, elemType, targetShape);
}
template<ov::element::Type_t elemType>
ov::runtime::Tensor generate_unique_possibilities(const ov::Shape &targetShape) {
using value_type = typename element_type_traits<elemType>::value_type;
@@ -691,7 +741,6 @@ ov::runtime::Tensor generate(const std::shared_ptr<ngraph::op::v6::ExperimentalD
return generate(std::dynamic_pointer_cast<ov::Node>(node), port, elemType, targetShape);
}
ov::runtime::Tensor generate(const std::shared_ptr<ngraph::op::v5::RNNSequence>& node,
size_t port,
const ov::element::Type& elemType,
@@ -733,6 +782,7 @@ InputsMap getInputMap() {
#include "openvino/opsets/opset8_tbl.hpp"
#include "openvino/opsets/opset9_tbl.hpp"
#include "ngraph_ops/opset_private_tbl.hpp"
#undef _OPENVINO_OP_REG
};
return inputsMap;
@@ -20,6 +20,7 @@ addIeTarget(
openvino::runtime
ngraph_reference
interpreter_backend
openvino::runtime::dev
ADD_CPPLINT
DEVELOPER_PACKAGE
tests
@@ -524,6 +524,13 @@ std::shared_ptr<ngraph::Node> makeGRU(const OutputVector& in,
ngraph::op::RecurrentSequenceDirection direction = ngraph::op::RecurrentSequenceDirection::FORWARD,
ngraph::helpers::SequenceTestsMode mode = ngraph::helpers::SequenceTestsMode::PURE_SEQ);
std::shared_ptr<ngraph::Node> makeAUGRU(const OutputVector& in,
const std::vector<ngraph::Shape>& constants,
std::size_t hidden_size,
bool make_sequence = false,
ngraph::op::RecurrentSequenceDirection direction = ngraph::op::RecurrentSequenceDirection::FORWARD,
ngraph::helpers::SequenceTestsMode mode = ngraph::helpers::SequenceTestsMode::PURE_SEQ);
std::shared_ptr<ngraph::Node> makeRNN(const OutputVector& in,
const std::vector<ngraph::Shape>& constants,
std::size_t hidden_size,
@@ -0,0 +1,77 @@
// Copyright (C) 2018-2022 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <vector>
#include <memory>
#include "ngraph_functions/builders.hpp"
#include "ngraph_ops/augru_cell.hpp"
#include "ngraph_ops/augru_sequence.hpp"
namespace ngraph {
namespace builder {
/**
* There are 2 options to paramter "in" when "make_sequence" is true.
* 0 1 2 3
* X init_hidden_state attention seq_length
* or,
* 0 1 2
* X init_hidden_state attention
*
*/
std::shared_ptr<ov::Node> makeAUGRU(const OutputVector& in,
const std::vector<ov::Shape>& constants,
std::size_t hidden_size,
bool make_sequence,
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);
W->set_friendly_name("augru_w");
auto R = ngraph::builder::makeConstant(in[0].get_element_type(), constants[1], empty, true);
R->set_friendly_name("augru_r");
auto B = ngraph::builder::makeConstant(in[0].get_element_type(), constants[2], empty, true);
B->set_friendly_name("augru_b");
if (!make_sequence) {
return std::make_shared<ov::op::internal::AUGRUCell>(in[0], in[1], W, R, B, in[2], hidden_size);
} else {
if (in.size() > 3 && in[3].get_partial_shape().is_dynamic()) {
return std::make_shared<ov::op::internal::AUGRUSequence>(in[0], in[1], in[3], W, R, B, in[2], hidden_size);
} 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;
}
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
if (in.size() < 4) throw std::runtime_error("Incorrect number of inputs for creation of Sequence operation");
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::internal::AUGRUSequence>(in[0], in[1], seq_lengths, W, R, B, in[2], hidden_size);
}
}
}
} // namespace builder
} // namespace ngraph