[CPU] Fix ScaleShift and FQ merge optimization (#9244)

This commit is contained in:
Egor Duplensky 2022-02-22 11:38:02 +03:00 committed by GitHub
parent 746b77c74a
commit 4075f8ed51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 319 additions and 256 deletions

View File

@ -337,25 +337,37 @@ void MKLDNNGraphOptimizer::FuseDeconvolutionAndSimpleOperation(MKLDNNGraph &grap
void MKLDNNGraphOptimizer::FuseMultiplyAndAdd(MKLDNNGraph &graph) {
auto& graphNodes = graph.GetNodes();
auto isSuitableSecondInput = [](MKLDNNNodePtr node, VectorDims dataDims) {
auto isSuitableSecondInput = [](const MKLDNNNodePtr& node, VectorDims dataDims) {
if (node->getType() != Input || !node->isConstant())
return false;
auto secondInputDims = node->getOutputShapeAtPort(0).getStaticDims();
const auto secondInputDims = node->getOutputShapeAtPort(0).getStaticDims();
if (secondInputDims.size() != dataDims.size() || secondInputDims.size() < 2)
return false;
if (secondInputDims[0] != 1 || !dimsEqualWeak(secondInputDims[1], dataDims[1]))
auto getChannelAxis = [](const VectorDims& dims) {
auto channelAxis = -1;
for (int i = 0; i < dims.size(); i ++) {
if (dims[i] != 1) {
if (channelAxis != -1) // more than one axis is != 1
return -1;
else
channelAxis = i;
}
}
return channelAxis;
};
const auto channelAxis = getChannelAxis(secondInputDims);
if (channelAxis == -1)
return false;
for (size_t i = 2; i < secondInputDims.size(); i++) {
if (secondInputDims[i] != 1)
return false;
}
if (secondInputDims[0] != 1 || !dimsEqualWeak(secondInputDims[channelAxis], dataDims[channelAxis]))
return false;
return true;
};
auto isSuitableParentNode = [&](MKLDNNNodePtr node) {
auto isSuitableParentNode = [&](const MKLDNNNodePtr& node) {
if (node->getAlgorithm() != EltwiseMultiply || !node->getFusedWith().empty() ||
node->getParentEdges().size() != 2 || node->getChildEdges().size() != 1)
return false;
@ -363,7 +375,7 @@ void MKLDNNGraphOptimizer::FuseMultiplyAndAdd(MKLDNNGraph &graph) {
return isSuitableSecondInput(node->getParentEdgesAtPort(1)[0]->getParent(), node->getInputShapeAtPort(0).getDims());
};
auto isSuitableChildNode = [&](MKLDNNNodePtr parentNode, MKLDNNNodePtr childNode) {
auto isSuitableChildNode = [&](const MKLDNNNodePtr& parentNode, const MKLDNNNodePtr& childNode) {
if (childNode->getAlgorithm() != EltwiseAdd || !childNode->getFusedWith().empty() || childNode->getParentEdges().size() != 2)
return false;
@ -430,7 +442,7 @@ void MKLDNNGraphOptimizer::FuseMultiplyAndAdd(MKLDNNGraph &graph) {
graph.RemoveEdge(remEdge);
}
auto parentEltwise = parentNode;
auto& parentEltwise = parentNode;
MKLDNNEdgePtr newEdge(new MKLDNNEdge(parent, parentEltwise, inNum, parentEltwise->getParentEdges().size()));
auto &graphEdges = graph.GetEdges();
graphEdges.push_back(newEdge);
@ -1701,36 +1713,37 @@ void MKLDNNGraphOptimizer::FuseClampAndFakeQuantize(MKLDNNGraph &graph) {
void MKLDNNGraphOptimizer::FusePerformedAsScaleShiftAndFakeQuantize(MKLDNNGraph &graph) {
auto& graphNodes = graph.GetNodes();
auto getConstPort = [](const MKLDNNNodePtr node) -> int {
if (node->getParentEdgesAtPort(0)[0]->getParent()->getType() == Input && node->getParentEdgesAtPort(0)[0]->getParent()->isConstant()) {
return 0;
} else if (node->getParentEdgesAtPort(1)[0]->getParent()->getType() == Input && node->getParentEdgesAtPort(1)[0]->getParent()->isConstant()) {
return 1;
} else {
auto getNonConstPort = [](const MKLDNNNodePtr& node) {
std::vector<int> nonConstPorts;
for (size_t i = 0; i < node->getParentEdges().size(); i++) {
const auto& parent = node->getParentEdgeAt(i)->getParent();
if (!(parent->getType() == Input && parent->isConstant()))
nonConstPorts.push_back(i);
}
// there are more than 1 nonconst port or missed
if (nonConstPorts.size() != 1)
return -1;
}
return nonConstPorts[0];
};
auto isSuitableScaleShiftNode = [getConstPort](MKLDNNNodePtr node) {
if (one_of(node->getAlgorithm(), EltwiseAdd, EltwiseSubtract, EltwiseMultiply, EltwiseDivide, EltwiseMulAdd)) {
MKLDNNNode *parent = nullptr;
if (node->getAlgorithm() != EltwiseMulAdd) {
const auto constPort = getConstPort(node);
if (constPort == -1) {
return false;
}
parent = node->getParentEdgesAtPort(1 - constPort)[0]->getParent().get();
}
return node->getType() == Eltwise && node->getChildEdges().size() == 1 && node->canBePerformedAsScaleShift(parent);
}
return false;
auto isSuitableScaleShiftNode = [getNonConstPort](const MKLDNNNodePtr& node) {
if (!one_of(node->getAlgorithm(), EltwiseAdd, EltwiseSubtract, EltwiseMultiply, EltwiseDivide, EltwiseMulAdd))
return false;
const auto nonConstPort = getNonConstPort(node);
if (nonConstPort == -1)
return false;
const MKLDNNNodePtr eltwiseInput = node->getParentEdgeAt(nonConstPort)->getParent();
return node->getChildEdges().size() == 1 && node->canBePerformedAsScaleShift(eltwiseInput.get());
};
auto isSuitableFakeQuantizeNode = [](MKLDNNNodePtr node) {
auto isSuitableFakeQuantizeNode = [](const MKLDNNNodePtr& node) {
return node->getType() == FakeQuantize && node->getAlgorithm() != FQBinarization;
};
auto fuseScaleShiftAndFakeQuantizeNodes = [getConstPort](MKLDNNNodePtr parent, MKLDNNNodePtr child) {
auto fuseScaleShiftAndFakeQuantizeNodes = [getNonConstPort](const MKLDNNNodePtr& parent, const MKLDNNNodePtr& child) {
auto fakeQuantizeNode = std::dynamic_pointer_cast<MKLDNNFakeQuantizeNode>(child);
if (fakeQuantizeNode == nullptr)
IE_THROW() << "Cannot cast " << child->getName() << " to FakeQuantize node";
@ -1742,11 +1755,13 @@ void MKLDNNGraphOptimizer::FusePerformedAsScaleShiftAndFakeQuantize(MKLDNNGraph
IE_THROW() << "Cannot cast " << parent->getName() << " to Eltwise node";
}
std::tie(scalesBuffer, shiftsBuffer) = parentEltwise->getScalesAndShifts(parent->getParentEdgesAtPort(1 - getConstPort(parent))[0]->getParent().get());
const MKLDNNNodePtr eltwiseInput = parentEltwise->getParentEdgeAt(getNonConstPort(parent))->getParent();
std::tie(scalesBuffer, shiftsBuffer) = parentEltwise->getScalesAndShifts(eltwiseInput.get());
const auto &outputShape = child->getOutputShapeAtPort(0);
VectorDims outputDims = outputShape.getDims();
const size_t channelPos = outputDims.size() > 1 ? 1 : 0;
const size_t channelPos = parent->getParentEdgeAt(0)->getParent()->getFusingAxis();
if (outputShape.isDynamic()) {
if (outputDims[channelPos] == Shape::UNDEFINED_DIM) {
if (scalesBuffer.size() > 1) {

View File

@ -1263,11 +1263,12 @@ MKLDNNNode* MKLDNNNode::NodesFactory::create(const std::shared_ptr<ngraph::Node>
}
bool MKLDNNNode::canBePerformedAsScaleShift(const MKLDNNNode *parentNode) const {
size_t fusingPort = 0;
// @todo graph optimizer can provide parentNode as nullptr. Should be avoided
const size_t channelAxis = parentNode ? parentNode->getFusingAxis() : MKLDNNNode::getFusingAxis();
IE_ASSERT(parentNode);
for (size_t i = (parentNode == nullptr ? 1 : 0); i < getParentEdges().size(); i++) {
size_t fusingPort = 0;
const size_t channelAxis = parentNode->getFusingAxis();
for (size_t i = 0; i < getParentEdges().size(); i++) {
MKLDNNNode *node = getParentEdgesAtPort(i)[0]->getParent().get();
if (node == nullptr) {
IE_THROW() << "Cannot get parent node for " << getName() << " on " << i << " port";

View File

@ -1156,6 +1156,20 @@ INSTANTIATE_TEST_SUITE_P(smoke_Conv_3D_FP32, ConvolutionLayerCPUTest,
::testing::Values(cpuEmptyPluginConfig)),
ConvolutionLayerCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_Conv_3D_FP32_fusingScaleShiftAndFakeQuantizePerChannel, ConvolutionLayerCPUTest,
::testing::Combine(
::testing::Combine(
convParams_ExplicitPadding_3D,
::testing::Values(ElementType::f32),
::testing::Values(ElementType::undefined),
::testing::Values(ElementType::undefined),
::testing::ValuesIn(inputShapes3d),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
::testing::ValuesIn(filterCPUInfoForDevice(CPUParams_3D)),
::testing::Values(fusingScaleShiftAndFakeQuantizePerChannel),
::testing::Values(cpuEmptyPluginConfig)),
ConvolutionLayerCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_Conv_3D_BF16, ConvolutionLayerCPUTest,
::testing::Combine(
::testing::Combine(

View File

@ -427,6 +427,7 @@ std::vector<fusingSpecificParams> fusingParamsSet3D_smoke {
fusingBias,
fusingMultiplyPerChannel,
fusingFakeQuantizePerChannel,
fusingScaleShiftAndFakeQuantizePerChannel,
};
std::vector<fusingSpecificParams> fusingParamsSet3D_nightly {
@ -866,6 +867,7 @@ std::vector<fusingSpecificParams> matmulFusingParams {
* so Relu cannot be fused in this case. Should be analysed */
// fusingFakeQuantizePerChannelRelu,
fusingFakeQuantizePerTensorRelu,
fusingScaleShiftAndFakeQuantizePerChannel,
};
const auto matMulParams = ::testing::Combine(::testing::ValuesIn(IS),

View File

@ -119,72 +119,72 @@ TEST_P(ConcatConvSumInPlaceTest, CompareWithRefs) {
namespace {
const auto fusingMulAddFQMullAdd = fusingSpecificParams{ std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params) {
ngraph::Shape newShape = generatePerChannelShape(inpNode);
auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(inpNode, constNode);
{[](postNodeConfig& cfg) {
ngraph::Shape newShape = generatePerChannelShape(cfg.input);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(cfg.input, constNode);
}, "Multiply(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params) {
ngraph::Shape newShape = generatePerChannelShape(inpNode);
auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(inpNode, constNode);
{[](postNodeConfig& cfg) {
ngraph::Shape newShape = generatePerChannelShape(cfg.input);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(cfg.input, constNode);
}, "Add(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(inpNode);
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
{[](postNodeConfig& cfg){
auto localPrc = cfg.input->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(cfg.input);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params) {
ngraph::Shape newShape = generatePerChannelShape(inpNode);
auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(inpNode, constNode);
{[](postNodeConfig& cfg) {
ngraph::Shape newShape = generatePerChannelShape(cfg.input);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(cfg.input, constNode);
}, "Multiply(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params) {
ngraph::Shape newShape = generatePerChannelShape(inpNode);
auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(inpNode, constNode);
{[](postNodeConfig& cfg) {
ngraph::Shape newShape = generatePerChannelShape(cfg.input);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(cfg.input, constNode);
}, "Add(PerChannel)"}}), {"Add"} };
const auto fusingDivSubFQ = fusingSpecificParams{ std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
ngraph::Shape secondMultInShape = generatePerChannelShape(inpNode);
auto secondMultInput = ngraph::builder::makeConstant(ngPrc, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Divide>(inpNode, secondMultInput);
{[](postNodeConfig& cfg){
ngraph::Shape secondMultInShape = generatePerChannelShape(cfg.input);
auto secondMultInput = ngraph::builder::makeConstant(cfg.type, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Divide>(cfg.input, secondMultInput);
}, "Divide(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
ngraph::Shape secondMultInShape = generatePerChannelShape(inpNode);
auto secondMultInput = ngraph::builder::makeConstant(ngPrc, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Subtract>(inpNode, secondMultInput);
{[](postNodeConfig& cfg){
ngraph::Shape secondMultInShape = generatePerChannelShape(cfg.input);
auto secondMultInput = ngraph::builder::makeConstant(cfg.type, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Subtract>(cfg.input, secondMultInput);
}, "Subtract(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(inpNode);
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
{[](postNodeConfig& cfg){
auto localPrc = cfg.input->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(cfg.input);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerChannel)"}}), {"FakeQuantize"} };
const auto fusingSigmoidFQFQ = fusingSpecificParams{ std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Sigmoid);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Sigmoid);
}, "Sigmoid"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(inpNode);
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
{[](postNodeConfig& cfg){
auto localPrc = cfg.input->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(cfg.input);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(inpNode);
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
{[](postNodeConfig& cfg){
auto localPrc = cfg.input->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(cfg.input);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerChannel)"}}), {"Sigmoid", "FakeQuantize", "FakeQuantize"} };
const auto fusingClampFQ = fusingSpecificParams{ std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Clamp, {}, {3.0f, 6.0f});
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Clamp, {}, {3.0f, 6.0f});
}, "Clamp"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(inpNode);
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
{[](postNodeConfig& cfg){
auto localPrc = cfg.input->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(cfg.input);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerChannel)"}}), {"FakeQuantize"} };

View File

@ -114,24 +114,24 @@ std::string CPUTestsBase::impls2str(const std::vector<std::string> &priority) {
return str;
}
void CPUTestsBase::CheckPluginRelatedResults(InferenceEngine::ExecutableNetwork &execNet, std::string nodeType) const {
void CPUTestsBase::CheckPluginRelatedResults(InferenceEngine::ExecutableNetwork &execNet, const std::string& nodeType) const {
if (nodeType.empty()) return;
ASSERT_TRUE(!selectedType.empty()) << "Node type is not defined.";
InferenceEngine::CNNNetwork execGraphInfo = execNet.GetExecGraphInfo();
auto function = execGraphInfo.getFunction();
CheckPluginRelatedResultsImpl(function, std::move(nodeType));
CheckPluginRelatedResultsImpl(function, nodeType);
}
void CPUTestsBase::CheckPluginRelatedResults(ov::CompiledModel &execNet, std::string nodeType) const {
void CPUTestsBase::CheckPluginRelatedResults(const ov::CompiledModel &execNet, const std::string& nodeType) const {
if (nodeType.empty()) return;
ASSERT_TRUE(!selectedType.empty()) << "Node type is not defined.";
auto function = execNet.get_runtime_model();
CheckPluginRelatedResultsImpl(function, std::move(nodeType));
CheckPluginRelatedResultsImpl(function, nodeType);
}
void CPUTestsBase::CheckPluginRelatedResultsImpl(std::shared_ptr<const ov::Model> function, std::string nodeType) const {
void CPUTestsBase::CheckPluginRelatedResultsImpl(const std::shared_ptr<const ov::Model>& function, const std::string& nodeType) const {
ASSERT_NE(nullptr, function);
for (const auto &node : function->get_ops()) {
const auto & rtInfo = node->get_rt_info();
@ -140,7 +140,7 @@ void CPUTestsBase::CheckPluginRelatedResultsImpl(std::shared_ptr<const ov::Model
IE_ASSERT(rtInfo.end() != it);
return it->second.as<std::string>();
};
auto getExecValueOutputsLayout = [] (std::shared_ptr<ngraph::Node> node) -> std::string {
auto getExecValueOutputsLayout = [] (const std::shared_ptr<ngraph::Node>& node) -> std::string {
auto rtInfo = node->get_rt_info();
auto it = rtInfo.find(ExecGraphInfoSerialization::OUTPUT_LAYOUTS);
IE_ASSERT(rtInfo.end() != it);
@ -261,7 +261,9 @@ std::string CPUTestsBase::getPrimitiveType() const {
}
CPUTestsBase::CPUInfo
CPUTestsBase::makeCPUInfo(std::vector<cpu_memory_format_t> inFmts, std::vector<cpu_memory_format_t> outFmts, std::vector<std::string> priority) {
CPUTestsBase::makeCPUInfo(const std::vector<cpu_memory_format_t>& inFmts,
const std::vector<cpu_memory_format_t>& outFmts,
const std::vector<std::string>& priority) {
CPUInfo cpuInfo;
if (!inFmts.empty()) {

View File

@ -124,9 +124,9 @@ public:
static cpu_memory_format_t cpu_str2fmt(const char *str);
static std::string fmts2str(const std::vector<cpu_memory_format_t> &fmts, const std::string &prefix);
static std::string impls2str(const std::vector<std::string> &priority);
static CPUInfo makeCPUInfo(std::vector<cpu_memory_format_t> inFmts,
std::vector<cpu_memory_format_t> outFmts,
std::vector<std::string> priority);
static CPUInfo makeCPUInfo(const std::vector<cpu_memory_format_t>& inFmts,
const std::vector<cpu_memory_format_t>& outFmts,
const std::vector<std::string>& priority);
//TODO: change to setter method
static std::string makeSelectedTypeStr(std::string implString, ngraph::element::Type_t elType);
@ -136,11 +136,11 @@ public:
const std::shared_ptr<ngraph::Node> &lastNode,
std::string name);
void CheckPluginRelatedResults(InferenceEngine::ExecutableNetwork &execNet, std::string nodeType) const;
void CheckPluginRelatedResults(ov::CompiledModel &execNet, std::string nodeType) const;
void CheckPluginRelatedResults(InferenceEngine::ExecutableNetwork &execNet, const std::string& nodeType) const;
void CheckPluginRelatedResults(const ov::CompiledModel &execNet, const std::string& nodeType) const;
protected:
virtual void CheckPluginRelatedResultsImpl(std::shared_ptr<const ov::Model> function, std::string nodeType) const;
virtual void CheckPluginRelatedResultsImpl(const std::shared_ptr<const ov::Model>& function, const std::string& nodeType) const;
/**
* @brief This function modifies the initial single layer test graph to add any necessary modifications that are specific to the cpu test scope.
* @param ngPrc Graph precision.

View File

@ -36,7 +36,7 @@ CpuTestWithFusing::modifyGraph(const ngraph::element::Type &ngPrc, ngraph::Param
return retNode;
}
void CpuTestWithFusing::CheckFusingResults(std::shared_ptr<const ov::Model> function, std::string nodeType) const {
void CpuTestWithFusing::CheckFusingResults(const std::shared_ptr<const ov::Model>& function, const std::string& nodeType) const {
ASSERT_NE(nullptr, function);
bool isNodeFound = false;
for (const auto & op : function->get_ops()) {
@ -55,7 +55,7 @@ void CpuTestWithFusing::CheckFusingResults(std::shared_ptr<const ov::Model> func
std::string opFriendlyName = op->get_friendly_name();
auto pos = originalLayersNames.find(opFriendlyName);
ASSERT_TRUE(pos != std::string::npos) << "Operation name " << op->get_friendly_name() << " has not been found in originalLayersNames!";
for (auto fusedOp : fusedOps) {
for (const auto& fusedOp : fusedOps) {
pos = originalLayersNames.find(fusedOp, checkFusingPosition ? pos : 0);
ASSERT_TRUE(pos != std::string::npos) << "Fused op " << fusedOp << " has not been found!";
}
@ -64,7 +64,7 @@ void CpuTestWithFusing::CheckFusingResults(std::shared_ptr<const ov::Model> func
ASSERT_TRUE(isNodeFound) << "Node type name: \"" << nodeType << "\" has not been found.";
}
void CpuTestWithFusing::CheckPluginRelatedResultsImpl(std::shared_ptr<const ov::Model> function, std::string nodeType) const {
void CpuTestWithFusing::CheckPluginRelatedResultsImpl(const std::shared_ptr<const ov::Model>& function, const std::string& nodeType) const {
CPUTestsBase::CheckPluginRelatedResultsImpl(function, nodeType);
CheckFusingResults(function, nodeType);
}
@ -87,8 +87,11 @@ std::shared_ptr<ngraph::Node>
postNodesMgr::addPostOps(const ngraph::element::Type &ngPrc, ngraph::ParameterVector &params, const std::shared_ptr<ngraph::Node> &lastNode) const {
std::shared_ptr<ngraph::Node> tmpNode = lastNode;
for (auto postNode : _postNodes) {
tmpNode = postNode.makeNode(tmpNode, ngPrc, params);
postNodeConfig cfg{lastNode, tmpNode, ngPrc, params};
for (const auto& postNode : _postNodes) {
cfg.input = tmpNode;
tmpNode = postNode.makeNode(cfg);
}
return tmpNode;
}

View File

@ -10,8 +10,15 @@
namespace CPUTestUtils {
struct postNodeConfig {
const std::shared_ptr<ngraph::Node> target;
std::shared_ptr<ngraph::Node> input;
const ngraph::element::Type& type;
ngraph::ParameterVector& params;
};
struct postNodeBuilder {
std::function<std::shared_ptr<ngraph::Node>(std::shared_ptr<ngraph::Node>, const ngraph::element::Type&, ngraph::ParameterVector&)> makeNode;
std::function<std::shared_ptr<ngraph::Node>(postNodeConfig& cfg)> makeNode;
std::string name;
};
@ -26,7 +33,7 @@ public:
class postFunctionMgr : public postOpMgr {
public:
postFunctionMgr(std::shared_ptr<ngraph::Function> function) : _pFunction(function) {}
postFunctionMgr(std::shared_ptr<ngraph::Function> function) : _pFunction(std::move(function)) {}
std::shared_ptr<ngraph::Node> addPostOps(const ngraph::element::Type &ngPrc,
ngraph::ParameterVector &params,
const std::shared_ptr<ngraph::Node> &lastNode) const override;
@ -65,10 +72,10 @@ protected:
ngraph::ParameterVector &params,
const std::shared_ptr<ngraph::Node> &lastNode) override;
void CheckPluginRelatedResultsImpl(std::shared_ptr<const ov::Model> function, std::string nodeType) const override;
void CheckPluginRelatedResultsImpl(const std::shared_ptr<const ov::Model>& function, const std::string& nodeType) const override;
private:
void CheckFusingResults(std::shared_ptr<const ov::Model> function, std::string nodeType) const;
void CheckFusingResults(const std::shared_ptr<const ov::Model>& function, const std::string& nodeType) const;
protected:
std::shared_ptr<postOpMgr> postOpMgrPtr;
@ -98,292 +105,311 @@ static ngraph::Shape generatePerChannelShape(const std::shared_ptr<ngraph::Node>
const auto emptyFusingSpec = fusingSpecificParams{nullptr, {}};
const auto fusingRelu = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Relu);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Relu);
}, "Relu"}}), {"Relu"}};
const auto fusingElu = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Elu, {}, {2.0f});
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Elu, {}, {2.0f});
}, "Elu"}}), {"Elu"}};
const auto fusingGelu = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Gelu);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Gelu);
}, "Gelu"}}), {"Gelu"}};
const auto fusingSigmoid = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Sigmoid);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Sigmoid);
}, "Sigmoid"}}), {"Sigmoid"}};
const auto fusingClamp = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Clamp, {}, {3.0f, 6.0f});
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Clamp, {}, {3.0f, 6.0f});
}, "Clamp"}}), {"Clamp"}};
const auto fusingTanh = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Tanh);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Tanh);
}, "Tanh"}}), {"Tanh"}};
const auto fusingAbs = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Abs);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Abs);
}, "Abs"}}), {"Abs"}};
const auto fusingSqrt = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Sqrt);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Sqrt);
}, "Sqrt"}}), {"Sqrt"}};
const auto fusingPReluPerChannel = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
ngraph::Shape newShape = generatePerChannelShape(inpNode);
{[](postNodeConfig& cfg){
ngraph::Shape newShape = generatePerChannelShape(cfg.target);
auto data = NGraphFunctions::Utils::generateVector<ngraph::element::Type_t::f32>(ngraph::shape_size(newShape));
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::LeakyRelu, newShape, data);
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::LeakyRelu, newShape, data);
}, "PRelu(PerChannel)"}}), {"PRelu"}};
const auto fusingPReluPerTensor = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
{[](postNodeConfig& cfg){
ngraph::Shape shape(1, 1);
auto data = NGraphFunctions::Utils::generateVector<ngraph::element::Type_t::f32>(ngraph::shape_size(shape));
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::LeakyRelu, shape, data);
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::LeakyRelu, shape, data);
}, "PRelu(PerTensor)"}}), {"PRelu"}};
const auto fusingSwish = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Swish, {}, {1.0f});
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Swish, {}, {1.0f});
}, "Swish"}}), {"Swish"}};
const auto fusingSoftPlus = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::SoftPlus, {}, {});
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::SoftPlus, {}, {});
}, "SoftPlus"}}), {"SoftPlus"}};
const auto fusingHSwish = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::HSwish, {}, {});
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::HSwish, {}, {});
}, "HSwish"}}), {"HSwish"}};
const auto fusingMish = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Mish, {}, {});
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Mish, {}, {});
}, "Mish"}}), {"Mish"}};
const auto fusingHSigmoid = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::HSigmoid);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::HSigmoid);
}, "HSigmoid"}}), {"HSigmoid"}};
const auto fusingReluAdd = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Relu);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Relu);
}, "Relu"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
ngraph::Shape newShape = generatePerChannelShape(inpNode);
auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(inpNode, constNode);
{[](postNodeConfig& cfg){
ngraph::Shape newShape = generatePerChannelShape(cfg.target);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(cfg.input, constNode);
}, "Add(PerChannel)"}}), {"Relu", "Add"}};
const auto fusingReluScaleShift = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Relu);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Relu);
}, "Relu"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
ngraph::Shape newShape = generatePerChannelShape(inpNode);
auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(inpNode, constNode);
{[](postNodeConfig& cfg){
ngraph::Shape newShape = generatePerChannelShape(cfg.target);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(cfg.input, constNode);
}, "Multiply(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
ngraph::Shape newShape = generatePerChannelShape(inpNode);
auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(inpNode, constNode);
{[](postNodeConfig& cfg){
ngraph::Shape newShape = generatePerChannelShape(cfg.target);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(cfg.input, constNode);
}, "Add(PerChannel)"}}), {"Relu", "Add"}};
const auto fusingScaleShift = fusingSpecificParams{ std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params) {
ngraph::Shape newShape = generatePerChannelShape(inpNode);
auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(inpNode, constNode);
{[](postNodeConfig& cfg) {
ngraph::Shape newShape = generatePerChannelShape(cfg.target);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(cfg.input, constNode);
}, "Multiply(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params) {
ngraph::Shape newShape = generatePerChannelShape(inpNode);
auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(inpNode, constNode);
{[](postNodeConfig& cfg) {
ngraph::Shape newShape = generatePerChannelShape(cfg.target);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(cfg.input, constNode);
}, "Add(PerChannel)"}}), {"Add"} };
const auto fusingScaleShiftAndFakeQuantizePerChannel = fusingSpecificParams{ std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](postNodeConfig& cfg) {
ngraph::Shape newShape = generatePerChannelShape(cfg.target);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(cfg.input, constNode);
}, "Multiply(PerChannel)"},
{[](postNodeConfig& cfg) {
ngraph::Shape newShape = generatePerChannelShape(cfg.target);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(cfg.input, constNode);
}, "Add(PerChannel)"},
{[](postNodeConfig& cfg){
auto localPrc = cfg.input->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(cfg.target);
// auto newShape = ngraph::Shape(cfg.inputNode->get_output_partial_shape(0).size(), 1);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerChannel)"}}), {"FakeQuantize"}};
const auto fusingFakeQuantizePerTensor = fusingSpecificParams{ std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
ngraph::Shape newShape(inpNode->get_output_partial_shape(0).size(), 1);
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
{[](postNodeConfig& cfg){
auto localPrc = cfg.input->get_element_type();
ngraph::Shape newShape(cfg.input->get_output_partial_shape(0).size(), 1);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerTensor)"}}), {"FakeQuantize"} };
const auto fusingFakeQuantizePerChannel = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(inpNode);
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
{[](postNodeConfig& cfg){
auto localPrc = cfg.input->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(cfg.target);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerChannel)"}}), {"FakeQuantize"}};
const auto fusingFakeQuantizePerChannelRelu = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(inpNode);
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
{[](postNodeConfig& cfg){
auto localPrc = cfg.input->get_element_type();
ngraph::Shape newShape = generatePerChannelShape(cfg.target);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Relu);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Relu);
}, "Relu"}}), {"FakeQuantize", "Relu"}};
const auto fusingFQPerChannelSigmoidFQPerChannel = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
auto shape = inpNode->get_output_partial_shape(0);
{[](postNodeConfig& cfg){
auto localPrc = cfg.input->get_element_type();
auto shape = cfg.input->get_output_partial_shape(0);
if (shape.size() == 1)
IE_THROW() << "If shape.size() == 1 then Granularity can be PerTensor only";
ngraph::Shape newShape(shape.size(), 1);
newShape[1] = shape[1].get_length();
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Sigmoid);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Sigmoid);
}, "Sigmoid"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
auto shape = inpNode->get_output_partial_shape(0);
{[](postNodeConfig& cfg){
auto localPrc = cfg.input->get_element_type();
auto shape = cfg.input->get_output_partial_shape(0);
if (shape.size() == 1)
IE_THROW() << "If shape.size() == 1 then Granularity can be PerTensor only";
ngraph::Shape newShape(shape.size(), 1);
newShape[1] = shape[1].get_length();
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerChannel)"}}), {"FakeQuantize", "Sigmoid", "FakeQuantize"}};
const auto fusingFakeQuantizePerTensorRelu = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params) {
auto localPrc = inpNode->get_element_type();
auto newShape = ngraph::Shape(inpNode->get_output_partial_shape(0).size(), 1);
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
{[](postNodeConfig& cfg) {
auto localPrc = cfg.input->get_element_type();
auto newShape = ngraph::Shape(cfg.input->get_output_partial_shape(0).size(), 1);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerTensor)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Relu);
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Relu);
}, "Relu"}}), {"FakeQuantize", "Relu"}};
const auto fusingSum = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto shape = inpNode->get_output_partial_shape(0);
ngraph::ParameterVector newParams = ngraph::builder::makeDynamicParams(ngPrc, {shape});
params.insert(params.end(), newParams.begin(), newParams.end());
{[](postNodeConfig& cfg){
auto shape = cfg.input->get_output_partial_shape(0);
ngraph::ParameterVector newParams = ngraph::builder::makeDynamicParams(cfg.type, {shape});
cfg.params.insert(cfg.params.end(), newParams.begin(), newParams.end());
auto newParamOuts = ngraph::helpers::convert2OutputVector(
ngraph::helpers::castOps2Nodes<ngraph::op::Parameter>(newParams));
return std::make_shared<ngraph::opset1::Add>(inpNode, newParamOuts[0]);
return std::make_shared<ngraph::opset1::Add>(cfg.input, newParamOuts[0]);
}, "Add(Parameters)"}}), {"Add"}};
const auto fusingSumEluFQ = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto shape = inpNode->get_output_partial_shape(0);
ngraph::ParameterVector newParams = ngraph::builder::makeDynamicParams(ngPrc, {shape});
params.insert(params.end(), newParams.begin(), newParams.end());
{[](postNodeConfig& cfg){
auto shape = cfg.input->get_output_partial_shape(0);
ngraph::ParameterVector newParams = ngraph::builder::makeDynamicParams(cfg.type, {shape});
cfg.params.insert(cfg.params.end(), newParams.begin(), newParams.end());
auto newParamOuts = ngraph::helpers::convert2OutputVector(
ngraph::helpers::castOps2Nodes<ngraph::op::Parameter>(newParams));
return std::make_shared<ngraph::opset1::Add>(inpNode, newParamOuts[0]);
return std::make_shared<ngraph::opset1::Add>(cfg.input, newParamOuts[0]);
}, "Add(Parameters)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::Elu, {}, {2.0f});
{[](postNodeConfig& cfg){
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::Elu, {}, {2.0f});
}, "Elu"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params) {
auto localPrc = inpNode->get_element_type();
auto newShape = ngraph::Shape(inpNode->get_output_partial_shape(0).size(), 1);
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
{[](postNodeConfig& cfg) {
auto localPrc = cfg.input->get_element_type();
auto newShape = ngraph::Shape(cfg.input->get_output_partial_shape(0).size(), 1);
return ngraph::builder::makeFakeQuantize(cfg.input, localPrc, 256, newShape);
}, "FakeQuantize(PerTensor)"}}), {"Add", "Elu", "FakeQuantize"}};
const auto fusingMultiplyPerTensor = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
{[](postNodeConfig& cfg){
ngraph::Shape secondMultInShape(1, 1);
auto secondMultInput = ngraph::builder::makeConstant(ngPrc, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::op::v1::Multiply>(inpNode, secondMultInput);
auto secondMultInput = ngraph::builder::makeConstant(cfg.type, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::op::v1::Multiply>(cfg.input, secondMultInput);
}, "Multiply(PerTensor)"}}), {"Multiply"}};
const auto fusingMultiplyPerChannel = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
ngraph::Shape secondMultInShape = generatePerChannelShape(inpNode);
auto secondMultInput = ngraph::builder::makeConstant(ngPrc, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(inpNode, secondMultInput);
{[](postNodeConfig& cfg){
ngraph::Shape secondMultInShape = generatePerChannelShape(cfg.target);
auto secondMultInput = ngraph::builder::makeConstant(cfg.type, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(cfg.input, secondMultInput);
}, "Multiply(PerChannel)"}}), {"Multiply"}};
const auto fusingAddPerTensor = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
{[](postNodeConfig& cfg){
ngraph::Shape secondMultInShape(1, 1);
auto secondMultInput = ngraph::builder::makeConstant(ngPrc, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(inpNode, secondMultInput);
auto secondMultInput = ngraph::builder::makeConstant(cfg.type, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(cfg.input, secondMultInput);
}, "Add(PerTensor)"}}), {"Add"}};
const auto fusingAddPerChannel = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
ngraph::Shape secondMultInShape = generatePerChannelShape(inpNode);
auto secondMultInput = ngraph::builder::makeConstant(ngPrc, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(inpNode, secondMultInput);
{[](postNodeConfig& cfg){
ngraph::Shape secondMultInShape = generatePerChannelShape(cfg.target);
auto secondMultInput = ngraph::builder::makeConstant(cfg.type, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(cfg.input, secondMultInput);
}, "Add(PerChannel)"}}), {"Add"}};
const auto fusingSubtractPerTensor = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
{[](postNodeConfig& cfg){
ngraph::Shape secondMultInShape(1, 1);
auto secondMultInput = ngraph::builder::makeConstant(ngPrc, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Subtract>(inpNode, secondMultInput);
auto secondMultInput = ngraph::builder::makeConstant(cfg.type, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Subtract>(cfg.input, secondMultInput);
}, "Subtract(PerTensor)"}}), {"Subtract"}};
const auto fusingSubtractPerChannel = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
ngraph::Shape secondMultInShape = generatePerChannelShape(inpNode);
auto secondMultInput = ngraph::builder::makeConstant(ngPrc, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Subtract>(inpNode, secondMultInput);
{[](postNodeConfig& cfg){
ngraph::Shape secondMultInShape = generatePerChannelShape(cfg.target);
auto secondMultInput = ngraph::builder::makeConstant(cfg.type, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Subtract>(cfg.input, secondMultInput);
}, "Subtract(PerChannel)"}}), {"Subtract"}};
const auto fusingDividePerTensor = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
{[](postNodeConfig& cfg){
ngraph::Shape secondMultInShape(1, 1);
auto secondMultInput = ngraph::builder::makeConstant(ngPrc, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Divide>(inpNode, secondMultInput);
auto secondMultInput = ngraph::builder::makeConstant(cfg.type, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Divide>(cfg.input, secondMultInput);
}, "Divide(PerTensor)"}}), {"Divide"}};
const auto fusingDividePerChannel = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
ngraph::Shape secondMultInShape = generatePerChannelShape(inpNode);
auto secondMultInput = ngraph::builder::makeConstant(ngPrc, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Divide>(inpNode, secondMultInput);
{[](postNodeConfig& cfg){
ngraph::Shape secondMultInShape = generatePerChannelShape(cfg.target);
auto secondMultInput = ngraph::builder::makeConstant(cfg.type, secondMultInShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Divide>(cfg.input, secondMultInput);
}, "Divide(PerChannel)"}}), {"Divide"}};
const auto fusingPRelu1D = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto shape = inpNode->get_output_partial_shape(0);
{[](postNodeConfig& cfg){
auto shape = cfg.input->get_output_partial_shape(0);
ngraph::Shape newShape({static_cast<size_t>(shape[1].get_length())});
auto data = NGraphFunctions::Utils::generateVector<ngraph::element::Type_t::f32>(ngraph::shape_size(newShape));
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::LeakyRelu, newShape, data);
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::LeakyRelu, newShape, data);
}, "PRelu1D"}}), {"PRelu"}};
const auto fusingPRelu1DScaleShift = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto shape = inpNode->get_output_partial_shape(0);
{[](postNodeConfig& cfg){
auto shape = cfg.input->get_output_partial_shape(0);
ngraph::Shape newShape({static_cast<size_t>(shape[1].get_length())});
auto data = NGraphFunctions::Utils::generateVector<ngraph::element::Type_t::f32>(ngraph::shape_size(newShape));
return ngraph::builder::makeActivation(inpNode, ngPrc, ngraph::helpers::LeakyRelu, newShape, data);
return ngraph::builder::makeActivation(cfg.input, cfg.type, ngraph::helpers::LeakyRelu, newShape, data);
}, "PRelu1D"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params) {
ngraph::Shape newShape = generatePerChannelShape(inpNode);
auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(inpNode, constNode);
{[](postNodeConfig& cfg) {
ngraph::Shape newShape = generatePerChannelShape(cfg.input);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Multiply>(cfg.input, constNode);
}, "Multiply(PerChannel)"},
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params) {
ngraph::Shape newShape = generatePerChannelShape(inpNode);
auto constNode = ngraph::builder::makeConstant(ngPrc, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(inpNode, constNode);
{[](postNodeConfig& cfg) {
ngraph::Shape newShape = generatePerChannelShape(cfg.input);
auto constNode = ngraph::builder::makeConstant(cfg.type, newShape, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(cfg.input, constNode);
}, "Add(PerChannel)"}}), {"Add"} };
const auto fusingBias = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params) {
size_t last_dim = inpNode->get_output_partial_shape(0).rbegin()->get_length();
auto bias = ngraph::builder::makeConstant(ngPrc, ngraph::Shape{last_dim}, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(inpNode, bias);
}, "fusingBias"}}), {"Add"}};
{[](postNodeConfig& cfg) {
size_t last_dim = cfg.input->get_output_partial_shape(0).rbegin()->get_length();
auto bias = ngraph::builder::makeConstant(cfg.type, ngraph::Shape{last_dim}, std::vector<float>{}, true);
return std::make_shared<ngraph::opset1::Add>(cfg.input, bias);
}, "fusingBias"}}), {"Add"}};
} // namespace CPUTestUtils