[CPU] Reuse the new nGraph shape infer functionality to the MKLDNN plugin (#9220)

This commit is contained in:
Tingqian Li 2022-01-18 16:46:35 +08:00 committed by GitHub
parent 822cb48a1e
commit 89f4a569d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 637 additions and 465 deletions

View File

@ -47,12 +47,12 @@ template<class T>
void shape_infer(const ov::op::util::ArithmeticReductionKeepDims* op, const std::vector<T> &input_shapes, std::vector<T> &output_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data = {}) {
NODE_VALIDATION_CHECK(op, input_shapes.size() == 2 && output_shapes.size() == 1);
reduce_shape_infer(op, op->get_keep_dims(), input_shapes[0], output_shapes[0]);
reduce_shape_infer(op, op->get_keep_dims(), input_shapes[0], output_shapes[0], constant_data);
}
template<class T>
void shape_infer(const ov::op::util::LogicalReductionKeepDims* op, const std::vector<T> &input_shapes, std::vector<T> &output_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data = {}) {
NODE_VALIDATION_CHECK(op, input_shapes.size() == 2 && output_shapes.size() == 1);
reduce_shape_infer(op, op->get_keep_dims(), input_shapes[0], output_shapes[0]);
reduce_shape_infer(op, op->get_keep_dims(), input_shapes[0], output_shapes[0], constant_data);
}

View File

@ -16,7 +16,8 @@ void copy_shape_infer(const OpType* op, const std::vector<T>& input_shapes, std:
template <class OpType, class T>
void first_input_passthrough_infer(const OpType* op, const std::vector<T>& input_shapes, std::vector<T>& output_shapes) {
NODE_VALIDATION_CHECK(op, output_shapes.size() == 1, "Incorrect number of output shapes");
NODE_VALIDATION_CHECK(op, output_shapes.size() == 1 && input_shapes.size() >= 1,
"Incorrect number of input and output shapes");
output_shapes[0] = input_shapes[0];
}

View File

@ -111,8 +111,9 @@ MKLDNNNode::MKLDNNNode(const std::shared_ptr<ngraph::Node>& op, const mkldnn::en
isDynamic = std::any_of(inputShapes.begin(), inputShapes.end(), [](const Shape& shape){ return shape.isDynamic(); }) ||
std::any_of(outputShapes.begin(), outputShapes.end(), [](const Shape& shape){ return shape.isDynamic(); });
if (isDynamic)
createShapeInferSubgraph(op);
if (isDynamic) {
shapeInference = make_shape_inference(op);
}
const auto& rtInfo = op->get_rt_info();
if (rtInfo.count("originalLayersNames")) {
@ -1419,54 +1420,71 @@ bool MKLDNNNode::needShapeInfer() const {
}
std::vector<VectorDims> MKLDNNNode::shapeInfer() const {
std::vector<Shape> shapes;
for (size_t i = 0; i < opToShapeInfer->get_input_size(); i++) {
shapes.push_back(opToShapeInfer->get_input_partial_shape(i).rank().get_length() == 0 ? Shape{} :
getParentEdgesAtPort(i)[0]->getMemory().getDesc().getShape());
}
auto newOutputShapes = shapeInferGeneric(shapes);
IE_ASSERT(newOutputShapes.size() == outputShapes.size());
return newOutputShapes;
return shapeInferGeneric();
}
std::vector<VectorDims> MKLDNNNode::shapeInferGeneric(const std::vector<Shape>& shapes) const {
if (shapes.size() < opToShapeInfer->get_input_size()) {
IE_THROW(Unexpected) << "MKLDNNNode::shapeInferGeneric input shapes vector size is " << shapes.size() << ", but " << opToShapeInfer->get_input_size() <<
" required for node with name: " << getName();
}
std::vector<VectorDims> MKLDNNNode::shapeInferGeneric(const std::vector<ov::StaticShape>& input_shapes,
uint32_t input_value_port_mask) const {
// collect input values
std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>> input_values;
if (input_value_port_mask) {
const auto & iranks = shapeInference->get_input_ranks();
for (size_t port = 0; port < iranks.size(); port++) {
if (input_value_port_mask & (1 << port)) {
const auto& memPtr = getParentEdgesAtPort(port)[0]->getMemory();
for (size_t i = 0; i < opToShapeInfer->get_input_size(); i++) {
if (!dynamic_cast<ngraph::opset1::Constant *>(opToShapeInfer->get_input_node_ptr(i))) {
opToShapeInfer->get_input_tensor(i).set_partial_shape(shapes[i].toPartialShape());
ov::Shape shape(memPtr.getStaticDims());
// use scalar shape {} instead of {1} if required by shapeInference
if (iranks[port] == 0) {
shape = ov::Shape();
}
input_values[port] = std::make_shared<ngraph::runtime::HostTensor>(
InferenceEngine::details::convertPrecision(memPtr.getDesc().getPrecision()),
shape,
memPtr.GetPtr());
}
}
}
opToShapeInfer->validate_and_infer_types();
// call shape inference API
std::vector<ov::StaticShape> output_shapes = shapeInference->infer(input_shapes, input_values);
std::vector<VectorDims> newOutputShapes(opToShapeInfer->get_output_size());
for (size_t i = 0; i < newOutputShapes.size(); i++) {
const auto &partShape = opToShapeInfer->get_output_partial_shape(i);
if (partShape.is_dynamic()) {
std::ostringstream errorMessage;
errorMessage << "Can't compute static output shape on " << i << " port for node with name: " << getName();
errorMessage << ". Input shapes = ( ";
for (size_t in = 0; in < opToShapeInfer->get_input_size(); in++) {
errorMessage << in << " port = " << opToShapeInfer->get_input_partial_shape(in) << ", ";
}
errorMessage << "). Output shapes = ( ";
for (size_t out = 0; out < opToShapeInfer->get_output_size(); out++) {
errorMessage << out << " port = " << opToShapeInfer->get_output_partial_shape(out) << ", ";
}
errorMessage << ")";
IE_THROW(NotImplemented) << errorMessage.str();
std::vector<VectorDims> result(output_shapes.size());
std::transform(output_shapes.begin(), output_shapes.end(), result.begin(), [](const ov::StaticShape& s) {
return s.to_shape();
});
return result;
}
std::vector<VectorDims> MKLDNNNode::shapeInferGeneric(const std::vector<Shape>& shapes,
uint32_t input_value_port_mask) const {
std::vector<ov::StaticShape> input_shapes;
input_shapes.reserve(shapes.size());
for (size_t i = 0; i < shapes.size(); i++)
input_shapes.emplace_back(shapes[i].getStaticDims());
return shapeInferGeneric(input_shapes, input_value_port_mask);
}
std::vector<VectorDims> MKLDNNNode::shapeInferGeneric(uint32_t input_value_port_mask) const {
std::vector<ov::StaticShape> input_shapes;
const auto & iranks = shapeInference->get_input_ranks();
input_shapes.reserve(iranks.size());
for (size_t port = 0; port < iranks.size(); port++) {
if (iranks[port] == 0) {
input_shapes.emplace_back();
} else {
input_shapes.emplace_back(getParentEdgesAtPort(port)[0]->getMemory().getStaticDims());
}
newOutputShapes[i] = partShape.get_shape();
}
return newOutputShapes;
return shapeInferGeneric(input_shapes, input_value_port_mask);
}
void MKLDNNNode::updateLastInputDims() {
@ -1496,16 +1514,3 @@ bool MKLDNNNode::canFuseSimpleOperation(const MKLDNNNodePtr& node) const {
}
return false;
}
void MKLDNNNode::createShapeInferSubgraph(const std::shared_ptr<ngraph::Node>& op) {
ngraph::OutputVector inputsForShapeInfer;
for (size_t i = 0; i < inputShapes.size(); i++) {
if (dynamic_cast<ngraph::opset1::Constant *>(op->get_input_node_ptr(i))) {
inputsForShapeInfer.push_back(op->get_input_node_ptr(i)->clone_with_new_inputs(ngraph::OutputVector{}));
} else {
inputsForShapeInfer.push_back(std::make_shared<ngraph::opset1::Parameter>(op->get_input_element_type(i),
op->get_input_partial_shape(i)));
}
}
opToShapeInfer = op->clone_with_new_inputs(inputsForShapeInfer);
}

View File

@ -31,6 +31,9 @@
#include "memory_desc/cpu_memory_desc.h"
#include "cache/multi_cache.h"
#include <utils/shape_inference/static_shape.hpp>
#include <utils/shape_inference/shape_inference.hpp>
namespace MKLDNNPlugin {
using MKLDNNNodePtr = std::shared_ptr<MKLDNNNode>;
@ -750,7 +753,8 @@ protected:
bool inputShapesModified() const;
virtual bool needShapeInfer() const;
std::vector<VectorDims> shapeInferGeneric(const std::vector<Shape>& inputDims) const;
std::vector<VectorDims> shapeInferGeneric(const std::vector<Shape>& inputDims, uint32_t value_port_mask = 0) const;
std::vector<VectorDims> shapeInferGeneric(uint32_t value_port_mask = 0) const;
virtual std::vector<VectorDims> shapeInfer() const;
// TODO [DS] : make pure after all nodes will be support dynamic shapes
virtual void executeDynamicImpl(mkldnn::stream strm) {
@ -770,7 +774,7 @@ protected:
std::vector<VectorDims> lastInputDims = {};
std::shared_ptr<ngraph::Node> opToShapeInfer;
std::shared_ptr<IShapeInfer> shapeInference;
private:
std::vector<MKLDNNEdgeWeakPtr> parentEdges;
@ -797,8 +801,6 @@ private:
bool isEdgesEmpty(const std::vector<MKLDNNEdgeWeakPtr>& edges) const;
void createShapeInferSubgraph(const std::shared_ptr<ngraph::Node>& op);
template <class PD, class D, typename FPD>
typename std::enable_if<!std::is_same<FPD, bool>::value, PD>::type
createPd(MKLDNNDescriptor desc) {
@ -817,11 +819,23 @@ private:
enum LOOK { LOOK_UP = 1, LOOK_DOWN = 2 };
ConstantType checkConstant(LOOK look, std::vector<MKLDNNNodePtr>& checkNodes);
std::vector<VectorDims> shapeInferGeneric(const std::vector<ov::StaticShape>& input_shapes,
uint32_t input_value_port_mask) const;
#ifdef CPU_DEBUG_CAPS
friend class Verbose;
#endif
};
constexpr uint64_t PortMask(int n) {
return 1 << n;
}
template <class... T>
constexpr uint64_t PortMask(int n, T... rest) {
return PortMask(rest...) | (1 << n);
}
class MKLDNNNode::NodesFactory : public openvino::cc::Factory<Type,
MKLDNNNode*(const std::shared_ptr<ngraph::Node>& op,
const mkldnn::engine &,

View File

@ -96,6 +96,10 @@ void MKLDNNBatchToSpaceNode::initSupportedPrimitiveDescriptors() {
}
}
std::vector<VectorDims> MKLDNNBatchToSpaceNode::shapeInfer() const {
return MKLDNNNode::shapeInferGeneric(PortMask(1, 2, 3));
}
static std::vector<size_t> getShape5D(const SizeVector &shape) {
std::vector<size_t> shape5D(5, 1);
for (int i = 0; i < 2; i++) {

View File

@ -21,6 +21,7 @@ public:
void execute(mkldnn::stream strm) override;
bool created() const override;
std::vector<VectorDims> shapeInfer() const override;
bool needPrepareParams() const override { return false; };
void executeDynamicImpl(mkldnn::stream strm) override;

View File

@ -182,29 +182,7 @@ bool MKLDNNBroadcastNode::needShapeInfer() const {
}
std::vector<VectorDims> MKLDNNBroadcastNode::shapeInfer() const {
ngraph::OutputVector inputsForShapeInfer {
std::make_shared<ov::op::v0::Parameter>(opToShapeInfer->get_input_element_type(INPUT_DATA_IDX),
getParentEdgesAtPort(INPUT_DATA_IDX)[0]->getMemory().GetShape().toPartialShape()),
std::make_shared<ov::op::v0::Constant>(ov::element::Type_t::i32,
getParentEdgesAtPort(TARGET_SHAPE_IDX)[0]->getMemory().GetShape().getStaticDims(),
getParentEdgesAtPort(TARGET_SHAPE_IDX)[0]->getMemory().GetPtr())
};
if (opToShapeInfer->get_input_size() > AXES_MAPPING_IDX) {
inputsForShapeInfer.push_back(std::make_shared<ov::op::v0::Constant>(ov::element::Type_t::i32,
getParentEdgesAtPort(AXES_MAPPING_IDX)[0]->getMemory().GetShape().getStaticDims(),
getParentEdgesAtPort(AXES_MAPPING_IDX)[0]->getMemory().GetPtr()));
}
const auto localShapeInferOp = opToShapeInfer->clone_with_new_inputs(inputsForShapeInfer);
localShapeInferOp->validate_and_infer_types();
std::vector<VectorDims> newOutputShapes(outputShapes.size());
for (size_t i = 0lu; i < newOutputShapes.size(); i++) {
const auto &partShape = localShapeInferOp->get_output_partial_shape(i);
newOutputShapes[i] = partShape.get_shape();
}
return newOutputShapes;
return MKLDNNNode::shapeInferGeneric(PortMask(TARGET_SHAPE_IDX, AXES_MAPPING_IDX));
}
bool MKLDNNBroadcastNode::isExecutable() const {

View File

@ -1066,15 +1066,10 @@ void MKLDNNConvolutionNode::executeDynamicImpl(mkldnn::stream strm) {
}
void MKLDNNConvolutionNode::updatePadding() {
//update padding. TODO [DS] : rewrite when the final shape inference interface is available
//update padding.
if (isDynamicNode() && autoPadding) {
if (auto convolutionOp = ov::as_type_ptr<ov::op::v1::Convolution>(opToShapeInfer)) {
paddingL = convolutionOp->get_pads_begin();
paddingR = convolutionOp->get_pads_end();
} else if (auto groupConvolutionOp = ov::as_type_ptr<ov::op::v1::GroupConvolution>(opToShapeInfer)) {
paddingL = groupConvolutionOp->get_pads_begin();
paddingR = groupConvolutionOp->get_pads_end();
}
paddingL = shapeInference->get_pads_begin();
paddingR = shapeInference->get_pads_end();
}
}

View File

@ -224,26 +224,6 @@ bool MKLDNNDeconvolutionNode::canFuse(const MKLDNNNodePtr& node) const {
return (fusedWith.empty() && node->canBePerformedAsScaleShift(this));
}
void MKLDNNDeconvolutionNode::initPadding(std::shared_ptr<ngraph::Node> op, const Shape &inDims, const std::vector<int32_t>& outSpDims) {
std::vector<ov::StaticShape> input_shapes{inDims.getStaticDims(), getWeightDims()};
ov::StaticShape output_shape_input;
if (externOutShape) {
IE_ASSERT(outSpDims.size() == getInputShapeAtPort(2).getStaticDims()[0]);
input_shapes.push_back({outSpDims.size()});
for (size_t i = 0; i < outSpDims.size(); i++) {
output_shape_input.push_back(outSpDims[i]);
}
}
if (getAlgorithm() == DeconvolutionCommon) {
auto deconv = ngraph::as_type_ptr<ngraph::op::v1::ConvolutionBackpropData>(op);
IE_ASSERT(ov::op::v1::resolve_auto_pad_for_shape_back_prop(deconv.get(), paddingL, paddingR, input_shapes, output_shape_input, 2, 2));
} else if (getAlgorithm() == DeconvolutionGrouped) {
auto deconv = ngraph::as_type_ptr<ngraph::op::v1::GroupConvolutionBackpropData>(op);
IE_ASSERT(ov::op::v1::resolve_auto_pad_for_shape_back_prop(deconv.get(), paddingL, paddingR, input_shapes, output_shape_input, 2, 3));
}
}
std::pair<VectorDims, VectorDims> MKLDNNDeconvolutionNode::makeDummyInOutShape() {
auto inShape = MemoryDescUtils::makeDummyShape(getInputShapeAtPort(0));
auto outShape = getOutputShapeAtPort(0);
@ -276,8 +256,9 @@ std::pair<VectorDims, VectorDims> MKLDNNDeconvolutionNode::makeDummyInOutShape()
inShape = Shape(inputDims);
}
initPadding(opToShapeInfer, inShape, lastOutputSpatialDims);
outShape = Shape(shapeInferInternal(inShape.getStaticDims(), lastOutputSpatialDims));
paddingL = shapeInference->get_pads_begin();
paddingR = shapeInference->get_pads_end();
}
return {inShape.getStaticDims(), outShape.getStaticDims()};
}
@ -464,8 +445,7 @@ VectorDims MKLDNNDeconvolutionNode::shapeInferInternal(const VectorDims &inDims,
outSpDims.data())});
}
std::vector<ov::StaticShape> outputShapes(1);
shape_inference(opToShapeInfer.get(), inputShapes, outputShapes, inputValues);
std::vector<ov::StaticShape> outputShapes = shapeInference->infer(inputShapes, inputValues);
return outputShapes.back().to_shape();
}
@ -592,7 +572,8 @@ void MKLDNNDeconvolutionNode::prepareParams() {
}
pAttrLocal = pAttr;
if (autoPad || externOutShape) {
initPadding(opToShapeInfer, inMemoryDesc->getShape(), externOutShape ? readOutputSpatialDims() : std::vector<int32_t>{});
paddingL = shapeInference->get_pads_begin();
paddingR = shapeInference->get_pads_end();
}
initPaddingR(inMemoryDesc->getShape(), outMemoryDesc->getShape());
} else {

View File

@ -1137,10 +1137,8 @@ void MKLDNNDeformableConvolutionNode::execute(mkldnn::stream strm) {
}
void MKLDNNDeformableConvolutionNode::updatePadding() {
//update padding. TODO [DS] : rewrite when the final shape inference interface is available
if (isDynamicNode() && autoPadding) {
auto defConvNodeBase = std::dynamic_pointer_cast<ngraph::op::util::DeformableConvolutionBase>(opToShapeInfer);
defConvAttr.padL = defConvNodeBase->get_pads_begin();
defConvAttr.padL = shapeInference->get_pads_begin();
}
}

View File

@ -121,6 +121,10 @@ void MKLDNNEmbeddingSegmentsSumNode::getIndices(int embIndex, const int*& indice
}
}
std::vector<VectorDims> MKLDNNEmbeddingSegmentsSumNode::shapeInfer() const {
return MKLDNNNode::shapeInferGeneric(PortMask(NUM_SEGMENTS_IDX));
}
void MKLDNNEmbeddingSegmentsSumNode::executeDynamicImpl(mkldnn::stream strm) {
execute(strm);
}

View File

@ -27,6 +27,7 @@ public:
protected:
void prepareParams() override;
std::vector<VectorDims> shapeInfer() const override;
void executeDynamicImpl(mkldnn::stream strm) override;
private:

View File

@ -2044,33 +2044,8 @@ bool MKLDNNInterpolateNode::needShapeInfer() const {
}
std::vector<VectorDims> MKLDNNInterpolateNode::shapeInfer() const {
std::vector<ov::StaticShape> input_shapes = {
getParentEdgesAtPort(DATA_ID)[0]->getMemory().GetShape().getStaticDims(),
getParentEdgesAtPort(TARGET_SHAPE_ID)[0]->getMemory().GetShape().getStaticDims(),
getParentEdgesAtPort(SCALES_ID)[0]->getMemory().GetShape().getStaticDims()
};
const size_t port = shapeCalcMode == InterpolateShapeCalcMode::sizes ? TARGET_SHAPE_ID : SCALES_ID;
const auto &memory = getParentEdgesAtPort(port)[0]->getMemory();
std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>> input_values = {
{port, std::make_shared<ngraph::runtime::HostTensor>(InferenceEngine::details::convertPrecision(memory.getDesc().getPrecision()),
memory.getStaticDims(), memory.GetPtr())}
};
if (getParentEdges().size() > AXES_ID) {
const auto &memory = getParentEdgesAtPort(AXES_ID)[0]->getMemory();
input_shapes.push_back(memory.getStaticDims());
input_values.insert({3, std::make_shared<ngraph::runtime::HostTensor>(InferenceEngine::details::convertPrecision(memory.getDesc().getPrecision()),
memory.getStaticDims(), memory.GetPtr())});
}
std::vector<ov::StaticShape> output_shapes = {{}};
shape_inference(opToShapeInfer.get(), input_shapes, output_shapes, input_values);
std::vector<VectorDims> result(output_shapes.size());
std::transform(output_shapes.begin(), output_shapes.end(), result.begin(), [](const ov::StaticShape& s){ return s.to_shape(); });
return result;
return shapeInferGeneric(PortMask(port, AXES_ID));
}
void MKLDNNInterpolateNode::executeDynamicImpl(mkldnn::stream strm) {

View File

@ -331,6 +331,10 @@ void MKLDNNPadNode::executeDynamicImpl(mkldnn::stream strm) {
execute(strm);
}
std::vector<VectorDims> MKLDNNPadNode::shapeInfer() const {
return MKLDNNNode::shapeInferGeneric(PortMask(PADS_BEGIN_ID, PADS_END_ID));
}
static inline size_t parallel_init(size_t start, size_t nDims, const VectorDims& dims, VectorDims& indexes) {
for (int j = nDims - 1; j >= 0; j--) {
indexes[j] = start % dims[j];

View File

@ -26,6 +26,7 @@ public:
bool isExecutable() const override;
protected:
std::vector<VectorDims> shapeInfer() const override;
void executeDynamicImpl(mkldnn::stream strm) override;
private:

View File

@ -297,32 +297,6 @@ void MKLDNNPoolingNode::getSupportedDescriptors() {
}
}
std::pair<std::vector<ptrdiff_t>, std::vector<ptrdiff_t>> MKLDNNPoolingNode::getPaddingFromNode(std::shared_ptr<ov::Node> node) const {
const auto convertPadding = [](const VectorDims &newPads) {
std::vector<ptrdiff_t> pads(newPads.size());
for (int i = 0; i < newPads.size(); i++) {
pads[i] = static_cast<ptrdiff_t>(newPads[i]);
}
return pads;
};
VectorDims padsBegin, padsEnd;
if (isMaxPool8) {
const auto pool = ov::as_type_ptr<const ov::op::v8::MaxPool>(opToShapeInfer);
padsBegin = pool->get_pads_begin();
padsEnd = pool->get_pads_end();
} else if (getAlgorithm() == PoolingMax) {
const auto pool = ov::as_type_ptr<const ov::op::v1::MaxPool>(opToShapeInfer);
padsBegin = pool->get_pads_begin();
padsEnd = pool->get_pads_end();
} else if (getAlgorithm() == PoolingAvg) {
const auto pool = ov::as_type_ptr<const ov::op::v1::AvgPool>(opToShapeInfer);
padsBegin = pool->get_pads_begin();
padsEnd = pool->get_pads_end();
}
return {convertPadding(padsBegin), convertPadding(padsEnd)};
}
void MKLDNNPoolingNode::prepareParams() {
const NodeDesc *selected_pd = getSelectedPrimitiveDescriptor();
if (selected_pd == nullptr)
@ -343,7 +317,8 @@ void MKLDNNPoolingNode::prepareParams() {
if (isDynamicNode()) {
if (auto_pad) {
std::tie(data_pad_begin, data_pad_end) = getPaddingFromNode(opToShapeInfer);
data_pad_begin = shapeInference->get_pads_begin();
data_pad_end = shapeInference->get_pads_end();
}
initEffectiveAttributes(inDesc->getShape(), outDesc->getShape());
}
@ -462,7 +437,8 @@ void MKLDNNPoolingNode::createDescriptor(const std::vector<MemoryDescPtr> &input
auto outDims = shapeInferGeneric({Shape(inDesc->getShape().getStaticDims())});
outDesc = outDesc->cloneWithNewDims(outDims[0]);
if (auto_pad) {
std::tie(data_pad_begin, data_pad_end) = getPaddingFromNode(opToShapeInfer);
data_pad_begin = shapeInference->get_pads_begin();
data_pad_end = shapeInference->get_pads_end();
}
initEffectiveAttributes(inDesc->getShape(), outDesc->getShape());
}

View File

@ -38,7 +38,6 @@ protected:
private:
void setPostOps(mkldnn::primitive_attr &attr, bool initWeights = false) const;
std::pair<std::vector<ptrdiff_t>, std::vector<ptrdiff_t>> getPaddingFromNode(std::shared_ptr<ov::Node> node) const;
void initEffectiveAttributes(const Shape &inDims, const Shape &outDims);
mkldnn::algorithm getPoolingAlgorithm() const;
std::shared_ptr<mkldnn::pooling_v2_forward::desc> createDescriptorInternal(const mkldnn::memory::desc& in_candidate,

View File

@ -83,6 +83,10 @@ void MKLDNNRangeNode::initSupportedPrimitiveDescriptors() {
}
}
std::vector<VectorDims> MKLDNNRangeNode::shapeInfer() const {
return MKLDNNNode::shapeInferGeneric(PortMask(RANGE_START, RANGE_LIMIT, RANGE_DELTA));
}
void MKLDNNRangeNode::executeDynamicImpl(mkldnn::stream strm) {
execute(strm);
}

View File

@ -19,6 +19,7 @@ public:
bool created() const override;
bool needPrepareParams() const override {return false;};
bool needShapeInfer() const override {return false;};
std::vector<VectorDims> shapeInfer() const override;
void executeDynamicImpl(mkldnn::stream strm) override;
static bool isSupportedOperation(const std::shared_ptr<const ngraph::Node>& op, std::string& errorMessage) noexcept;

View File

@ -1868,6 +1868,10 @@ bool MKLDNNReduceNode::isExecutable() const {
return !isInputTensorAtPortEmpty(REDUCE_DATA);
}
std::vector<VectorDims> MKLDNNReduceNode::shapeInfer() const {
return MKLDNNNode::shapeInferGeneric(PortMask(REDUCE_INDEXES));
}
void MKLDNNReduceNode::prepareParams() {
src_dims = getParentEdgesAtPort(REDUCE_DATA)[0]->getMemory().getDesc().getShape().getDims();
std::vector<int> reduce_axes;

View File

@ -91,6 +91,7 @@ public:
void createPrimitive() override;
bool created() const override;
void execute(mkldnn::stream strm) override;
std::vector<VectorDims> shapeInfer() const override;
void executeDynamicImpl(mkldnn::stream strm) override;
bool canFuse(const MKLDNNNodePtr& node) const override;
bool canBeInPlace() const override {

View File

@ -74,40 +74,8 @@ void MKLDNNReferenceNode::execute(mkldnn::stream strm) {
}
}
// TODO [DS]: rewrite after new shape infer will be added
std::vector<VectorDims> MKLDNNReferenceNode::shapeInfer() const {
ngraph::OutputVector inputsForShapeInfer;
for (size_t i = 0; i < opToShapeInfer->get_input_size(); i++) {
const auto &mem = getParentEdgesAtPort(i)[0]->getMemory();
const auto dims = opToShapeInfer->get_input_partial_shape(i).rank().get_length() == 0 ? VectorDims{} : mem.getStaticDims();
inputsForShapeInfer.push_back(std::make_shared<ngraph::opset1::Constant>(InferenceEngine::details::convertPrecision(mem.getDesc().getPrecision()),
dims,
mem.GetPtr()));
}
const auto localShapeInferOp = opToShapeInfer->clone_with_new_inputs(inputsForShapeInfer);
localShapeInferOp->validate_and_infer_types();
std::vector<VectorDims> newOutputShapes(outputShapes.size());
for (size_t i = 0; i < newOutputShapes.size(); i++) {
const auto &partShape = localShapeInferOp->get_output_partial_shape(i);
if (partShape.is_dynamic()) {
std::ostringstream errorMessage;
errorMessage << "Can't compute static output shape on " << i << " port for node with name: " << getName();
errorMessage << ". Input shapes = ( ";
for (size_t in = 0; in < opToShapeInfer->get_input_size(); in++) {
errorMessage << in << " port = " << opToShapeInfer->get_input_partial_shape(in) << ", ";
}
errorMessage << "). Output shapes = ( ";
for (size_t out = 0; out < opToShapeInfer->get_output_size(); out++) {
errorMessage << out << " port = " << opToShapeInfer->get_output_partial_shape(out) << ", ";
}
errorMessage << ")";
IE_THROW(NotImplemented) << errorMessage.str();
}
newOutputShapes[i] = partShape.get_shape();
}
return newOutputShapes;
return MKLDNNNode::shapeInferGeneric(0xFFFFFFFF);
}
void MKLDNNReferenceNode::executeDynamicImpl(mkldnn::stream strm) {

View File

@ -75,7 +75,6 @@ bool MKLDNNReshapeNode::needShapeInfer() const {
return false;
}
// TODO [DS]: rewrite after new shape infer will be added
std::vector<VectorDims> MKLDNNReshapeNode::shapeInfer() const {
const auto &memPtr = getParentEdgesAtPort(1)[0]->getMemory();
@ -86,16 +85,7 @@ std::vector<VectorDims> MKLDNNReshapeNode::shapeInfer() const {
lastSecondInputValues[i] = sndInput[i];
}
std::vector<ov::StaticShape> input_shapes = {getParentEdgesAtPort(0)[0]->getMemory().GetShape().getStaticDims(), memPtr.getStaticDims()};
std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>> input_values = {
{1, std::make_shared<ngraph::runtime::HostTensor>(ngraph::element::Type_t::i32, memPtr.getStaticDims(), memPtr.GetPtr())}
};
std::vector<ov::StaticShape> output_shapes = {{}};
shape_inference(opToShapeInfer.get(), input_shapes, output_shapes, input_values);
std::vector<VectorDims> result(output_shapes.size());
std::transform(output_shapes.begin(), output_shapes.end(), result.begin(), [](const ov::StaticShape& s){ return s.to_shape(); });
return result;
return shapeInferGeneric(PortMask(1));
}
void MKLDNNReshapeNode::getSupportedDescriptors() {

View File

@ -97,6 +97,10 @@ void MKLDNNSpaceToBatchNode::initSupportedPrimitiveDescriptors() {
}
}
std::vector<VectorDims> MKLDNNSpaceToBatchNode::shapeInfer() const {
return MKLDNNNode::shapeInferGeneric(PortMask(1, 2, 3));
}
static std::vector<size_t> getShape5D(const SizeVector &shape) {
std::vector<size_t> shape5D(5, 1);
for (int i = 0; i < 2; i++) {

View File

@ -21,6 +21,7 @@ public:
void execute(mkldnn::stream strm) override;
bool created() const override;
std::vector<VectorDims> shapeInfer() const override;
bool needPrepareParams() const override { return false; };
void executeDynamicImpl(mkldnn::stream strm) override;

View File

@ -239,6 +239,10 @@ bool MKLDNNSplitNode::needPrepareParams() const {
return MKLDNNNode::inputShapesModified();
}
std::vector<VectorDims> MKLDNNSplitNode::shapeInfer() const {
return MKLDNNNode::shapeInferGeneric(PortMask(1, 2));
}
void MKLDNNSplitNode::prepareParams() {
const auto &srcMemPtr = getParentEdgesAtPort(0)[0]->getMemoryPtr();
if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr()) {

View File

@ -29,6 +29,7 @@ public:
bool needPrepareParams() const override;
void prepareParams() override;
std::vector<VectorDims> shapeInfer() const override;
void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); }
private:

View File

@ -123,23 +123,7 @@ bool MKLDNNTileNode::needShapeInfer() const {
}
std::vector<VectorDims> MKLDNNTileNode::shapeInfer() const {
ngraph::OutputVector inputsForShapeInfer {
std::make_shared<ov::op::v0::Parameter>(opToShapeInfer->get_input_element_type(TILE_INPUT),
getParentEdgesAtPort(TILE_INPUT)[0]->getMemory().GetShape().toPartialShape()),
std::make_shared<ov::op::v0::Constant>(ov::element::Type_t::i32,
getParentEdgesAtPort(TILE_REPEATS)[0]->getMemory().GetShape().getStaticDims(),
getParentEdgesAtPort(TILE_REPEATS)[0]->getMemory().GetPtr())
};
const auto localShapeInferOp = opToShapeInfer->clone_with_new_inputs(inputsForShapeInfer);
localShapeInferOp->validate_and_infer_types();
std::vector<VectorDims> newOutputShapes(outputShapes.size());
for (size_t i = 0lu; i < newOutputShapes.size(); i++) {
const auto &partShape = localShapeInferOp->get_output_partial_shape(i);
newOutputShapes[i] = partShape.get_shape();
}
return newOutputShapes;
return MKLDNNNode::shapeInferGeneric(PortMask(TILE_REPEATS));
}
void MKLDNNTileNode::executeDynamicImpl(mkldnn::stream strm) {

View File

@ -167,39 +167,7 @@ bool MKLDNNTopKNode::needShapeInfer() const {
}
std::vector<VectorDims> MKLDNNTopKNode::shapeInfer() const {
if (dynamic_cast<ngraph::opset1::Constant*>(opToShapeInfer->get_input_node_ptr(1))) {
return MKLDNNNode::shapeInfer();
}
opToShapeInfer->get_input_tensor(0).set_partial_shape(getParentEdgesAtPort(0)[0]->getMemory().getDesc().getShape().toPartialShape());
const auto& kMemory = getParentEdgesAtPort(1)[0]->getMemory();
const auto ngPrecision = InferenceEngine::details::convertPrecision(kMemory.getDesc().getPrecision());
const auto kConst = ngraph::opset1::Constant::create(ngPrecision, VectorDims{}, kMemory.GetPtr());
const auto localShapeInferOp = opToShapeInfer->clone_with_new_inputs({ opToShapeInfer->input_value(0), kConst });
localShapeInferOp->validate_and_infer_types();
std::vector<VectorDims> newOutputShapes(outputShapes.size());
for (size_t i = 0; i < newOutputShapes.size(); ++i) {
const auto& pShape = localShapeInferOp->get_output_partial_shape(i);
if (pShape.is_dynamic()) {
std::ostringstream errorMessage;
errorMessage << "Can't compute static output shape on " << i << " port for node with name: " << getName();
errorMessage << ". Input shapes = ( ";
for (size_t in = 0; in < opToShapeInfer->get_input_size(); in++) {
errorMessage << in << " port = " << opToShapeInfer->get_input_partial_shape(in) << ", ";
}
errorMessage << "). Output shapes = ( ";
for (size_t out = 0; out < opToShapeInfer->get_output_size(); out++) {
errorMessage << out << " port = " << opToShapeInfer->get_output_partial_shape(out) << ", ";
}
errorMessage << ")";
IE_THROW(NotImplemented) << errorMessage.str();
}
newOutputShapes[i] = pShape.get_shape();
}
return newOutputShapes;
return MKLDNNNode::shapeInferGeneric(PortMask(1));
}
template <class Compare1, template <typename> class Compare2>

View File

@ -14,14 +14,23 @@
#include <openvino/opsets/opset8.hpp>
#include "assign_shape_inference.hpp"
#include "bucketize_shape_inference.hpp"
#include "convolution_shape_inference.hpp"
#include "ctc_greedy_decoder_seq_len_shape_inference.hpp"
#include "ctc_greedy_decoder_shape_inference.hpp"
#include "ctc_loss_shape_inference.hpp"
#include "detection_output_shape_inference.hpp"
#include "einsum_shape_inference.hpp"
#include "embedding_segments_sum_shape_inference.hpp"
#include "embeddingbag_offsets_shape_inference.hpp"
#include "experimental_detectron_detection_output_shape_inference.hpp"
#include "experimental_detectron_generate_proposals_shape_inference.hpp"
#include "experimental_detectron_prior_grid_generator_shape_inference.hpp"
#include "experimental_detectron_roi_feature_shape_inference.hpp"
#include "experimental_detectron_topkrois_shape_inference.hpp"
#include "extract_image_patches_shape_inference.hpp"
#include "fake_quantize.hpp"
#include "fft_base_shape_inference.hpp"
#include "gather_elements_shape_inference.hpp"
#include "gather_shape_inference.hpp"
#include "gather_tree_shape_inference.hpp"
@ -46,226 +55,507 @@
#include "bucketize_shape_inference.hpp"
#include "embedding_segments_sum_shape_inference.hpp"
#include "embeddingbag_offsets_shape_inference.hpp"
#include "experimental_detectron_roi_feature_shape_inference.hpp"
#include "pad_shape_inference.hpp"
#include "proposal_shape_inference.hpp"
#include "range_shape_inference.hpp"
#include "read_value_shape_inference.hpp"
#include "reduce_shape_inference.hpp"
#include "region_yolo_shape_inference.hpp"
#include "reorg_yolo_shape_inference.hpp"
#include "split_shape_inference.hpp"
#include "topk_shape_inference.hpp"
#include "variadic_split_shape_inference.hpp"
#include "einsum_shape_inference.hpp"
#include "strided_slice_shape_inference.hpp"
#include "experimental_detectron_generate_proposals_shape_inference.hpp"
#include "reverse_sequence_shape_inference.hpp"
#include "roi_align_shape_inference.hpp"
#include "roll_shape_inference.hpp"
#include "proposal_shape_inference.hpp"
#include "detection_output_shape_inference.hpp"
#include "scatter_elements_update_shape_inference.hpp"
#include "scatter_nd_base_shape_inference.hpp"
#include "select_shape_inference.hpp"
#include "shape_inference.hpp"
#include "shape_nodes.hpp"
#include "shuffle_channels_shape_inference.hpp"
#include "split_shape_inference.hpp"
#include "broadcast_shape_inference.hpp"
#include "static_shape.hpp"
#include "strided_slice_shape_inference.hpp"
#include "tile_shape_inference.hpp"
#include "topk_shape_inference.hpp"
#include "utils.hpp"
#include "variadic_split_shape_inference.hpp"
void shape_inference(ov::Node* op,
const std::vector<ov::StaticShape>& input_shapes,
std::vector<ov::StaticShape>& output_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data) {
if (auto node = ov::as_type<ov::opset8::Convolution>(op)) {
ov::CoordinateDiff pads_begin, pads_end;
bool status = resolve_auto_pad_for_shape(node, pads_begin, pads_end, input_shapes, 2, 2);
auto shapeInfer = make_shape_inference(op->shared_from_this());
output_shapes = shapeInfer->infer(input_shapes, constant_data);
}
class entryBase : public IShapeInfer {
public:
entryBase(std::shared_ptr<ov::Node> node) : node(node) {
for (size_t i = 0; i < node->get_input_size(); i++) {
const auto& shape = node->get_input_partial_shape(i);
if (shape.rank().is_static()) {
input_ranks.push_back(shape.rank().get_length());
} else {
input_ranks.push_back(-1);
}
}
}
const ov::CoordinateDiff& get_pads_begin() override {
OPENVINO_ASSERT(false, "entryBase do not support get_pads_begin() by default.");
}
const ov::CoordinateDiff& get_pads_end() override {
OPENVINO_ASSERT(false, "entryBase do not support get_pads_end() by default.");
}
const std::vector<int64_t>& get_input_ranks() override {
return input_ranks;
}
protected:
std::vector<int64_t> input_ranks;
std::shared_ptr<ov::Node> node;
};
template <typename OP>
class entryIO : public entryBase {
public:
using entryBase::entryBase;
std::vector<ov::StaticShape> infer(
const std::vector<ov::StaticShape>& input_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data) override {
auto op = static_cast<OP*>(node.get());
std::vector<ov::StaticShape> output_shapes(op->get_output_size());
shape_infer(op, input_shapes, output_shapes);
return output_shapes;
}
};
template <typename OP>
class entryIOC : public entryBase {
public:
using entryBase::entryBase;
std::vector<ov::StaticShape> infer(
const std::vector<ov::StaticShape>& input_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data) override {
auto op = static_cast<OP*>(node.get());
std::vector<ov::StaticShape> output_shapes(op->get_output_size());
shape_infer(op, input_shapes, output_shapes, constant_data);
return output_shapes;
}
};
class entryCopy : public entryBase {
public:
using entryBase::entryBase;
std::vector<ov::StaticShape> infer(
const std::vector<ov::StaticShape>& input_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data) override {
auto op = node.get();
std::vector<ov::StaticShape> output_shapes(op->get_output_size());
copy_shape_infer(op, input_shapes, output_shapes);
return output_shapes;
}
};
class entryFirstPassthrough : public entryBase {
public:
using entryBase::entryBase;
std::vector<ov::StaticShape> infer(
const std::vector<ov::StaticShape>& input_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data) override {
auto op = node.get();
std::vector<ov::StaticShape> output_shapes(op->get_output_size());
first_input_passthrough_infer(op, input_shapes, output_shapes);
return output_shapes;
}
};
class entryEltwise : public entryBase {
public:
using entryBase::entryBase;
std::vector<ov::StaticShape> infer(
const std::vector<ov::StaticShape>& input_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data) override {
auto op = node.get();
std::vector<ov::StaticShape> output_shapes(op->get_output_size());
eltwise_shape_infer(op, input_shapes, output_shapes);
return output_shapes;
}
};
class entryFallback : public entryBase {
public:
std::shared_ptr<ov::Node> local_op_default;
entryFallback(std::shared_ptr<ov::Node> node) : entryBase(node) {
ngraph::OutputVector new_inputs;
auto op = node.get();
for (size_t i = 0; i < op->get_input_size(); ++i) {
if (dynamic_cast<ov::opset1::Constant*>(op->get_input_node_ptr(i))) {
new_inputs.push_back(op->get_input_node_ptr(i)->clone_with_new_inputs(ov::OutputVector{}));
} else {
new_inputs.push_back(std::make_shared<ov::opset1::Parameter>(op->get_input_element_type(i),
op->get_input_partial_shape(i)));
}
}
local_op_default = op->clone_with_new_inputs(new_inputs);
}
virtual void post_validate_and_infer_types(const std::shared_ptr<ov::Node>& local_op) {}
std::vector<ov::StaticShape> infer(
const std::vector<ov::StaticShape>& input_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data) override {
auto op = node.get();
std::vector<ov::StaticShape> output_shapes;
std::shared_ptr<ov::Node> local_op;
if (!constant_data.empty()) {
ngraph::OutputVector new_inputs;
for (size_t i = 0; i < op->get_input_size(); ++i) {
if (constant_data.count(i)) {
new_inputs.push_back(std::make_shared<ov::opset1::Constant>(constant_data.at(i)));
} else if (dynamic_cast<ov::opset1::Constant*>(op->get_input_node_ptr(i))) {
new_inputs.push_back(op->get_input_node_ptr(i)->clone_with_new_inputs(ov::OutputVector{}));
} else {
new_inputs.push_back(std::make_shared<ov::opset1::Parameter>(op->get_input_element_type(i),
input_shapes[i].to_partial_shape()));
}
}
local_op = op->clone_with_new_inputs(new_inputs);
} else {
local_op = local_op_default;
OPENVINO_SUPPRESS_DEPRECATED_START
for (size_t i = 0; i < local_op->get_input_size(); i++) {
if (dynamic_cast<ov::opset1::Parameter*>(local_op->get_input_node_ptr(i))) {
local_op->get_input_tensor(i).set_partial_shape(input_shapes[i].to_partial_shape());
}
}
OPENVINO_SUPPRESS_DEPRECATED_END
}
local_op->validate_and_infer_types();
output_shapes.resize(local_op->get_output_size());
for (size_t i = 0; i < output_shapes.size(); ++i) {
const auto& partial_shape = local_op->get_output_partial_shape(i);
if (partial_shape.is_dynamic()) {
std::ostringstream errorMessage;
errorMessage << "Can't compute static output shape on " << i
<< " port for node with name: " << op->get_name();
errorMessage << ". Input shapes = ( ";
for (size_t in = 0; in < op->get_input_size(); in++) {
errorMessage << in << " port = " << op->get_input_partial_shape(in) << ", ";
}
errorMessage << "). Output shapes = ( ";
for (size_t out = 0; out < op->get_output_size(); out++) {
errorMessage << out << " port = " << op->get_output_partial_shape(out) << ", ";
}
errorMessage << ")";
OPENVINO_ASSERT(false, errorMessage.str());
}
output_shapes[i] = ov::StaticShape(partial_shape.to_shape());
}
post_validate_and_infer_types(local_op);
return output_shapes;
}
};
static inline ov::CoordinateDiff convertPadding(const ov::CoordinateDiff& newPads) {
return newPads;
}
static inline ov::CoordinateDiff convertPadding(const ov::Shape& newPads) {
std::vector<ptrdiff_t> pads(newPads.size());
for (int i = 0; i < newPads.size(); i++) {
pads[i] = static_cast<ptrdiff_t>(newPads[i]);
}
return pads;
}
template <typename OP>
class entryFallbackWithPadding : public entryFallback {
public:
using entryFallback::entryFallback;
ov::CoordinateDiff pads_begin, pads_end;
const ov::CoordinateDiff& get_pads_begin() override {
return pads_begin;
}
const ov::CoordinateDiff& get_pads_end() override {
return pads_end;
}
void post_validate_and_infer_types(const std::shared_ptr<ov::Node>& local_op) override {
auto node = dynamic_cast<OP*>(local_op.get());
OPENVINO_ASSERT(node);
pads_begin = convertPadding(node->get_pads_begin());
pads_end = convertPadding(node->get_pads_end());
}
};
template <typename OP>
class entryInterpolate : public entryBase {
public:
using entryBase::entryBase;
std::vector<ov::StaticShape> infer(
const std::vector<ov::StaticShape>& input_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data) override {
std::vector<size_t> pads_begin, pads_end;
auto op = static_cast<OP*>(node.get());
std::vector<ov::StaticShape> output_shapes(op->get_output_size());
correct_pads_attr(op, pads_begin, pads_end, input_shapes);
shape_infer(op, pads_begin, pads_end, input_shapes, output_shapes, constant_data);
return output_shapes;
}
};
template <typename OP>
class entryConv : public entryBase {
public:
entryConv(std::shared_ptr<OP> node, bool is_grouped) : entryBase(node), is_grouped(is_grouped) {}
const ov::CoordinateDiff& get_pads_begin() override {
return pads_begin;
}
const ov::CoordinateDiff& get_pads_end() override {
return pads_end;
}
std::vector<ov::StaticShape> infer(
const std::vector<ov::StaticShape>& input_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data) override {
auto op = static_cast<OP*>(node.get());
std::vector<ov::StaticShape> output_shapes(op->get_output_size());
bool status = resolve_auto_pad_for_shape(op, pads_begin, pads_end, input_shapes, 2, is_grouped ? 3 : 2);
OPENVINO_ASSERT(status,
"Convolution shape inference doesn't have enough information to calculate static shapes");
shape_infer(node, pads_begin, pads_end, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset8::GroupConvolution>(op)) {
ov::CoordinateDiff pads_begin, pads_end;
bool status = resolve_auto_pad_for_shape(node, pads_begin, pads_end, input_shapes, 2, 3);
OPENVINO_ASSERT(status,
"GroupConvolution shape inference doesn't have enough information to calculate static shapes");
shape_infer(node, pads_begin, pads_end, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset8::ConvolutionBackpropData>(op)) {
ov::CoordinateDiff pads_begin, pads_end;
shape_infer(op, pads_begin, pads_end, input_shapes, output_shapes);
return output_shapes;
}
protected:
ov::CoordinateDiff pads_begin, pads_end;
bool is_grouped;
};
template <typename OP>
class entryConvBackprop : public entryBase {
public:
entryConvBackprop(std::shared_ptr<OP> node, bool is_grouped) : entryBase(node), is_grouped(is_grouped) {}
const ov::CoordinateDiff& get_pads_begin() override {
return pads_begin;
}
const ov::CoordinateDiff& get_pads_end() override {
return pads_end;
}
std::vector<ov::StaticShape> infer(
const std::vector<ov::StaticShape>& input_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data) override {
ov::StaticShape output_shape_input;
if (node->get_input_size() == 3)
auto op = static_cast<OP*>(node.get());
std::vector<ov::StaticShape> output_shapes(op->get_output_size());
if (op->get_input_size() == 3)
get_data_as_shape<ov::StaticShape>(2, op, output_shape_input, constant_data);
bool status =
resolve_auto_pad_for_shape_back_prop(node, pads_begin, pads_end, input_shapes, output_shape_input, 2, 2);
bool status = resolve_auto_pad_for_shape_back_prop(op,
pads_begin,
pads_end,
input_shapes,
output_shape_input,
2,
is_grouped ? 3 : 2);
OPENVINO_ASSERT(
status,
"ConvolutionBackpropData shape inference doesn't have enough information to calculate static shapes");
shape_infer(node, pads_begin, pads_end, output_shape_input, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset8::GroupConvolutionBackpropData>(op)) {
ov::CoordinateDiff pads_begin, pads_end;
ov::StaticShape output_shape_input;
if (node->get_input_size() == 3)
get_data_as_shape<ov::StaticShape>(2, op, output_shape_input, constant_data);
bool status =
resolve_auto_pad_for_shape_back_prop(node, pads_begin, pads_end, input_shapes, output_shape_input, 2, 3);
OPENVINO_ASSERT(
status,
"GroupConvolutionBackpropData shape inference doesn't have enough information to calculate static shapes");
shape_infer(node, pads_begin, pads_end, output_shape_input, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::op::util::ArithmeticReductionKeepDims>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::op::util::LogicalReductionKeepDims>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (ov::is_type<ov::op::util::UnaryElementwiseArithmetic>(op) ||
ov::is_type<ov::opset1::Convert>(op) || ov::is_type<ov::opset1::Clamp>(op) ||
ov::is_type<ov::opset1::GRN>(op) || ov::is_type<ov::opset1::LRN>(op) ||
ov::is_type<ov::opset1::LogicalNot>(op) || ov::is_type<ov::opset4::Mish>(op) ||
ov::is_type<ov::opset2::MVN>(op) || ov::is_type<ov::opset6::MVN>(op) ||
ov::is_type<ov::opset1::PRelu>(op) || ov::is_type<ov::opset1::Relu>(op) ||
ov::is_type<ov::opset4::Swish>(op) || ov::is_type<ov::opset1::Elu>(op) ||
ov::is_type<ov::opset1::Softmax>(op) || ov::is_type<ov::opset8::Softmax>(op) ||
ov::is_type<ov::opset5::Round>(op)) {
copy_shape_infer(node, input_shapes, output_shapes);
shape_infer(op, pads_begin, pads_end, output_shape_input, input_shapes, output_shapes);
return output_shapes;
}
protected:
ov::CoordinateDiff pads_begin, pads_end;
bool is_grouped;
};
template <typename OP>
std::shared_ptr<entryIOC<OP>> make_shared_entryIOC(std::shared_ptr<OP> node) {
return std::make_shared<entryIOC<OP>>(node);
}
template <typename OP>
std::shared_ptr<entryIO<OP>> make_shared_entryIO(std::shared_ptr<OP> node) {
return std::make_shared<entryIO<OP>>(node);
}
std::shared_ptr<IShapeInfer> make_shape_inference(const std::shared_ptr<ngraph::Node>& op) {
if (auto node = ov::as_type_ptr<ov::opset8::Convolution>(op)) {
return std::make_shared<entryConv<ov::opset8::Convolution>>(node, false);
} else if (auto node = ov::as_type_ptr<ov::opset8::GroupConvolution>(op)) {
return std::make_shared<entryConv<ov::opset8::GroupConvolution>>(node, true);
} else if (auto node = ov::as_type_ptr<ov::opset8::ConvolutionBackpropData>(op)) {
return std::make_shared<entryConvBackprop<ov::opset8::ConvolutionBackpropData>>(node, false);
} else if (auto node = ov::as_type_ptr<ov::opset8::GroupConvolutionBackpropData>(op)) {
return std::make_shared<entryConvBackprop<ov::opset8::GroupConvolutionBackpropData>>(node, true);
} else if (auto node = ov::as_type_ptr<ov::op::util::ArithmeticReductionKeepDims>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::op::util::LogicalReductionKeepDims>(op)) {
return make_shared_entryIOC(node);
} else if (ov::is_type<ov::op::util::UnaryElementwiseArithmetic>(op) || ov::is_type<ov::opset1::Convert>(op) ||
ov::is_type<ov::opset1::Clamp>(op) || ov::is_type<ov::opset1::GRN>(op) ||
ov::is_type<ov::opset1::LogicalNot>(op) || ov::is_type<ov::opset4::Mish>(op) ||
ov::is_type<ov::opset2::MVN>(op) || ov::is_type<ov::opset1::Relu>(op) ||
ov::is_type<ov::opset1::Elu>(op) || ov::is_type<ov::opset1::Softmax>(op) ||
ov::is_type<ov::opset8::Softmax>(op) || ov::is_type<ov::opset5::Round>(op)) {
return std::make_shared<entryCopy>(op);
} else if (ov::is_type<ov::opset6::MVN>(op) || ov::is_type<ov::opset1::LRN>(op) ||
ov::is_type<ov::opset1::PRelu>(op) || ov::is_type<ov::opset4::Swish>(op)) {
return std::make_shared<entryFirstPassthrough>(op);
} else if (ov::is_type<ov::op::util::BinaryElementwiseArithmetic>(op) ||
ov::is_type<ov::op::util::BinaryElementwiseComparison>(op) ||
ov::is_type<ov::op::util::BinaryElementwiseLogical>(op)) {
eltwise_shape_infer(op, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::FakeQuantize>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::Reshape>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset1::Squeeze>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset1::Unsqueeze>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset1::ShapeOf>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset3::ShapeOf>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset6::ExperimentalDetectronDetectionOutput>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset3::TopK>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset3::Bucketize>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset3::EmbeddingSegmentsSum>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset3::EmbeddingBagOffsetsSum>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset6::ExperimentalDetectronROIFeatureExtractor>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::Pad>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset4::Range>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset1::Range>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset1::RegionYolo>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset2::ReorgYolo>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::Split>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset1::VariadicSplit>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset7::Einsum>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::StridedSlice>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset3::Assign>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset6::Assign>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset6::ExperimentalDetectronPriorGridGenerator>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::LSTMCell>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset6::LSTMCell>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset3::ReadValue>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset6::ReadValue>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset6::Tile>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset6::ExperimentalDetectronTopKROIs>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset4::Interpolate>(op)) {
std::vector<size_t> pads_begin, pads_end;
correct_pads_attr(node, pads_begin, pads_end, input_shapes);
shape_infer(node, pads_begin, pads_end, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset1::Interpolate>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset3::ScatterElementsUpdate>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset4::ScatterNDUpdate>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset6::GatherElements>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::op::util::GatherBase>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset1::GatherTree>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::OneHot>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset4::CTCLoss>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset7::DFT>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset7::IDFT>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset6::CTCGreedyDecoderSeqLen>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset6::CTCGreedyDecoder>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset3::ExtractImagePatches>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::ReverseSequence>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset7::Roll>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset6::ExperimentalDetectronGenerateProposalsSingleImage>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset4::Proposal>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::Proposal>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset3::ROIAlign>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::DetectionOutput>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset8::DetectionOutput>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::Select>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::ShuffleChannels>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset2::BatchToSpace>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset2::SpaceToBatch>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset1::DepthToSpace>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset1::SpaceToDepth>(op)) {
shape_infer(node, input_shapes, output_shapes);
} else if (auto node = ov::as_type<ov::opset4::Broadcast>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
} else if (auto node = ov::as_type<ov::opset1::Broadcast>(op)) {
shape_infer(node, input_shapes, output_shapes, constant_data);
return std::make_shared<entryEltwise>(op);
} else if (auto node = ov::as_type_ptr<ov::opset1::FakeQuantize>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::Reshape>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::Squeeze>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::Unsqueeze>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::ShapeOf>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset3::ShapeOf>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::ExperimentalDetectronDetectionOutput>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset3::TopK>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset3::Bucketize>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset3::EmbeddingSegmentsSum>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset3::EmbeddingBagOffsetsSum>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::ExperimentalDetectronROIFeatureExtractor>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::Pad>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset4::Range>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::Range>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::RegionYolo>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset2::ReorgYolo>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::Split>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::VariadicSplit>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset7::Einsum>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::StridedSlice>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset3::Assign>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::Assign>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::ExperimentalDetectronPriorGridGenerator>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::LSTMCell>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::LSTMCell>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset3::ReadValue>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::ReadValue>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::Tile>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::ExperimentalDetectronTopKROIs>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset4::Interpolate>(op)) {
return std::make_shared<entryInterpolate<ov::opset4::Interpolate>>(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::Interpolate>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset3::ScatterElementsUpdate>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset4::ScatterNDUpdate>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::GatherElements>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::op::util::GatherBase>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::GatherTree>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::OneHot>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset4::CTCLoss>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset7::DFT>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset7::IDFT>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::CTCGreedyDecoderSeqLen>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::CTCGreedyDecoder>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset3::ExtractImagePatches>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::ReverseSequence>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset7::Roll>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset6::ExperimentalDetectronGenerateProposalsSingleImage>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset4::Proposal>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::Proposal>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset3::ROIAlign>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::DetectionOutput>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset8::DetectionOutput>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::Select>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::ShuffleChannels>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset2::BatchToSpace>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset2::SpaceToBatch>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::DepthToSpace>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::SpaceToDepth>(op)) {
return make_shared_entryIO(node);
} else if (auto node = ov::as_type_ptr<ov::opset4::Broadcast>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::opset1::Broadcast>(op)) {
return make_shared_entryIOC(node);
} else if (auto node = ov::as_type_ptr<ov::op::v8::MaxPool>(op)) {
return std::make_shared<entryFallbackWithPadding<ov::op::v8::MaxPool>>(node);
} else if (auto node = ov::as_type_ptr<ov::op::v1::MaxPool>(op)) {
return std::make_shared<entryFallbackWithPadding<ov::op::v1::MaxPool>>(node);
} else if (auto node = ov::as_type_ptr<ov::op::v1::AvgPool>(op)) {
return std::make_shared<entryFallbackWithPadding<ov::op::v1::AvgPool>>(node);
} else if (auto node = ov::as_type_ptr<ov::op::v1::DeformableConvolution>(op)) {
return std::make_shared<entryFallbackWithPadding<ov::op::v1::DeformableConvolution>>(node);
} else if (auto node = ov::as_type_ptr<ov::op::v8::DeformableConvolution>(op)) {
return std::make_shared<entryFallbackWithPadding<ov::op::v8::DeformableConvolution>>(node);
} else {
ngraph::OutputVector new_inputs;
for (size_t i = 0; i < op->get_input_size(); ++i) {
if (constant_data.count(i)) {
new_inputs.push_back(std::make_shared<ov::opset1::Constant>(constant_data.at(i)));
} else {
new_inputs.push_back(std::make_shared<ov::opset1::Parameter>(op->get_input_element_type(i),
input_shapes[i].to_partial_shape()));
}
}
const auto local_op = op->clone_with_new_inputs(new_inputs);
local_op->validate_and_infer_types();
output_shapes.resize(op->get_output_size());
for (size_t i = 0; i < output_shapes.size(); ++i) {
const auto& partial_shape = local_op->get_output_partial_shape(i);
OPENVINO_ASSERT(
partial_shape.is_static(),
"On device shape infer shouldn't support default shape infer for nodes with internal dynamism");
output_shapes[i] = ov::StaticShape(partial_shape.to_shape());
}
return std::make_shared<entryFallback>(op);
}
}

View File

@ -4,13 +4,28 @@
#pragma once
#include <openvino/core/node.hpp>
#include <ngraph/runtime/host_tensor.hpp>
#include <openvino/core/core.hpp>
#include <openvino/core/node.hpp>
#include "static_shape.hpp"
void shape_inference(ov::Node* op,
const std::vector<ov::StaticShape>& input_shapes,
std::vector<ov::StaticShape>& output_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data = {});
class IShapeInfer {
public:
virtual std::vector<ov::StaticShape> infer(
const std::vector<ov::StaticShape>& input_shapes,
const std::map<size_t, std::shared_ptr<ngraph::runtime::HostTensor>>& constant_data) = 0;
// infer may generate padding as by-product, these APIs is designed to retrieve them back
virtual const ov::CoordinateDiff& get_pads_begin() = 0;
virtual const ov::CoordinateDiff& get_pads_end() = 0;
virtual const std::vector<int64_t>& get_input_ranks() = 0;
};
std::shared_ptr<IShapeInfer> make_shape_inference(const std::shared_ptr<ngraph::Node>& op);