[CPU] Pooling dynamism support (#8361)

This commit is contained in:
Maxim Andronov 2021-11-17 11:25:45 +03:00 committed by GitHub
parent fb05f36611
commit 14d1f7c844
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 695 additions and 308 deletions

View File

@ -19,10 +19,7 @@ bool BlockedMemoryDesc::isCompatible(const BlockedMemoryDesc &rhs) const {
return false;
}
// this check needed to avoid inserting unnecessary reorders if the memory is used in place and the batch size is equal to 1
size_t skipAxis = this->getShape().getRank() > 0 && this->getShape().getDims().front() == 1 ? 0 :
Shape::UNDEFINED_DIM; //ignore batch axis if batch size == 1
if (!dimsEqualWeak(this->getStrides(), rhs.getStrides(), skipAxis)) {
if (!dimsEqualWeak(this->getStrides(), rhs.getStrides())) {
return false;
}

View File

@ -236,7 +236,7 @@ bool DnnlBlockedMemoryDesc::isCompatible(const DnnlBlockedMemoryDesc& rhs) const
if (one_of(wrappedThis.format_kind(), format_kind::undef, format_kind::any))
return false;
int stride_start = wrappedThis.ndims() > 0 && wrappedThis.dims()[0] == 1 ? 1 : 0; // ignore batch axis stride if batch size == 1
int stride_start = 0;
const auto thisExtra = this->desc.data.extra;
const auto rhsExtra = rhs.desc.data.extra;

View File

@ -65,12 +65,7 @@ void MKLDNNEdge::drop() {
_drop_from(getChild()->parentEdges);
}
bool MKLDNNEdge::needReorder() {
if (!getInputDesc().isCompatible(getOutputDesc())) {
return true;
}
bool MKLDNNEdge::enforceReorder() {
bool canBeInPlaceConflicts = false;
auto parentNode = getParent();
auto parentSPD = parentNode->getSelectedPrimitiveDescriptor();
@ -142,6 +137,107 @@ bool MKLDNNEdge::needReorder() {
return false;
}
static inline bool isPhycicalMemCompatible(const MemoryDesc& lhsMemDesc, const MemoryDesc& rhsMemDesc) {
if (!lhsMemDesc.isDefined() || !rhsMemDesc.isDefined() ||
!(lhsMemDesc.getType() & MemoryDescType::Blocked) || !(rhsMemDesc.getType() & MemoryDescType::Blocked) ||
(lhsMemDesc.getType() == DnnlBlocked && !lhsMemDesc.as<const DnnlMemoryDesc>()->hasEmptyExtraData()) ||
(rhsMemDesc.getType() == DnnlBlocked && !rhsMemDesc.as<const DnnlMemoryDesc>()->hasEmptyExtraData()))
return false;
const auto lhsBlockMemDesc = lhsMemDesc.as<BlockedMemoryDesc>();
const auto rhsBlockMemDesc = rhsMemDesc.as<BlockedMemoryDesc>();
if (lhsBlockMemDesc->getShape() != rhsBlockMemDesc->getShape() || lhsBlockMemDesc->getPrecision() != rhsBlockMemDesc->getPrecision())
return false;
// dims padding check
bool isZeroDimsPaddings =
std::all_of(lhsBlockMemDesc->getOffsetPaddingToData().begin(), lhsBlockMemDesc->getOffsetPaddingToData().end(), [](size_t x){ return x == 0; }) &&
std::all_of(rhsBlockMemDesc->getOffsetPaddingToData().begin(), rhsBlockMemDesc->getOffsetPaddingToData().end(), [](size_t x){ return x == 0; });
bool isSameElementsCount = lhsBlockMemDesc->getPaddedElementsCount() == rhsBlockMemDesc->getPaddedElementsCount();
if (!isZeroDimsPaddings || !isSameElementsCount)
return false;
// tensor padding check
if (lhsBlockMemDesc->getOffsetPadding() != rhsBlockMemDesc->getOffsetPadding()) {
return false;
}
// stride check
const auto lhsBlockDims = lhsBlockMemDesc->getBlockDims();
std::vector<size_t> lhsStridesDefault(lhsBlockDims.size());
lhsStridesDefault[lhsBlockDims.size() - 1] = 1;
for (size_t i = 2; i <= lhsBlockDims.size(); i++) {
lhsStridesDefault[lhsBlockDims.size() - i] = lhsStridesDefault[lhsBlockDims.size() - (i - 1)] * lhsBlockDims[lhsBlockDims.size() - (i - 1)];
}
auto rhsBlockDims = rhsBlockMemDesc->getBlockDims();
std::vector<size_t> rhsStridesDefault(rhsBlockDims.size());
rhsStridesDefault[rhsBlockDims.size() - 1] = 1;
for (size_t i = 2; i <= rhsBlockDims.size(); i++) {
rhsStridesDefault[rhsBlockDims.size() - i] =
rhsStridesDefault[rhsBlockDims.size() - (i - 1)] * rhsBlockDims[rhsBlockDims.size() - (i - 1)];
}
// this check needed to avoid inserting unnecessary reorders if the memory is used in place and the batch size is equal to 1
// in nodes like concate and split
size_t lhsSkipAxis = lhsBlockDims.size() > 0 && lhsBlockDims[0] == 1 ? 0 : Shape::UNDEFINED_DIM;
size_t rhsSkipAxis = rhsBlockDims.size() > 0 && rhsBlockDims[0] == 1 ? 0 : Shape::UNDEFINED_DIM;
bool isDenseTensor = dimsEqualStrong(lhsStridesDefault, lhsBlockMemDesc->getStrides(), lhsSkipAxis) &&
dimsEqualStrong(rhsStridesDefault, rhsBlockMemDesc->getStrides(), rhsSkipAxis);
if (!isDenseTensor)
return false;
auto getCleanDim = [&](const VectorDims& dims, const VectorDims& flag) {
if (dims.size() != flag.size())
return dims;
std::vector<size_t> ret;
for (int i = 0; i < dims.size(); i++) {
if (flag[i] != 1) {
ret.push_back(dims[i]);
}
}
return ret;
};
// block dim check
auto lhsBlockDimsClean = getCleanDim(lhsBlockDims, lhsBlockDims);
auto rhsBlockDimsClean = getCleanDim(rhsBlockDims, rhsBlockDims);
if (!dimsEqualStrong(lhsBlockDimsClean, rhsBlockDimsClean))
return false;
// order check
auto lhsOrderClean = getCleanDim(lhsBlockMemDesc->getOrder(), lhsBlockDims);
auto rhsOrderClean = getCleanDim(rhsBlockMemDesc->getOrder(), rhsBlockDims);
if (!dimsEqualStrong(lhsOrderClean, rhsOrderClean))
return false;
return true;
}
MKLDNNEdge::ReorderStatus MKLDNNEdge::needReorder() {
bool optimized = false;
if (!getInputDesc().isCompatible(getOutputDesc())) {
if (isPhycicalMemCompatible(getInputDesc(), getOutputDesc()) && !getParent()->isConstant()) {
optimized = true;
} else {
return ReorderStatus::Regular;
}
}
// put here as more costly than compatible check
if (enforceReorder()) {
return ReorderStatus::Regular;
}
if (optimized) {
return ReorderStatus::Optimized;
}
return ReorderStatus::No;
}
void MKLDNNEdge::reuse(MKLDNNMemoryPtr ptr) {
if (status != Status::NeedAllocation)
return;

View File

@ -35,6 +35,12 @@ public:
Validated
};
enum class ReorderStatus {
Regular = 0,
Optimized = 1,
No = 2
};
inline Status getStatus() const noexcept {
return status;
}
@ -54,7 +60,7 @@ public:
const MKLDNNMemory& getMemory();
MKLDNNMemoryPtr& getMemoryPtr();
bool needReorder();
ReorderStatus needReorder();
bool isDropped() const;
bool isUseExternalMemory() const;
@ -87,6 +93,7 @@ private:
const MemoryDesc& getInputDesc() const;
const MemoryDesc& getOutputDesc() const;
const MemoryDesc& getDesc() const;
bool enforceReorder();
enum LOOK { LOOK_UP = 1, LOOK_DOWN = 2, LOOK_BOTH = LOOK_UP | LOOK_DOWN, LOOK_NO_RECURRENT = 4 };

View File

@ -470,12 +470,34 @@ void MKLDNNGraph::InitEdges() {
uniqueLayerNames.insert(node->getName());
}
for (auto i = 0; i < numberOfEdges; i++) {
if (graphEdges[i]->needReorder()) {
auto edge = graphEdges[i];
bool insertReorder = true;
auto insertReorder = [&](MKLDNNEdgePtr& edge, bool isOptimized) {
std::string basicLayerName = edge->getParent()->getName() + "_" +
MKLDNNReorderNode::getReorderArgs(edge->getInputDesc(), edge->getOutputDesc()) + "_" +
edge->getChild()->getName();
std::string layerName = basicLayerName;
int idx = 0;
while (uniqueLayerNames.find(layerName) != uniqueLayerNames.end()) {
idx++;
layerName = basicLayerName + "_" + std::to_string(idx);
}
uniqueLayerNames.insert(layerName);
// Check if there is a reorder that supports the type conversion
// optimized flag indicate that just desc update w/o actual physical memory movement.
InsertReorder(edge, layerName, edge->getInputDesc(), edge->getOutputDesc(), isOptimized);
};
auto updateEdge = [&](int& i) {
graphEdges.erase(graphEdges.begin() + i);
i--;
numberOfEdges--;
};
for (auto i = 0; i < numberOfEdges; i++) {
auto edge = graphEdges[i];
auto reorderStatus = graphEdges[i]->needReorder();
if (reorderStatus == MKLDNNEdge::ReorderStatus::Regular) {
MKLDNNEdge::ReorderStatus reorderStatusInternal = MKLDNNEdge::ReorderStatus::Regular;
// Check if there is a reorder that needs the precision conversion
if (edge->getInputDesc().getPrecision() != edge->getOutputDesc().getPrecision() &&
!isReorderAvailable(edge->getInputDesc(), edge->getOutputDesc(), this->getEngine())) {
// If we are here, then we need to insert Convert, because there are no reorders that support such type conversion
@ -491,29 +513,17 @@ void MKLDNNGraph::InitEdges() {
InsertNode(edge, convertNode, true);
//Check if reorder is still needed
if (convertNode->getChildEdgeAt(0)->needReorder()) {
reorderStatusInternal = convertNode->getChildEdgeAt(0)->needReorder();
if (reorderStatusInternal != MKLDNNEdge::ReorderStatus::No)
edge = convertNode->getChildEdgeAt(0);
} else {
insertReorder = false;
}
}
if (insertReorder) {
std::string basicLayerName = edge->getParent()->getName() + "_" +
MKLDNNReorderNode::getReorderArgs(edge->getInputDesc(), edge->getOutputDesc()) + "_" +
edge->getChild()->getName();
std::string layerName = basicLayerName;
int idx = 0;
while (uniqueLayerNames.find(layerName) != uniqueLayerNames.end()) {
idx++;
layerName = basicLayerName + "_" + std::to_string(idx);
}
uniqueLayerNames.insert(layerName);
InsertReorder(edge, layerName, edge->getInputDesc(), edge->getOutputDesc());
if (reorderStatusInternal != MKLDNNEdge::ReorderStatus::No) {
insertReorder(edge, reorderStatusInternal == MKLDNNEdge::ReorderStatus::Optimized);
}
graphEdges.erase(graphEdges.begin() + i);
i--;
numberOfEdges--;
updateEdge(i);
} else if (reorderStatus == MKLDNNEdge::ReorderStatus::Optimized) {
insertReorder(edge, true);
updateEdge(i);
}
}
}

View File

@ -725,7 +725,6 @@ protected:
}
std::vector<VectorDims> lastInputDims = {};
std::shared_ptr<ngraph::Node> opToShapeInfer;
private:

View File

@ -1181,7 +1181,20 @@ void MKLDNNEltwiseNode::initSupportedPrimitiveDescriptors() {
portConfig.inPlace = (!i && canBeInPlace() && inputPrecisions[i] == outputPrecision) ? 0 : -1;
portConfig.constant = false;
portConfig.desc = createMemoryDesc(getInputShapeAtPort(i), inputPrecisions[i], offset);
const auto &srcShape = getInputShapeAtPort(i);
portConfig.desc = createMemoryDesc(srcShape, inputPrecisions[i], offset);
if (!isDynamicNode() && srcShape.getDims()[0] == 1) {
const auto denseDesc = portConfig.desc->as<BlockedMemoryDesc>();
auto strides = denseDesc->getStrides();
strides[0] = Shape::UNDEFINED_DIM;
portConfig.desc = std::make_shared<CpuBlockedMemoryDesc>(denseDesc->getPrecision(),
denseDesc->getShape(),
denseDesc->getBlockDims(),
denseDesc->getOrder(),
denseDesc->getOffsetPadding(),
denseDesc->getOffsetPaddingToData(),
strides);
}
config.inConfs.push_back(portConfig);
}
@ -1190,7 +1203,20 @@ void MKLDNNEltwiseNode::initSupportedPrimitiveDescriptors() {
portConfig.inPlace = -1;
portConfig.constant = false;
portConfig.desc = createMemoryDesc(getOutputShapeAtPort(0), outputPrecision, offset);
const auto &dstShape = getOutputShapeAtPort(0);
portConfig.desc = createMemoryDesc(dstShape, outputPrecision, offset);
if (!isDynamicNode() && dstShape.getDims()[0] == 1) {
const auto denseDesc = portConfig.desc->as<BlockedMemoryDesc>();
auto strides = denseDesc->getStrides();
strides[0] = Shape::UNDEFINED_DIM;
portConfig.desc = std::make_shared<CpuBlockedMemoryDesc>(denseDesc->getPrecision(),
denseDesc->getShape(),
denseDesc->getBlockDims(),
denseDesc->getOrder(),
denseDesc->getOffsetPadding(),
denseDesc->getOffsetPaddingToData(),
strides);
}
config.outConfs.push_back(portConfig);

View File

@ -46,13 +46,16 @@ void MKLDNNNonZeroNode::getSupportedDescriptors() {
void MKLDNNNonZeroNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
const Precision precs[6] = { Precision::FP32, Precision::BF16, Precision::I32,
Precision::U32, Precision::I8, Precision::U8 };
for (const auto prec : precs) {
addSupportedPrimDesc({{LayoutType::ncsp, prec}},
{{LayoutType::ncsp, Precision::I32}},
impl_desc_type::ref);
const auto &inPrc = getOriginalInputPrecisionAtPort(0);
if (!one_of(inPrc, Precision::FP32, Precision::BF16, Precision::I32, Precision::U32, Precision::I8, Precision::U8)) {
IE_THROW() << "Can't create primitive descriptor for NonZero layer with name: " << getName() << " doesn't support "
<< inPrc.name() << " precision on 0 port";
}
addSupportedPrimDesc({{LayoutType::ncsp}},
{{LayoutType::ncsp, Precision::I32}},
impl_desc_type::ref);
}
template <typename T>

View File

@ -22,10 +22,6 @@ using namespace InferenceEngine;
bool MKLDNNPoolingNode::isSupportedOperation(const std::shared_ptr<const ngraph::Node>& op, std::string& errorMessage) noexcept {
try {
if (isDynamicNgraphNode(op)) {
errorMessage = "Doesn't support op with dynamic shapes";
return false;
}
if (!ngraph::as_type_ptr<const ngraph::op::v1::MaxPool>(op) && !ngraph::as_type_ptr<const ngraph::op::v1::AvgPool>(op)) {
errorMessage = "Only opset1 MaxPool and AvgPool operations are supported";
return false;
@ -61,6 +57,7 @@ MKLDNNPoolingNode::MKLDNNPoolingNode(const std::shared_ptr<ngraph::Node>& op, co
for (int i = 0; i < maxPoolOp->get_pads_end().size(); i++) {
data_pad_end.push_back(static_cast<ptrdiff_t>(maxPoolOp->get_pads_end()[i]));
}
auto_pad = (maxPoolOp->get_auto_pad() == ov::op::PadType::SAME_LOWER || maxPoolOp->get_auto_pad() == ov::op::PadType::SAME_UPPER);
} else if (avgPoolOp) {
algorithm = PoolingAvg;
exclude_pad = avgPoolOp->get_exclude_pad();
@ -77,6 +74,7 @@ MKLDNNPoolingNode::MKLDNNPoolingNode(const std::shared_ptr<ngraph::Node>& op, co
for (int i = 0; i < avgPoolOp->get_pads_end().size(); i++) {
data_pad_end.push_back(static_cast<ptrdiff_t>(avgPoolOp->get_pads_end()[i]));
}
auto_pad = (avgPoolOp->get_auto_pad() == ov::op::PadType::SAME_LOWER || avgPoolOp->get_auto_pad() == ov::op::PadType::SAME_UPPER);
}
}
@ -96,6 +94,23 @@ std::vector<memory::format_tag> MKLDNNPoolingNode::getAvailableFormatsForDims(co
return {memory::format_tag::any};
}
void MKLDNNPoolingNode::initEffectivePad(const Shape &inShape, const Shape &outShape) {
effective_pad_begin = data_pad_begin;
effective_pad_end.resize(data_pad_end.size());
const auto &inDims = inShape.getStaticDims();
const auto &outDims = outShape.getStaticDims();
for (int i = 0; i < effective_pad_end.size(); i++) {
int krn = kernel[i];
int src = inDims[2 + i];
int dst = outDims[2 + i];
int calc_dst = (src - krn + data_pad_begin[i]) / stride[i] + 1;
effective_pad_end[i] = (dst - calc_dst) * stride[i];
}
}
void MKLDNNPoolingNode::getSupportedDescriptors() {
if (!descs.empty())
return;
@ -129,24 +144,16 @@ void MKLDNNPoolingNode::getSupportedDescriptors() {
auto inputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(inputPrecision);
auto outputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(outputPrecision);
effective_pad_begin = data_pad_begin;
effective_pad_end.resize(data_pad_end.size());
auto parentShape = getInputShapeAtPort(0);
auto childShape = getOutputShapeAtPort(0);
const auto &parentShape = getInputShapeAtPort(0);
const auto &childShape = getOutputShapeAtPort(0);
const size_t inputRank = getInputShapeAtPort(0).getRank();
if ((inputRank < 4) || (inputRank > 5))
IE_THROW() << "Pooling layer. Unsupported mode. Only 4D and 5D blobs are supported as input.";
for (int i = 0; i < effective_pad_end.size(); i++) {
int krn = kernel[i];
int src = getInputShapeAtPort(0).getStaticDims()[2 + i];
int dst = getOutputShapeAtPort(0).getStaticDims()[2 + i];
initEffectivePad(MemoryDescUtils::makeDummyShape(parentShape),
MemoryDescUtils::makeDummyShape(childShape));
int calc_dst = (src - krn + data_pad_begin[i]) / stride[i] + 1;
effective_pad_end[i] = (dst - calc_dst) * stride[i];
}
if (inputPrecision == Precision::I8 || inputPrecision == Precision::U8) {
// We have to extend i8i8_pooling_fwd_t from oneDNN to support BF16 output data type
if (outputDataType == memory::data_type::bf16)
@ -157,7 +164,7 @@ void MKLDNNPoolingNode::getSupportedDescriptors() {
const auto out_candidate = std::make_shared<DnnlBlockedMemoryDesc>(childShape, outputDataType, inputRank == 5 ?
memory::format_tag::ndhwc : memory::format_tag::nhwc);
createDescriptor({ in_candidate }, { out_candidate });
} else if ((inputRank == 4 || inputRank == 5) && parentShape.getStaticDims()[1] == 1) {
} else if ((inputRank == 4 || inputRank == 5) && parentShape.getDims()[1] == 1) {
// WA. We should force planar layout since it provides better performance
const auto in_candidate = std::make_shared<DnnlBlockedMemoryDesc>(parentShape, inputDataType, inputRank == 5 ?
memory::format_tag::ncdhw : memory::format_tag::nchw);
@ -178,14 +185,70 @@ void MKLDNNPoolingNode::getSupportedDescriptors() {
}
}
void MKLDNNPoolingNode::createPrimitive() {
if (prim)
return;
std::pair<std::vector<ptrdiff_t>, std::vector<ptrdiff_t>> MKLDNNPoolingNode::getPaddingFromNode(std::shared_ptr<ngraph::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;
};
mkldnn::primitive_attr attr;
setPostOps(attr, true);
VectorDims padsBegin, padsEnd;
if (getAlgorithm() == PoolingMax) {
const auto pool = ngraph::as_type_ptr<const ngraph::op::v1::MaxPool>(opToShapeInfer);
padsBegin = pool->get_pads_begin();
padsEnd = pool->get_pads_end();
} else if (getAlgorithm() == PoolingAvg) {
const auto pool = ngraph::as_type_ptr<const ngraph::op::v1::AvgPool>(opToShapeInfer);
padsBegin = pool->get_pads_begin();
padsEnd = pool->get_pads_end();
}
return {convertPadding(padsBegin), convertPadding(padsEnd)};
}
auto prim_desc = createPrimitiveDescriptor<pooling_forward::primitive_desc, pooling_forward::desc>(attr);
void MKLDNNPoolingNode::prepareParams() {
const NodeDesc *selected_pd = getSelectedPrimitiveDescriptor();
if (selected_pd == nullptr)
IE_THROW() << "Pooling node with name '" << getName() << "' did not set preferable primitive descriptor";
AttrPtr attr;
if (isDynamicNode()) {
if (!pAttr) {
pAttr = initPrimitiveAttr();
}
attr = pAttr;
} else {
attr = initPrimitiveAttr();
}
auto inDesc = getParentEdgesAtPort(0)[0]->getMemory().GetDescWithType<DnnlMemoryDesc>();
const auto& in_candidate = inDesc->getDnnlDesc();
auto outDesc = getChildEdgesAtPort(0)[0]->getMemory().GetDescWithType<DnnlMemoryDesc>();
const auto& out_candidate = outDesc->getDnnlDesc();
if (isDynamicNode()) {
if (auto_pad) {
std::tie(data_pad_begin, data_pad_end) = getPaddingFromNode(opToShapeInfer);
}
initEffectivePad(inDesc->getShape(), outDesc->getShape());
}
mkldnn::algorithm alg = getPoolingAlgorithm();
MKLDNNDescriptor desc{createDescriptorInternal(in_candidate, out_candidate, alg)};
pooling_forward::primitive_desc prim_desc;
primitive_desc_iterator itpd = desc.createPrimitiveDescriptorIterator(getEngine(), *attr);
while (static_cast<bool>(itpd)) {
impl_desc_type impl_type = parse_impl_name(itpd.impl_info_str());
if (impl_type == selected_pd->getImplementationType()) {
prim_desc = itpd.get();
break;
}
if (!itpd.next_impl())
IE_THROW() << "Primitive descriptor was not found for node " << getName() << ".";
}
prim.reset(new pooling_forward(prim_desc));
@ -194,16 +257,19 @@ void MKLDNNPoolingNode::createPrimitive() {
primArgs = {{DNNL_ARG_SRC, src}, {DNNL_ARG_DST, dst}};
}
void MKLDNNPoolingNode::createPrimitive() {
if (inputShapesDefined()) {
if (needPrepareParams())
prepareParams();
updateLastInputDims();
}
}
bool MKLDNNPoolingNode::created() const {
return getType() == Pooling;
}
void MKLDNNPoolingNode::createDescriptor(const std::vector<MemoryDescPtr> &inputDesc,
const std::vector<MemoryDescPtr> &outputDesc) {
auto in_candidate = MemoryDescUtils::convertToDnnlMemoryDesc(inputDesc[0])->getDnnlDesc();
auto out_candidate = MemoryDescUtils::convertToDnnlMemoryDesc(outputDesc[0])->getDnnlDesc();
mkldnn::algorithm alg;
mkldnn::algorithm MKLDNNPoolingNode::getPoolingAlgorithm() const {
if (algorithm == PoolingAvg) {
bool not_zero_l = false;
for (auto lr : data_pad_begin) {
@ -220,12 +286,20 @@ void MKLDNNPoolingNode::createDescriptor(const std::vector<MemoryDescPtr> &input
}
}
if (!exclude_pad && (not_zero_l || not_zero_r))
alg = mkldnn::algorithm::pooling_avg_include_padding;
return mkldnn::algorithm::pooling_avg_include_padding;
else
alg = mkldnn::algorithm::pooling_avg_exclude_padding;
return mkldnn::algorithm::pooling_avg_exclude_padding;
} else if (algorithm == PoolingMax) {
alg = mkldnn::algorithm::pooling_max;
return mkldnn::algorithm::pooling_max;
} else {
return mkldnn::algorithm::undef;
}
}
std::shared_ptr<pooling_forward::desc> MKLDNNPoolingNode::createDescriptorInternal(const mkldnn::memory::desc& in_candidate,
const mkldnn::memory::desc& out_candidate,
const mkldnn::algorithm alg) const {
if (alg == mkldnn::algorithm::undef) {
IE_THROW() << "Unsupported pooling type";
}
@ -253,6 +327,30 @@ void MKLDNNPoolingNode::createDescriptor(const std::vector<MemoryDescPtr> &input
}
}
return desc_ptr;
}
void MKLDNNPoolingNode::createDescriptor(const std::vector<MemoryDescPtr> &inputDesc,
const std::vector<MemoryDescPtr> &outputDesc) {
auto inDesc = inputDesc[0]->isDefined() ? inputDesc[0] : MemoryDescUtils::makeDummyDesc(*inputDesc[0]);
auto dnnlInDesc = MemoryDescUtils::convertToDnnlMemoryDesc(inDesc);
auto in_candidate = dnnlInDesc->getDnnlDesc();
auto outDesc = outputDesc[0];
if (!outDesc->isDefined()) {
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);
}
initEffectivePad(inDesc->getShape(), outDesc->getShape());
}
auto dnnlOutDesc = MemoryDescUtils::convertToDnnlBlockedMemoryDesc(*outDesc);
auto out_candidate = dnnlOutDesc.getDnnlDesc();
mkldnn::algorithm alg = getPoolingAlgorithm();
auto desc_ptr = createDescriptorInternal(in_candidate, out_candidate, alg);
descs.emplace_back(desc_ptr);
}
@ -272,12 +370,8 @@ void MKLDNNPoolingNode::initSupportedPrimitiveDescriptors() {
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
auto desc = getSrcMemDesc(itpd, i);
if (desc->getType() & MemoryDescType::Blocked) {
dataConfig.desc = desc->as<BlockedMemoryDesc>()->cloneWithUndefStridesAndOffset();
} else {
dataConfig.desc = std::move(desc);
}
dataConfig.desc = getSrcMemDesc(itpd, i);
config.inConfs.push_back(dataConfig);
}
@ -285,12 +379,8 @@ void MKLDNNPoolingNode::initSupportedPrimitiveDescriptors() {
PortConfig dataConfig;
dataConfig.inPlace = canBeInPlace() ? 0 : -1;
dataConfig.constant = false;
auto desc = getDstMemDesc(itpd, i);
if (desc->getType() & MemoryDescType::Blocked) {
dataConfig.desc = desc->as<BlockedMemoryDesc>()->cloneWithUndefStridesAndOffset();
} else {
dataConfig.desc = std::move(desc);
}
dataConfig.desc = getDstMemDesc(itpd, i);
config.outConfs.push_back(dataConfig);
}
impl_desc_type impl_type = parse_impl_name(itpd.impl_info_str());
@ -382,7 +472,15 @@ void MKLDNNPoolingNode::initDescriptor(const NodeConfig& config) {
selectedPD->setConfig(rightConfig);
}
void MKLDNNPoolingNode::setPostOps(mkldnn::primitive_attr &attr, bool initWeights) {
MKLDNNNode::AttrPtr MKLDNNPoolingNode::initPrimitiveAttr() const {
auto attr = std::make_shared<mkldnn::primitive_attr>(mkldnn::primitive_attr());
setPostOps(*attr, true);
return attr;
}
void MKLDNNPoolingNode::setPostOps(mkldnn::primitive_attr &attr, bool initWeights) const {
mkldnn::post_ops ops;
for (auto &node : fusedWith) {

View File

@ -28,11 +28,27 @@ public:
return false;
}
void prepareParams() override;;
void executeDynamicImpl(mkldnn::stream strm) override { execute(strm); }
static bool isSupportedOperation(const std::shared_ptr<const ngraph::Node>& op, std::string& errorMessage) noexcept;
private:
void setPostOps(mkldnn::primitive_attr &attr, bool initWeights = false);
protected:
AttrPtr initPrimitiveAttr() const override;
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<ngraph::Node> node) const;
void initEffectivePad(const Shape &inDims, const Shape &outDims);
mkldnn::algorithm getPoolingAlgorithm() const;
std::shared_ptr<mkldnn::pooling_forward::desc> createDescriptorInternal(const mkldnn::memory::desc& in_candidate,
const mkldnn::memory::desc& out_candidate,
const mkldnn::algorithm alg) const;
AttrPtr pAttr;
bool auto_pad = false;
bool exclude_pad = false;
std::vector<ptrdiff_t> stride;
std::vector<ptrdiff_t> kernel;

View File

@ -38,7 +38,8 @@ inline std::vector<size_t> getNormalizedDimsBySize(const InferenceEngine::SizeVe
*/
inline bool isPerTensorOrPerChannelBroadcastable(const InferenceEngine::SizeVector &firstInputDims, const InferenceEngine::SizeVector& secondInputDims,
bool weakComparison = false) {
bool (*dimsEqual)(size_t, size_t) = weakComparison ? static_cast<bool (*)(size_t, size_t)>(dimsEqualWeak) : dimsEqualStrong;
bool (*dimsEqual)(size_t, size_t) = weakComparison ? static_cast<bool (*)(size_t, size_t)>(dimsEqualWeak) :
static_cast<bool (*)(size_t, size_t)>(dimsEqualStrong);
if (secondInputDims.size() > firstInputDims.size())
return false;
if (std::accumulate(secondInputDims.begin(), secondInputDims.end(), 1, std::multiplies<size_t>()) == 1)

View File

@ -67,6 +67,26 @@ inline bool dimsEqualStrong(size_t lhs, size_t rhs) {
return (lhs == rhs && lhs != Shape::UNDEFINED_DIM && rhs != Shape::UNDEFINED_DIM);
}
/**
* @brief Compares that two shapes are equal
* @param lhs
* first shape
* @param rhs
* second shape
* @return result of comparison
*/
inline bool dimsEqualStrong(const std::vector<size_t>& lhs, const std::vector<size_t>& rhs, size_t skipAxis = Shape::UNDEFINED_DIM) {
if (lhs.size() != rhs.size())
return false;
for (size_t i = 0; i < lhs.size(); i++) {
if (i != skipAxis && !dimsEqualStrong(lhs[i], rhs[i]))
return false;
}
return true;
}
/**
* @brief Compares that two dims are equal or undefined
* @param lhs
@ -87,7 +107,7 @@ inline bool dimsEqualWeak(size_t lhs, size_t rhs) {
* second shape
* @param skipAxis
* marks shape axis which shouldn't be validated
* @return order
* @return result of comparison
*/
inline bool dimsEqualWeak(const std::vector<size_t>& lhs, const std::vector<size_t>& rhs, size_t skipAxis = Shape::UNDEFINED_DIM) {
if (lhs.size() != rhs.size())

View File

@ -159,6 +159,16 @@ const std::vector<std::vector<InputShape>> inputShapes4D_axis1 = {
{{{1, 3}, {3, 16}, {1, 10}, {2, 8}}, {{2, 16, 5, 7}, {1, 5, 10, 2}, {3, 3, 1, 8}}},
{{{1, 3}, {1, 64}, {1, 10}, {2, 8}}, {{2, 64, 5, 7}, {1, 45, 10, 2}, {3, 1, 1, 8}}}
},
{
{{{1, 18, 10, 2}}, {{1, 18, 10, 2}, {1, 18, 10, 2}}},
{{-1, -1, -1, -1}, {{1, 3, 10, 2}, {1, 5, 10, 2}}},
{{{1, 5, 10, 2}}, {{1, 5, 10, 2}, {1, 5, 10, 2}}}
},
{
{{{-1, 8, -1, -1}}, {{2, 8, 5, 7}, {1, 8, 10, 2}}},
{{{-1, 3, -1, -1}}, {{2, 3, 5, 7}, {1, 3, 10, 2}}},
{{{-1, -1, -1, -1}}, {{2, 16, 5, 7}, {1, 7, 10, 2}}}
}
};
INSTANTIATE_TEST_SUITE_P(smoke_Concat4D_CPU_dynamic_axis_1, ConcatLayerCPUTest,

View File

@ -8,9 +8,11 @@
#include "shared_test_classes/base/ov_subgraph.hpp"
#include "ngraph_functions/builders.hpp"
#include "functional_test_utils/ov_tensor_utils.hpp"
#include "test_utils/cpu_test_utils.hpp"
using namespace ov::test;
using namespace ngraph;
using namespace CPUTestUtils;
namespace CPULayerTestsDefinitions {
@ -45,7 +47,7 @@ using NmsParams = std::tuple<InputShapeParams,
ngraph::element::Type, // Output type
std::string>; // Device name
class NmsLayerCPUTest : public testing::WithParamInterface<NmsParams>, virtual public SubgraphBaseTest {
class NmsLayerCPUTest : public testing::WithParamInterface<NmsParams>, virtual public SubgraphBaseTest, public CPUTestsBase {
public:
static std::string getTestCaseName(const testing::TestParamInfo<NmsParams>& obj) {
InputShapeParams inShapeParams;
@ -183,17 +185,7 @@ protected:
auto nms = std::make_shared<ngraph::op::v5::NonMaxSuppression>(params[0], params[1], maxOutBoxesPerClassNode, iouThrNode, scoreThrNode,
softNmsSigmaNode, boxEncoding, sortResDescend, outType);
if (targetDevice == CommonTestUtils::DEVICE_CPU) {
function = std::make_shared<Function>(nms, params, "NMS");
} else {
auto nms_0_identity = std::make_shared<opset5::Multiply>(nms->output(0), opset5::Constant::create(outType, Shape{1}, {1}));
auto nms_1_identity = std::make_shared<opset5::Multiply>(nms->output(1), opset5::Constant::create(paramsPrec, Shape{1}, {1}));
auto nms_2_identity = std::make_shared<opset5::Multiply>(nms->output(2), opset5::Constant::create(outType, Shape{1}, {1}));
nms_0_identity->set_friendly_name("Multiply_0");
nms_1_identity->set_friendly_name("Multiply_1");
nms_2_identity->set_friendly_name("Multiply_2");
function = std::make_shared<Function>(OutputVector{nms_0_identity, nms_1_identity, nms_2_identity}, params, "NMS");
}
function = makeNgraphFunction(paramsPrec, params, nms, "NMS");
}
private:
@ -410,7 +402,10 @@ private:
};
TEST_P(NmsLayerCPUTest, CompareWithRefs) {
SKIP_IF_CURRENT_TEST_IS_DISABLED()
run();
// CheckPluginRelatedResults(executableNetwork, "NonMaxSuppression");
};
const std::vector<InputShapeParams> inShapeParams = {

View File

@ -4,62 +4,33 @@
#include "ngraph_functions/builders.hpp"
#include "test_utils/cpu_test_utils.hpp"
#include "shared_test_classes/single_layer/pooling.hpp"
#include "test_utils/fusing_test_utils.hpp"
#include "shared_test_classes/single_layer/pooling.hpp"
#include "shared_test_classes/base/ov_subgraph.hpp"
using namespace InferenceEngine;
using namespace ov::test;
using namespace CPUTestUtils;
using namespace LayerTestsDefinitions;
namespace CPULayerTestsDefinitions {
typedef std::tuple<
poolLayerTestParamsSet,
CPUSpecificParams,
fusingSpecificParams
> poolLayerCpuTestParamsSet;
using poolLayerCpuTestParamsSet = std::tuple<LayerTestsDefinitions::poolSpecificParams,
InputShape,
ElementType,
bool,
CPUSpecificParams,
fusingSpecificParams>;
class PoolingLayerCPUTest : public testing::WithParamInterface<poolLayerCpuTestParamsSet>,
virtual public LayerTestsUtils::LayerTestsCommon, public CpuTestWithFusing {
virtual public SubgraphBaseTest, public CpuTestWithFusing {
public:
static std::string getTestCaseName(const testing::TestParamInfo<poolLayerCpuTestParamsSet>& obj) {
poolLayerTestParamsSet basicParamsSet;
LayerTestsDefinitions::poolSpecificParams basicParamsSet;
InputShape inputShapes;
ElementType inPrc;
bool isInt8;
CPUSpecificParams cpuParams;
fusingSpecificParams fusingParams;
std::tie(basicParamsSet, cpuParams, fusingParams) = obj.param;
std::ostringstream result;
result << PoolingLayerTest::getTestCaseName(testing::TestParamInfo<poolLayerTestParamsSet>(
basicParamsSet, 0));
result << CPUTestsBase::getTestCaseName(cpuParams);
result << CpuTestWithFusing::getTestCaseName(fusingParams);
return result.str();
}
protected:
void SetUp() override {
poolLayerTestParamsSet basicParamsSet;
CPUSpecificParams cpuParams;
fusingSpecificParams fusingParams;
std::tie(basicParamsSet, cpuParams, fusingParams) = this->GetParam();
poolSpecificParams poolParams;
std::vector<size_t> inputShape;
InferenceEngine::Precision netPrecision;
std::tie(poolParams, netPrecision, inPrc, outPrc, inLayout, outLayout, inputShape, targetDevice) = basicParamsSet;
if (outPrc == Precision::UNSPECIFIED) {
outPrc = inPrc;
}
std::tie(inFmts, outFmts, priority, selectedType) = cpuParams;
std::tie(postOpMgrPtr, fusedOps) = fusingParams;
if (selectedType.empty()) {
selectedType = getPrimitiveType();
}
selectedType = selectedType + "_" + inPrc.name();
std::tie(basicParamsSet, inputShapes, inPrc, isInt8, cpuParams, fusingParams) = obj.param;
ngraph::helpers::PoolingTypes poolType;
std::vector<size_t> kernel, stride;
@ -67,14 +38,79 @@ protected:
ngraph::op::PadType padType;
ngraph::op::RoundingType roundingType;
bool excludePad;
std::tie(poolType, kernel, stride, padBegin, padEnd, roundingType, padType, excludePad) = poolParams;
std::tie(poolType, kernel, stride, padBegin, padEnd, roundingType, padType, excludePad) = basicParamsSet;
auto ngPrc = FuncTestUtils::PrecisionUtils::convertIE2nGraphPrc(netPrecision);
auto params = ngraph::builder::makeParams(ngPrc, {inputShape});
auto paramOuts = ngraph::helpers::convert2OutputVector(
ngraph::helpers::castOps2Nodes<ngraph::op::Parameter>(params));
std::ostringstream results;
results << "IS=(";
results << CommonTestUtils::partialShape2str({inputShapes.first}) << ")_";
results << "TS=";
for (const auto& shape : inputShapes.second) {
results << CommonTestUtils::vec2str(shape) << "_";
}
results << "Prc=" << inPrc << "_";
switch (poolType) {
case ngraph::helpers::PoolingTypes::MAX:
results << "MaxPool_";
break;
case ngraph::helpers::PoolingTypes::AVG:
results << "AvgPool_";
results << "ExcludePad=" << excludePad << "_";
break;
}
results << "K" << CommonTestUtils::vec2str(kernel) << "_";
results << "S" << CommonTestUtils::vec2str(stride) << "_";
results << "PB" << CommonTestUtils::vec2str(padBegin) << "_";
results << "PE" << CommonTestUtils::vec2str(padEnd) << "_";
results << "Rounding=" << roundingType << "_";
results << "AutoPad=" << padType << "_";
results << "INT8=" << isInt8 << "_";
std::shared_ptr<ngraph::Node> pooling = ngraph::builder::makePooling(paramOuts[0],
results << CPUTestsBase::getTestCaseName(cpuParams);
results << CpuTestWithFusing::getTestCaseName(fusingParams);
return results.str();
return results.str();
}
protected:
void SetUp() override {
targetDevice = CommonTestUtils::DEVICE_CPU;
LayerTestsDefinitions::poolSpecificParams basicParamsSet;
InputShape inputShapes;
ElementType inPrc;
bool isInt8;
CPUSpecificParams cpuParams;
fusingSpecificParams fusingParams;
std::tie(basicParamsSet, inputShapes, inPrc, isInt8, cpuParams, fusingParams) = this->GetParam();
ngraph::helpers::PoolingTypes poolType;
std::vector<size_t> kernel, stride;
std::vector<size_t> padBegin, padEnd;
ngraph::op::PadType padType;
ngraph::op::RoundingType roundingType;
bool excludePad;
std::tie(poolType, kernel, stride, padBegin, padEnd, roundingType, padType, excludePad) = basicParamsSet;
std::tie(inFmts, outFmts, priority, selectedType) = cpuParams;
std::tie(postOpMgrPtr, fusedOps) = fusingParams;
if (selectedType.empty()) {
selectedType = getPrimitiveType();
}
selectedType = selectedType + "_" + InferenceEngine::details::convertPrecision(inPrc).name();
init_input_shapes({inputShapes});
auto params = ngraph::builder::makeDynamicParams(inPrc, inputDynamicShapes);
std::shared_ptr<ngraph::Node> poolInput = params[0];
if (isInt8) {
ov::Shape newShape(poolInput->get_output_partial_shape(0).size(), 1);
poolInput = ngraph::builder::makeFakeQuantize(poolInput, inPrc, 256, newShape);
}
std::shared_ptr<ngraph::Node> pooling = ngraph::builder::makePooling(poolInput,
stride,
padBegin,
padEnd,
@ -84,180 +120,206 @@ protected:
excludePad,
poolType);
function = makeNgraphFunction(ngPrc, params, pooling, "Pooling");
function = makeNgraphFunction(inPrc, params, pooling, "PoolingCPU");
}
};
TEST_P(PoolingLayerCPUTest, CompareWithRefs) {
SKIP_IF_CURRENT_TEST_IS_DISABLED()
Run();
CheckPluginRelatedResults(executableNetwork, "Pooling");
run();
// CheckPluginRelatedResults(executableNetwork, "Pooling");
}
namespace {
const auto avx512 = CPUSpecificParams{{}, {}, {"jit_avx512"}, "jit_avx512"};
const auto avx = CPUSpecificParams{{}, {}, {"jit_avx"}, "jit_avx"};
const auto sse42 = CPUSpecificParams{{}, {}, {"jit_sse42"}, "jit_sse42"};
const auto ref = CPUSpecificParams{{}, {}, {"ref_any"}, "ref_any"};
const std::vector<CPUSpecificParams> vecCpuConfigs = {ref, sse42, avx, avx512};
const std::vector<Precision> inpOutPrecision = {Precision::FP32, Precision::BF16};
const std::vector<ElementType> inpOutPrecision = {ElementType::f32/*, ElementType::bf16*/};
const std::vector<std::vector<size_t>> inputShapes4D = {
std::vector<size_t>{3, 4, 64, 64},
std::vector<size_t>{2, 8, 8, 12},
std::vector<size_t>{1, 16, 16, 12},
std::vector<size_t>{1, 21, 8, 4},
std::vector<size_t>{1, 32, 8, 8},
const std::vector<InputShape> inputShapes4D = {
{ {}, {{3, 4, 64, 64}} },
{ {}, {{2, 8, 8, 12}} },
{ {}, {{1, 16, 16, 12}} },
{ {}, {{1, 21, 8, 4}} },
{ {}, {{1, 32, 8, 8}} },
{
// dynamic
{-1, -1, -1, -1},
// target
{
{1, 32, 8, 8},
{1, 21, 8, 4},
{2, 8, 8, 12}
}
},
{
// dynamic
{{1, 5}, {4, 32}, {1, 64}, {1, 64}},
// target
{
{3, 4, 64, 64},
{1, 16, 16, 12},
{1, 32, 8, 8}
}
}
};
const std::vector<std::vector<size_t>> inputShapes5D = {
std::vector<size_t>{1, 4, 16, 16, 16},
std::vector<size_t>{2, 8, 8, 8, 8},
std::vector<size_t>{2, 16, 12, 16, 20},
std::vector<size_t>{1, 19, 16, 20, 8},
std::vector<size_t>{1, 32, 16, 8, 12},
const std::vector<InputShape> inputShapes5D = {
{ {}, {{1, 4, 16, 16, 16}} },
{ {}, {{2, 8, 8, 8, 8}} },
{ {}, {{2, 16, 12, 16, 20}} },
{ {}, {{1, 19, 16, 20, 8}} },
{ {}, {{1, 32, 16, 8, 12}} },
{
// dynamic
{-1, -1, -1, -1, -1},
// target
{
{2, 8, 8, 8, 8},
{1, 19, 16, 20, 8},
{1, 4, 16, 16, 16}
}
},
{
// dynamic
{{1, 5}, {4, 32}, {1, 64}, {1, 64}, {1, 25}},
// target
{
{1, 4, 16, 16, 16},
{1, 32, 16, 8, 12},
{3, 16, 4, 8, 3}
}
}
};
const std::vector<poolSpecificParams> paramsMax4D = {
poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2}, {2, 2}, {0, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {4, 2}, {2, 2}, {0, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {4, 2}, {2, 1}, {0, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
};
const std::vector<poolSpecificParams> paramsAvg4D = {
poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {1, 0}, {0, 0},
const std::vector<LayerTestsDefinitions::poolSpecificParams> paramsMax4D = {
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2}, {2, 2}, {0, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_LOWER, false },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2}, {2, 2}, {0, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_UPPER, false },
poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {0, 0}, {0, 0},
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {4, 2}, {2, 2}, {0, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {4, 2}, {2, 1}, {0, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
};
const std::vector<LayerTestsDefinitions::poolSpecificParams> paramsAvg4D = {
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {1, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_LOWER, true },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {1, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_UPPER, true },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {1, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_LOWER, false },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {1, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_UPPER, false },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {0, 0}, {0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, true },
poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {4, 4}, {4, 4}, {2, 2}, {2, 2},
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {4, 4}, {4, 4}, {2, 2}, {2, 2},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, true },
};
const std::vector<poolSpecificParams> paramsAvg4D_RefOnly = {
poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {2, 2}, {2, 2},
const std::vector<LayerTestsDefinitions::poolSpecificParams> paramsAvg4D_RefOnly = {
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2}, {2, 2}, {2, 2}, {2, 2},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
};
INSTANTIATE_TEST_SUITE_P(smoke_MaxPool_CPU_4D, PoolingLayerCPUTest,
::testing::Combine(
::testing::Combine(
::testing::ValuesIn(paramsMax4D),
::testing::Values(Precision::FP32),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShapes4D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)),
::testing::Values(emptyFusingSpec)),
::testing::ValuesIn(paramsMax4D),
::testing::ValuesIn(inputShapes4D),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(false),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)),
::testing::Values(emptyFusingSpec)),
PoolingLayerCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_AvgPool_CPU_4D, PoolingLayerCPUTest,
::testing::Combine(
::testing::Combine(
::testing::ValuesIn(paramsAvg4D),
::testing::Values(Precision::FP32),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShapes4D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)),
::testing::Values(emptyFusingSpec)),
::testing::ValuesIn(paramsAvg4D),
::testing::ValuesIn(inputShapes4D),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(false),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)),
::testing::Values(emptyFusingSpec)),
PoolingLayerCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_AvgPool_CPU_4D_NotOptimized, PoolingLayerCPUTest,
::testing::Combine(
::testing::Combine(
::testing::ValuesIn(paramsAvg4D_RefOnly),
::testing::Values(Precision::FP32),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShapes4D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
::testing::Values(ref),
::testing::Values(emptyFusingSpec)),
::testing::ValuesIn(paramsAvg4D_RefOnly),
::testing::ValuesIn(inputShapes4D),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(false),
::testing::Values(ref),
::testing::Values(emptyFusingSpec)),
PoolingLayerCPUTest::getTestCaseName);
const std::vector<poolSpecificParams> paramsMax5D = {
poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2, 2}, {1, 1, 1}, {0, 0, 0}, {0, 0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2, 2}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 3, 4}, {2, 2, 2}, {1, 1, 1}, {1, 2, 3},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
};
const std::vector<poolSpecificParams> paramsAvg5D = {
poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {1, 0, 0}, {0, 0, 0},
const std::vector<LayerTestsDefinitions::poolSpecificParams> paramsMax5D = {
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2, 2}, {1, 1, 1}, {0, 0, 0}, {0, 0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_LOWER, false },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2, 2}, {1, 1, 1}, {0, 0, 0}, {0, 0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_UPPER, false },
poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {0, 0, 0}, {0, 0, 0},
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 2, 2}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::MAX, {2, 3, 4}, {2, 2, 2}, {1, 1, 1}, {1, 2, 3},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
};
const std::vector<LayerTestsDefinitions::poolSpecificParams> paramsAvg5D = {
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {1, 0, 0}, {0, 0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_LOWER, true },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {1, 0, 0}, {0, 0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_UPPER, true },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {1, 0, 0}, {0, 0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_LOWER, false },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {1, 0, 0}, {0, 0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::SAME_UPPER, false },
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {0, 0, 0}, {0, 0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, true },
poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {3, 3, 3}, {3, 3, 3}, {1, 1, 1}, {0, 0, 0},
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {3, 3, 3}, {3, 3, 3}, {1, 1, 1}, {0, 0, 0},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, true },
poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {4, 4, 4}, {4, 4, 4}, {2, 2, 2}, {2, 2, 2},
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {4, 4, 4}, {4, 4, 4}, {2, 2, 2}, {2, 2, 2},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, true },
};
const std::vector<poolSpecificParams> paramsAvg5D_RefOnly = {
poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {2, 2, 2}, {2, 2, 2},
const std::vector<LayerTestsDefinitions::poolSpecificParams> paramsAvg5D_RefOnly = {
LayerTestsDefinitions::poolSpecificParams{ ngraph::helpers::PoolingTypes::AVG, {2, 2, 2}, {2, 2, 2}, {2, 2, 2}, {2, 2, 2},
ngraph::op::RoundingType::CEIL, ngraph::op::PadType::EXPLICIT, false },
};
INSTANTIATE_TEST_SUITE_P(smoke_MaxPool_CPU_5D, PoolingLayerCPUTest,
::testing::Combine(
::testing::Combine(
::testing::ValuesIn(paramsMax5D),
::testing::Values(Precision::FP32),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShapes5D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)),
::testing::Values(emptyFusingSpec)),
PoolingLayerCPUTest::getTestCaseName);
::testing::Combine(
::testing::ValuesIn(paramsMax5D),
::testing::ValuesIn(inputShapes5D),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(false),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)),
::testing::Values(emptyFusingSpec)),
PoolingLayerCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_AvgPool_CPU_5D, PoolingLayerCPUTest,
::testing::Combine(
::testing::Combine(
::testing::ValuesIn(paramsAvg5D),
::testing::Values(Precision::FP32),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShapes5D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)),
::testing::Values(emptyFusingSpec)),
PoolingLayerCPUTest::getTestCaseName);
::testing::Combine(
::testing::ValuesIn(paramsAvg5D),
::testing::ValuesIn(inputShapes5D),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(false),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigs)),
::testing::Values(emptyFusingSpec)),
PoolingLayerCPUTest::getTestCaseName);
INSTANTIATE_TEST_SUITE_P(smoke_AvgPool_CPU_5D_NotOptimized, PoolingLayerCPUTest,
::testing::Combine(
::testing::Combine(
::testing::ValuesIn(paramsAvg5D_RefOnly),
::testing::Values(Precision::FP32),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(InferenceEngine::Precision::UNSPECIFIED),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShapes5D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
::testing::Values(ref),
::testing::Values(emptyFusingSpec)),
PoolingLayerCPUTest::getTestCaseName);
::testing::Combine(
::testing::ValuesIn(paramsAvg5D_RefOnly),
::testing::ValuesIn(inputShapes5D),
::testing::ValuesIn(inpOutPrecision),
::testing::Values(false),
::testing::Values(ref),
::testing::Values(emptyFusingSpec)),
PoolingLayerCPUTest::getTestCaseName);
/* === Fusing === */
@ -279,35 +341,82 @@ std::vector<fusingSpecificParams> fusingParamsSet {
fusingFakeQuantizePerChannel,
};
const std::vector<InputShape> inputShapes4D_int8 = {
{ {}, {{3, 4, 64, 64}} },
{ {}, {{2, 8, 8, 12}} },
{ {}, {{1, 16, 16, 12}} },
{ {}, {{1, 21, 8, 4}} },
{ {}, {{1, 32, 8, 8}} },
{
// dynamic
{-1, 32, -1, -1},
// target
{
{1, 32, 8, 8},
{1, 32, 8, 4},
{2, 32, 8, 12}
}
},
{
// dynamic
{{1, 5}, 16, {1, 64}, {1, 64}},
// target
{
{3, 16, 32, 32},
{1, 16, 16, 12},
{1, 16, 8, 8}
}
}
};
INSTANTIATE_TEST_SUITE_P(smoke_AvgPool_CPU_4D_I8, PoolingLayerCPUTest,
::testing::Combine(
::testing::Combine(
::testing::ValuesIn(paramsAvg4D),
::testing::Values(Precision::FP32),
::testing::Values(Precision::I8),
::testing::Values(Precision::FP32),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShapes4D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigsFusing_4D)),
::testing::ValuesIn(fusingParamsSet)),
PoolingLayerCPUTest::getTestCaseName);
::testing::Combine(
::testing::ValuesIn(paramsAvg4D),
::testing::ValuesIn(inputShapes4D_int8),
::testing::Values(ElementType::f32),
::testing::Values(true),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigsFusing_4D)),
::testing::ValuesIn(fusingParamsSet)),
PoolingLayerCPUTest::getTestCaseName);
const std::vector<InputShape> inputShapes5D_int8 = {
{ {}, {{1, 4, 16, 16, 16}} },
{ {}, {{2, 8, 8, 8, 8}} },
{ {}, {{2, 16, 12, 16, 20}} },
{ {}, {{1, 19, 16, 20, 8}} },
{ {}, {{1, 32, 16, 8, 12}} },
{
// dynamic
{-1, 32, -1, -1, -1},
// target
{
{2, 32, 8, 8, 8},
{1, 32, 16, 20, 8},
{1, 32, 16, 16, 16}
}
},
{
// dynamic
{{1, 5}, 16, {1, 64}, {1, 64}, {1, 25}},
// target
{
{1, 16, 16, 16, 16},
{1, 16, 16, 8, 12},
{2, 16, 8, 8, 8}
}
}
};
INSTANTIATE_TEST_SUITE_P(smoke_AvgPool_CPU_5D_I8, PoolingLayerCPUTest,
::testing::Combine(
::testing::Combine(
::testing::ValuesIn(paramsAvg5D),
::testing::Values(Precision::FP32),
::testing::Values(Precision::I8),
::testing::Values(Precision::FP32),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::Values(InferenceEngine::Layout::ANY),
::testing::ValuesIn(inputShapes5D),
::testing::Values(CommonTestUtils::DEVICE_CPU)),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigsFusing_5D)),
::testing::ValuesIn(fusingParamsSet)),
PoolingLayerCPUTest::getTestCaseName);
::testing::Combine(
::testing::ValuesIn(paramsAvg5D),
::testing::ValuesIn(inputShapes5D_int8),
::testing::Values(ElementType::f32),
::testing::Values(true),
::testing::ValuesIn(filterCPUInfoForDevice(vecCpuConfigsFusing_5D)),
::testing::ValuesIn(fusingParamsSet)),
PoolingLayerCPUTest::getTestCaseName);
} // namespace
} // namespace CPULayerTestsDefinitions
} // namespace CPULayerTestsDefinitions

