[CPU] Introduce empty undefined memory descriptor (#23437)

### Details:
 - The example use case is to generalize processing of the operation
 with and without bias.
 When the operation has no bias, it is possible to create memory
 using empty memory descriptor, and use the exact same code as if bias
 actually exists.
- Many headers are affected to break the chain of implicit intersecting
includes

### Tickets:
 - 131590

### Todo:
 - [ ] Add unit tests
This commit is contained in:
Egor Duplenskii 2024-04-16 10:11:14 +02:00 committed by GitHub
parent 879bb9ac57
commit 835fda6a0b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
26 changed files with 240 additions and 83 deletions

View File

@ -3,6 +3,7 @@
//
#include "cpu_memory.h"
#include "memory_desc/cpu_memory_desc_utils.h"
#include <common/memory_desc_wrapper.hpp>
#include "nodes/reorder.h"
#if defined(__linux__)

View File

@ -6,7 +6,6 @@
#include "memory_desc/cpu_memory_desc.h"
#include "dnnl_extension_utils.h"
#include "memory_desc/cpu_memory_desc_utils.h"
#include <onednn/dnnl.h>
#include <cpu_shape.h>

View File

@ -4,7 +4,6 @@
#include "cpu_shape.h"
#include "utils/general_utils.h"
#include "memory_desc/cpu_memory_desc_utils.h"
namespace ov {
namespace intel_cpu {
@ -39,7 +38,7 @@ std::string Shape::toString() const {
size_t i = 0;
do {
if (dims[i] == Shape::UNDEFINED_DIM) {
output << MemoryDescUtils::dim2str(minDims[i]) << " - " << MemoryDescUtils::dim2str(maxDims[i]);
output << dim2str(minDims[i]) << " - " << dim2str(maxDims[i]);
} else {
output << dims[i];
}

View File

@ -2,13 +2,33 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "cpu_types.h"
#include "cpu_shape.h"
#include <string>
#include <vector>
#include <sstream>
namespace ov {
namespace intel_cpu {
std::string dim2str(Dim dim) {
return dim == Shape::UNDEFINED_DIM ? "?" : std::to_string(dim);
}
std::string dims2str(const VectorDims& dims) {
std::stringstream output;
output << "{";
if (!dims.empty()) {
auto itr = dims.begin();
do {
output << dim2str(*itr);
} while (++itr != dims.end() && output << ", ");
}
output << "}";
return output.str();
}
using TypeToNameMap = ov::intel_cpu::caseless_unordered_map<std::string, Type>;
static const TypeToNameMap& get_type_to_name_tbl() {

View File

@ -15,6 +15,9 @@ namespace intel_cpu {
using Dim = std::size_t;
using VectorDims = std::vector<Dim>;
std::string dim2str(Dim dim);
std::string dims2str(const VectorDims& dims);
enum class Type {
Unknown,
If,

View File

@ -10,7 +10,7 @@
#include "itt.h"
#include "memory_state.h"
#include "nodes/common/cpu_convert.h"
#include "nodes/common/cpu_memcpy.h"
#include "memory_desc/cpu_memory_desc_utils.h"
#include "nodes/memory.hpp"
#include "openvino/core/shape.hpp"
#include "openvino/runtime/make_tensor.hpp"

View File

@ -3,8 +3,8 @@
//
#include "cpu_blocked_memory_desc.h"
#include "cpu_memory.h"
#include "dnnl_blocked_memory_desc.h"
#include "utils/general_utils.h"
namespace ov {
namespace intel_cpu {

View File

@ -5,11 +5,13 @@
#pragma once
#include "blocked_memory_desc.h"
#include "utils/general_utils.h"
#include "dnnl_extension_utils.h"
namespace ov {
namespace intel_cpu {
class DnnlBlockedMemoryDesc;
class CpuBlockedMemoryDesc : public BlockedMemoryDesc {
public:
CpuBlockedMemoryDesc(ov::element::Type prc, const Shape& shape);

View File

@ -6,7 +6,6 @@
#include "cpu_shape.h"
#include "cpu_types.h"
#include "memory_desc/cpu_memory_desc_utils.h"
#include "openvino/core/type/element_type.hpp"
/**
@ -35,8 +34,8 @@ enum MemoryDescType {
Undef = 0,
Blocked = 1,
Dnnl = 1 << 1,
DnnlBlocked = Blocked | Dnnl
DnnlBlocked = Blocked | Dnnl,
Empty = 1 << 2,
};
enum class LayoutType : unsigned {
@ -90,7 +89,7 @@ public:
OPENVINO_THROW("ParameterMismatch: Can not clone with new dims. Descriptor's shape: ",
getShape().toString(),
" is incompatible with provided dimensions: ",
MemoryDescUtils::dims2str(dims),
dims2str(dims),
".");
}
@ -132,6 +131,10 @@ public:
return getMaxMemSize() != MemoryDesc::UNDEFINED_SIZE;
}
bool empty() const {
return type == Empty;
}
template <typename T,
typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
typename std::enable_if<std::is_base_of<MemoryDesc, T>::value, int>::type = 0>

View File

@ -2,10 +2,13 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "memory_desc/cpu_memory_desc_utils.h"
#include "memory_desc/cpu_blocked_memory_desc.h"
#include "memory_desc/dnnl_blocked_memory_desc.h"
#include "graph_context.h"
#include "cpu_memory_desc.h"
#include "memory_desc/cpu_memory_desc_utils.h"
#include "memory_desc/empty_memory_desc.h"
#include <cpu_memory.h>
#include <vector>
#include <cpu_memory.h>
@ -24,6 +27,8 @@ DnnlMemoryDescPtr MemoryDescUtils::convertToDnnlMemoryDesc(const MemoryDescPtr &
return std::shared_ptr<DnnlBlockedMemoryDesc>(new DnnlBlockedMemoryDesc(cpuDesc->getPrecision(), cpuDesc->getShape(), cpuDesc->getBlockDims(),
cpuDesc->getOrder(), cpuDesc->getOffsetPadding(),
cpuDesc->getOffsetPaddingToData(), cpuDesc->getStrides()));
} else if (MemoryDescType::Empty == desc->getType()) {
return DnnlExtensionUtils::makeDescriptor(dnnl::memory::desc());
} else if (MemoryDescType::Dnnl & desc->getType()) {
return std::dynamic_pointer_cast<DnnlMemoryDesc>(desc);
} else {
@ -39,7 +44,7 @@ DnnlBlockedMemoryDesc MemoryDescUtils::convertToDnnlBlockedMemoryDesc(const Memo
return DnnlBlockedMemoryDesc(cpuDesc->getPrecision(), cpuDesc->getShape(), cpuDesc->getBlockDims(), cpuDesc->getOrder(), cpuDesc->getOffsetPadding(),
cpuDesc->getOffsetPaddingToData(), cpuDesc->getStrides());
} else {
OPENVINO_THROW("Cannot convert MemoryDesc to DnnlMemoryDesc");
OPENVINO_THROW("Cannot convert MemoryDesc to DnnlBlockedMemoryDesc");
}
}
@ -47,7 +52,7 @@ BlockedMemoryDescPtr MemoryDescUtils::convertToBlockedMemoryDesc(const MemoryDes
if (desc->getType() & MemoryDescType::Blocked) {
return std::dynamic_pointer_cast<BlockedMemoryDesc>(desc);
} else {
OPENVINO_THROW("Can not convert unsupported memory descriptor");
OPENVINO_THROW("Cannot convert MemoryDesc to BlockedMemoryDesc");
}
}
@ -92,30 +97,20 @@ CpuBlockedMemoryDescPtr MemoryDescUtils::generateCpuBlockedMemoryDesc(const ov::
blk_strides);
}
std::string MemoryDescUtils::dim2str(Dim dim) {
return dim == Shape::UNDEFINED_DIM ? "?" : std::to_string(dim);
}
std::string MemoryDescUtils::dims2str(const VectorDims& dims) {
std::stringstream output;
output << "{";
if (!dims.empty()) {
auto itr = dims.begin();
do {
output << dim2str(*itr);
} while (++itr != dims.end() && output << ", ");
}
output << "}";
return output.str();
}
std::shared_ptr<MemoryDesc> MemoryDescUtils::makeDummyDesc(const MemoryDesc &desc, Dim dummyVal) {
auto dummyShape = makeDummyShape(desc.getShape(), dummyVal);
return desc.cloneWithNewDims(dummyShape.getStaticDims());
}
std::shared_ptr<MemoryDesc> MemoryDescUtils::makeEmptyDesc() {
static auto emptyDesc = std::make_shared<EmptyMemoryDesc>();
return emptyDesc;
}
std::shared_ptr<IMemory> MemoryDescUtils::makeEmptyMemory(const GraphContext::CPtr context) {
return std::make_shared<StaticMemory>(context->getEngine(), makeEmptyDesc(), nullptr);
}
Shape MemoryDescUtils::makeDummyShape(const Shape &shape, Dim dummyVal) {
const auto& minDims = shape.getMinDims();
const auto& maxDims = shape.getMaxDims();

View File

@ -4,12 +4,12 @@
#pragma once
#include <memory>
#include "cpu_shape.h"
#include "cpu_types.h"
#include "openvino/runtime/itensor.hpp"
#include "openvino/runtime/so_ptr.hpp"
#include "onednn/dnnl.h"
#include "graph_context.h"
namespace ov {
namespace intel_cpu {
@ -19,7 +19,9 @@ class DnnlMemoryDesc;
class BlockedMemoryDesc;
class DnnlBlockedMemoryDesc;
class CpuBlockedMemoryDesc;
class EmptyMemoryDesc;
class IMemory;
class Memory;
class MemoryDescUtils {
public:
@ -63,6 +65,14 @@ public:
*/
static std::shared_ptr<MemoryDesc> makeDummyDesc(const MemoryDesc& desc, Dim dummyVal = DEFAULT_DUMMY_VAL);
/**
* @brief Make an empty memory descriptor
* @note Shape{0}, undefined
* @return empty memory descriptor
*/
static std::shared_ptr<MemoryDesc> makeEmptyDesc();
static std::shared_ptr<IMemory> makeEmptyMemory(const GraphContext::CPtr context);
/**
* @brief Makes a static dummy shape where all undefined values are replaced with the smallest value between the parameter and the upper bound dim
* @param shape a Shape object from which the new static shape is generated

View File

@ -444,7 +444,7 @@ static dnnl::memory::desc cloneDescWithNewDims(const dnnl::memory::desc& desc,
dnnl::impl::memory_desc_t& newCdesc = *newMklDesc.get();
auto retCode = dnnl::impl::fill_blocked(newCdesc, perm, innerBlks, innerIdxs);
if (retCode != dnnl::impl::status::success) {
OPENVINO_THROW("Can not clone DnnlBlockedMemoryDesc with dims: ", MemoryDescUtils::dims2str(dims));
OPENVINO_THROW("Can not clone DnnlBlockedMemoryDesc with dims: ", dims2str(dims));
}
// dnnl::impl::fill_blocked always set offset0 to 0
// so we need to restore actual value

View File

@ -5,15 +5,16 @@
#pragma once
#include "dnnl_memory_desc.h"
#include "blocked_memory_desc.h"
#include "memory_desc/blocked_memory_desc.h"
#include "openvino/util/util.hpp"
#include "cpu_memory.h"
#include "dnnl_extension_utils.h"
#include <common/memory_desc_wrapper.hpp>
namespace ov {
namespace intel_cpu {
class CpuBlockedMemoryDesc;
OPENVINO_DISABLE_WARNING_MSVC_BEGIN(4250) // Visual Studio warns us about inheritance via dominance but it's done intentionally
// so turn it off
class DnnlBlockedMemoryDesc : public BlockedMemoryDesc, public DnnlMemoryDesc {

View File

@ -0,0 +1,94 @@
// Copyright (C) 2018-2023 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "cpu_memory_desc.h"
#include "cpu_shape.h"
#include "openvino/core/except.hpp"
#include "openvino/core/type/element_type.hpp"
#include "utils/general_utils.h"
namespace ov {
namespace intel_cpu {
/**
* @brief Represents an empty memory descriptor.
*
* The main purpose is to create an empty Memory.
* Empty Memory is used to generalize passing an optional memory (such as bias)
* when both pointer to the memory data and nullptr are valid
*/
class EmptyMemoryDesc : public MemoryDesc {
public:
EmptyMemoryDesc():
MemoryDesc(Shape{0}, Empty) {
/* status never changes for an empty memory desc
* so "define" beforehand to ensure isDefined() is thread safe */
status = MemoryDesc::descStatus::Defined;
}
MemoryDescPtr clone() const override {
return std::make_shared<EmptyMemoryDesc>(*this);
}
bool isCompatible(const MemoryDesc& rhs) const override {
return everyone_is(this->getType(), rhs.getType(), Empty);
};
ov::element::Type getPrecision() const override {
return ov::element::undefined;
}
size_t getOffsetPadding() const override {
return 0;
}
bool hasLayoutType(LayoutType layoutType) const override {
return false;
}
std::string serializeFormat() const override {
return "empty";
}
size_t getMaxMemSize() const override {
return 0;
}
MemoryDescPtr cloneWithNewPrecision(const ov::element::Type prec) const override {
OPENVINO_THROW("Clone an empty memory desc with any precision (", prec, ") is prohibited");
}
private:
size_t getElementOffset(size_t elemNumber) const override {
return 0;
}
bool canComputeMemSizeZeroDims() const override {
return false;
}
size_t getCurrentMemSizeImp() const override {
return 0;
}
size_t getOffset(const VectorDims& v) const {
return 0;
}
bool isDefinedImp() const override {
return true;
}
MemoryDescPtr cloneWithNewDimsImp(const VectorDims& dims) const override {
OPENVINO_THROW("Clone an empty memory desc with any new dimensions is prohibited");
}
void setPrecision(ov::element::Type prc) override {
OPENVINO_THROW("Setting any precision (", prc, ") for an empty memory desc is prohibited");
}
};
using EmptyMemoryDescPtr = std::shared_ptr<EmptyMemoryDesc>;
using EmptyMemoryDescCPtr = std::shared_ptr<const EmptyMemoryDesc>;
} // namespace intel_cpu
} // namespace ov

View File

@ -7,6 +7,7 @@
#include <nodes/common/cpu_convert.h>
#include "cpu_memory.h"
#include "memory_desc/cpu_blocked_memory_desc.h"
#include "memory_desc/cpu_memory_desc_utils.h"
#include "dnnl_extension_utils.h"
#include "cpu_tensor.h"
#include "utils/plain_tensor.hpp"

View File

@ -3,6 +3,7 @@
//
#include "arbitrary_order_desc_creator.h"
#include "utils/general_utils.h"
namespace ov {
namespace intel_cpu {
@ -36,4 +37,4 @@ size_t ArbitraryOrderDescCreator::getMinimalRank() const {
}
} // namespace intel_cpu
} // namespace ov
} // namespace ov

View File

@ -193,10 +193,7 @@ std::shared_ptr<DnnlConvolutionPrimitive> DnnlConvolutionPrimitive::create(
const DnnlShapeAgnosticDataPtr& shapeAgnosticData) {
const auto& srcDesc = MemoryDescUtils::convertToDnnlMemoryDesc(memory.at(ARG_SRC)->getDescPtr());
const auto& weiDesc = MemoryDescUtils::convertToDnnlMemoryDesc(memory.at(ARG_WEI)->getDescPtr());
// @todo remove after empty memory desc is introduced
const DnnlMemoryDescPtr biaDesc = memory.at(ARG_BIAS)->getDescPtr()->getCurrentMemSize() != 0
? MemoryDescUtils::convertToDnnlMemoryDesc(memory.at(ARG_BIAS)->getDescPtr())
: DnnlExtensionUtils::makeDescriptor(dnnl::memory::desc{});
const auto& biaDesc = MemoryDescUtils::convertToDnnlMemoryDesc(memory.at(ARG_BIAS)->getDescPtr());
const auto& dstDesc = MemoryDescUtils::convertToDnnlMemoryDesc(memory.at(ARG_DST)->getDescPtr());
const Key dnnlConvKey{srcDesc, weiDesc, biaDesc, dstDesc, shapeAgnosticData->primAttrs.attr};

View File

@ -8,12 +8,11 @@
#include <oneapi/dnnl/dnnl.hpp>
#include "cpu_memory.h"
#include "memory_desc/cpu_memory_desc.h"
#include "nodes/executors/dnnl/dnnl_fullyconnected_primitive.hpp"
#include "nodes/executors/dnnl/dnnl_convolution_primitive.hpp"
#include "nodes/executors/dnnl/dnnl_aliases.hpp"
#include "nodes/executors/executor.hpp"
#include "nodes/executors/executor_config.hpp"
#include "memory_desc/cpu_memory_desc_utils.h"
#include "nodes/executors/memory_arguments.hpp"
namespace ov {

View File

@ -83,9 +83,7 @@ std::shared_ptr<DnnlFCPrimitive> DnnlFCPrimitive::create(const MemoryArgs& memor
const DnnlShapeAgnosticDataPtr& shapeAgnosticData) {
const auto& srcDesc = MemoryDescUtils::convertToDnnlMemoryDesc(memory.at(ARG_SRC)->getDescPtr());
const auto& weiDesc = MemoryDescUtils::convertToDnnlMemoryDesc(memory.at(ARG_WEI)->getDescPtr());
const DnnlMemoryDescPtr biaDesc = memory.at(ARG_BIAS)->getDescPtr()->getCurrentMemSize() != 0
? MemoryDescUtils::convertToDnnlMemoryDesc(memory.at(ARG_BIAS)->getDescPtr())
: DnnlExtensionUtils::makeDescriptor(dnnl::memory::desc{});
const auto& biaDesc = MemoryDescUtils::convertToDnnlMemoryDesc(memory.at(ARG_BIAS)->getDescPtr());
const auto& dstDesc = MemoryDescUtils::convertToDnnlMemoryDesc(memory.at(ARG_DST)->getDescPtr());
Key dnnlFCKey{
@ -188,7 +186,7 @@ static DnnlPrimitiveAttrs createPrimitiveAttrs(const FCAttrs& attrs,
isINT8,
1 << 0,
attrs.dequantizationScales,
attrs.withBias,
!memory.at(ARG_BIAS)->getDesc().empty(),
outputDataType);
if (attrs.decompressionMultiplyPtr)
@ -314,6 +312,7 @@ DnnlShapeAgnosticDataPtr DnnlFCPrimitive::createShapeAgnosticData(const FCAttrs&
DEBUG_LOG("Creating shape agnostic data");
auto srcDesc = memory.at(ARG_SRC)->getDescPtr();
const auto& weiDesc = memory.at(ARG_WEI)->getDescPtr();
const auto& biasDesc = memory.at(ARG_BIAS)->getDescPtr();
auto dstDesc = memory.at(ARG_DST)->getDescPtr();
const auto useWeightsDecompression = useWeightsDecompressionImpl(srcDesc->getPrecision(), weiDesc->getPrecision());
@ -339,13 +338,9 @@ DnnlShapeAgnosticDataPtr DnnlFCPrimitive::createShapeAgnosticData(const FCAttrs&
const dnnl::memory::desc srcDnnlDesc = MemoryDescUtils::convertToDnnlMemoryDesc(srcDesc)->getDnnlDesc();
const dnnl::memory::desc weiDnnlDesc = MemoryDescUtils::convertToDnnlMemoryDesc(weiDesc)->getDnnlDesc();
const dnnl::memory::desc dstDnnlDesc = MemoryDescUtils::convertToDnnlMemoryDesc(dstDesc)->getDnnlDesc();
const dnnl::memory::desc biaDnnlDesc = MemoryDescUtils::convertToDnnlMemoryDesc(biasDesc)->getDnnlDesc();
const auto useSparseWeights = attrs.sparseWeights;
const dnnl::memory::desc biaDnnlDesc =
memory.at(ARG_BIAS)->getDescPtr()->getCurrentMemSize() != 0
? MemoryDescUtils::convertToDnnlMemoryDesc(memory.at(ARG_BIAS)->getDescPtr())->getDnnlDesc()
: dnnl::memory::desc{};
const auto primDesc = createPrimitiveDesc(srcDnnlDesc,
weiDnnlDesc,
biaDnnlDesc,

View File

@ -98,8 +98,15 @@ static bool fullyMatchConfiguration(const MemoryDescArgs& currentDescriptors,
for (size_t i = 0; i < typeConfig.size(); i++) {
const auto& type = typeConfig[i];
const auto& desc = currentDescriptors.at(notation[i]);
if ((!one_of(desc->getPrecision(), type, ov::element::undefined)) || !desc->hasLayoutType(layoutConfig[i]))
return false;
if (desc->empty())
continue;
if (desc->getPrecision() != type)
return false; // type mismatch
if (!desc->hasLayoutType(layoutConfig[i]))
return false; // layout mismatch
}
return true;
@ -118,7 +125,10 @@ static MemoryDescArgs createOptimalDescriptors(const MemoryDescArgs& currentDesc
const auto& type = typeConfig[i];
const auto& layout = layoutConfig[i];
if (one_of(descType, ov::element::undefined, type)) {
if (desc->empty())
continue;
if (descType == type && desc->hasLayoutType(layout)) {
continue;
}

View File

@ -16,7 +16,6 @@
#include "memory_desc/blocked_memory_desc.h"
#include "memory_desc/cpu_memory_desc.h"
#include "memory_desc/cpu_memory_desc_utils.h"
#include "memory_desc/dnnl_blocked_memory_desc.h"
#include "nodes/executors/executor.hpp"
#include "nodes/executors/fullyconnected_config.hpp"
#include "openvino/core/type/element_type.hpp"
@ -63,16 +62,6 @@ FullyConnected::FullyConnected(const std::shared_ptr<ov::Node>& op, const GraphC
std::string errorMessage;
if (!isSupportedOperation(op, errorMessage))
OPENVINO_THROW_NOT_IMPLEMENTED(errorMessage);
auto createEmptyMemoryDesc = [](const ov::element::Type type) {
return std::make_shared<CpuBlockedMemoryDesc>(type, Shape{0});
};
auto createEmptyMemory = [&createEmptyMemoryDesc](const GraphContext::CPtr context, const ov::element::Type type) {
return std::make_shared<Memory>(context->getEngine(), createEmptyMemoryDesc(type), nullptr);
};
emptyMemory = createEmptyMemory(context, ov::element::undefined);
}
bool FullyConnected::canBeExecutedInInt8() const {
@ -236,14 +225,10 @@ void FullyConnected::initSupportedPrimitiveDescriptors() {
dstDescs.push_back(dstDesc);
}
auto createEmptyMemoryDesc = [](const ov::element::Type type) {
return std::make_shared<CpuBlockedMemoryDesc>(type, Shape{0});
};
MemoryDescArgs descs{
{ARG_SRC, srcDescs[0]},
{ARG_WEI, srcDescs[1]},
{ARG_BIAS, attrs.withBias ? srcDescs[2] : createEmptyMemoryDesc(ov::element::undefined)},
{ARG_BIAS, attrs.withBias ? srcDescs[2] : MemoryDescUtils::makeEmptyDesc()},
{ARG_DST, dstDescs[0]},
};
@ -265,7 +250,7 @@ void FullyConnected::initSupportedPrimitiveDescriptors() {
void FullyConnected::createPrimitive() {
memory[ARG_SRC] = getSrcMemoryAtPort(DATA_ID);
memory[ARG_WEI] = getSrcMemoryAtPort(WEIGHTS_ID);
memory[ARG_BIAS] = attrs.withBias ? getSrcMemoryAtPort(BIAS_ID) : emptyMemory;
memory[ARG_BIAS] = attrs.withBias ? getSrcMemoryAtPort(BIAS_ID) : MemoryDescUtils::makeEmptyMemory(context);
memory[ARG_DST] = getDstMemoryAtPort(0);
// @todo should we preconfigure only for dynamic shapes?
// Since for static shapes primitive is created in scope of compile_model() anyway

View File

@ -76,7 +76,6 @@ private:
FCAttrs attrs;
PostOps postOps;
MemoryArgs memory;
MemoryPtr emptyMemory;
ExecutorFactoryPtr<FCAttrs, node::FullyConnected> factory;
ExecutorPtr executor = nullptr;
std::string errorPrefix;

View File

@ -8,10 +8,9 @@
#include "memory.hpp"
#include "scaled_attn.h"
#include "common/cpu_convert.h"
#include "common/cpu_memcpy.h"
#include "utils/general_utils.h"
#include "memory_desc/dnnl_blocked_memory_desc.h"
#include "utils/ngraph_utils.hpp"
#include "memory_desc/cpu_memory_desc_utils.h"
#include "shape_inference/shape_inference_pass_through.hpp"
#include "common/arbitrary_order_desc_creator.h"

View File

@ -9,6 +9,7 @@
#include "non_max_suppression.h"
#include "cpu_types.h"
#include "openvino/core/parallel.hpp"
#include "utils/general_utils.h"
#include "shape_inference/shape_inference_internal_dyn.hpp"
@ -18,8 +19,6 @@
#include <queue>
namespace ov {
namespace intel_cpu {
namespace node {
@ -891,14 +890,14 @@ void NonMaxSuppression::check1DInput(const Shape& shape, const std::string& name
THROW_CPU_NODE_ERR("has unsupported '", name, "' input rank: ", shape.getRank());
if (shape.getRank() == 1)
if (shape.getDims()[0] != 1)
THROW_CPU_NODE_ERR("has unsupported '", name, "' input 1st dimension size: ", MemoryDescUtils::dim2str(shape.getDims()[0]));
THROW_CPU_NODE_ERR("has unsupported '", name, "' input 1st dimension size: ", dim2str(shape.getDims()[0]));
}
void NonMaxSuppression::checkOutput(const Shape& shape, const std::string& name, const size_t port) {
if (shape.getRank() != 2)
THROW_CPU_NODE_ERR("has unsupported '", name, "' output rank: ", shape.getRank());
if (shape.getDims()[1] != 3)
THROW_CPU_NODE_ERR("has unsupported '", name, "' output 2nd dimension size: ", MemoryDescUtils::dim2str(shape.getDims()[1]));
THROW_CPU_NODE_ERR("has unsupported '", name, "' output 2nd dimension size: ", dim2str(shape.getDims()[1]));
}
bool NonMaxSuppression::isExecutable() const {

View File

@ -6,10 +6,10 @@
#include "utils/general_utils.h"
#include "nodes/common/cpu_memcpy.h"
#include "nodes/common/cpu_convert.h"
#include "utils/bfloat16.hpp"
#include "input.h"
#include "dnnl_extension_utils.h"
#include "memory_desc/dnnl_blocked_memory_desc.h"
#include "memory_desc/cpu_memory_desc_utils.h"
#include "common/primitive_hashing_utils.hpp"
#include <memory>
#include "shape_inference/shape_inference_ngraph.hpp"

View File

@ -0,0 +1,45 @@
// Copyright (C) 2024 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include <gtest/gtest.h>
#include "dnnl_extension_utils.h"
#include "memory_desc/cpu_blocked_memory_desc.h"
#include "memory_desc/dnnl_blocked_memory_desc.h"
#include "memory_desc/cpu_memory_desc.h"
#include "memory_desc/cpu_memory_desc_utils.h"
#include "openvino/core/type/element_type.hpp"
using namespace ov::intel_cpu;
TEST(MemoryTest, EmptyMemoryDescVerifyPublicInterface) {
const auto emptyDesc = MemoryDescUtils::makeEmptyDesc();
ASSERT_EQ(emptyDesc->getType(), MemoryDescType::Empty);
ASSERT_EQ(emptyDesc->getShape(), Shape{0});
ASSERT_TRUE(emptyDesc->empty());
ASSERT_TRUE(emptyDesc->clone()->empty());
ASSERT_EQ(emptyDesc->getPrecision(), ov::element::undefined);
ASSERT_EQ(emptyDesc->getOffsetPadding(), 0);
for (const auto& layout : {LayoutType::ncsp, LayoutType::nspc, LayoutType::nCsp8c, LayoutType::nCsp16c}) {
ASSERT_FALSE(emptyDesc->hasLayoutType(layout));
}
ASSERT_EQ(emptyDesc->serializeFormat(), "empty");
ASSERT_EQ(emptyDesc->getMaxMemSize(), 0);
ASSERT_THROW(emptyDesc->cloneWithNewPrecision(ov::element::f32), ov::Exception);
// compatible with empty memory desc
ASSERT_TRUE(emptyDesc->isCompatible(*emptyDesc->clone()));
// not compatible with any other memory desc
ASSERT_FALSE(emptyDesc->isCompatible(CpuBlockedMemoryDesc{ov::element::f32, Shape{1, 2, 3}}));
ASSERT_FALSE(emptyDesc->isCompatible(DnnlBlockedMemoryDesc{ov::element::u8, Shape{1}}));
ASSERT_FALSE(emptyDesc->isCompatible(CpuBlockedMemoryDesc{ov::element::undefined, Shape{0}}));
}