diff --git a/src/core/shape_inference/include/reduce_shape_inference.hpp b/src/core/shape_inference/include/reduce_shape_inference.hpp index 999ac7042c7..fe82d658b16 100644 --- a/src/core/shape_inference/include/reduce_shape_inference.hpp +++ b/src/core/shape_inference/include/reduce_shape_inference.hpp @@ -47,12 +47,12 @@ template void shape_infer(const ov::op::util::ArithmeticReductionKeepDims* op, const std::vector &input_shapes, std::vector &output_shapes, const std::map>& 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 void shape_infer(const ov::op::util::LogicalReductionKeepDims* op, const std::vector &input_shapes, std::vector &output_shapes, const std::map>& 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); } diff --git a/src/core/shape_inference/include/utils.hpp b/src/core/shape_inference/include/utils.hpp index 3ba1ff0c488..e0dbc3c364a 100644 --- a/src/core/shape_inference/include/utils.hpp +++ b/src/core/shape_inference/include/utils.hpp @@ -16,7 +16,8 @@ void copy_shape_infer(const OpType* op, const std::vector& input_shapes, std: template void first_input_passthrough_infer(const OpType* op, const std::vector& input_shapes, std::vector& 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]; } diff --git a/src/plugins/intel_cpu/src/mkldnn_node.cpp b/src/plugins/intel_cpu/src/mkldnn_node.cpp index 473408571cf..0151018eaef 100644 --- a/src/plugins/intel_cpu/src/mkldnn_node.cpp +++ b/src/plugins/intel_cpu/src/mkldnn_node.cpp @@ -111,8 +111,9 @@ MKLDNNNode::MKLDNNNode(const std::shared_ptr& 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 MKLDNNNode::shapeInfer() const { - std::vector 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 MKLDNNNode::shapeInferGeneric(const std::vector& 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 MKLDNNNode::shapeInferGeneric(const std::vector& input_shapes, + uint32_t input_value_port_mask) const { + // collect input values + std::map> 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(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( + InferenceEngine::details::convertPrecision(memPtr.getDesc().getPrecision()), + shape, + memPtr.GetPtr()); + } } } - opToShapeInfer->validate_and_infer_types(); + // call shape inference API + std::vector output_shapes = shapeInference->infer(input_shapes, input_values); - std::vector 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 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 MKLDNNNode::shapeInferGeneric(const std::vector& shapes, + uint32_t input_value_port_mask) const { + std::vector 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 MKLDNNNode::shapeInferGeneric(uint32_t input_value_port_mask) const { + std::vector 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& op) { - ngraph::OutputVector inputsForShapeInfer; - for (size_t i = 0; i < inputShapes.size(); i++) { - if (dynamic_cast(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(op->get_input_element_type(i), - op->get_input_partial_shape(i))); - } - } - opToShapeInfer = op->clone_with_new_inputs(inputsForShapeInfer); -} diff --git a/src/plugins/intel_cpu/src/mkldnn_node.h b/src/plugins/intel_cpu/src/mkldnn_node.h index 7dbadaa3796..15c427d273e 100644 --- a/src/plugins/intel_cpu/src/mkldnn_node.h +++ b/src/plugins/intel_cpu/src/mkldnn_node.h @@ -31,6 +31,9 @@ #include "memory_desc/cpu_memory_desc.h" #include "cache/multi_cache.h" +#include +#include + namespace MKLDNNPlugin { using MKLDNNNodePtr = std::shared_ptr; @@ -750,7 +753,8 @@ protected: bool inputShapesModified() const; virtual bool needShapeInfer() const; - std::vector shapeInferGeneric(const std::vector& inputDims) const; + std::vector shapeInferGeneric(const std::vector& inputDims, uint32_t value_port_mask = 0) const; + std::vector shapeInferGeneric(uint32_t value_port_mask = 0) const; virtual std::vector 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 lastInputDims = {}; - std::shared_ptr opToShapeInfer; + std::shared_ptr shapeInference; private: std::vector parentEdges; @@ -797,8 +801,6 @@ private: bool isEdgesEmpty(const std::vector& edges) const; - void createShapeInferSubgraph(const std::shared_ptr& op); - template typename std::enable_if::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& checkNodes); + std::vector shapeInferGeneric(const std::vector& 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 +constexpr uint64_t PortMask(int n, T... rest) { + return PortMask(rest...) | (1 << n); +} + class MKLDNNNode::NodesFactory : public openvino::cc::Factory& op, const mkldnn::engine &, diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_batch_to_space_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_batch_to_space_node.cpp index 60a37375cdc..eed2f5a2694 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_batch_to_space_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_batch_to_space_node.cpp @@ -96,6 +96,10 @@ void MKLDNNBatchToSpaceNode::initSupportedPrimitiveDescriptors() { } } +std::vector MKLDNNBatchToSpaceNode::shapeInfer() const { + return MKLDNNNode::shapeInferGeneric(PortMask(1, 2, 3)); +} + static std::vector getShape5D(const SizeVector &shape) { std::vector shape5D(5, 1); for (int i = 0; i < 2; i++) { diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_batch_to_space_node.h b/src/plugins/intel_cpu/src/nodes/mkldnn_batch_to_space_node.h index 91fe87e4f71..7299cf8a801 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_batch_to_space_node.h +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_batch_to_space_node.h @@ -21,6 +21,7 @@ public: void execute(mkldnn::stream strm) override; bool created() const override; + std::vector shapeInfer() const override; bool needPrepareParams() const override { return false; }; void executeDynamicImpl(mkldnn::stream strm) override; diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_broadcast_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_broadcast_node.cpp index eba9e00666f..fe905761c65 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_broadcast_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_broadcast_node.cpp @@ -182,29 +182,7 @@ bool MKLDNNBroadcastNode::needShapeInfer() const { } std::vector MKLDNNBroadcastNode::shapeInfer() const { - ngraph::OutputVector inputsForShapeInfer { - std::make_shared(opToShapeInfer->get_input_element_type(INPUT_DATA_IDX), - getParentEdgesAtPort(INPUT_DATA_IDX)[0]->getMemory().GetShape().toPartialShape()), - std::make_shared(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::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 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 { diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_conv_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_conv_node.cpp index f0b7fcd412d..578940bad1f 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_conv_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_conv_node.cpp @@ -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(opToShapeInfer)) { - paddingL = convolutionOp->get_pads_begin(); - paddingR = convolutionOp->get_pads_end(); - } else if (auto groupConvolutionOp = ov::as_type_ptr(opToShapeInfer)) { - paddingL = groupConvolutionOp->get_pads_begin(); - paddingR = groupConvolutionOp->get_pads_end(); - } + paddingL = shapeInference->get_pads_begin(); + paddingR = shapeInference->get_pads_end(); } } diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_deconv_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_deconv_node.cpp index eb54a82cec8..7d276f7a169 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_deconv_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_deconv_node.cpp @@ -224,26 +224,6 @@ bool MKLDNNDeconvolutionNode::canFuse(const MKLDNNNodePtr& node) const { return (fusedWith.empty() && node->canBePerformedAsScaleShift(this)); } -void MKLDNNDeconvolutionNode::initPadding(std::shared_ptr op, const Shape &inDims, const std::vector& outSpDims) { - std::vector 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(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(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 MKLDNNDeconvolutionNode::makeDummyInOutShape() { auto inShape = MemoryDescUtils::makeDummyShape(getInputShapeAtPort(0)); auto outShape = getOutputShapeAtPort(0); @@ -276,8 +256,9 @@ std::pair 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 outputShapes(1); - shape_inference(opToShapeInfer.get(), inputShapes, outputShapes, inputValues); + std::vector 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{}); + paddingL = shapeInference->get_pads_begin(); + paddingR = shapeInference->get_pads_end(); } initPaddingR(inMemoryDesc->getShape(), outMemoryDesc->getShape()); } else { diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_def_conv_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_def_conv_node.cpp index 3515fbeac16..e159a0ff2ea 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_def_conv_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_def_conv_node.cpp @@ -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(opToShapeInfer); - defConvAttr.padL = defConvNodeBase->get_pads_begin(); + defConvAttr.padL = shapeInference->get_pads_begin(); } } diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_embedding_segments_sum_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_embedding_segments_sum_node.cpp index 58e5de78882..bcf8523d3e6 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_embedding_segments_sum_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_embedding_segments_sum_node.cpp @@ -121,6 +121,10 @@ void MKLDNNEmbeddingSegmentsSumNode::getIndices(int embIndex, const int*& indice } } +std::vector MKLDNNEmbeddingSegmentsSumNode::shapeInfer() const { + return MKLDNNNode::shapeInferGeneric(PortMask(NUM_SEGMENTS_IDX)); +} + void MKLDNNEmbeddingSegmentsSumNode::executeDynamicImpl(mkldnn::stream strm) { execute(strm); } diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_embedding_segments_sum_node.h b/src/plugins/intel_cpu/src/nodes/mkldnn_embedding_segments_sum_node.h index 31b3f4163e1..1d120072914 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_embedding_segments_sum_node.h +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_embedding_segments_sum_node.h @@ -27,6 +27,7 @@ public: protected: void prepareParams() override; + std::vector shapeInfer() const override; void executeDynamicImpl(mkldnn::stream strm) override; private: diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_interpolate_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_interpolate_node.cpp index 270e05ff986..0b952dddd22 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_interpolate_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_interpolate_node.cpp @@ -2044,33 +2044,8 @@ bool MKLDNNInterpolateNode::needShapeInfer() const { } std::vector MKLDNNInterpolateNode::shapeInfer() const { - std::vector 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> input_values = { - {port, std::make_shared(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(InferenceEngine::details::convertPrecision(memory.getDesc().getPrecision()), - memory.getStaticDims(), memory.GetPtr())}); - } - - std::vector output_shapes = {{}}; - shape_inference(opToShapeInfer.get(), input_shapes, output_shapes, input_values); - - std::vector 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) { diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_pad_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_pad_node.cpp index 7d4178e2866..a0ac1ca87f2 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_pad_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_pad_node.cpp @@ -331,6 +331,10 @@ void MKLDNNPadNode::executeDynamicImpl(mkldnn::stream strm) { execute(strm); } +std::vector 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]; diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_pad_node.h b/src/plugins/intel_cpu/src/nodes/mkldnn_pad_node.h index d8beaac96cd..585be6cff71 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_pad_node.h +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_pad_node.h @@ -26,6 +26,7 @@ public: bool isExecutable() const override; protected: + std::vector shapeInfer() const override; void executeDynamicImpl(mkldnn::stream strm) override; private: diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_pooling_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_pooling_node.cpp index afd8ad64312..753c04d352c 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_pooling_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_pooling_node.cpp @@ -297,32 +297,6 @@ void MKLDNNPoolingNode::getSupportedDescriptors() { } } -std::pair, std::vector> MKLDNNPoolingNode::getPaddingFromNode(std::shared_ptr node) const { - const auto convertPadding = [](const VectorDims &newPads) { - std::vector pads(newPads.size()); - for (int i = 0; i < newPads.size(); i++) { - pads[i] = static_cast(newPads[i]); - } - return pads; - }; - - VectorDims padsBegin, padsEnd; - if (isMaxPool8) { - const auto pool = ov::as_type_ptr(opToShapeInfer); - padsBegin = pool->get_pads_begin(); - padsEnd = pool->get_pads_end(); - } else if (getAlgorithm() == PoolingMax) { - const auto pool = ov::as_type_ptr(opToShapeInfer); - padsBegin = pool->get_pads_begin(); - padsEnd = pool->get_pads_end(); - } else if (getAlgorithm() == PoolingAvg) { - const auto pool = ov::as_type_ptr(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 &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()); } diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_pooling_node.h b/src/plugins/intel_cpu/src/nodes/mkldnn_pooling_node.h index a60423cd036..b06aaae6bfb 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_pooling_node.h +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_pooling_node.h @@ -38,7 +38,6 @@ protected: private: void setPostOps(mkldnn::primitive_attr &attr, bool initWeights = false) const; - std::pair, std::vector> getPaddingFromNode(std::shared_ptr node) const; void initEffectiveAttributes(const Shape &inDims, const Shape &outDims); mkldnn::algorithm getPoolingAlgorithm() const; std::shared_ptr createDescriptorInternal(const mkldnn::memory::desc& in_candidate, diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_range_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_range_node.cpp index 48175474b79..39ee671184f 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_range_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_range_node.cpp @@ -83,6 +83,10 @@ void MKLDNNRangeNode::initSupportedPrimitiveDescriptors() { } } +std::vector MKLDNNRangeNode::shapeInfer() const { + return MKLDNNNode::shapeInferGeneric(PortMask(RANGE_START, RANGE_LIMIT, RANGE_DELTA)); +} + void MKLDNNRangeNode::executeDynamicImpl(mkldnn::stream strm) { execute(strm); } diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_range_node.h b/src/plugins/intel_cpu/src/nodes/mkldnn_range_node.h index 720c3111729..de82299ac44 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_range_node.h +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_range_node.h @@ -19,6 +19,7 @@ public: bool created() const override; bool needPrepareParams() const override {return false;}; bool needShapeInfer() const override {return false;}; + std::vector shapeInfer() const override; void executeDynamicImpl(mkldnn::stream strm) override; static bool isSupportedOperation(const std::shared_ptr& op, std::string& errorMessage) noexcept; diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_reduce_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_reduce_node.cpp index c71b8399b50..650410c6da4 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_reduce_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_reduce_node.cpp @@ -1868,6 +1868,10 @@ bool MKLDNNReduceNode::isExecutable() const { return !isInputTensorAtPortEmpty(REDUCE_DATA); } +std::vector MKLDNNReduceNode::shapeInfer() const { + return MKLDNNNode::shapeInferGeneric(PortMask(REDUCE_INDEXES)); +} + void MKLDNNReduceNode::prepareParams() { src_dims = getParentEdgesAtPort(REDUCE_DATA)[0]->getMemory().getDesc().getShape().getDims(); std::vector reduce_axes; diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_reduce_node.h b/src/plugins/intel_cpu/src/nodes/mkldnn_reduce_node.h index 8992d5fd5d7..94f061e57db 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_reduce_node.h +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_reduce_node.h @@ -91,6 +91,7 @@ public: void createPrimitive() override; bool created() const override; void execute(mkldnn::stream strm) override; + std::vector shapeInfer() const override; void executeDynamicImpl(mkldnn::stream strm) override; bool canFuse(const MKLDNNNodePtr& node) const override; bool canBeInPlace() const override { diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_reference_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_reference_node.cpp index ec6b891a678..4d1c3b9e251 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_reference_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_reference_node.cpp @@ -74,40 +74,8 @@ void MKLDNNReferenceNode::execute(mkldnn::stream strm) { } } -// TODO [DS]: rewrite after new shape infer will be added std::vector 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(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 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) { diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_reshape_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_reshape_node.cpp index 35dd1e74946..05041079883 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_reshape_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_reshape_node.cpp @@ -75,7 +75,6 @@ bool MKLDNNReshapeNode::needShapeInfer() const { return false; } -// TODO [DS]: rewrite after new shape infer will be added std::vector MKLDNNReshapeNode::shapeInfer() const { const auto &memPtr = getParentEdgesAtPort(1)[0]->getMemory(); @@ -86,16 +85,7 @@ std::vector MKLDNNReshapeNode::shapeInfer() const { lastSecondInputValues[i] = sndInput[i]; } - std::vector input_shapes = {getParentEdgesAtPort(0)[0]->getMemory().GetShape().getStaticDims(), memPtr.getStaticDims()}; - std::map> input_values = { - {1, std::make_shared(ngraph::element::Type_t::i32, memPtr.getStaticDims(), memPtr.GetPtr())} - }; - std::vector output_shapes = {{}}; - shape_inference(opToShapeInfer.get(), input_shapes, output_shapes, input_values); - - std::vector 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() { diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_space_to_batch_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_space_to_batch_node.cpp index 83ab528e1b2..d93b4ecbeb3 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_space_to_batch_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_space_to_batch_node.cpp @@ -97,6 +97,10 @@ void MKLDNNSpaceToBatchNode::initSupportedPrimitiveDescriptors() { } } +std::vector MKLDNNSpaceToBatchNode::shapeInfer() const { + return MKLDNNNode::shapeInferGeneric(PortMask(1, 2, 3)); +} + static std::vector getShape5D(const SizeVector &shape) { std::vector shape5D(5, 1); for (int i = 0; i < 2; i++) { diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_space_to_batch_node.h b/src/plugins/intel_cpu/src/nodes/mkldnn_space_to_batch_node.h index 33c893b0c94..b3f0a6de503 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_space_to_batch_node.h +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_space_to_batch_node.h @@ -21,6 +21,7 @@ public: void execute(mkldnn::stream strm) override; bool created() const override; + std::vector shapeInfer() const override; bool needPrepareParams() const override { return false; }; void executeDynamicImpl(mkldnn::stream strm) override; diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_split_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_split_node.cpp index 348c1238fe9..b58fc8624d3 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_split_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_split_node.cpp @@ -239,6 +239,10 @@ bool MKLDNNSplitNode::needPrepareParams() const { return MKLDNNNode::inputShapesModified(); } +std::vector MKLDNNSplitNode::shapeInfer() const { + return MKLDNNNode::shapeInferGeneric(PortMask(1, 2)); +} + void MKLDNNSplitNode::prepareParams() { const auto &srcMemPtr = getParentEdgesAtPort(0)[0]->getMemoryPtr(); if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr()) { diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_split_node.h b/src/plugins/intel_cpu/src/nodes/mkldnn_split_node.h index 00c0f719bf2..812fc785a33 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_split_node.h +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_split_node.h @@ -29,6 +29,7 @@ public: bool needPrepareParams() const override; void prepareParams() override; + std::vector shapeInfer() const override; void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); } private: diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_tile_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_tile_node.cpp index 4a035681c25..3013bba8ede 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_tile_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_tile_node.cpp @@ -123,23 +123,7 @@ bool MKLDNNTileNode::needShapeInfer() const { } std::vector MKLDNNTileNode::shapeInfer() const { - ngraph::OutputVector inputsForShapeInfer { - std::make_shared(opToShapeInfer->get_input_element_type(TILE_INPUT), - getParentEdgesAtPort(TILE_INPUT)[0]->getMemory().GetShape().toPartialShape()), - std::make_shared(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 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) { diff --git a/src/plugins/intel_cpu/src/nodes/mkldnn_topk_node.cpp b/src/plugins/intel_cpu/src/nodes/mkldnn_topk_node.cpp index 956292f0b23..57934890586 100644 --- a/src/plugins/intel_cpu/src/nodes/mkldnn_topk_node.cpp +++ b/src/plugins/intel_cpu/src/nodes/mkldnn_topk_node.cpp @@ -167,39 +167,7 @@ bool MKLDNNTopKNode::needShapeInfer() const { } std::vector MKLDNNTopKNode::shapeInfer() const { - if (dynamic_cast(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 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 Compare2> diff --git a/src/plugins/intel_cpu/src/utils/shape_inference/shape_inference.cpp b/src/plugins/intel_cpu/src/utils/shape_inference/shape_inference.cpp index cf5a9ac20e9..b8668ba2a43 100644 --- a/src/plugins/intel_cpu/src/utils/shape_inference/shape_inference.cpp +++ b/src/plugins/intel_cpu/src/utils/shape_inference/shape_inference.cpp @@ -14,14 +14,23 @@ #include #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& input_shapes, std::vector& output_shapes, const std::map>& constant_data) { - if (auto node = ov::as_type(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 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& get_input_ranks() override { + return input_ranks; + } + +protected: + std::vector input_ranks; + std::shared_ptr node; +}; + +template +class entryIO : public entryBase { +public: + using entryBase::entryBase; + + std::vector infer( + const std::vector& input_shapes, + const std::map>& constant_data) override { + auto op = static_cast(node.get()); + std::vector output_shapes(op->get_output_size()); + shape_infer(op, input_shapes, output_shapes); + return output_shapes; + } +}; + +template +class entryIOC : public entryBase { +public: + using entryBase::entryBase; + + std::vector infer( + const std::vector& input_shapes, + const std::map>& constant_data) override { + auto op = static_cast(node.get()); + std::vector 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 infer( + const std::vector& input_shapes, + const std::map>& constant_data) override { + auto op = node.get(); + std::vector 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 infer( + const std::vector& input_shapes, + const std::map>& constant_data) override { + auto op = node.get(); + std::vector 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 infer( + const std::vector& input_shapes, + const std::map>& constant_data) override { + auto op = node.get(); + std::vector 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 local_op_default; + + entryFallback(std::shared_ptr 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(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(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& local_op) {} + + std::vector infer( + const std::vector& input_shapes, + const std::map>& constant_data) override { + auto op = node.get(); + std::vector output_shapes; + + std::shared_ptr 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(constant_data.at(i))); + } else if (dynamic_cast(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(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(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 pads(newPads.size()); + for (int i = 0; i < newPads.size(); i++) { + pads[i] = static_cast(newPads[i]); + } + return pads; +} + +template +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& local_op) override { + auto node = dynamic_cast(local_op.get()); + OPENVINO_ASSERT(node); + pads_begin = convertPadding(node->get_pads_begin()); + pads_end = convertPadding(node->get_pads_end()); + } +}; + +template +class entryInterpolate : public entryBase { +public: + using entryBase::entryBase; + + std::vector infer( + const std::vector& input_shapes, + const std::map>& constant_data) override { + std::vector pads_begin, pads_end; + auto op = static_cast(node.get()); + std::vector 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 +class entryConv : public entryBase { +public: + entryConv(std::shared_ptr 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 infer( + const std::vector& input_shapes, + const std::map>& constant_data) override { + auto op = static_cast(node.get()); + std::vector 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(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(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 +class entryConvBackprop : public entryBase { +public: + entryConvBackprop(std::shared_ptr 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 infer( + const std::vector& input_shapes, + const std::map>& constant_data) override { ov::StaticShape output_shape_input; - if (node->get_input_size() == 3) + auto op = static_cast(node.get()); + std::vector output_shapes(op->get_output_size()); + if (op->get_input_size() == 3) get_data_as_shape(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(op)) { - ov::CoordinateDiff pads_begin, pads_end; - ov::StaticShape output_shape_input; - if (node->get_input_size() == 3) - get_data_as_shape(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(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (ov::is_type(op) || - ov::is_type(op) || ov::is_type(op) || - ov::is_type(op) || ov::is_type(op) || - ov::is_type(op) || ov::is_type(op) || - ov::is_type(op) || ov::is_type(op) || - ov::is_type(op) || ov::is_type(op) || - ov::is_type(op) || ov::is_type(op) || - ov::is_type(op) || ov::is_type(op) || - ov::is_type(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 +std::shared_ptr> make_shared_entryIOC(std::shared_ptr node) { + return std::make_shared>(node); +} + +template +std::shared_ptr> make_shared_entryIO(std::shared_ptr node) { + return std::make_shared>(node); +} + +std::shared_ptr make_shape_inference(const std::shared_ptr& op) { + if (auto node = ov::as_type_ptr(op)) { + return std::make_shared>(node, false); + } else if (auto node = ov::as_type_ptr(op)) { + return std::make_shared>(node, true); + } else if (auto node = ov::as_type_ptr(op)) { + return std::make_shared>(node, false); + } else if (auto node = ov::as_type_ptr(op)) { + return std::make_shared>(node, true); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (ov::is_type(op) || ov::is_type(op) || + ov::is_type(op) || ov::is_type(op) || + ov::is_type(op) || ov::is_type(op) || + ov::is_type(op) || ov::is_type(op) || + ov::is_type(op) || ov::is_type(op) || + ov::is_type(op) || ov::is_type(op)) { + return std::make_shared(op); + } else if (ov::is_type(op) || ov::is_type(op) || + ov::is_type(op) || ov::is_type(op)) { + return std::make_shared(op); } else if (ov::is_type(op) || ov::is_type(op) || ov::is_type(op)) { - eltwise_shape_infer(op, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - std::vector 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(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); - } else if (auto node = ov::as_type(op)) { - shape_infer(node, input_shapes, output_shapes, constant_data); + return std::make_shared(op); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return std::make_shared>(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIO(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return make_shared_entryIOC(node); + } else if (auto node = ov::as_type_ptr(op)) { + return std::make_shared>(node); + } else if (auto node = ov::as_type_ptr(op)) { + return std::make_shared>(node); + } else if (auto node = ov::as_type_ptr(op)) { + return std::make_shared>(node); + } else if (auto node = ov::as_type_ptr(op)) { + return std::make_shared>(node); + } else if (auto node = ov::as_type_ptr(op)) { + return std::make_shared>(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(constant_data.at(i))); - } else { - new_inputs.push_back(std::make_shared(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(op); } } diff --git a/src/plugins/intel_cpu/src/utils/shape_inference/shape_inference.hpp b/src/plugins/intel_cpu/src/utils/shape_inference/shape_inference.hpp index 98096213953..d4943d9a8ca 100644 --- a/src/plugins/intel_cpu/src/utils/shape_inference/shape_inference.hpp +++ b/src/plugins/intel_cpu/src/utils/shape_inference/shape_inference.hpp @@ -4,13 +4,28 @@ #pragma once -#include #include +#include +#include + #include "static_shape.hpp" - - void shape_inference(ov::Node* op, const std::vector& input_shapes, std::vector& output_shapes, - const std::map>& constant_data = {}); \ No newline at end of file + const std::map>& constant_data = {}); + +class IShapeInfer { +public: + virtual std::vector infer( + const std::vector& input_shapes, + const std::map>& 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& get_input_ranks() = 0; +}; + +std::shared_ptr make_shape_inference(const std::shared_ptr& op);