View File

@ -219,18 +219,18 @@ const auto fusingScaleShift = fusingSpecificParams{ std::make_shared<postNodesMg
const auto fusingFakeQuantizePerTensor = fusingSpecificParams{ std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
ngraph::Shape newShape(inpNode->get_shape().size(), 1);
ngraph::Shape newShape(inpNode->get_output_partial_shape(0).size(), 1);
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
}, "FakeQuantize(PerTensor)"}}), {"FakeQuantize"} };
const auto fusingFakeQuantizePerChannel = fusingSpecificParams{std::make_shared<postNodesMgr>(std::vector<postNodeBuilder>{
{[](std::shared_ptr<ngraph::Node> inpNode, const ngraph::element::Type& ngPrc, ngraph::ParameterVector& params){
auto localPrc = inpNode->get_element_type();
auto shape = inpNode->get_shape();
auto shape = inpNode->get_output_partial_shape(0);
if (shape.size() == 1)
IE_THROW() << "If shape.size() == 1 then Granularity can be PerTensor only";
ngraph::Shape newShape(shape.size(), 1);
newShape[1] = shape[1];
newShape[1] = shape[1].get_length();
return ngraph::builder::makeFakeQuantize(inpNode, localPrc, 256, newShape);
}, "FakeQuantize(PerChannel)"}}), {"FakeQuantize"}};