[CPU]Fix regression issue. (#23904)

### Details:
 - *Add callback fun param for selectPreferPrimitiveDescriptor*
 - *Update Snippet node selectPreferPrimitiveDescriptor algorithm.*
 - *Add test*

### Tickets:
 - *137307*

---------

Signed-off-by: xipingya <xiping.yan@intel.com>
This commit is contained in:
Xiping Yan 2024-04-26 16:21:25 +08:00 committed by GitHub
parent 53ca00bc81
commit f32c023c91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 193 additions and 0 deletions

View File

@ -283,6 +283,75 @@ void Snippet::initSupportedPrimitiveDescriptors() {
}
void Snippet::selectOptimalPrimitiveDescriptor() {
// Check if memory desc is in SupportedPrimitiveDescriptors.
auto memDescInSupportedPD = [&](const ov::intel_cpu::MemoryDescPtr& parentMemDesc,
const size_t& idx,
size_t& supportedPDIdx) {
for (auto& type : getImplPriority()) {
for (size_t i = 0; i < getSupportedPrimitiveDescriptors().size(); i++) {
const auto& supportedPrimitiveDesc = getSupportedPrimitiveDescriptors()[i];
const impl_desc_type supportedType = supportedPrimitiveDesc.getImplementationType();
if (supportedType == type) {
const auto& supportedMemDesc = supportedPrimitiveDesc.getConfig().inConfs[idx].getMemDesc();
// Static shape + same shape + same precision + same layout
if (parentMemDesc->getShape().isStatic() && supportedMemDesc->getShape().isStatic() &&
parentMemDesc->getShape() == supportedMemDesc->getShape() &&
parentMemDesc->getPrecision() == supportedMemDesc->getPrecision()) {
if ((parentMemDesc->hasLayoutType(LayoutType::ncsp) &&
supportedMemDesc->hasLayoutType(LayoutType::ncsp)) ||
(parentMemDesc->hasLayoutType(LayoutType::nspc) &&
supportedMemDesc->hasLayoutType(LayoutType::nspc))) {
supportedPDIdx = i;
return true;
}
}
}
}
}
return false;
};
if (getParentEdges().size() == 3u) {
auto check_special_shape = [](const ov::intel_cpu::Shape& shape) {
// SShape=[1,?,1,1]
if (shape.isStatic()) {
const auto& dims = shape.getDims();
if (dims.size() == 4u) {
return dims[0] == 1u && dims[1] > 1u && dims[2] == 1u && dims[3] == 1u;
}
}
return false;
};
int num_sshape_ncsp = 0;
int num_nonsshape_nspc = 0;
size_t selectedPDIdx = 0;
for (size_t i = 0; i < getParentEdges().size(); i++) {
auto parentEdge = getParentEdgeAt(i);
auto parentPtr = parentEdge->getParent();
auto parent_spd = parentPtr->getSelectedPrimitiveDescriptor();
auto parentDesc = parent_spd->getConfig().outConfs[0].getMemDesc();
size_t supportedPDIdx = 0;
if (check_special_shape(parentDesc->getShape()) && parentDesc->hasLayoutType(LayoutType::ncsp) &&
memDescInSupportedPD(parentDesc, i, supportedPDIdx)) {
num_sshape_ncsp++;
}
if ((!check_special_shape(parentDesc->getShape())) && parentDesc->hasLayoutType(LayoutType::nspc) &&
memDescInSupportedPD(parentDesc, i, supportedPDIdx)) {
num_nonsshape_nspc++;
selectedPDIdx = supportedPDIdx;
}
}
bool foundOptimalPD = num_sshape_ncsp == 2 && num_nonsshape_nspc == 1;
if (foundOptimalPD) {
selectPrimitiveDescriptorByIndex(selectedPDIdx);
return;
}
}
// fallback
selectPreferPrimitiveDescriptor(getImplPriority(), true);
}

View File

@ -0,0 +1,124 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "openvino/opsets/opset8.hpp"
#include "ov_models/builders.hpp"
#include "shared_test_classes/base/ov_subgraph.hpp"
#include "test_utils/cpu_test_utils.hpp"
namespace ov {
namespace test {
/*
input1(f32_abcd_{1,64,32,32}) input2(f32_abcd_{1,128,1,1})
| |
Reorder(f32_acdb_{1,64,32,32}) const |
| / |
| / |
Convolution(f32_acdb_{1,1,30,30}) Range_1520 VariadicSplit(f32_abcd_{1,64,1,1}, f32_abcd_{1,64,1,1})
| / \ /
| / \ /
| / \ /
| / \ /
MVN(f32_acdb_{1,1,30,30}) Reorder1(f32_acdb_{1,64,1,1}) Reorder2(f32_acdb_{1,64,1,1})
\ / /
\ / /
\ / /
\ / /
Subgraph(f32_acdb_{1,64,30,30})
|
|
Convolution(f32_acdb_{1,1,28,28})
|
Result
The Subgraph node have 3 inputs: they don't have same layout.
Expected: Reorder is inserted after VariadicSplit[0] and VariadicSplit[1], not inserted after MVN.
Because VariadicSplit's output layout is [1,64,1,1], it' reorder almost have calculation.
*/
class SubgraphSelectPD : virtual public SubgraphBaseStaticTest {
protected:
void SetUp() override {
targetDevice = ov::test::utils::DEVICE_CPU;
abs_threshold = 2e-2;
auto type = element::f32;
constexpr int const1 = 32;
auto input1 = std::make_shared<ov::opset8::Parameter>(type, Shape{1, const1 / 2, 8, 8});
input1->set_friendly_name("input1");
auto input2 = std::make_shared<ov::opset8::Parameter>(type, Shape{1, const1, 1, 1});
input2->set_friendly_name("input2");
auto variadicSplit = std::make_shared<ov::op::v1::VariadicSplit>(
input2,
ov::opset8::Constant::create(element::i64, Shape{1}, {1}),
ov::opset8::Constant::create(element::i64, Shape{2}, {const1 / 2, const1 / 2}));
variadicSplit->set_friendly_name("variadicSplit");
auto add1 = std::make_shared<ov::opset8::Add>(variadicSplit->output(0),
ov::opset8::Constant::create(type, Shape{1}, {0}));
add1->set_friendly_name("add1");
auto shapeof = std::make_shared<ov::opset8::ShapeOf>(input1);
auto rankof = std::make_shared<ov::opset8::ShapeOf>(shapeof);
auto squeeze =
std::make_shared<ov::opset8::Squeeze>(rankof, ov::opset8::Constant::create(element::i64, Shape{1}, {0}));
auto range = std::make_shared<ov::opset8::Range>(ov::opset8::Constant::create(element::i64, Shape{}, {2}),
squeeze,
ov::opset8::Constant::create(element::i64, Shape{}, {1}),
ov::element::i64);
auto create_conv = [&](const std::shared_ptr<ov::Node>& input_node) {
auto conv = std::make_shared<ov::opset8::Convolution>(
input_node,
ngraph::builder::makeConstant(type,
Shape{const1 / 2u, const1 / 2u, 3, 3},
std::vector<float>{},
true,
0.1f,
0.9f),
Strides{1, 1},
CoordinateDiff{1, 1},
CoordinateDiff{1, 1},
Strides{1, 1});
conv->get_rt_info() =
CPUTestUtils::CPUTestsBase::makeCPUInfo({CPUTestUtils::nhwc}, {CPUTestUtils::nhwc}, {});
return conv;
};
auto create_relu = [&](const std::shared_ptr<ov::Node>& input_node) {
return std::make_shared<ov::opset8::PRelu>(input_node,
ov::opset8::Constant::create(element::f32, Shape{1}, {1}));
};
auto conv1 = create_conv(input1);
auto mvn =
std::make_shared<ov::opset8::MVN>(create_relu(conv1), range, false, 0.1, op::MVNEpsMode::INSIDE_SQRT);
auto mul = std::make_shared<ov::opset8::Multiply>(create_relu(add1), mvn);
auto add2 = std::make_shared<ov::opset8::Add>(variadicSplit->output(1), mul);
auto conv2 = create_conv(create_relu(add2));
conv2->set_friendly_name("conv2");
function = std::make_shared<ov::Model>(conv2, ParameterVector{input1, input2});
}
void TearDown() override {
auto runtime_function = compiledModel.get_runtime_model();
int nodes_found = 0;
for (const auto& n : runtime_function->get_ordered_ops()) {
auto layer_type = n->get_rt_info().at(ov::exec_model_info::LAYER_TYPE).as<std::string>();
if (layer_type == "Subgraph") {
nodes_found++;
auto output_layout = n->get_rt_info().at(ov::exec_model_info::OUTPUT_LAYOUTS).as<std::string>();
// The optimal choose should be: 'nhwc'.
ASSERT_EQ(output_layout, "acdb");
}
}
ASSERT_GT(nodes_found, 0);
}
};
TEST_F(SubgraphSelectPD, smoke_CompareWithRefs) {
run();
}
} // namespace test
} // namespace ov