[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:
parent
53ca00bc81
commit
f32c023c91
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue