[CPU] Unified memory descriptor (#6328)

This commit is contained in:
Maksim Kutakov authored and GitHub committed 2021-08-02 09:19:15 +03:00
1 parent d28ecc4f2f
commit 35696ca1db
129 files changed
+3996 -3722

No files matched your search

+8
View File
@@ -304,6 +304,14 @@ public:
*/
static Layout getLayoutByDims(const SizeVector& dims);
/**
* @brief Returns the standard layout for the specified tensor rank
*
* @param rank of the requested layout
* @return the standard memory layout
*/
static Layout getLayoutByRank(size_t rank);
private:
/**
* Memory layout
@@ -161,8 +161,8 @@ bool TensorDesc::operator!=(const TensorDesc& rhs) const {
return !(*this == rhs);
}
Layout TensorDesc::getLayoutByDims(const SizeVector& dims) {
switch (dims.size()) {
Layout TensorDesc::getLayoutByRank(size_t rank) {
switch (rank) {
case 0:
return Layout::SCALAR;
case 1:
@@ -180,6 +180,10 @@ Layout TensorDesc::getLayoutByDims(const SizeVector& dims) {
}
}
Layout TensorDesc::getLayoutByDims(const SizeVector& dims) {
return getLayoutByRank(dims.size());
}
size_t TensorDesc::offset(const SizeVector& v) const {
if (layout == Layout::ANY) IE_THROW() << "Cannot calculate offset for any format!";
@@ -0,0 +1,247 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "cpu_blocked_memory_desc.h"
#include "mkldnn_memory.h"
#include "utils/cpu_utils.hpp"
using namespace MKLDNNPlugin;
BlockedMemoryDesc::BlockedMemoryDesc(InferenceEngine::Precision prc, const std::vector<size_t>& dims) : MemoryDesc(dims, Blocked) , precision(prc) {
order.resize(dims.size());
std::iota(order.begin(), order.end(), 0);
blockedDims = dims;
offsetPadding = 0;
offsetPaddingToData.resize(dims.size(), 0);
strides.resize(order.size());
strides[strides.size() - 1] = 1;
for (size_t i = 2; i <= order.size(); i++) {
strides[strides.size() - i] = strides[strides.size() - (i - 1)] * blockedDims[blockedDims.size() - (i - 1)];
}
}
BlockedMemoryDesc::BlockedMemoryDesc(InferenceEngine::Precision prc, const std::vector<size_t>& dims, const std::vector<size_t>& blockedDims,
const std::vector<size_t>& order, size_t offsetPadding, const std::vector<size_t>& offsetPaddingToData,
const std::vector<size_t>& strides) : MemoryDesc(dims, Blocked), precision(prc) {
if (std::any_of(order.begin(), order.end(), [](size_t val) { return val == Shape::UNDEFINED_DIM; })) {
IE_THROW() << "BlockedMemoryDesc do not support undefined order.";
}
if (std::any_of(blockedDims.begin() + dims.size(), blockedDims.end(), [](size_t val) { return val == Shape::UNDEFINED_DIM; })) {
IE_THROW() << "BlockedMemoryDesc doesn't support undefined blockedDims.";
}
this->order = order;
this->blockedDims = blockedDims;
this->offsetPadding = offsetPadding;
if (offsetPaddingToData.empty() && !order.empty()) {
this->offsetPaddingToData.resize(order.size());
this->offsetPaddingToData[order.size() - 1] = 0;
for (size_t i = 2; i <= order.size(); i++) {
this->offsetPaddingToData[order.size() - i] = 0;
}
} else {
this->offsetPaddingToData = offsetPaddingToData;
}
if (strides.empty() && !order.empty()) {
if (std::any_of(this->blockedDims.begin(), this->blockedDims.end(), [](size_t val) { return val == Shape::UNDEFINED_DIM; })) {
this->strides.resize(order.size(), Shape::UNDEFINED_DIM);
} else {
this->strides.resize(order.size());
this->strides[order.size() - 1] = 1;
for (size_t i = 2; i <= order.size(); i++) {
this->strides[order.size() - i] = this->strides[order.size() - (i - 1)] * this->blockedDims[blockedDims.size() - (i - 1)];
}
}
} else {
this->strides = strides;
}
if (!everyone_is(this->order.size(), this->blockedDims.size(), this->offsetPaddingToData.size(), this->strides.size())) {
IE_THROW() << "Order, blocked dims, offset padding to data and strides must have equals size";
}
}
bool BlockedMemoryDesc::isDefined() const {
bool defined = true;
defined = defined && std::none_of(blockedDims.cbegin(), blockedDims.cend(), [](size_t val) { return val == Shape::UNDEFINED_DIM; });
defined = defined && std::none_of(strides.cbegin(), strides.cend(), [](size_t val) { return val == Shape::UNDEFINED_DIM; });
defined = defined && std::none_of(order.cbegin(), order.cend(), [](size_t val) { return val == Shape::UNDEFINED_DIM; });
defined = defined && std::none_of(offsetPaddingToData.cbegin(), offsetPaddingToData.cend(), [](size_t val) { return val == Shape::UNDEFINED_DIM; });
defined = defined && offsetPadding != Shape::UNDEFINED_DIM;
return defined;
}
bool BlockedMemoryDesc::isCompatible(const MemoryDesc& rhs) const {
const MemoryDesc* pRhs = &rhs;
if (auto blockingDesc = dynamic_cast<const BlockedMemoryDesc*>(pRhs)) {
return isCompatible(*blockingDesc);
} else if (auto mkldnnDesc = dynamic_cast<const MKLDNNMemoryDesc*>(pRhs)) {
return mkldnnDesc->isCompatible(*this);
} else {
return false;
}
}
bool BlockedMemoryDesc::isCompatible(const BlockedMemoryDesc& rhs) const {
if (this->getShape() != rhs.getShape() || this->getPrecision() != rhs.getPrecision())
return false;
if (!dimsEqualWeak(this->getBlockDims(), rhs.getBlockDims())) {
return false;
}
if (!dimsEqualWeak(this->getOffsetPaddingToData(), rhs.getOffsetPaddingToData())) {
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)) {
return false;
}
if (!dimsEqualWeak(this->getOrder(), rhs.getOrder())) {
return false;
}
return dimsEqualWeak(this->getOffsetPadding(), rhs.getOffsetPadding());
}
bool BlockedMemoryDesc::isCompatible(const MKLDNNMemoryDesc& rhs) const {
return rhs.isCompatible(*this);
}
size_t BlockedMemoryDesc::getMemSizeImp() const {
int64_t e_size = getOffsetPadding() + 1; // size in bytes (from begin of data to last element)
for (int j = 0; j < getBlockDims().size(); j++)
e_size += (getBlockDims()[j] - 1) * getStrides()[j];
e_size *= getPrecision() == InferenceEngine::Precision::BIN ? 1 : getPrecision().size();
return e_size;
}
size_t BlockedMemoryDesc::getOffset(const InferenceEngine::SizeVector& v) const {
InferenceEngine::SizeVector off_v = v;
size_t n_blocked_dims = order.size();
if (blockedDims.size() != n_blocked_dims || strides.size() != n_blocked_dims) {
IE_THROW() << "Cannot calculate offset. Incorrect primitive descriptor!";
}
InferenceEngine::SizeVector blockedShift(n_blocked_dims);
for (size_t i = 1; i <= n_blocked_dims; i++) {
blockedShift[n_blocked_dims - i] = off_v[order[n_blocked_dims - i]] % blockedDims[n_blocked_dims - i];
off_v[order[n_blocked_dims - i]] /= blockedDims[n_blocked_dims - i];
}
size_t offset = getOffsetPadding();
for (size_t d = 0; d < n_blocked_dims; ++d) {
const size_t p = blockedShift[d] + getOffsetPaddingToData()[d];
offset += p * strides[d];
}
return offset;
}
size_t BlockedMemoryDesc::getElementOffset(size_t elemNumber) const {
// TODO [DS]: rewrite to support dynamic shapes
auto& dims = shape.getStaticDims();
size_t n_dims = dims.size();
InferenceEngine::SizeVector pos(n_dims);
for (size_t rd = 1; rd <= n_dims; ++rd) {
const size_t d = n_dims - rd;
const size_t cur_dim = dims[d];
pos[d] = elemNumber % cur_dim;
elemNumber /= cur_dim;
}
return getOffset(pos);
}
bool BlockedMemoryDesc::hasLayoutType(LayoutType layoutType) const {
switch (layoutType) {
case LayoutType::ncsp:
return isPlainFormat();
case LayoutType::nspc:
return isTailCFormat();
case LayoutType::nCsp8c:
return isBlockedCFormat(8);
case LayoutType::nCsp16c:
return isBlockedCFormat(16);
default:
return false;
}
}
bool BlockedMemoryDesc::isPlainFormat() const {
if (shape.getRank() != order.size()) {
return false;
}
for (size_t i = 0; i < order.size(); ++i) {
if (order[i] != i) {
return false;
}
}
return true;
}
bool BlockedMemoryDesc::isBlockedCFormat(size_t blk_size) const {
if ((order.size() - shape.getRank()) != 1) {
return false;
}
for (size_t i = 0; i < order.size() - 1; ++i) {
if (order[i] != i) {
return false;
}
}
if (order.back() != 1) {
return false;
}
if (blockedDims.back() != blk_size) {
return false;
}
return true;
}
bool BlockedMemoryDesc::isTailCFormat() const {
if (shape.getRank() < 3) {
return false;
}
if (shape.getRank() != order.size()) {
return false;
}
if (!std::is_sorted(order.begin(), --order.end())) {
return false;
}
if (order.back() != 1) {
return false;
}
return true;
}
std::string BlockedMemoryDesc::serializeFormat() const {
std::stringstream result;
char startLetter = 'a';
std::unordered_map<size_t, size_t> mapAxisBlockSize;
for (size_t i = shape.getRank(); i < order.size(); ++i) {
mapAxisBlockSize.insert({order[i], blockedDims[i]});
}
for (size_t i = 0; i < shape.getRank(); ++i) {
char nextLetter = startLetter + order[i];
if (mapAxisBlockSize.count(i)) {
nextLetter = toupper(nextLetter);
}
result << nextLetter;
}
for (auto& item : mapAxisBlockSize) {
result << item.second << char(startLetter + item.first);
}
return result.str();
}
@@ -0,0 +1,100 @@
// Copyright (C) 2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "cpu_memory_desc.h"
namespace MKLDNNPlugin {
class MKLDNNMemoryDesc;
class BlockedMemoryDesc : public MemoryDesc {
public:
BlockedMemoryDesc(InferenceEngine::Precision prc, const std::vector<size_t>& dims);
BlockedMemoryDesc(InferenceEngine::Precision prc, const std::vector<size_t>& dims, const std::vector<size_t>& blockedDims,
const std::vector<size_t>& order, size_t offsetPadding = 0, const std::vector<size_t>& offsetPaddingToData = {},
const std::vector<size_t>& strides = {});
MemoryDescPtr clone() const override {
return MKLDNNPlugin::make_unique<BlockedMemoryDesc>(*this);
}
bool isDefined() const override;
bool isCompatible(const MemoryDesc& rhs) const override;
bool isCompatible(const BlockedMemoryDesc& rhs) const;
bool isCompatible(const MKLDNNMemoryDesc& rhs) const;
InferenceEngine::Precision getPrecision() const override {
return precision;
}
void setPrecision(InferenceEngine::Precision prc) override {
precision = std::move(prc);
}
const std::vector<size_t>& getBlockDims() const {
return blockedDims;
}
/**
* @brief Returns the vector of order
*
* @return order
*/
const std::vector<size_t>& getOrder() const {
return order;
}
/**
* @brief Returns the per-dimension offset vector
*
* @return offsets
*/
const std::vector<size_t>& getOffsetPaddingToData() const {
return offsetPaddingToData;
}
/**
* @brief Returns the offset to the current memory block
*
* @return offset
*/
size_t getOffsetPadding() const {
return offsetPadding;
}
/**
* @brief Returns strides for each dimension
*
* @return strides
*/
const std::vector<size_t>& getStrides() const {
return strides;
}
bool hasLayoutType(LayoutType layoutType) const override;
std::string serializeFormat() const override;
private:
size_t getElementOffset(size_t elemNumber) const override;
size_t getMemSizeImp() const override;
size_t getOffset(const InferenceEngine::SizeVector& v) const;
bool isPlainFormat() const;
bool isBlockedCFormat(size_t blk_size) const;
bool isTailCFormat() const;
private:
InferenceEngine::Precision precision;
std::vector<size_t> blockedDims;
std::vector<size_t> strides;
std::vector<size_t> order;
std::vector<size_t> offsetPaddingToData;
size_t offsetPadding;
};
} // namespace MKLDNNPlugin
@@ -0,0 +1,110 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ie_common.h>
#include <ie_precision.hpp>
#include "cpu_shape.h"
#include "utils/general_utils.h"
namespace MKLDNNPlugin {
enum MemoryDescType {
Blocked,
Mkldnn
};
enum class LayoutType : unsigned {
nspc, // general per channels format
ncsp, // general planar
nCsp8c, // general channels blocked by 8
nCsp16c // general channels blocked by 16
};
class MemoryDesc {
public:
MemoryDescType getType() const {
return type;
}
const Shape& getShape() const {
return shape;
}
virtual ~MemoryDesc() = default;
virtual InferenceEngine::Precision getPrecision() const = 0;
virtual void setPrecision(InferenceEngine::Precision prc) = 0;
virtual std::unique_ptr<MemoryDesc> clone() const = 0;
virtual bool isCompatible(const MemoryDesc& rhs) const = 0;
// Checks that all dimensions, offsets, strides, etc are defined (!= UNDEFINED_DIM)
virtual bool isDefined() const = 0;
virtual bool hasLayoutType(LayoutType layoutType) const = 0;
virtual std::string serializeFormat() const = 0;
/**
* @brief Get minimal required memory size in bytes.
* @return return minimal required memory size in bytes or UNDEFINED_SIZE in case undefined descriptor
*/
size_t getCurrentSize() const {
size_t retVal = UNDEFINED_SIZE;
if (isDefined()) {
retVal = getMemSizeImp();
}
return retVal;
}
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>
T* as() {
T* casted = dynamic_cast<T*>(this);
if (!casted)
IE_THROW() << "Cannot dynamically cast MemoryDesc";
return casted;
}
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>
const T* as() const {
const T* casted = dynamic_cast<const T*>(this);
if (!casted)
IE_THROW() << "Cannot dynamically cast MemoryDesc";
return casted;
}
static constexpr size_t UNDEFINED_SIZE = std::numeric_limits<size_t>::max();
protected:
MemoryDesc(const Shape& shape, MemoryDescType type)
: shape(shape), type(type) {}
MemoryDesc(const std::vector<size_t>& dims, MemoryDescType type)
: shape(dims), type(type) {}
virtual size_t getMemSizeImp() const = 0;
// Get offset to the n'th element. Returns physical index of the element by the logical one considering padding, layout, blocking etc.
virtual size_t getElementOffset(size_t elemNumber) const = 0;
MemoryDescType type;
Shape shape;
friend class BlobDumper;
// WA: optimizedNspc2Ncsp used getElementOffset inside implementation
friend class MKLDNNSplitNode;
};
using MemoryDescPtr = std::unique_ptr<MemoryDesc>;
using MemoryDescConstPtr = std::unique_ptr<const MemoryDesc>;
} // namespace MKLDNNPlugin
@@ -0,0 +1,395 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "cpu_memory_desc.h"
#include "cpu_memory_desc_utils.h"
#include "mkldnn_memory.h"
#include "utils/general_utils.h"
#include "utils/cpu_utils.hpp"
#include <limits>
#include <vector>
#include <numeric>
#include <blob_factory.hpp>
using namespace mkldnn;
using namespace MKLDNNPlugin;
using namespace InferenceEngine;
namespace MKLDNNPlugin {
/**
* Convert to BlockedDescriptor
*
* mkl: IOhw_4i16o4i dims {32, 64, 128, 128}
* strides // the order of outer dims is encoded here
* inner_blks 4 16 4
* inner_idxs 1 0 1
*
* IE tensor desc has more expressive ability. Any oneDNN blocked tensor can be covreted.
* How to convert into IE representation:
* 0. Detect a new_outer_order of outer_dims via descending strides.
* 1. IE strides : concatenate strides in new_outer_order and inner strides.
* 2. IE dims : concatenate outer dims in new_outer_order with auto padding and inner blocks
* 3. IE order : concatenate new_outer_order and inner_idxs
*/
BlockedMemoryDesc MemoryDescUtils::convertToBlockedDescriptor(const MKLDNNMemoryDesc& inpDesc) {
mkldnn::memory::desc desc = inpDesc;
const auto dims = desc.dims();
if (desc.data.format_kind != dnnl_blocked)
IE_THROW() << "Conversion is not possible";
const auto &blk_desc = desc.data.format_desc.blocking;
const size_t outer_ndims = dims.size();
const size_t inner_ndims = blk_desc.inner_nblks;
const size_t total_ndims = outer_ndims + inner_ndims;
// strides of inner dims. In case of 4i16o4i will be {64, 4, 1}
std::vector<size_t> inner_strides(inner_ndims, 1);
for (size_t i = 1; i < blk_desc.inner_nblks; i++) {
inner_strides[blk_desc.inner_nblks - 1 - i] = inner_strides[blk_desc.inner_nblks - i] * blk_desc.inner_blks[blk_desc.inner_nblks - i];
}
// total inner block size. in case of 4i16o4i will be {16, 16, 1, 1}
std::vector<size_t> total_block_per_dim(outer_ndims, 1);
for (int i = 0; i < inner_ndims; i++) {
total_block_per_dim[blk_desc.inner_idxs[i]] *= blk_desc.inner_blks[i];
}
std::vector<size_t> outer_block_dims(std::begin(dims), std::begin(dims) + outer_ndims);
for (size_t i = 0; i < outer_block_dims.size(); i++) {
outer_block_dims[i] = div_up(outer_block_dims[i], total_block_per_dim[i]);
}
// order of outer dims. In case of IOhw_ will be {1, 0, 2, 3}
std::vector<size_t> outer_order(outer_ndims);
std::iota(outer_order.begin(), outer_order.end(), 0);
std::sort(outer_order.begin(), outer_order.end(),
[&blk_desc, &outer_block_dims] (size_t ind_l, size_t ind_r) {
return (blk_desc.strides[ind_l] > blk_desc.strides[ind_r]) ||
(blk_desc.strides[ind_l] == blk_desc.strides[ind_r] && outer_block_dims[ind_l] > outer_block_dims[ind_r]);
});
// IE blocked order
// [new_outer_order] U [inner_idxs]
SizeVector ie_blk_order(total_ndims, 0);
std::copy(outer_order.begin(), outer_order.end(), ie_blk_order.begin());
std::copy(blk_desc.inner_idxs, blk_desc.inner_idxs + blk_desc.inner_nblks, ie_blk_order.begin() + dims.size());
// IE blocked strides
// [outer_strides via new_outer_order] U [inner_strides]
SizeVector ie_blk_strides(total_ndims, 0);
std::copy(inner_strides.rbegin(), inner_strides.rend(), ie_blk_strides.rbegin());
std::transform(outer_order.begin(), outer_order.end(), ie_blk_strides.begin(),
[&] (size_t i) { return blk_desc.strides[i]; });
// IE blocked dims
// [dims via new_outer_order with auto pad] U [inner_blk_dims]
SizeVector ie_blk_dims(total_ndims, 0);
std::copy(blk_desc.inner_blks, blk_desc.inner_blks + blk_desc.inner_nblks,
ie_blk_dims.end() - blk_desc.inner_nblks);
std::transform(outer_order.begin(), outer_order.end(), ie_blk_dims.begin(),
[&] (size_t i) { return outer_block_dims[i]; });
// IE offset padded to data. Same as for oneDNN
SizeVector ie_blk_offset_to_data {desc.data.padded_offsets, desc.data.padded_offsets + desc.data.ndims};
size_t ie_blk_offset0 = desc.data.offset0;
// TODO: The tensor desc implementation allow to specify offset_to_data for inner blocked dims.
// Which is not obvious behavior. It required offset_to_data.size == total_ndims, so will
// fill it with zero.
ie_blk_offset_to_data.insert(ie_blk_offset_to_data.end(), inner_ndims, 0);
BlockedMemoryDesc res(MKLDNNMemory::convertToIePrec(desc.data_type()), SizeVector {begin(dims), end(dims)}, ie_blk_dims,
ie_blk_order, ie_blk_offset0, ie_blk_offset_to_data, ie_blk_strides);
return res;
}
InferenceEngine::TensorDesc MemoryDescUtils::convertToTensorDesc(const MemoryDesc& desc) {
if (auto blockingDesc = dynamic_cast<const BlockedMemoryDesc*>(&desc)) {
return InferenceEngine::TensorDesc(blockingDesc->getPrecision(), blockingDesc->getShape().getStaticDims(),
{blockingDesc->getBlockDims(), blockingDesc->getOrder(), blockingDesc->getOffsetPadding(),
blockingDesc->getOffsetPaddingToData(), blockingDesc->getStrides()});
} else if (auto mkldnnDesc = dynamic_cast<const MKLDNNMemoryDesc*>(&desc)) {
auto blockingDesc = convertToBlockedDescriptor(*mkldnnDesc);
return InferenceEngine::TensorDesc(blockingDesc.getPrecision(), blockingDesc.getShape().getStaticDims(),
{blockingDesc.getBlockDims(), blockingDesc.getOrder(), blockingDesc.getOffsetPadding(),
blockingDesc.getOffsetPaddingToData(), blockingDesc.getStrides()});
}
IE_THROW() << "Cannot convert MemoryDesc to InferenceEngine::TensorDesc";
return InferenceEngine::TensorDesc();
}
MKLDNNMemoryDesc MemoryDescUtils::convertToMKLDNNMemoryDesc(const MemoryDesc& desc) {
if (MemoryDescType::Blocked == desc.getType()) {
return convertToMKLDNNMemoryDesc(*(desc.as<BlockedMemoryDesc>()));
} else if (MemoryDescType::Mkldnn == desc.getType()) {
return *(desc.as<MKLDNNMemoryDesc>());
} else {
IE_THROW() << "Cannot convert MemoryDesc to MKLDNNMemoryDesc";
}
}
MKLDNNMemoryDesc MemoryDescUtils::convertToMKLDNNMemoryDesc(const BlockedMemoryDesc& desc) {
dnnl_memory_desc_t mkldnnDesc;
// scalar case
if (desc.getShape().getRank() == 0) {
mkldnn::memory::desc convertedDesc;
convertedDesc.data.format_kind = dnnl_blocked;
convertedDesc.data.data_type = memory::convert_to_c(MKLDNNMemory::convertToDataType(desc.getPrecision()));
convertedDesc.data.ndims = 1;
convertedDesc.data.dims[0] = 1;
convertedDesc.data.padded_dims[0] = 1;
convertedDesc.data.format_desc.blocking.strides[0] = 1;
convertedDesc.data.padded_offsets[0] = 0;
convertedDesc.data.offset0 = desc.getOffsetPadding();
return MKLDNNMemoryDesc(convertedDesc);
}
auto dims = desc.getShape().getStaticDims();
auto ie_blkdDims = desc.getBlockDims();
auto ie_order = desc.getOrder();
auto ie_offsetsToData = desc.getOffsetPaddingToData();
auto ie_strides = desc.getStrides();
size_t outer_ndims = dims.size();
size_t inner_ndims = ie_order.size() - dims.size();
bool is_descending_strides = true;
for (int i = 1; i < ie_strides.size(); i++) {
is_descending_strides &= (ie_strides[i-1] >= ie_strides[i]);
}
// TODO: That's strong constrains and can be mitigated. IE::TensorDesc allow to transpose blocked dims
// and may be we can achieve correct "descending strides" form which allow conversion.
if (!is_descending_strides)
IE_THROW() << "Unsupported case for conversion";
std::vector<size_t> outer_order(outer_ndims, outer_ndims + 1); // outer_order[i] is index of stride for i-th dimension
for (size_t i = 0; i < outer_ndims; i++) {
outer_order[ie_order[i]] = i;
}
bool outer_is_correct_permutation_of_n =
std::find(outer_order.begin(), outer_order.end(), outer_ndims + 1) == outer_order.end();
if (!outer_is_correct_permutation_of_n)
IE_THROW() << "Unsupported case for conversion";
bool inner_block_are_dense = one_of(ie_strides.back(), 0, 1); // stride 1 - is dense case, 0 - broad casted
for (int i = outer_ndims; i < ie_strides.size() - 1; i++) {
inner_block_are_dense &= (ie_strides[i] == ie_strides[i+1] * ie_blkdDims[i+1]);
}
if (!inner_block_are_dense)
IE_THROW() << "Unsupported case for conversion";
bool inner_pad_offsets_is_zero = std::all_of(ie_offsetsToData.begin() + outer_ndims, ie_offsetsToData.end(),
[](size_t pad) { return pad == 0; });
if (!inner_pad_offsets_is_zero)
IE_THROW() << "Unsupported case for conversion";
// Fill general memory desc fields
mkldnnDesc.format_kind = dnnl_blocked;
mkldnnDesc.extra.flags = 0;
mkldnnDesc.data_type = memory::convert_to_c(MKLDNNMemory::convertToDataType(desc.getPrecision()));
mkldnnDesc.ndims = dims.size();
mkldnnDesc.offset0 = desc.getOffsetPadding();
std::copy(dims.begin(), dims.end(), mkldnnDesc.dims);
std::copy(ie_offsetsToData.begin(), ie_offsetsToData.begin() + outer_ndims, mkldnnDesc.padded_offsets);
std::fill(mkldnnDesc.padded_dims, mkldnnDesc.padded_dims + outer_ndims, 1);
for (size_t i = 0; i < ie_order.size(); i++) {
auto idx = ie_order[i];
mkldnnDesc.padded_dims[idx] *= ie_blkdDims[i];
}
// Fill blocking desc
auto &dnn_blk_desc = mkldnnDesc.format_desc.blocking;
dnn_blk_desc.inner_nblks = inner_ndims;
std::copy(ie_blkdDims.end() - inner_ndims, ie_blkdDims.end(), dnn_blk_desc.inner_blks);
std::copy(ie_order.end() - inner_ndims, ie_order.end(), dnn_blk_desc.inner_idxs);
for (size_t i = 0; i < outer_ndims; i++) {
dnn_blk_desc.strides[i] = ie_strides[outer_order[i]];
}
return MKLDNNMemoryDesc(mkldnnDesc);
}
/**
* Construct from IE::TensorDesc
* @param tDesc
*
* IE IOhw_4i16o4i dims(N) = {32, 64, 128, 128}
* blockedDims {4, 2, 128, 128, 4, 16, 4} // total dims(inner, outermost, auto blocked/padded). Generally sorted by strides.
* strides {8388608, 4194304, 32768, 256, 64, 4, 1} // strides for blockedDims, growing sequence
* order {1, 0, 2, 3, 1, 0, 1} // matching to original dims
*
* All vectors blockedDims/strides/order have same size equals total num of internal blocked dims(inner_dims + outer_dims)
*
* Tensor descriptor filing is not deterministic. It allows any permutation of index which keeps order of
* real dims spliting.
* for {1, 0, 2, 3, 1, 0, 1} we can swap elements [1] <=> [4]
* but not [0]<=>[4] because it breacke spliting original dims into internal blocked dims
* Normalization of representation: Make strides growing but keep layout same as original. Not all
* layout allow us to meet normalize form of tensor desc.
*
* Limitation of conversion first N elements of order should be permutation of [0,1,2 ... N]
*/
MKLDNNMemoryDesc MemoryDescUtils::convertToMKLDNNMemoryDesc(const InferenceEngine::TensorDesc& tDesc) {
mkldnn::memory::desc mkldnnDesc({}, mkldnn::memory::data_type::undef, mkldnn::memory::format_tag::undef);
auto dims = tDesc.getDims();
// TODO: implicit conversion of dims is no good...
if (tDesc.getLayout() == Layout::SCALAR) {
mkldnnDesc.data.format_kind = dnnl_blocked;
mkldnnDesc.data.data_type = memory::convert_to_c(MKLDNNMemory::convertToDataType(tDesc.getPrecision()));
mkldnnDesc.data.ndims = 1;
mkldnnDesc.data.dims[0] = 1;
mkldnnDesc.data.padded_dims[0] = 1;
mkldnnDesc.data.format_desc.blocking.strides[0] = 1;
mkldnnDesc.data.padded_offsets[0] = 0;
mkldnnDesc.data.offset0 = tDesc.getBlockingDesc().getOffsetPadding();
return MKLDNNMemoryDesc(mkldnnDesc);
}
if (tDesc.getLayout() == Layout::ANY) {
mkldnnDesc.data.format_kind = dnnl_format_kind_any;
mkldnnDesc.data.data_type = memory::convert_to_c(MKLDNNMemory::convertToDataType(tDesc.getPrecision()));
mkldnnDesc.data.ndims = dims.size();
std::copy(dims.begin(), dims.end(), mkldnnDesc.data.dims);
std::copy(dims.begin(), dims.end(), mkldnnDesc.data.padded_dims);
mkldnnDesc.data.offset0 = tDesc.getBlockingDesc().getOffsetPadding();
std::fill(mkldnnDesc.data.padded_offsets, mkldnnDesc.data.padded_offsets + dims.size(), 0);
return MKLDNNMemoryDesc(mkldnnDesc);
}
auto ie_blkdDims = tDesc.getBlockingDesc().getBlockDims();
auto ie_order = tDesc.getBlockingDesc().getOrder();
auto ie_offsetsToData = tDesc.getBlockingDesc().getOffsetPaddingToData();
auto ie_strides = tDesc.getBlockingDesc().getStrides();
size_t outer_ndims = dims.size();
size_t inner_ndims = ie_order.size() - dims.size();
bool is_descending_strides = true;
for (int i = 1; i < ie_strides.size(); i++) {
is_descending_strides &= (ie_strides[i-1] >= ie_strides[i]);
}
// TODO: That's strong constrains and can be mitigated. IE::TensorDesc allow to transpose blocked dims
// and may be we can achieve correct "descending strides" form which allow conversion.
if (!is_descending_strides)
IE_THROW() << "Unsupported case for conversion";
std::vector<size_t> outer_order(outer_ndims, outer_ndims + 1); // outer_order[i] is index of stride for i-th dimension
for (size_t i = 0; i < outer_ndims; i++) {
outer_order[ie_order[i]] = i;
}
bool outer_is_correct_permutation_of_n =
std::find(outer_order.begin(), outer_order.end(), outer_ndims + 1) == outer_order.end();
if (!outer_is_correct_permutation_of_n)
IE_THROW() << "Unsupported case for conversion";
bool inner_block_are_dense = one_of(ie_strides.back(), 0, 1); // stride 1 - is dense case, 0 - broad casted
for (int i = outer_ndims; i < ie_strides.size() - 1; i++) {
inner_block_are_dense &= (ie_strides[i] == ie_strides[i+1] * ie_blkdDims[i+1]);
}
if (!inner_block_are_dense)
IE_THROW() << "Unsupported case for conversion";
bool inner_pad_offsets_is_zero = std::all_of(ie_offsetsToData.begin() + outer_ndims, ie_offsetsToData.end(),
[](size_t pad) { return pad == 0; });
if (!inner_pad_offsets_is_zero)
IE_THROW() << "Unsupported case for conversion";
// Fill general memory desc fields
mkldnnDesc.data.format_kind = dnnl_blocked;
mkldnnDesc.data.data_type = memory::convert_to_c(MKLDNNMemory::convertToDataType(tDesc.getPrecision()));
mkldnnDesc.data.ndims = dims.size();
mkldnnDesc.data.offset0 = tDesc.getBlockingDesc().getOffsetPadding();
std::copy(dims.begin(), dims.end(), mkldnnDesc.data.dims);
std::copy(ie_offsetsToData.begin(), ie_offsetsToData.begin() + outer_ndims, mkldnnDesc.data.padded_offsets);
std::fill(mkldnnDesc.data.padded_dims, mkldnnDesc.data.padded_dims + outer_ndims, 1);
for (size_t i = 0; i < ie_order.size(); i++) {
auto idx = ie_order[i];
mkldnnDesc.data.padded_dims[idx] *= ie_blkdDims[i];
}
// Fill blocking desc
auto &dnn_blk_desc = mkldnnDesc.data.format_desc.blocking;
dnn_blk_desc.inner_nblks = inner_ndims;
std::copy(ie_blkdDims.end() - inner_ndims, ie_blkdDims.end(), dnn_blk_desc.inner_blks);
std::copy(ie_order.end() - inner_ndims, ie_order.end(), dnn_blk_desc.inner_idxs);
for (size_t i = 0; i < outer_ndims; i++) {
dnn_blk_desc.strides[i] = ie_strides[outer_order[i]];
}
return MKLDNNMemoryDesc(mkldnnDesc);
}
BlockedMemoryDesc MemoryDescUtils::convertToBlockedDescriptor(const MemoryDesc &desc) {
if (desc.getType() == MemoryDescType::Blocked) {
return *(desc.as<BlockedMemoryDesc>());
} else if (desc.getType() == MemoryDescType::Mkldnn) {
return MemoryDescUtils::convertToBlockedDescriptor(*(desc.as<MKLDNNMemoryDesc>()));
} else {
IE_THROW() << "Cannot convert to blocked memory descriptor. Unsupported memory desc type";
}
}
MemoryDescPtr MemoryDescUtils::applyUndefinedOffset(const MKLDNNMemoryDesc& desc) {
if (desc.getFormatKind() != dnnl_format_kind_t::dnnl_blocked)
IE_THROW() << "applyUndefinedOffset doesn't support not dnnl_blocked MKLDNNMemoryDesc";
mkldnn::memory::desc retDesc = desc;
retDesc.data.offset0 = Shape::UNDEFINED_DIM;
return MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(retDesc);
}
MemoryDescPtr MemoryDescUtils::applyUndefinedOffset(const BlockedMemoryDesc &desc) {
std::vector<size_t> strides;
std::vector<size_t> offsetPaddingToData;
strides.resize(desc.getBlockDims().size(), Shape::UNDEFINED_DIM);
offsetPaddingToData.resize(desc.getBlockDims().size(), 0);
size_t offsetPadding = Shape::UNDEFINED_DIM;
return MKLDNNPlugin::make_unique<BlockedMemoryDesc>(desc.getPrecision(), desc.getShape().getDims(), desc.getBlockDims(),
desc.getOrder(), offsetPadding, offsetPaddingToData, strides);
}
MemoryDescPtr MemoryDescUtils::resetOffset(const MemoryDesc* desc) {
if (MemoryDescType::Blocked == desc->getType()) {
auto blockedDesc = desc->as<BlockedMemoryDesc>();
return MKLDNNPlugin::make_unique<BlockedMemoryDesc>(blockedDesc->getPrecision(), blockedDesc->getShape().getDims(),
blockedDesc->getBlockDims(), blockedDesc->getOrder());
} else if (MemoryDescType::Mkldnn == desc->getType()) {
auto mkldnnDesc = desc->as<MKLDNNMemoryDesc>();
mkldnn::memory::desc retDesc = *mkldnnDesc;
retDesc.data.offset0 = 0;
return MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(retDesc);
} else {
IE_THROW() << "resetOffset support Blocked and Mkldnn descpriptors only";
}
}
InferenceEngine::Blob::Ptr MemoryDescUtils::interpretAsBlob(const MKLDNNMemory &mem) {
// TODO [DS]: Rewrite when IE is moved to the new TensorDescriptor
auto& memDesc = mem.GetDesc();
InferenceEngine::TensorDesc desc = convertToTensorDesc(memDesc);
desc = InferenceEngine::TensorDesc(desc.getPrecision(), memDesc.getShape().getStaticDims(), desc.getBlockingDesc());
return MKLDNNPlugin::isEmptyTensorDesc(desc) ? make_blob_with_precision(desc) : make_blob_with_precision(desc, mem.GetData());
}
} // namespace MKLDNNPlugin
@@ -0,0 +1,88 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ie_layouts.h>
#include <ie_blob.h>
namespace MKLDNNPlugin {
class MKLDNNMemoryDesc;
class BlockedMemoryDesc;
class MKLDNNMemory;
class MemoryDescUtils {
public:
/**
* @brief Converts MemoryDesc to InferenceEngine::TensorDesc
* @param desc MemoryDesc to be converted
* @return converted InferenceEngine::TensorDesc
*/
static InferenceEngine::TensorDesc convertToTensorDesc(const MemoryDesc& desc);
/**
* @brief Converts MemoryDesc to MKLDNNMemoryDesc
* @param desc MemoryDesc to be converted
* @return converted MKLDNNMemoryDesc
*/
static MKLDNNMemoryDesc convertToMKLDNNMemoryDesc(const MemoryDesc& desc);
/**
* @brief Converts BlockedMemoryDesc to MKLDNNMemoryDesc
* @param desc BlockedMemoryDesc to be converted
* @return converted MKLDNNMemoryDesc
*/
static MKLDNNMemoryDesc convertToMKLDNNMemoryDesc(const BlockedMemoryDesc& desc);
/**
* @brief Converts InferenceEngine::TensorDesc to MKLDNNMemoryDesc
* @param desc InferenceEngine::TensorDesc to be converted
* @return converted MKLDNNMemoryDesc
*/
static MKLDNNMemoryDesc convertToMKLDNNMemoryDesc(const InferenceEngine::TensorDesc& desc);
/**
* @brief Converts MemoryDesc to BlockedMemoryDesc
* @param desc MemoryDesc to be converted
* @return converted BlockedMemoryDesc
*/
static BlockedMemoryDesc convertToBlockedDescriptor(const MemoryDesc& desc);
/**
* @brief Converts MKLDNNMemoryDesc to BlockedMemoryDesc
* @param desc MKLDNNMemoryDesc to be converted
* @return converted BlockedMemoryDesc
*/
static BlockedMemoryDesc convertToBlockedDescriptor(const MKLDNNMemoryDesc& inpDesc);
/**
* @brief Creates MKLDNNMemoryDesc with offset0 of UNDEFINED_DIM size
* @param desc modifiable MKLDNNMemoryDesc
* @return pointer to MKLDNNMemoryDesc
*/
static MemoryDescPtr applyUndefinedOffset(const MKLDNNMemoryDesc& desc);
/**
* @brief Creates BlockedMemoryDesc with offsetPadding, strides of UNDEFINED_DIM size and offsetPaddingToData of 0 size
* @param desc modifiable BlockedMemoryDesc
* @return pointer to BlockedMemoryDesc
*/
static MemoryDescPtr applyUndefinedOffset(const BlockedMemoryDesc& desc);
/**
* @brief Creates MemoryDesc with offsetPadding of 0 size
* @param desc modifiable MemoryDesc
* @return pointer to MemoryDesc
*/
static MemoryDescPtr resetOffset(const MemoryDesc* desc);
/**
* @brief Creates InferenceEngine::Blob from MKLDNNMemory
* @param desc MKLDNNMemory from which will be created InferenceEngine::Blob
* @return pointer to InferenceEngine::Blob
*/
static InferenceEngine::Blob::Ptr interpretAsBlob(const MKLDNNMemory& mem);
};
} // namespace MKLDNNPlugin
@@ -0,0 +1,159 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include "perf_count.h"
#include <vector>
#include <utility>
#include <ie_common.h>
#include <ngraph/partial_shape.hpp>
#include "mkldnn_dims.h"
namespace MKLDNNPlugin {
class Shape {
public:
Shape() = default;
explicit Shape(const ngraph::PartialShape& shape) {
minDims = shape.get_min_shape();
maxDims = shape.get_max_shape();
type = shape.is_static() ? ShapeType::Static : ShapeType::Dynamic;
initDims();
}
explicit Shape(const InferenceEngine::SizeVector& shape) {
minDims = shape;
maxDims = shape;
type = ShapeType::Static;
initDims();
}
/**
* @brief
* for static shape
* maxDims = [2, 3, 4, 5]
* minDims = [2, 3, 4, 5]
* dims = [2, 3, 4, 5]
* @return return lower bound of shape = [2, 3, 4, 5]
* for dynamic shape
* maxDims = [6, 6, 6, 6]
* minDims = [1, 1, 1, 1]
* dims = [UNDEFINED_DIM, UNDEFINED_DIM, UNDEFINED_DIM, UNDEFINED_DIM]
* @return return lower bound of shape = [1, 1, 1, 1]
*/
const std::vector<size_t>& getMinDims() const {
return minDims;
}
/**
* @brief
* for static shape
* maxDims = [2, 3, 4, 5]
* minDims = [2, 3, 4, 5]
* dims = [2, 3, 4, 5]
* @return return upper bound of shape = [2, 3, 4, 5]
* for dynamic shape
* maxDims = [6, 6, 6, 6]
* minDims = [1, 1, 1, 1]
* dims = [UNDEFINED_DIM, UNDEFINED_DIM, UNDEFINED_DIM, UNDEFINED_DIM]
* @return return upper bound of shape = [6, 6, 6, 6]
*/
const std::vector<size_t>& getMaxDims() const {
return maxDims;
}
/**
* @brief return defined shape or throw exception for dynamic case
* @return return shape
*/
const std::vector<size_t>& getStaticDims() const {
if (type != ShapeType::Static) {
IE_THROW() << "Cannot get dims for non static shape";
}
return minDims;
}
/**
* @brief
* for static shape
* maxDims = [2, 3, 4, 5]
* minDims = [2, 3, 4, 5]
* dims = [2, 3, 4, 5]
* @return return defined shape = [2, 3, 4, 5]
* for dynamic shape
* maxDims = [2, 3, 6, 6]
* minDims = [2, 3, 1, 1]
* dims = [2, 3, UNDEFINED_DIM, UNDEFINED_DIM]
* @return return shape with defined and undefined dims = [2, 3, UNDEFINED_DIM, UNDEFINED_DIM]
*/
const std::vector<size_t>& getDims() const {
return dims;
}
bool isStatic() const {
return type == ShapeType::Static;
}
size_t getRank() const {
return minDims.size();
}
size_t getElementsCount() const {
if (type != ShapeType::Static) {
IE_THROW() << "Cannot get elements count for non static shape";
}
size_t size = 1;
for (int i = 0; i < minDims.size(); i++) {
size *= minDims[i];
}
return size;
}
ngraph::PartialShape toPartialShape() const {
std::vector<ngraph::Dimension> nGraphDims;
nGraphDims.reserve(minDims.size());
for (int i = 0; i < minDims.size(); i++) {
nGraphDims.emplace_back(minDims[i], maxDims[i]);
}
return ngraph::PartialShape(nGraphDims);
}
bool operator == (const Shape& rhs) const {
return minDims == rhs.minDims && maxDims == rhs.maxDims;
}
bool operator != (const Shape& rhs) const {
return !(*this == rhs);
}
enum : size_t {
UNDEFINED_DIM = 0xffffffffffffffff
};
private:
void initDims() {
dims.resize(minDims.size());
for (int i = 0; i < minDims.size(); i++) {
dims[i] = minDims[i] == maxDims[i] ? minDims[i] : UNDEFINED_DIM;
}
}
enum class ShapeType {
Static,
Dynamic
} type {ShapeType::Static};
std::vector<size_t> minDims;
std::vector<size_t> maxDims;
std::vector<size_t> dims;
};
} // namespace MKLDNNPlugin
@@ -6,7 +6,6 @@
#include "mkldnn_node.h"
#include "mkldnn_extension_utils.h"
#include <blob_factory.hpp>
#include "utils/cpu_utils.hpp"
using namespace mkldnn;
namespace MKLDNNPlugin {
@@ -29,7 +28,7 @@ const MKLDNNNodePtr MKLDNNEdge::getChild() const {
}
bool MKLDNNEdge::isUseExternalMemory() const {
return externalMemoryPtr;
return useExternalMemory;
}
bool MKLDNNEdge::isDropped() const {
@@ -77,7 +76,7 @@ bool MKLDNNEdge::needReorder() {
int inNumber = getInputNum();
bool in_place = inPlace();
bool childCanChangeMem = childSPD->getConfig().outConfs.empty();
for (const auto conf : childSPD->getConfig().outConfs) {
for (const auto& conf : childSPD->getConfig().outConfs) {
if (conf.inPlace == outNumber && outNumber >= 0)
childCanChangeMem = true;
}
@@ -89,7 +88,7 @@ bool MKLDNNEdge::needReorder() {
int outNumber = edge->getOutputNum();
if (childSPD->getConfig().outConfs.empty())
count++;
for (const auto conf : childSPD->getConfig().outConfs) {
for (const auto& conf : childSPD->getConfig().outConfs) {
if (conf.inPlace == outNumber)
count++;
}
@@ -114,7 +113,7 @@ bool MKLDNNEdge::needReorder() {
outNumber >= 0 && outNumber < childSPD->getConfig().inConfs.size() && childSPD->getConfig().inConfs[outNumber].inPlace >= 0)
canBeInPlaceConflicts = true;
}
return canBeInPlaceConflicts || !MKLDNNExtensionUtils::initTensorsAreEqual(getInputDesc(), getOutputDesc());
return canBeInPlaceConflicts || !getInputDesc().isCompatible(getOutputDesc());
}
void MKLDNNEdge::reuse(MKLDNNMemoryPtr ptr) {
@@ -124,35 +123,6 @@ void MKLDNNEdge::reuse(MKLDNNMemoryPtr ptr) {
status = Status::Allocated;
}
const InferenceEngine::TensorDesc& MKLDNNEdge::getInputDescRO() const {
return inputDesc;
}
InferenceEngine::TensorDesc MKLDNNEdge::getInputDesc() {
if (inputDesc.getLayout() == InferenceEngine::Layout::ANY) {
inputDesc = getSpecifiedInputDesc({});
}
return inputDesc;
}
const InferenceEngine::TensorDesc& MKLDNNEdge::getOutputDescRO() const {
return outputDesc;
}
InferenceEngine::TensorDesc MKLDNNEdge::getOutputDesc() {
if (outputDesc.getLayout() == InferenceEngine::Layout::ANY) {
outputDesc = getSpecifiedOutputDesc({});
}
return outputDesc;
}
InferenceEngine::TensorDesc MKLDNNEdge::getDesc() {
if (!MKLDNNExtensionUtils::initTensorsAreEqual(getInputDesc(), getOutputDesc()))
IE_THROW() << "Cannot get descriptor for edge: " << getParent()->getName() << "->"
<< getChild()->getName();
return getInputDesc();
}
int MKLDNNEdge::getInputNum() const {
return parent_port;
}
@@ -168,45 +138,29 @@ void MKLDNNEdge::allocate(const void* mem_ptr) {
if (memoryPtr)
IE_THROW() << "Unexpected behaviour: status == NeedAllocation but memory is already allocated.";
auto inputDesc = getInputDesc();
auto outputDesc = getOutputDesc();
if (!MKLDNNExtensionUtils::initTensorsAreEqual(outputDesc, inputDesc) ||
(inputDesc.getDims().size() > 0 && inputDesc.getDims()[0] != 1 &&
(inputDesc.getPrecision() != outputDesc.getPrecision() ||
inputDesc.getBlockingDesc() != outputDesc.getBlockingDesc())))
IE_THROW() << "Cannot allocate memory. Nodes have primitive descriptors with different formats.";
if (inputDesc.getLayout() == InferenceEngine::Layout::ANY)
IE_THROW() << "Cannot get input descriptor!";
auto& inputDesc = getInputDesc();
auto& outputDesc = getOutputDesc();
if (!inputDesc.isDefined() || !outputDesc.isDefined())
IE_THROW() << "Cannot allocate memory for undefined descriptors.";
if (!inputDesc.isCompatible(outputDesc))
IE_THROW() << "Cannot allocate memory for incompatible descriptors.";
auto parentPtr = getParent();
memoryPtr.reset(new MKLDNNMemory(parentPtr->getEngine()));
memoryPtr->Create(MKLDNNMemoryDesc(inputDesc), mem_ptr, false); // no pads zeroing
memoryPtr->Create(inputDesc, mem_ptr, false); // no pads zeroing
status = Status::Allocated;
}
std::string MKLDNNEdge::name() {
auto tensorDescToStr = [](InferenceEngine::TensorDesc const & desc) {
std::string name = desc.getPrecision().name();
auto blockingDesc = desc.getBlockingDesc();
auto dims = blockingDesc.getBlockDims();
if (!dims.empty()) {
name += "[";
for (size_t i = 1; i < dims.size(); ++i) {
name += std::to_string(dims[i - 1]) + ",";
}
name += std::to_string(dims.back()) + "]";
}
return name;
};
std::string MKLDNNEdge::name() const {
auto parentPtr = getParent();
auto childPtr = getChild();
return parentPtr->getName() + std::to_string(parent_port) + tensorDescToStr(getInputDesc())
+ "<->" + childPtr->getName() + std::to_string(child_port);
std::stringstream result;
result << parentPtr->getName() << " port " << parent_port << " <-> " << childPtr->getName() << " port " << child_port;
return result.str();
}
void MKLDNNEdge::externalAllocate(MKLDNNWeightsSharing::Ptr weightsCache) {
@@ -221,7 +175,7 @@ void MKLDNNEdge::externalAllocate(MKLDNNWeightsSharing::Ptr weightsCache) {
auto ptr = weightsCache->findOrCreate(name(), alloc, false);
memoryPtr = *ptr;
externalMemoryPtr = true;
useExternalMemory = true;
status = Status::Allocated;
} else {
allocate();
@@ -242,10 +196,13 @@ void MKLDNNEdge::changeStatus(MKLDNNEdge::Status state) {
status = state;
}
const MKLDNNDims& MKLDNNEdge::getDims() {
if (!dims.ndims()) {
MKLDNNDims outDims;
MKLDNNDims inDims;
// TODO [DS]: remove while DynamicShapes migration
// TODO [DS]: How should we validate shape compatibility?
// TODO [DS]: Why do we allow uninitialized shape?
const Shape& MKLDNNEdge::getShape() {
if (!shape.getRank()) {
Shape inShape;
Shape outShape;
auto childPtr = getChild();
auto parentPtr = getParent();
@@ -254,8 +211,8 @@ const MKLDNNDims& MKLDNNEdge::getDims() {
IE_THROW() << "Error cannot find input data for " << child.lock()->getName()
<< " from " << parent.lock()->getName();
}
if (inNum < childPtr->inDims.size()) {
outDims = childPtr->inDims[inNum];
if (inNum < childPtr->inputShapes.size()) {
outShape = childPtr->inputShapes[inNum];
}
int outNum = getInputNum();
@@ -263,84 +220,34 @@ const MKLDNNDims& MKLDNNEdge::getDims() {
IE_THROW() << "Error cannot find output data for " << parent.lock()->getName()
<< " to " << child.lock()->getName();
}
if (outNum >= parentPtr->outDims.size())
if (outNum >= parentPtr->outputShapes.size())
outNum = 0;
if (outNum < parentPtr->outDims.size()) {
inDims = parentPtr->outDims[outNum];
if (outNum < parentPtr->outputShapes.size()) {
inShape = parentPtr->outputShapes[outNum];
}
if (inDims.ndims() && outDims.ndims() && inDims.ndims() != outDims.ndims() && inDims.size() != outDims.size())
if (inShape.getRank() && outShape.getRank() && inShape.getRank() != outShape.getRank() && inShape.getElementsCount() != outShape.getElementsCount())
IE_THROW() << "Nodes " << getParent()->getName() << " and " << getChild()->getName()
<< " have incompatible dimensions!";
if (outDims.ndims() != 0) {
dims = outDims;
} else if (inDims.ndims() != 0) {
dims = inDims;
if (outShape.getRank() != 0) {
shape = outShape;
} else if (inShape.getRank() != 0) {
shape = inShape;
} else {
dims = MKLDNNDims({(size_t)1});
shape = Shape(InferenceEngine::SizeVector({1}));
}
if (!(outDims.ndims() == 0 && inDims.ndims() == 0) && !dims.ndims())
if (!(outShape.getRank() == 0 && inShape.getRank() == 0) && !shape.getRank())
IE_THROW() << "Cannot detect right dims for nodes " << getParent()->getName()
<< " and " << getChild()->getName();
}
return dims;
return shape;
}
bool MKLDNNEdge::nodeCanChangeDesc(const MKLDNNNodePtr &node) const {
PrimitiveDescInfo * selectedPd = node->getSelectedPrimitiveDescriptor();
if (selectedPd == nullptr)
IE_THROW() << "Primitive descriptor for node " << node->getName() << " is not selected.";
for (auto &inputDesc : selectedPd->getConfig().inConfs) {
if (inputDesc.desc.getLayout() != InferenceEngine::Layout::ANY) {
return true;
}
}
for (auto &outDesc : selectedPd->getConfig().outConfs) {
if (outDesc.desc.getLayout() != InferenceEngine::Layout::ANY) {
return true;
}
}
MKLDNNDims inputDims;
for (size_t i = 0; i < node->getParentEdges().size(); i++) {
if (inputDims.size() == 1 && inputDims.ndims() == 0) {
inputDims = node->getParentEdgeAt(i)->getDims();
continue;
}
if (inputDims.ndims() != node->getParentEdgeAt(i)->getDims().ndims()) {
return true;
}
}
for (size_t i = 0; i < node->getChildEdges().size(); i++) {
if (inputDims.size() == 1 && inputDims.ndims() == 0) {
inputDims = node->getChildEdgeAt(i)->getDims();
continue;
}
if (inputDims.ndims() != node->getChildEdgeAt(i)->getDims().ndims()) {
return true;
}
}
return false;
}
/// In we have {any, any, any} -> {any} or {any} -> {any, any, any} or {any} -> {any} it means that
/// layer doesn't change memory format
/// We don't support {any, any, nchw} -> {any}
InferenceEngine::TensorDesc MKLDNNEdge::getSpecifiedInputDesc(std::map<memory::format_tag, size_t> formats, size_t enterCountUp, size_t enterCountDown) {
InferenceEngine::TensorDesc inDesc;
if (inputDesc.getLayout() != InferenceEngine::Layout::ANY) {
return inputDesc;
}
const MemoryDesc& MKLDNNEdge::getInputDesc() const {
auto parentPtr = getParent();
if (parentPtr->getSelectedPrimitiveDescriptor() == nullptr)
IE_THROW() << "Primitive descriptor for node " << parentPtr->getName() << " is not selected.";
@@ -349,248 +256,48 @@ InferenceEngine::TensorDesc MKLDNNEdge::getSpecifiedInputDesc(std::map<memory::f
if (inputIdx < 0)
IE_THROW() << "Edge cannot be found for node" << parentPtr->getName() << ".";
if (inputIdx >= parentPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs.size())
auto& outConfs = parentPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs;
if (outConfs.empty())
IE_THROW() << "Node " << parentPtr->getName() << " has empty output config list.";
if (inputIdx >= outConfs.size())
inputIdx = 0;
inDesc = parentPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs[inputIdx].desc;
if (inDesc.getLayout() != InferenceEngine::Layout::ANY) {
return inDesc;
}
bool isFormatChanging = nodeCanChangeDesc(parentPtr);
if (!isFormatChanging && inputIdx < parentPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs.size() &&
parentPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs[inputIdx].desc.getLayout() != InferenceEngine::Layout::ANY) {
inDesc = parentPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs[inputIdx].desc;
parentPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs[inputIdx].desc = inDesc;
return inDesc;
}
for (size_t i = 0; i < parentPtr->getChildEdges().size(); i++) {
auto childEdge = parentPtr->getChildEdgeAt(i);
auto child = childEdge->getChild();
int childIdx = childEdge->getOutputNum();
if (!child->getSelectedPrimitiveDescriptor() || childIdx < 0 ||
childEdge->getDims().ndims() != getDims().ndims()) {
continue;
}
if (child->getSelectedPrimitiveDescriptor()->getConfig().inConfs.size() <= childIdx)
childIdx = 0;
memory::format_tag childInDesc = MKLDNNMemoryDesc(child->getSelectedPrimitiveDescriptor()->getConfig().inConfs[childIdx].desc).getFormat();
if (childInDesc != memory::format_tag::any && childInDesc != memory::format_tag::undef) {
if (formats.find(childInDesc) == formats.end())
formats[childInDesc] = 1;
else
formats[childInDesc] += 1;
continue;
}
if (nodeCanChangeDesc(child))
continue;
if (enterCountUp < 2) {
childInDesc = MKLDNNMemoryDesc(childEdge->getSpecifiedOutputDesc(formats, enterCountUp, ++enterCountDown)).getFormat();
if (childInDesc != memory::format_tag::any && childInDesc != memory::format_tag::undef) {
if (formats.find(childInDesc) == formats.end())
formats[childInDesc] = 1;
else
formats[childInDesc] += 1;
}
}
}
if (!isFormatChanging) {
for (size_t i = 0; i < parentPtr->getParentEdges().size(); i++) {
auto parentEdge = parentPtr->getParentEdgeAt(i);
auto parent = parentEdge->getParent();
int parentIdx = parentEdge->getInputNum();
if (!parent->getSelectedPrimitiveDescriptor() || parentIdx < 0 ||
parentEdge->getDims().ndims() != getDims().ndims()) {
continue;
}
if (parent->getSelectedPrimitiveDescriptor()->getConfig().outConfs.size() <= parentIdx) {
parentIdx = 0;
}
memory::format_tag parentOutDesc = MKLDNNMemoryDesc(parent->getSelectedPrimitiveDescriptor()->getConfig().outConfs[parentIdx].desc).getFormat();
if (parentOutDesc != memory::format_tag::any && parentOutDesc != memory::format_tag::undef) {
if (formats.find(parentOutDesc) == formats.end())
formats[parentOutDesc] = 1;
else
formats[parentOutDesc] += 1;
continue;
}
if (nodeCanChangeDesc(parent))
continue;
if (enterCountUp < 2) {
parentOutDesc = MKLDNNMemoryDesc(parentEdge->getSpecifiedInputDesc(formats, ++enterCountUp, enterCountDown)).getFormat();
if (parentOutDesc != memory::format_tag::any && parentOutDesc != memory::format_tag::undef) {
if (formats.find(parentOutDesc) == formats.end())
formats[parentOutDesc] = 1;
else
formats[parentOutDesc] += 1;
}
}
}
}
size_t maxFormatCount = 0;
memory::format_tag desc = MKLDNNMemory::GetPlainFormat(getDims());
for (auto &it : formats) {
if (maxFormatCount < it.second && MKLDNNMemory::isConsistant(getDims(), it.first)) {
maxFormatCount = it.second;
desc = it.first;
}
}
auto inDataType = MKLDNNMemoryDesc(parentPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs[inputIdx].desc).getDataType();
parentPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs[inputIdx].desc = MKLDNNMemoryDesc(getDims(), inDataType, desc);
if (!isFormatChanging && inputIdx < parentPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs.size() &&
parentPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs[inputIdx].desc.getLayout() == InferenceEngine::Layout::ANY) {
parentPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs[inputIdx].desc =
MKLDNNExtensionUtils::getUninitTensorDesc(MKLDNNMemoryDesc(getDims(), inDataType, desc));
}
return MKLDNNMemoryDesc(getDims(), inDataType, desc);
return *(outConfs[inputIdx].desc);
}
InferenceEngine::TensorDesc MKLDNNEdge::getSpecifiedOutputDesc(std::map<memory::format_tag, size_t> formats, size_t enterCountUp, size_t enterCountDown) {
InferenceEngine::TensorDesc outDesc;
if (outputDesc.getLayout() != InferenceEngine::Layout::ANY) {
return outputDesc;
}
const MemoryDesc& MKLDNNEdge::getOutputDesc() const {
auto childPtr = getChild();
auto parentPtr = getParent();
if (childPtr->getSelectedPrimitiveDescriptor() == nullptr)
IE_THROW() << "Primitive descriptor for node " << childPtr->getName() << " is not selected.";
int outputIdx = getOutputNum();
int inputIdx = getInputNum();
if (outputIdx < 0) {
IE_THROW() << "Edge cannot be found for node" << childPtr->getName() << ".";
}
if (outputIdx >= childPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs.size())
auto& inConfs = childPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs;
if (inConfs.empty())
IE_THROW() << "Node " << childPtr->getName() << " has empty input config list.";
if (outputIdx >= inConfs.size())
outputIdx = 0;
outDesc = childPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs[outputIdx].desc;
if (outDesc.getLayout() != InferenceEngine::Layout::ANY) {
return outDesc;
}
return *(inConfs[outputIdx].desc);
}
if (inputIdx >= parentPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs.size())
inputIdx = 0;
const MemoryDesc& MKLDNNEdge::getDesc() const {
if (!getInputDesc().isCompatible(getOutputDesc()))
IE_THROW() << "Cannot get descriptor for edge: " << getParent()->getName() << "->"
<< getChild()->getName();
bool isFormatChanging = nodeCanChangeDesc(childPtr);
if ((!isFormatChanging && outputIdx < childPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs.size() &&
childPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs[outputIdx].desc.getLayout() != InferenceEngine::Layout::ANY) ||
(isFormatChanging && inputIdx >= 0 &&
parentPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs[inputIdx].desc.getLayout() != InferenceEngine::Layout::ANY)) {
auto inputDataType = childPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs[outputIdx].desc.getPrecision();
if (!isFormatChanging)
outDesc = childPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs[outputIdx].desc;
else
outDesc = parentPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs[inputIdx].desc;
childPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs[outputIdx].desc = InferenceEngine::TensorDesc(inputDataType, getDims().ToSizeVector(),
{outDesc.getBlockingDesc().getBlockDims(),
outDesc.getBlockingDesc().getOrder()});
return childPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs[outputIdx].desc;
}
for (size_t i = 0; i < childPtr->getParentEdges().size(); i++) {
auto parentEdge = childPtr->getParentEdgeAt(i);
auto parent = parentEdge->getParent();
int parentIdx = parentEdge->getInputNum();
if (!parent->getSelectedPrimitiveDescriptor() || parentIdx < 0 ||
parentEdge->getDims().ndims() != getDims().ndims()) {
continue;
}
if (parent->getSelectedPrimitiveDescriptor()->getConfig().outConfs.size() <= parentIdx) {
parentIdx = 0;
}
memory::format_tag parentOutDesc = MKLDNNMemoryDesc(parent->getSelectedPrimitiveDescriptor()->getConfig().outConfs[parentIdx].desc).getFormat();
if (parentOutDesc != memory::format_tag::any && parentOutDesc != memory::format_tag::undef) {
if (formats.find(parentOutDesc) == formats.end())
formats[parentOutDesc] = 1;
else
formats[parentOutDesc] += 1;
continue;
}
if (nodeCanChangeDesc(parent))
continue;
if (enterCountDown < 2) {
parentOutDesc = MKLDNNMemoryDesc(parentEdge->getSpecifiedInputDesc(formats, ++enterCountUp, enterCountDown)).getFormat();
if (parentOutDesc != memory::format_tag::any && parentOutDesc != memory::format_tag::undef) {
if (formats.find(parentOutDesc) == formats.end())
formats[parentOutDesc] = 1;
else
formats[parentOutDesc] += 1;
}
}
}
if (!isFormatChanging) {
for (size_t i = 0; i < childPtr->getChildEdges().size(); i++) {
auto childEdge = childPtr->getChildEdgeAt(i);
auto child = childEdge->getChild();
int childIdx = childEdge->getOutputNum();
if (!child->getSelectedPrimitiveDescriptor() || childIdx < 0 ||
childEdge->getDims().ndims() != getDims().ndims()) {
continue;
}
if (child->getSelectedPrimitiveDescriptor()->getConfig().inConfs.size() <= childIdx) {
childIdx = 0;
}
memory::format_tag childInDesc = MKLDNNMemoryDesc(child->getSelectedPrimitiveDescriptor()->getConfig().inConfs[childIdx].desc).getFormat();
if (childInDesc != memory::format_tag::any && childInDesc != memory::format_tag::undef) {
if (formats.find(childInDesc) == formats.end())
formats[childInDesc] = 1;
else
formats[childInDesc] += 1;
continue;
}
if (nodeCanChangeDesc(child))
continue;
if (enterCountDown < 2) {
childInDesc = MKLDNNMemoryDesc(childEdge->getSpecifiedOutputDesc(formats, enterCountUp, ++enterCountDown)).getFormat();
if (childInDesc != memory::format_tag::any && childInDesc != memory::format_tag::undef) {
if (formats.find(childInDesc) == formats.end())
formats[childInDesc] = 1;
else
formats[childInDesc] += 1;
}
}
}
}
size_t maxFormatCount = 0;
memory::format_tag format = MKLDNNMemory::GetPlainFormat(getDims());
for (auto &it : formats) {
if (maxFormatCount < it.second && MKLDNNMemory::isConsistant(getDims(), it.first)) {
maxFormatCount = it.second;
format = it.first;
}
}
auto inDataType = MKLDNNMemoryDesc(childPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs[getOutputNum()].desc).getDataType();
childPtr->getSelectedPrimitiveDescriptor()->getConfig().inConfs[outputIdx].desc = MKLDNNMemoryDesc(getDims(), inDataType, format);
if (!isFormatChanging && outputIdx < childPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs.size() &&
childPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs[outputIdx].desc.getLayout() == InferenceEngine::Layout::ANY) {
childPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs[outputIdx].desc =
MKLDNNExtensionUtils::getUninitTensorDesc(MKLDNNMemoryDesc(getDims(), inDataType, format));
}
return childPtr->getSelectedPrimitiveDescriptor()->getConfig().outConfs[outputIdx].desc;
return getInputDesc();
}
const MKLDNNMemory &MKLDNNEdge::getMemory() {
if (status == Status::NotAllocated) {
memoryPtr.reset(new MKLDNNMemory(getParent()->getEngine()));
memoryPtr->Create(MKLDNNMemoryDesc(getDesc()), getSharedEdge()->getMemoryPtr()->GetData());
memoryPtr->Create(getDesc(), getSharedEdge()->getMemoryPtr()->GetData());
memoryFromEdge.reset();
changeStatus(Status::Allocated);
}
@@ -601,7 +308,7 @@ const MKLDNNMemory &MKLDNNEdge::getMemory() {
MKLDNNMemoryPtr &MKLDNNEdge::getMemoryPtr() {
if (status == Status::NotAllocated) {
memoryPtr.reset(new MKLDNNMemory(getParent()->getEngine()));
memoryPtr->Create(MKLDNNMemoryDesc(getDesc()), getSharedEdge()->getMemoryPtr()->GetData());
memoryPtr->Create(getDesc(), getSharedEdge()->getMemoryPtr()->GetData());
memoryFromEdge.reset();
changeStatus(Status::Allocated);
}
@@ -609,19 +316,6 @@ MKLDNNMemoryPtr &MKLDNNEdge::getMemoryPtr() {
return memoryPtr;
}
InferenceEngine::Blob::Ptr MKLDNNEdge::getBlob() {
if (!memoryPtr)
IE_THROW() << "Cannot get blob! Edge isn't initialized.";
InferenceEngine::TensorDesc desc = getDesc();
if (desc.getLayout() == InferenceEngine::Layout::ANY)
desc = InferenceEngine::TensorDesc(desc.getPrecision(), dims.ToSizeVector(), desc.getLayout());
else
desc = InferenceEngine::TensorDesc(desc.getPrecision(), dims.ToSizeVector(), desc.getBlockingDesc());
return isEmptyTensorDesc(desc) ? make_blob_with_precision(desc) : make_blob_with_precision(desc, memoryPtr->GetData());
}
void MKLDNNEdge::sharedMemFrom(const MKLDNNEdgePtr &edge) {
memoryFromEdge = edge;
status = Status::NotAllocated;
@@ -633,7 +327,7 @@ void MKLDNNEdge::validate() {
getMemory();
getParent();
getChild();
getDims();
getShape();
if (status != Status::Allocated) {
IE_THROW() << "Error memory is not allocated!";
@@ -644,8 +338,7 @@ void MKLDNNEdge::validate() {
MKLDNNEdgePtr MKLDNNEdge::getSharedEdge() const {
auto memoryFromEdgePtr = memoryFromEdge.lock();
if (!memoryFromEdgePtr) {
IE_THROW() << "Cannot get memory ptr for edge(" << getParent()->getName() << "->"
<< getChild()->getName() << "). The pointer on the edge with memory is empty!";
IE_THROW() << "Cannot get memory ptr for edge( " << name() << " ). The pointer on the edge with memory is empty!";
}
return memoryFromEdgePtr;
}
@@ -5,11 +5,9 @@
#pragma once
#include <ie_blob.h>
#include <memory>
#include "mkldnn_memory.h"
#include "mkldnn_dims.h"
#include "cpu_shape.h"
#include "cpu_memory_desc.h"
#include "mkldnn_weights_cache.hpp"
#include "mkldnn/ie_mkldnn.h"
#include <map>
#include <memory>
@@ -53,10 +51,7 @@ public:
const std::shared_ptr<MKLDNNNode> getParent() const;
const std::shared_ptr<MKLDNNNode> getChild() const;
InferenceEngine::Blob::Ptr getBlob();
InferenceEngine::TensorDesc getDesc();
const MKLDNNDims &getDims();
const Shape &getShape();
const MKLDNNMemory& getMemory();
MKLDNNMemoryPtr& getMemoryPtr();
@@ -73,34 +68,23 @@ public:
MKLDNNEdgePtr getSharedEdge() const;
MKLDNNEdgePtr getSharedEdge(std::nothrow_t) const;
const InferenceEngine::TensorDesc& getInputDescRO() const;
const InferenceEngine::TensorDesc& getOutputDescRO() const;
private:
std::string name();
std::string name() const;
std::weak_ptr<MKLDNNNode> parent;
std::weak_ptr<MKLDNNNode> child;
int parent_port;
int child_port;
bool externalMemoryPtr = false;
bool useExternalMemory = false;
MKLDNNEdgeWeakPtr memoryFromEdge;
MKLDNNDims dims;
Shape shape;
MKLDNNMemoryPtr memoryPtr;
Status status = Status::Uninitialized;
InferenceEngine::TensorDesc getInputDesc();
InferenceEngine::TensorDesc getOutputDesc();
InferenceEngine::TensorDesc getSpecifiedInputDesc(std::map<mkldnn::memory::format_tag, size_t> formats,
size_t enterCountUp = 1, size_t enterCountDown = 0);
InferenceEngine::TensorDesc getSpecifiedOutputDesc(std::map<mkldnn::memory::format_tag, size_t> formats,
size_t enterCountUp = 0, size_t enterCountDown = 1);
InferenceEngine::TensorDesc inputDesc;
InferenceEngine::TensorDesc outputDesc;
bool nodeCanChangeDesc(const std::shared_ptr<MKLDNNPlugin::MKLDNNNode>& node) const;
const MemoryDesc& getInputDesc() const;
const MemoryDesc& getOutputDesc() const;
const MemoryDesc& getDesc() const;
enum LOOK { LOOK_UP = 1, LOOK_DOWN = 2, LOOK_BOTH = LOOK_UP | LOOK_DOWN, LOOK_NO_RECURRENT = 4 };
@@ -32,7 +32,7 @@ uint8_t MKLDNNExtensionUtils::sizeOfDataType(mkldnn::memory::data_type dataType)
}
}
memory::data_type MKLDNNExtensionUtils::IEPrecisionToDataType(InferenceEngine::Precision prec) {
memory::data_type MKLDNNExtensionUtils::IEPrecisionToDataType(const InferenceEngine::Precision& prec) {
switch (prec) {
case InferenceEngine::Precision::FP32:
return memory::data_type::f32;
@@ -47,6 +47,8 @@ memory::data_type MKLDNNExtensionUtils::IEPrecisionToDataType(InferenceEngine::P
return memory::data_type::u8;
case InferenceEngine::Precision::BIN:
return memory::data_type::bin;
case InferenceEngine::Precision::UNSPECIFIED:
return memory::data_type::undef;
default: {
IE_THROW() << "The plugin does not support " << prec.name();
}
@@ -67,155 +69,18 @@ InferenceEngine::Precision MKLDNNExtensionUtils::DataTypeToIEPrecision(memory::d
return InferenceEngine::Precision::U8;
case memory::data_type::bin:
return InferenceEngine::Precision::BIN;
case memory::data_type::undef:
return InferenceEngine::Precision::UNSPECIFIED;
default: {
IE_THROW() << "Unsupported data type.";
}
}
}
InferenceEngine::TensorDesc MKLDNNExtensionUtils::getUninitTensorDesc(const InferenceEngine::TensorDesc &desc) {
std::vector<size_t> notInitArr;
std::vector<size_t> zeroArr;
for (size_t i = 0; i < desc.getBlockingDesc().getBlockDims().size(); i++) {
notInitArr.push_back(std::numeric_limits<size_t>::max());
zeroArr.push_back(0);
}
// MKLDNN doesn't support offset_padding_to_data[i] != 0 (assert(src_d_blk.offset_padding_to_data[d] == 0);)
return desc.getLayout() == InferenceEngine::Layout::ANY ? desc :
InferenceEngine::TensorDesc(desc.getPrecision(), desc.getDims(),
{desc.getBlockingDesc().getBlockDims(), desc.getBlockingDesc().getOrder(),
std::numeric_limits<size_t>::max(), zeroArr, notInitArr});
InferenceEngine::SizeVector MKLDNNExtensionUtils::convertToSizeVector(const mkldnn::memory::dims& dims) {
return InferenceEngine::SizeVector(dims.begin(), dims.end());
}
bool MKLDNNExtensionUtils::initTensorsAreEqual(const InferenceEngine::TensorDesc &desc1, const InferenceEngine::TensorDesc &desc2) {
if (desc1.getDims() != desc2.getDims() || desc1.getPrecision() != desc2.getPrecision())
return false;
if (desc1.getLayout() == InferenceEngine::Layout::SCALAR && desc2.getLayout() == InferenceEngine::Layout::SCALAR)
return true;
if (desc1.getLayout() == InferenceEngine::Layout::ANY || desc2.getLayout() == InferenceEngine::Layout::ANY)
return true;
bool batch1 = desc1.getDims()[0] == 1;
const auto& in1Block = desc1.getBlockingDesc();
const auto& in2Block = desc2.getBlockingDesc();
size_t uninitNum = std::numeric_limits<size_t>::max();
if (in1Block.getBlockDims().size() != in2Block.getBlockDims().size())
return false;
for (size_t i = 0; i < in1Block.getBlockDims().size(); i++) {
if (in1Block.getBlockDims()[i] != in2Block.getBlockDims()[i] &&
in1Block.getBlockDims()[i] != uninitNum && in2Block.getBlockDims()[i] != uninitNum)
return false;
if (in1Block.getOffsetPaddingToData()[i] != in2Block.getOffsetPaddingToData()[i] &&
in1Block.getOffsetPaddingToData()[i] != uninitNum && in2Block.getOffsetPaddingToData()[i] != uninitNum)
return false;
if (i >= batch1 && in1Block.getStrides()[i] != in2Block.getStrides()[i] &&
in1Block.getStrides()[i] != uninitNum && in2Block.getStrides()[i] != uninitNum)
return false;
if (in1Block.getOrder()[i] != in2Block.getOrder()[i] &&
in1Block.getOrder()[i] != uninitNum && in2Block.getOrder()[i] != uninitNum)
return false;
}
return !(in1Block.getOffsetPadding() != in2Block.getOffsetPadding() &&
in1Block.getOffsetPadding() != uninitNum && in2Block.getOffsetPadding() != uninitNum);
}
PartialBlkDesc PartialBlkDesc::makePlain(const InferenceEngine::SizeVector &dims) {
PartialBlkDesc res;
res.outer_order.resize(dims.size());
std::iota(res.outer_order.begin(), res.outer_order.end(), 0);
return res;
}
PartialBlkDesc PartialBlkDesc::makeCBlocked(const InferenceEngine::SizeVector &dims, size_t block_size) {
PartialBlkDesc res;
res.outer_order.resize(dims.size());
std::iota(res.outer_order.begin(), res.outer_order.end(), 0);
res.inner_blk_size = {block_size};
res.inner_blk_idxes = {1};
return res;
}
PartialBlkDesc PartialBlkDesc::makeTailC(const InferenceEngine::SizeVector &dims) {
PartialBlkDesc res = makePlain(dims);
if (dims.size() > 2) {
auto itr = res.outer_order.begin() + 1;
std::rotate(itr, itr + 1, res.outer_order.end());
}
return res;
}
PartialBlkDesc PartialBlkDesc::extractFrom(const InferenceEngine::TensorDesc &desc) {
if (desc.getLayout() == InferenceEngine::ANY)
IE_THROW() << "Cannot extract partial blocked descriptor for `ANY` layout";
const auto &dims = desc.getDims();
const auto &blk = desc.getBlockingDesc();
const auto &blk_dims = blk.getBlockDims();
const auto &blk_order = blk.getOrder();
PartialBlkDesc res;
res.outer_order = {blk_order.begin(), blk_order.begin() + dims.size()};
res.inner_blk_idxes = {blk_order.begin() + dims.size(), blk_order.end()};
res.inner_blk_size = {blk_dims.begin() + dims.size(), blk_dims.end()};
return res;
}
bool PartialBlkDesc::isAutoExtendedWith(const InferenceEngine::SizeVector &dims) const {
auto tmp_dims = dims;
for (int i = 0; i < inner_blk_size.size(); i++) {
auto idx = inner_blk_idxes[i];
auto blk = inner_blk_size[i];
if (tmp_dims[idx] % blk == 0)
tmp_dims[idx] /= blk;
else
return true;
}
return false;
}
bool PartialBlkDesc::operator == (const PartialBlkDesc& it) const {
return std::tie(this->inner_blk_idxes,
this->inner_blk_size,
this->outer_order) ==
std::tie(it.inner_blk_idxes,
it.inner_blk_size,
it.outer_order);
}
// Lexicographical compare of content
bool PartialBlkDesc::operator < (const PartialBlkDesc& it) const {
return std::tie(this->inner_blk_idxes,
this->inner_blk_size,
this->outer_order) <
std::tie(it.inner_blk_idxes,
it.inner_blk_size,
it.outer_order);
}
std::string MKLDNNExtensionUtils::getReorderArgs(const InferenceEngine::TensorDesc &parentDesc, const InferenceEngine::TensorDesc &childDesc) {
std::string inArgs, outArgs;
if (parentDesc.getPrecision() != childDesc.getPrecision()) {
inArgs += (inArgs.empty() ? "" : "_") + std::string(parentDesc.getPrecision().name());
outArgs += (outArgs.empty() ? "" : "_") + std::string(childDesc.getPrecision().name());
}
auto fmt_tag_src = MKLDNNMemoryDesc(parentDesc).getFormat();
auto fmt_tag_dst = MKLDNNMemoryDesc(childDesc).getFormat();
if (fmt_tag_src != fmt_tag_dst || one_of(mkldnn::memory::format_tag::undef, fmt_tag_src, fmt_tag_dst)) {
inArgs += (inArgs.empty() ? "" : "_") + MKLDNNMemory::formatToString(fmt_tag_src);
outArgs += (outArgs.empty() ? "" : "_") + MKLDNNMemory::formatToString(fmt_tag_dst);
}
return inArgs + "_" + outArgs;
}
InferenceEngine::Precision MKLDNNExtensionUtils::getMaxPrecision(std::vector<InferenceEngine::Precision> precisions) {
if (!precisions.empty()) {
std::sort(precisions.begin(), precisions.end(),
[](const InferenceEngine::Precision &lhs, const InferenceEngine::Precision &rhs) {
return lhs.size() > rhs.size();
});
return precisions[0];
}
return InferenceEngine::Precision::UNSPECIFIED;
std::vector<dnnl::memory::dim> MKLDNNExtensionUtils::convertToDnnlDims(const InferenceEngine::SizeVector& dims) {
return std::vector<dnnl::memory::dim>(dims.begin(), dims.end());;
}
@@ -11,77 +11,17 @@
#include <string>
#include "mkldnn.hpp"
#include "mkldnn_memory.h"
#include "cpu_memory_desc.h"
namespace MKLDNNPlugin {
/**
* Partial tensor descriptor
*
* Represent a classes of layout. As example Plain, TailC, CBlocked and other.
*
* The tensor are in one layout family if they have same PartialBlkDesc.
*
* Any tensor will have same PartialBlkDesc as it subview tensor.
*
* PartialBlkDesc plus Dims allow to reconstruct real tensorDesc (dense representation).
*/
class PartialBlkDesc {
public:
/**
* Check if this partial blocking desc will lead to additional zero padding
* for real tensor with provided dims
*
* Example: dims [2, 3, 8, 8] with blocking by 16 for second dim. Will lead
* to effective dims [2, 16, 8, 8] with zeroing all values
* [:, 3:16, :, :]
*
* @param dims to check on zero auto padding
* @return true if provided dims will use auto padding. Otherwise false.
*/
bool isAutoExtendedWith(const InferenceEngine::SizeVector &dims) const;
/**
* Construct PartialBlkDesc from provided TensorDesc
*
* PartialBlkDesc has less expressiveness power so some information from TensorDesc will be dropped.
* The different TensorDesc object will has equal PartialBlkDesc.
*
* @param desc to extract PartialBlkDesc information about kind of layout
* @return PartialBlkDesc object corresponds layout described in desc
*/
static PartialBlkDesc extractFrom(const InferenceEngine::TensorDesc &desc);
/** Construct plain PartialBlkDesc based on dims information */
static PartialBlkDesc makePlain(const InferenceEngine::SizeVector &dims);
/** Construct blocked Channel PartialBlkDesc based on dims information */
static PartialBlkDesc makeCBlocked(const InferenceEngine::SizeVector &dims, size_t block_size);
/** Construct per Channel PartialBlkDesc based on dims information */
static PartialBlkDesc makeTailC(const InferenceEngine::SizeVector &dims);
/** Compare operators. Allow to use it as key for std::map */
bool operator == (const PartialBlkDesc& it) const;
bool operator < (const PartialBlkDesc& it) const;
private:
PartialBlkDesc() = default;
InferenceEngine::SizeVector outer_order;
InferenceEngine::SizeVector inner_blk_size;
InferenceEngine::SizeVector inner_blk_idxes;
};
class MKLDNNExtensionUtils {
public:
static uint8_t sizeOfDataType(mkldnn::memory::data_type dataType);
static mkldnn::memory::data_type IEPrecisionToDataType(InferenceEngine::Precision prec);
static mkldnn::memory::data_type IEPrecisionToDataType(const InferenceEngine::Precision& prec);
static InferenceEngine::Precision DataTypeToIEPrecision(mkldnn::memory::data_type dataType);
static InferenceEngine::TensorDesc getUninitTensorDesc(const InferenceEngine::TensorDesc& desc);
static bool initTensorsAreEqual(const InferenceEngine::TensorDesc &desc1, const InferenceEngine::TensorDesc &desc2);
static std::string getReorderArgs(const InferenceEngine::TensorDesc &parentDesc, const InferenceEngine::TensorDesc &childDesc);
static InferenceEngine::Precision getMaxPrecision(std::vector<InferenceEngine::Precision> precisions);
static InferenceEngine::SizeVector convertToSizeVector(const mkldnn::memory::dims& dims);
static std::vector<dnnl::memory::dim> convertToDnnlDims(const InferenceEngine::SizeVector& dims);
};
} // namespace MKLDNNPlugin
@@ -39,6 +39,7 @@
#include "utils/node_dumper.h"
#include "utils/ngraph_utils.hpp"
#include "utils/cpu_utils.hpp"
#include "cpu_memory_desc_utils.h"
#include <ngraph/node.hpp>
#include <ngraph/function.hpp>
@@ -47,15 +48,6 @@
#include <transformations/utils/utils.hpp>
#include <low_precision/low_precision.hpp>
/*****************************************************
* Debug capability
* - PRINT_GRAPH_INFO : Define it to enable printing
* additional information to std output.
*
* @todo Align with CPU_DEBUG_CAPS implementation
*****************************************************/
// #define PRINT_GRAPH_INFO
using namespace mkldnn;
using namespace MKLDNNPlugin;
using namespace InferenceEngine;
@@ -168,7 +160,7 @@ void MKLDNNGraph::Replicate(const std::shared_ptr<const ngraph::Function> &subgr
auto parentNode = portInfo.first;
auto port = portInfo.second;
const auto nodeName = std::string("stub_") + std::to_string(unusedOutput.get_index()) + "_" + parentNode->getName();
const MKLDNNNodePtr outNode = std::make_shared<MKLDNNInputNode>(parentNode->outDims[port].ToSizeVector(),
const MKLDNNNodePtr outNode = std::make_shared<MKLDNNInputNode>(parentNode->outputShapes[port],
parentNode->getOriginalOutputPrecisionAtPort(port),
nodeName, "Result", getEngine(), weightsCache);
MKLDNNEdgePtr edge(new MKLDNNEdge(parentNode, outNode, port, 0));
@@ -269,7 +261,7 @@ void MKLDNNGraph::Replicate(const CNNNetwork &network, const MKLDNNExtensionMana
auto parentNode = op2node[unusedOutput.get_node_shared_ptr()];
const auto port = unusedOutput.get_index();
const auto nodeName = std::string("stub_") + std::to_string(unusedOutput.get_index()) + "_" + parentNode->getName();
const MKLDNNNodePtr outNode = std::make_shared<MKLDNNInputNode>(parentNode->outDims[port].ToSizeVector(),
const MKLDNNNodePtr outNode = std::make_shared<MKLDNNInputNode>(parentNode->outputShapes[port],
parentNode->getOriginalOutputPrecisionAtPort(port),
nodeName, "Result", getEngine(), weightsCache);
MKLDNNEdgePtr edge(new MKLDNNEdge(parentNode, outNode, port, 0));
@@ -306,15 +298,15 @@ void MKLDNNGraph::Replicate(const CNNNetwork &network, const MKLDNNExtensionMana
// Loading mean images
for (const auto& input : inputsInfo) {
MKLDNNDims outDims;
if (!inputNodesMap[input.first]->getChildEdgeAt(0)->getDims().ndims()) {
outDims = MKLDNNDims(InferenceEngine::SizeVector(1, 1));
Shape outShape;
if (!inputNodesMap[input.first]->outputShapes.front().getRank()) {
outShape = Shape(SizeVector({1, 1}));
} else {
outDims = inputNodesMap[input.first]->getChildEdgeAt(0)->getDims();
outShape = inputNodesMap[input.first]->outputShapes.front();
}
InputInfo::Ptr ii = inputsInfo[input.first];
if (ii && ii->getPreProcess().getNumberOfChannels()) {
_normalizePreprocMap[input.first].Load(outDims, ii);
_normalizePreprocMap[input.first].Load(outShape, ii);
}
}
}
@@ -446,9 +438,9 @@ void MKLDNNGraph::ExecuteConstantNodesOnly() {
}
}
static bool isReorderAvailable(const TensorDesc& parentDesc, const TensorDesc& childDesc, const mkldnn::engine& eng) {
memory::desc dstMemDesc = MKLDNNMemoryDesc(childDesc);
memory::desc srcMemDesc = MKLDNNMemoryDesc(parentDesc);
static bool isReorderAvailable(const MemoryDesc& parentDesc, const MemoryDesc& childDesc, const mkldnn::engine& eng) {
memory::desc dstMemDesc = MemoryDescUtils::convertToMKLDNNMemoryDesc(childDesc);
memory::desc srcMemDesc = MemoryDescUtils::convertToMKLDNNMemoryDesc(parentDesc);;
mkldnn::primitive_attr attr;
dnnl_primitive_desc_t result = nullptr;
@@ -480,14 +472,14 @@ void MKLDNNGraph::InitEdges() {
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
const auto inDesc = edge->getInputDesc();
const auto outDesc = edge->getOutputDesc();
const auto& inDesc = edge->getInputDesc();
const auto& outDesc = edge->getOutputDesc();
std::string convertName = edge->getParent()->getName() + "_" +
inDesc.getPrecision().name() + "_" + outDesc.getPrecision().name();
auto convertNode = std::make_shared<MKLDNNConvertNode>(inDesc.getDims(), inDesc.getPrecision(), outDesc.getPrecision(), convertName,
this->getEngine(), this->weightsCache);
auto convertNode = std::make_shared<MKLDNNConvertNode>(inDesc.getShape().getStaticDims(), inDesc.getPrecision(), outDesc.getPrecision(),
convertName, this->getEngine(), this->weightsCache);
convertNode->setDescs(inDesc, outDesc);
InsertNode(edge, convertNode, true);
@@ -501,7 +493,7 @@ void MKLDNNGraph::InitEdges() {
if (insertReorder) {
std::string basicLayerName = edge->getParent()->getName() + "_" +
MKLDNNExtensionUtils::getReorderArgs(edge->getInputDesc(), edge->getOutputDesc()) + "_" +
MKLDNNReorderNode::getReorderArgs(edge->getInputDesc(), edge->getOutputDesc()) + "_" +
edge->getChild()->getName();
std::string layerName = basicLayerName;
int idx = 0;
@@ -610,22 +602,10 @@ void MKLDNNGraph::AllocateWithReuse() {
int e_start = edge->getParent()->execIndex;
int e_finish = edge->getChild()->execIndex;
const BlockingDesc block_desk = edge->getDesc().getBlockingDesc();
int64_t e_size = block_desk.getOffsetPadding() + 1; // size in bytes (from begin of data to last element)
for (int j = 0; j < block_desk.getBlockDims().size(); j++)
e_size += (block_desk.getBlockDims()[j] - 1) * block_desk.getStrides()[j];
// In some cases computational formula above doesn't work properly (e.g. for OhIw8o4i layout).
// This WA allows to limit the size of allocated memory from below.
// TODO: need to properly investigate the root cause of incorrect computations
int64_t min_size = 1;
for (int64_t dim : block_desk.getBlockDims()) {
min_size *= dim;
int64_t e_size = edge->getDesc().getCurrentSize(); // size in bytes (from the beginning of data to the last element)
if (e_size == MemoryDesc::UNDEFINED_SIZE) {
IE_THROW() << "Can not allocate memory since the size is undefined.";
}
e_size = std::max(e_size, min_size);
e_size *= edge->getDesc().getPrecision() == Precision::BIN ? 1 : edge->getDesc().getPrecision().size();
box.start = std::min(e_start, box.start);
box.finish = std::max(e_finish, box.finish);
@@ -659,7 +639,7 @@ void MKLDNNGraph::AllocateWithReuse() {
size_t total_size = static_cast<size_t>(memSolver.solve()) * alignment;
memWorkspace = std::make_shared<MKLDNNMemory>(eng);
memWorkspace->Create(MKLDNNMemoryDesc(TensorDesc(Precision::I8, {total_size}, Layout::C)));
memWorkspace->Create(MKLDNNMemoryDesc({total_size}, mkldnn::memory::data_type::s8));
if (edge_clusters.empty())
return;
@@ -719,13 +699,11 @@ void MKLDNNGraph::PushInputData(const std::string& name, const InferenceEngine::
auto input = inputNodesMap.find(name);
if (input != inputNodesMap.end()) {
MKLDNNDims outDims = input->second->getChildEdgeAt(0)->getDims();
const void *ext_data_ptr = in->cbuffer();
void *inter_data_ptr = input->second->getChildEdgeAt(0)->getMemory().GetData();
if (ext_data_ptr != inter_data_ptr) {
auto ext_tdesc = MKLDNNMemoryDesc {in->getTensorDesc()};
auto ext_tdesc = MemoryDescUtils::convertToMKLDNNMemoryDesc(in->getTensorDesc());
auto ext_mem = MKLDNNMemory(eng);
ext_mem.Create(ext_tdesc, ext_data_ptr, false);
@@ -736,7 +714,8 @@ void MKLDNNGraph::PushInputData(const std::string& name, const InferenceEngine::
// todo: make sure 'name' exists in this map...
if (_normalizePreprocMap.find(name) != _normalizePreprocMap.end()) {
if (in->getTensorDesc().getPrecision() == InferenceEngine::Precision::FP32) {
_normalizePreprocMap[name].NormalizeImage(outDims, reinterpret_cast<float *>(inter_data_ptr),
_normalizePreprocMap[name].NormalizeImage(input->second->getChildEdgeAt(0)->getShape(),
reinterpret_cast<float *>(inter_data_ptr),
in->getTensorDesc().getLayout());
} else {
IE_THROW() << "Mean image of type " << in->getTensorDesc().getPrecision().name() << " is unsupported";
@@ -784,7 +763,7 @@ void MKLDNNGraph::PullOutputData(const BlobMap &out) {
MB_to_process = std::min<int>(config.batchLimit, MB_to_process);
size_t size_to_copy = intr_blob.GetElementsCount() * MB_to_process / MB;
const auto actualDesc = node->getParentEdgeAt(0)->getDesc();
const auto actualDesc = MemoryDescUtils::convertToTensorDesc(node->getParentEdgeAt(0)->getDesc());
const auto expectedDesc = ext_blob->getTensorDesc();
// TODO [NM]: need to create universal reorder which will be detect cases when we really need to use it
@@ -799,7 +778,7 @@ void MKLDNNGraph::PullOutputData(const BlobMap &out) {
}
if (actualDesc.getBlockingDesc() != expectedDesc.getBlockingDesc() && !isScalarOutput) {
auto outBlobDesc = MKLDNNMemoryDesc{expectedDesc};
auto outBlobDesc = MemoryDescUtils::convertToMKLDNNMemoryDesc(expectedDesc);
auto outBloMem = MKLDNNMemory(eng);
outBloMem.Create(outBlobDesc, ext_blob_ptr, false);
@@ -904,7 +883,7 @@ void MKLDNNGraph::SortTopologically() {
// Make first N (N == port_num) edge indexes are matched with port index
for (auto &node : graphNodes) {
{
int port_num = node->inDims.size();
int port_num = node->inputShapes.size();
std::vector<MKLDNNEdgePtr> res(port_num);
for (int i = 0; i < node->parentEdges.size(); i++) {
@@ -918,7 +897,7 @@ void MKLDNNGraph::SortTopologically() {
node->parentEdges = {res.begin(), res.end()};
}
{
int port_num = node->outDims.size();
int port_num = node->outputShapes.size();
std::vector<MKLDNNEdgePtr> res(port_num);
for (int i = 0; i < node->childEdges.size(); i++) {
@@ -983,7 +962,7 @@ Config MKLDNNGraph::getProperty() const {
Blob::Ptr MKLDNNGraph::getInputBlob(const std::string& name) {
auto itr = inputNodesMap.find(name);
if (itr != inputNodesMap.end()) {
return itr->second->getChildEdgeAt(0)->getBlob();
return MemoryDescUtils::interpretAsBlob(itr->second->getChildEdgeAt(0)->getMemory());
}
return nullptr;
}
@@ -991,7 +970,7 @@ Blob::Ptr MKLDNNGraph::getInputBlob(const std::string& name) {
Blob::Ptr MKLDNNGraph::getOutputBlob(const std::string& name) {
auto itr = outputNodesMap.find(name);
if (itr != outputNodesMap.end()) {
return itr->second->getParentEdgeAt(0)->getBlob();
return MemoryDescUtils::interpretAsBlob(itr->second->getParentEdgeAt(0)->getMemory());
}
return nullptr;
}
@@ -1103,7 +1082,7 @@ void MKLDNNGraph::DropDWConvNode(const MKLDNNNodePtr &node) {
MKLDNNEdgePtr newEdge(new MKLDNNEdge(parent, parentConv, inNum, outNum));
graphEdges.push_back(newEdge);
parent->addEdge(newEdge);
parentConv->inDims.push_back(newEdge->getDims());
parentConv->inputShapes.push_back(Shape(newEdge->getShape()));
}
}
@@ -1135,15 +1114,14 @@ void MKLDNNGraph::RemoveDroppedEdges() {
}
}
MKLDNNNodePtr MKLDNNGraph::InsertReorder(MKLDNNEdgePtr edge, std::string layerName, const TensorDesc& inDesc, const TensorDesc& outDesc,
bool isOptimized, InferenceEngine::Blob::Ptr scales) {
MKLDNNNodePtr MKLDNNGraph::InsertReorder(MKLDNNEdgePtr edge, std::string layerName, const MemoryDesc& inDesc, const MemoryDesc& outDesc,
bool isOptimized) {
MKLDNNNodePtr newReorder(new MKLDNNReorderNode(layerName, getEngine(), weightsCache));
auto *reorderPtr = dynamic_cast<MKLDNNReorderNode *>(newReorder.get());
if (reorderPtr == nullptr) {
IE_THROW() << "MKLDNNGraph::InsertReorder: Cannot cast to MKLDNNReorderNode";
}
reorderPtr->setDescs(inDesc, outDesc);
reorderPtr->_scales = scales;
reorderPtr->setOptimized(isOptimized);
InsertNode(edge, newReorder, true);
@@ -115,17 +115,17 @@ public:
* @param layerName
* Reorder layer name
* @param inDesc
* input tensor descriptor
* input memory descriptor
* @param outDesc
* output tensor descriptor
* output memory descriptor
* @param isOptimized
* optimization flag; if isOptimized is true then Reorder node does nothing
* @param scales
* pointer to the blob containing scales
* @return pointer to the new Reorder node.
*/
MKLDNNNodePtr InsertReorder(MKLDNNEdgePtr edge, std::string layerName, const InferenceEngine::TensorDesc& inDesc,
const InferenceEngine::TensorDesc& outDesc, bool isOptimized = false, InferenceEngine::Blob::Ptr scales = nullptr);
MKLDNNNodePtr InsertReorder(MKLDNNEdgePtr edge, std::string layerName, const MemoryDesc& inDesc,
const MemoryDesc& outDesc, bool isOptimized = false);
/**
* @brief Insert MKLDNNNode at the edge-specified location.
@@ -10,7 +10,6 @@
#include <ngraph/variant.hpp>
#include "ngraph/ngraph.hpp"
#include "utils/debug_capabilities.h"
#include <vector>
#include <string>
#include <memory>
@@ -46,11 +45,11 @@ std::map<std::string, std::string> extract_node_metadata(const MKLDNNNodePtr &no
std::string outputPrecisionsStr;
if (!node->getChildEdges().empty()) {
outputPrecisionsStr = node->getChildEdgeAt(0)->getDesc().getPrecision().name();
outputPrecisionsStr = node->getChildEdgeAt(0)->getMemory().GetDesc().getPrecision().name();
bool isAllEqual = true;
for (size_t i = 1; i < node->getChildEdges().size(); i++) {
if (node->getChildEdgeAt(i-1)->getDesc().getPrecision() != node->getChildEdgeAt(i)->getDesc().getPrecision()) {
if (node->getChildEdgeAt(i - 1)->getMemory().GetDesc().getPrecision() != node->getChildEdgeAt(i)->getMemory().GetDesc().getPrecision()) {
isAllEqual = false;
break;
}
@@ -59,12 +58,12 @@ std::map<std::string, std::string> extract_node_metadata(const MKLDNNNodePtr &no
// If all output precisions are the same, we store the name only once
if (!isAllEqual) {
for (size_t i = 1; i < node->getChildEdges().size(); i++)
outputPrecisionsStr += "," + std::string(node->getChildEdgeAt(i)->getDesc().getPrecision().name());
outputPrecisionsStr += "," + std::string(node->getChildEdgeAt(i)->getMemory().GetDesc().getPrecision().name());
}
} else {
// Branch to correctly handle output nodes
if (!node->getParentEdges().empty()) {
outputPrecisionsStr = node->getParentEdgeAt(0)->getDesc().getPrecision().name();
outputPrecisionsStr = node->getParentEdgeAt(0)->getMemory().GetDesc().getPrecision().name();
}
}
serialization_info[ExecGraphInfoSerialization::OUTPUT_PRECISIONS] = outputPrecisionsStr;
@@ -73,12 +72,11 @@ std::map<std::string, std::string> extract_node_metadata(const MKLDNNNodePtr &no
auto outDescs = node->getSelectedPrimitiveDescriptor()->getConfig().outConfs;
if (!outDescs.empty()) {
auto fmt0 = MKLDNNMemoryDesc(outDescs[0].desc).getFormat();
outputLayoutsStr = mkldnn::utils::fmt2str(fmt0);
outputLayoutsStr = outDescs[0].desc->serializeFormat();
bool isAllEqual = true;
for (size_t i = 1; i < outDescs.size(); i++) {
if (MKLDNNMemoryDesc(outDescs[i - 1].desc).getFormat() != MKLDNNMemoryDesc(outDescs[i].desc).getFormat()) {
if (outDescs[i - 1].desc->serializeFormat() != outDescs[i].desc->serializeFormat()) {
isAllEqual = false;
break;
}
@@ -87,8 +85,7 @@ std::map<std::string, std::string> extract_node_metadata(const MKLDNNNodePtr &no
// If all output layouts are the same, we store the name only once
if (!isAllEqual) {
for (size_t i = 1; i < outDescs.size(); i++) {
auto fmt = MKLDNNMemoryDesc(outDescs[i].desc).getFormat();
outputLayoutsStr += "," + std::string(mkldnn::utils::fmt2str(fmt));
outputLayoutsStr += "," + outDescs[i].desc->serializeFormat();
}
}
} else {
@@ -163,10 +160,8 @@ InferenceEngine::CNNNetwork dump_graph_as_ie_ngraph_net(const MKLDNNGraph &graph
auto meta_data = extract_node_metadata(node);
std::shared_ptr<ngraph::Node> return_node;
if (is_input) {
auto desc = node->getChildEdgeAt(0)->getDesc();
auto param = std::make_shared<ngraph::op::Parameter>(
details::convertPrecision(desc.getPrecision()),
ngraph::PartialShape(desc.getDims()));
auto& desc = node->getChildEdgeAt(0)->getMemory().GetDesc();
auto param = std::make_shared<ngraph::op::Parameter>(details::convertPrecision(desc.getPrecision()), desc.getShape().toPartialShape());
return_node = param;
params.push_back(param);
} else if (is_output) {
@@ -177,10 +172,8 @@ InferenceEngine::CNNNetwork dump_graph_as_ie_ngraph_net(const MKLDNNGraph &graph
get_inputs(node), node->getSelectedPrimitiveDescriptor()->getConfig().outConfs.size());
for (size_t port = 0; port < return_node->get_output_size(); ++port) {
auto desc = node->getChildEdgeAt(port)->getDesc();
return_node->set_output_type(port,
details::convertPrecision(desc.getPrecision()),
ngraph::PartialShape(desc.getDims()));
auto& desc = node->getChildEdgeAt(port)->getMemory().GetDesc();
return_node->set_output_type(port, details::convertPrecision(desc.getPrecision()), desc.getShape().toPartialShape());
}
}
@@ -237,18 +230,19 @@ void serializeToXML(const MKLDNNGraph &graph, const std::string& path) {
void serializeToCout(const MKLDNNGraph &graph) {
for (const auto& node : graph.GetNodes()) {
std::cout << "name: " << node->getName() << " [ ";
if (!node->getParentEdges().empty()) {
const auto& parentEdge = *(node->getParentEdges()[0].lock());
const auto& prnt_out_desc = parentEdge.getOutputDescRO();
std::cout << "in: " << prnt_out_desc.getPrecision().name()
<< "/l=" << prnt_out_desc.getLayout()
<< "; ";
}
if (!node->getChildEdges().empty()) {
const auto& childEdge = *(node->getChildEdges()[0].lock());
const auto& chld_in_desc = childEdge.getInputDescRO();
std::cout << "out: " << chld_in_desc.getPrecision().name()
<< "/l=" << chld_in_desc.getLayout();
auto nodeDesc = node->getSelectedPrimitiveDescriptor();
if (nodeDesc) {
auto& inConfs = nodeDesc->getConfig().inConfs;
if (!inConfs.empty()) {
std::cout << "in: " << inConfs.front().desc->getPrecision().name()
<< "/l=" << inConfs.front().desc->serializeFormat()
<< "; ";
}
auto& outConfs = nodeDesc->getConfig().outConfs;
if (!outConfs.empty()) {
std::cout << "out: " << outConfs.front().desc->getPrecision().name()
<< "/l=" << outConfs.front().desc->serializeFormat();
}
}
std::cout << " ]" << std::endl;
}
@@ -43,6 +43,7 @@
#include <algorithm>
#include "mkldnn_itt.h"
#include "cpu_memory_desc_utils.h"
using namespace mkldnn;
using namespace MKLDNNPlugin;
@@ -165,15 +166,15 @@ void MKLDNNGraphOptimizer::FuseConvolutionAndBias(MKLDNNGraph &graph) {
if (biasNode->getType() != Input || !biasNode->isConstant() || biasNode->getChildEdges().size() != 1)
return false;
auto convOutDims = parentNode->getChildEdgesAtPort(0)[0]->getDims().ToSizeVector();
auto biasDims = getNormalizedDimsBySize(biasNode->getChildEdgesAtPort(0)[0]->getDims().ToSizeVector(),
auto convOutDims = parentNode->getChildEdgesAtPort(0)[0]->getShape().getDims();
auto biasDims = getNormalizedDimsBySize(biasNode->getChildEdgesAtPort(0)[0]->getShape().getDims(),
convOutDims.size());
// TODO [NM]: Legacy ConvBias fusion transformation supports both per-tensor (via explicit broadcasing) and per-channel cases.
// Most of the real models contain per-channel bias, so we need to reavaluate the need to support per-tensor variant.
if (convOutDims.size() != biasDims.size() || biasDims.size() < 2)
return false;
if (biasDims[0] != 1 || biasDims[1] != convOutDims[1])
if (biasDims[0] != 1 || !dimsEqualStrong(biasDims[1], convOutDims[1]))
return false;
for (int i = 2; i < biasDims.size(); i++) {
@@ -249,8 +250,8 @@ void MKLDNNGraphOptimizer::FuseConvolutionAndBias(MKLDNNGraph &graph) {
graphEdges.push_back(newEdge);
parent->addEdge(newEdge);
parent->outDims[inNum] = MKLDNNDims({parentEltwise->outDims[0][1]});
parentEltwise->inDims.push_back(parent->outDims[0]);
parent->outputShapes[inNum] = Shape(SizeVector{parentEltwise->outputShapes[0].getStaticDims()[1]});
parentEltwise->inputShapes.push_back(parent->outputShapes[0]);
}
}
@@ -299,17 +300,17 @@ void MKLDNNGraphOptimizer::FuseDeconvolutionAndSimpleOperation(MKLDNNGraph &grap
void MKLDNNGraphOptimizer::FuseMultiplyAndAdd(MKLDNNGraph &graph) {
auto& graphNodes = graph.GetNodes();
auto isSutableSecondInput = [](MKLDNNNodePtr node, MKLDNNDims dataDims) {
auto isSutableSecondInput = [](MKLDNNNodePtr node, SizeVector dataDims) {
if (node->getType() != Input || !node->isConstant())
return false;
auto secondInputDims = node->outDims[0];
if (secondInputDims.ndims() != dataDims.ndims() || secondInputDims.ndims() < 2)
auto secondInputDims = node->outputShapes[0].getDims();
if (secondInputDims.size() != dataDims.size() || secondInputDims.size() < 2)
return false;
if (secondInputDims[0] != 1 || secondInputDims[1] != dataDims[1])
if (secondInputDims[0] != 1 || !dimsEqualStrong(secondInputDims[1], dataDims[1]))
return false;
for (size_t i = 2; i < secondInputDims.ndims(); i++) {
for (size_t i = 2; i < secondInputDims.size(); i++) {
if (secondInputDims[i] != 1)
return false;
}
@@ -322,14 +323,14 @@ void MKLDNNGraphOptimizer::FuseMultiplyAndAdd(MKLDNNGraph &graph) {
node->getParentEdges().size() != 2 || node->getChildEdges().size() != 1)
return false;
return isSutableSecondInput(node->getParentEdgesAtPort(1)[0]->getParent(), node->getParentEdgesAtPort(0)[0]->getDims());
return isSutableSecondInput(node->getParentEdgesAtPort(1)[0]->getParent(), node->getParentEdgesAtPort(0)[0]->getShape().getDims());
};
auto isSutableChildNode = [&](MKLDNNNodePtr parentNode, MKLDNNNodePtr childNode) {
if (childNode->getAlgorithm() != EltwiseAdd || !childNode->getFusedWith().empty() || childNode->getParentEdges().size() != 2)
return false;
return isSutableSecondInput(childNode->getParentEdgesAtPort(1)[0]->getParent(), childNode->getParentEdgesAtPort(0)[0]->getDims());
return isSutableSecondInput(childNode->getParentEdgesAtPort(1)[0]->getParent(), childNode->getParentEdgesAtPort(0)[0]->getShape().getDims());
};
auto parent = graphNodes.begin();
@@ -397,7 +398,7 @@ void MKLDNNGraphOptimizer::FuseMultiplyAndAdd(MKLDNNGraph &graph) {
graphEdges.push_back(newEdge);
parent->addEdge(newEdge);
parentEltwise->inDims.push_back(parent->outDims[0]);
parentEltwise->inputShapes.push_back(parent->outputShapes[0]);
}
}
@@ -416,9 +417,9 @@ void MKLDNNGraphOptimizer::FuseConvolutionAndZeroPoints(MKLDNNGraph &graph) {
bool retVal = false;
if (node->getType() == Convolution) {
if (auto convNode = std::dynamic_pointer_cast<MKLDNNConvolutionNode>(node)) {
auto ndims = convNode->getParentEdgeAt(0)->getDims().ndims();
auto rank = convNode->getParentEdgeAt(0)->getShape().getRank();
// int8 depthwise convolution does not support fusing zero points in 3D case
if (implication(convNode->isDepthWise(), ndims == 4)) {
if (implication(convNode->isDepthWise(), rank == 4)) {
retVal = true;
}
}
@@ -431,8 +432,12 @@ void MKLDNNGraphOptimizer::FuseConvolutionAndZeroPoints(MKLDNNGraph &graph) {
if (convNode == nullptr)
IE_THROW() << "Cannot get convolution node " << node->getName();
int IC = node->getParentEdgesAtPort(0)[0]->getDims()[1];
int OC = node->getChildEdgesAtPort(0)[0]->getDims()[1];
int IC = node->getParentEdgesAtPort(0)[0]->getShape().getDims()[1];
int OC = node->getChildEdgesAtPort(0)[0]->getShape().getDims()[1];
if (Shape::UNDEFINED_DIM == IC || Shape::UNDEFINED_DIM == OC) {
return false;
}
if (parent0->getType() == Eltwise) {
if (!parent0->getFusedWith().empty() || !parent1->getFusedWith().empty())
@@ -452,19 +457,19 @@ void MKLDNNGraphOptimizer::FuseConvolutionAndZeroPoints(MKLDNNGraph &graph) {
return false;
auto arg0 = parent0->getParentEdgesAtPort(1)[0]->getParent();
if (arg0->getChildEdges().size() == 1 && arg0->getType() == Input && arg0->isConstant()) {
if (arg0->getType() == Input && arg0->isConstant()) {
if (arg0->getOriginalOutputPrecisionAtPort(0) != Precision::U8)
return false;
if (parent0->getParentEdgesAtPort(1)[0]->getDims().size() < 2) {
if (parent0->getParentEdgesAtPort(1)[0]->getShape().getRank() < 2) {
return false;
}
auto zpDims = parent0->getParentEdgesAtPort(1)[0]->getDims();
if (zpDims[0] != 1 || zpDims[1] != IC)
auto zpDims = parent0->getParentEdgesAtPort(1)[0]->getShape().getDims();
if (zpDims[0] != 1 || !dimsEqualStrong(zpDims[1], IC))
return false;
for (int i = 2; i < zpDims.ndims(); i++) {
for (int i = 2; i < zpDims.size(); i++) {
if (zpDims[i] != 1)
return false;
}
@@ -485,7 +490,12 @@ void MKLDNNGraphOptimizer::FuseConvolutionAndZeroPoints(MKLDNNGraph &graph) {
if (zeroPointsData == nullptr)
IE_THROW() << "zeroPointsBlob has not allocated buffer";
for (int j = 0; j < parent0->getParentEdgesAtPort(1)[0]->getDims()[1]; j++) {
auto zeroPointDataSize = parent0->getParentEdgesAtPort(1)[0]->getShape().getDims()[1];
if (Shape::UNDEFINED_DIM == zeroPointDataSize) {
return false;
}
for (int j = 0; j < zeroPointDataSize; j++) {
convNode->inputZeroPoints.push_back(zeroPointsData[j]);
}
} else {
@@ -524,11 +534,13 @@ void MKLDNNGraphOptimizer::FuseConvolutionAndZeroPoints(MKLDNNGraph &graph) {
ptrdiff_t G = convNode->getGroupNum();
const int groupOffset = convNode->getAlgorithm() == ConvolutionGrouped ? 1 : 0;
ptrdiff_t OC = weightsConstant->outDims[0][0 + groupOffset];
ptrdiff_t IC = weightsConstant->outDims[0][1 + groupOffset];
ptrdiff_t KD = weightsConstant->outDims[0].ndims() == (5 + groupOffset) ? weightsConstant->outDims[0][weightsConstant->outDims[0].ndims() - 3] : 1;
ptrdiff_t KH = weightsConstant->outDims[0][weightsConstant->outDims[0].ndims() - 2];
ptrdiff_t KW = weightsConstant->outDims[0][weightsConstant->outDims[0].ndims() - 1];
auto& weightsConstantDims = weightsConstant->outputShapes[0].getStaticDims();
ptrdiff_t OC = weightsConstantDims[0 + groupOffset];
ptrdiff_t IC = weightsConstantDims[1 + groupOffset];
ptrdiff_t KD = weightsConstantDims.size() == (5 + groupOffset) ? weightsConstantDims[weightsConstantDims.size() - 3] : 1;
ptrdiff_t KH = weightsConstantDims[weightsConstantDims.size() - 2];
ptrdiff_t KW = weightsConstantDims[weightsConstantDims.size() - 1];
for (size_t g = 0; g < G; g++) {
for (size_t oc = 0; oc < OC; oc++) {
@@ -588,7 +600,7 @@ void MKLDNNGraphOptimizer::FuseFullyConnectedAndSimpleOperation(MKLDNNGraph &gra
auto& graphNodes = graph.GetNodes();
auto isSutableParentNode = [](MKLDNNNodePtr node) {
return node->getType() == FullyConnected && node->getChildEdges().size() == 1 && node->getParentEdgeAt(0)->getDims().ndims() != 3;
return node->getType() == FullyConnected && node->getChildEdges().size() == 1 && node->getParentEdgeAt(0)->getShape().getRank() != 3;
};
auto parent = graphNodes.begin();
@@ -653,12 +665,12 @@ void MKLDNNGraphOptimizer::FuseConvolutionAndDWConvolution(MKLDNNGraph &graph) {
const auto &strides = conv->getStride();
const auto &paddings = conv->getPaddingL();
const auto &inDims = node->getParentEdgeAt(0)->getDims();
const auto &outDims = node->getChildEdgeAt(0)->getDims();
const auto &inDims = node->getParentEdgeAt(0)->getShape().getDims();
const auto &outDims = node->getChildEdgeAt(0)->getShape().getDims();
bool isSupportedParams = conv->getGroupNum() == 1 &&
inDims.ndims() == 4 &&
inDims[inDims.ndims() - 1] == outDims[outDims.ndims() - 1] &&
inDims[inDims.ndims() - 2] == outDims[outDims.ndims() - 2] &&
inDims.size() == 4 &&
dimsEqualStrong(inDims[inDims.size() - 1], outDims[outDims.size() - 1]) &&
dimsEqualStrong(inDims[inDims.size() - 2], outDims[outDims.size() - 2]) &&
is1x1Convolution(conv) && // TODO [oneDNN] : fusing is permitted only with 1x1 convolutions
everyone_is(1, strides[strides.size() - 1], strides[strides.size() - 2]) &&
everyone_is(0, paddings[paddings.size() - 1], paddings[paddings.size() - 2]) &&
@@ -702,8 +714,8 @@ void MKLDNNGraphOptimizer::FuseConvolutionAndDWConvolution(MKLDNNGraph &graph) {
const auto weightRank = convChild->getWeightDims().size();
const auto stridesSize = convChild->getStride().size();
bool isSupportedParams = convChild->outDims[0][1] == convChild->getGroupNum() &&
convChild->outDims[0][1] != 1 &&
bool isSupportedParams = dimsEqualStrong(convChild->outputShapes[0].getDims()[1], convChild->getGroupNum()) &&
convChild->outputShapes[0].getDims()[1] != 1 &&
everyone_is(3, convChild->getWeightDims()[weightRank - 1], convChild->getWeightDims()[weightRank - 2]) &&
everyone_is(1, convChild->getPaddingL()[stridesSize - 1], convChild->getPaddingL()[stridesSize - 2]) &&
everyone_is(1, convChild->getPaddingR()[stridesSize - 1], convChild->getPaddingR()[stridesSize - 2]) &&
@@ -711,14 +723,18 @@ void MKLDNNGraphOptimizer::FuseConvolutionAndDWConvolution(MKLDNNGraph &graph) {
convChild->getStride()[stridesSize - 1] == convChild->getStride()[stridesSize - 2] &&
withBias &&
one_of(convChild->getStride()[stridesSize - 1], 1, 2) &&
childNode->getChildEdgeAt(0)->getDims().ndims() == 4;
childNode->getChildEdgeAt(0)->getShape().getRank() == 4;
return isSupportedParams;
};
auto isFusingWorthwhile = [&](const MKLDNNNodePtr &parentNode, const MKLDNNNodePtr &childNode) {
auto inDims = childNode->inDims[0];
auto outDims = childNode->outDims[0];
if (!childNode->inputShapes[0].isStatic() || !childNode->outputShapes[0].isStatic()) {
return false;
}
auto inDims = childNode->inputShapes[0].getStaticDims();
auto outDims = childNode->outputShapes[0].getStaticDims();
int elemSize = childNode->getOriginalOutputPrecisionAtPort(0).size();
int L3_cache_size = utils::get_cache_size(3, false);
@@ -864,11 +880,7 @@ void MKLDNNGraphOptimizer::FusePoolingAndFakeQuantize(MKLDNNGraph &graph) {
};
auto isSutableChildNode = [](MKLDNNNodePtr node) {
bool ret = node->getType() == FakeQuantize && node->getAlgorithm() != Algorithm::FQBinarization;
for (size_t i = 1; i < node->getParentEdges().size(); i++) {
ret &= node->getParentEdgesAtPort(i)[0]->getParent()->getChildEdges().size() == 1;
}
return ret;
return node->getType() == FakeQuantize && node->getAlgorithm() != Algorithm::FQBinarization;
};
for (int i = 0; i < graphNodes.size(); i++) {
@@ -1080,9 +1092,9 @@ void MKLDNNGraphOptimizer::FuseConvolutionSumAndConvolutionSumActivation(MKLDNNG
if (mergedConv->fusedWith.size() > 0 &&
(mergedConv->fusedWith[0]->getType() == Convolution || mergedConv->fusedWith[0]->getType() == BinaryConvolution)) {
// Merged with DW_conv. Shape may change
mergedConv->inDims.push_back(mergedConv->fusedWith[0]->outDims[0]);
mergedConv->inputShapes.push_back(mergedConv->fusedWith[0]->outputShapes[0]);
} else {
mergedConv->inDims.push_back(mergedConv->outDims[0]);
mergedConv->inputShapes.push_back(mergedConv->outputShapes[0]);
}
size_t childIdx = 0lu;
@@ -1356,7 +1368,7 @@ void MKLDNNGraphOptimizer::FuseEltwiseAndSimple(MKLDNNGraph &graph) {
graphEdges.push_back(newEdge);
parent->addEdge(newEdge);
parent->outDims[inNum] = child->inDims[outNum];
parent->outputShapes[inNum] = child->inputShapes[outNum];
}
} else {
MKLDNNEdgePtr &remEdge = p_edge;
@@ -1377,7 +1389,7 @@ void MKLDNNGraphOptimizer::FuseEltwiseAndSimple(MKLDNNGraph &graph) {
graphEdges.push_back(newEdge);
parent->addEdge(newEdge);
parentNode->inDims.push_back(parent->outDims[0]);
parentNode->inputShapes.push_back(parent->outputShapes[0]);
}
}
@@ -1404,16 +1416,6 @@ void MKLDNNGraphOptimizer::DropDoubleReorders(MKLDNNGraph &graph) {
if (nn == nullptr)
IE_THROW() << "Cannot get reorder layer " << nextNode->getName();
auto scales = n->_scales;
if (n->_scales != nullptr && nn->_scales != nullptr) {
IE_THROW() << "Merging scales of two subsequent reorders is unsupported yet";
} else {
if (scales == nullptr) {
scales = nn->_scales;
}
}
MKLDNNNodePtr p = n->getParentEdgeAt(0)->getParent();
MKLDNNNodePtr c = nn->getChildEdgeAt(0)->getChild();
@@ -1434,7 +1436,7 @@ void MKLDNNGraphOptimizer::DropDoubleReorders(MKLDNNGraph &graph) {
std::string layerName = edge->getParent()->getName() + "_ScaleReorder_" + edge->getChild()->getName();
graph.InsertReorder(edge, layerName, n->getInput(), nn->getOutput(), false, scales);
graph.InsertReorder(edge, layerName, n->getInput(), nn->getOutput(), false);
graph.GetEdges().erase(std::remove(graph.GetEdges().begin(), graph.GetEdges().end(), edge), graph.GetEdges().end());
}
}
@@ -1444,21 +1446,16 @@ void MKLDNNGraphOptimizer::FuseBroadcastAndEltwise(MKLDNNGraph &graph) {
std::vector<MKLDNNNodePtr>& graphNodes = graph.GetNodes();
for (auto &graphNode : graphNodes) {
if (graphNode->getType() != Broadcast
if (graphNode->getType() != Generic
|| graphNode->getTypeStr() != "Broadcast"
|| graphNode->getChildEdges().size() != 1lu
|| graphNode->getChildEdgeAt(0)->getChild()->getType() != Eltwise)
continue;
bool ret = true;
for (size_t i = 1; i < graphNode->getParentEdges().size(); i++) {
ret &= graphNode->getParentEdgesAtPort(i)[0]->getParent()->getChildEdges().size() == 1;
}
if (!ret) continue;
MKLDNNNodePtr& broadcastNode = graphNode;
MKLDNNNodePtr eltwiseNode = broadcastNode->getChildEdgeAt(0)->getChild();
eltwiseNode->inDims[broadcastNode->getChildEdgeAt(0)->getOutputNum()]
= broadcastNode->getParentEdgeAt(0)->getDims();
eltwiseNode->inputShapes[broadcastNode->getChildEdgeAt(0)->getOutputNum()]
= broadcastNode->getParentEdgeAt(0)->getShape();
auto& edges = graph.GetEdges();
for (size_t i = 1lu; i < broadcastNode->getParentEdges().size(); i++) {
@@ -1682,9 +1679,14 @@ void MKLDNNGraphOptimizer::MergeTransposeAndReorder(MKLDNNGraph &graph) {
}
auto& transposeOrder = transposeNode->getOrder();
auto& layoutOrder = transposeNode->getSelectedPrimitiveDescriptor()->getConfig().outConfs[0].desc.getBlockingDesc().getOrder();
auto& inOrder = reorderNode->getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc.getBlockingDesc().getOrder();
auto& outOrder = reorderNode->getSelectedPrimitiveDescriptor()->getConfig().outConfs[0].desc.getBlockingDesc().getOrder();
auto layoutOrder = MemoryDescUtils::convertToBlockedDescriptor(
*transposeNode->getSelectedPrimitiveDescriptor()->getConfig().outConfs[0].desc).getOrder();
auto inBlockedDesc = MemoryDescUtils::convertToBlockedDescriptor(*reorderNode->getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc);
auto outBlockedDesc = MemoryDescUtils::convertToBlockedDescriptor(*reorderNode->getSelectedPrimitiveDescriptor()->getConfig().outConfs[0].desc);
auto& inOrder = inBlockedDesc.getOrder();
auto& outOrder = outBlockedDesc.getOrder();
if (transposeOrder.size() != layoutOrder.size() || layoutOrder.size() != inOrder.size() || inOrder.size() != outOrder.size()) {
return false;
@@ -1760,18 +1762,18 @@ void MKLDNNGraphOptimizer::MergeTransposeAndReorder(MKLDNNGraph &graph) {
graph.DropNode(parentNode);
graph.DropNode(childNode);
auto inDesc = parentNode->getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc;
auto outDesc = childNode->getSelectedPrimitiveDescriptor()->getConfig().outConfs[0].desc;
auto& inDesc = parentNode->getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc;
auto& outDesc = childNode->getSelectedPrimitiveDescriptor()->getConfig().outConfs[0].desc;
auto inPrec = inDesc.getPrecision();
auto outPrec = outDesc.getPrecision();
auto inPrec = inDesc->getPrecision();
auto outPrec = outDesc->getPrecision();
auto reorderInDesc = TensorDesc(inDesc);
auto reorderOutDesc = TensorDesc(outDesc);
reorderOutDesc.setPrecision(inPrec);
auto reorderInDesc = inDesc->clone();
auto reorderOutDesc = outDesc->clone();
reorderOutDesc->setPrecision(inPrec);
std::string reorderlayerName = parentParentNode->getName() + "_" +
MKLDNNExtensionUtils::getReorderArgs(reorderInDesc, reorderOutDesc) + "_" + "fake";
MKLDNNReorderNode::getReorderArgs(*reorderInDesc, *reorderOutDesc) + "_" + "fake";
MKLDNNEdgePtr edge;
for (auto &childEdge : parentParentNode->getChildEdges()) {
@@ -1784,17 +1786,17 @@ void MKLDNNGraphOptimizer::MergeTransposeAndReorder(MKLDNNGraph &graph) {
IE_THROW() << "Transpose node '" << parentNode->getName() << "' has invalid edges.";
}
auto reorderNode = graph.InsertReorder(edge, reorderlayerName, reorderInDesc, reorderOutDesc, true);
auto reorderNode = graph.InsertReorder(edge, reorderlayerName, *reorderInDesc, *reorderOutDesc, true);
// case 2
if (inPrec != outPrec) {
auto reorderInDesc2 = TensorDesc(reorderOutDesc);
auto reorderOutDesc2 = TensorDesc(outDesc);
auto reorderInDesc2 = reorderOutDesc->clone();
auto reorderOutDesc2 = outDesc->clone();
std::string reorderLayerName2 = reorderNode->getName() + "_" +
MKLDNNExtensionUtils::getReorderArgs(reorderInDesc2, reorderOutDesc2) + "_" + childChildNode->getName();
MKLDNNReorderNode::getReorderArgs(*reorderInDesc2, *reorderOutDesc2) + "_" + childChildNode->getName();
graph.InsertReorder(reorderNode->getChildEdgeAt(0), reorderLayerName2, reorderInDesc2, reorderOutDesc2, false);
graph.InsertReorder(reorderNode->getChildEdgeAt(0), reorderLayerName2, *reorderInDesc2, *reorderOutDesc2, false);
}
};
@@ -440,6 +440,7 @@ void MKLDNNPlugin::MKLDNNInferRequest::changeDefaultPtr() {
auto& child = input->second->getChildEdgeAt(i)->getChild();
if (child->isConstant())
canBeInPlace = false;
auto* concat = dynamic_cast<MKLDNNConcatNode *>(child.get());
if (canBeInPlace && concat && concat->isOptimized())
canBeInPlace = false;
@@ -2,23 +2,24 @@
// SPDX-License-Identifier: Apache-2.0
//
#include <limits>
#include <vector>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <unordered_set>
#include <utility>
#include "utils/general_utils.h"
#include <mkldnn_types.h>
#include <dnnl_types.h>
#include <common/memory_desc_wrapper.hpp>
#include "mkldnn_memory.h"
#include "mkldnn_extension_utils.h"
#include "nodes/common/cpu_memcpy.h"
#include "nodes/common/cpu_convert.h"
#include "mkldnn/ie_mkldnn.h"
#include "cpu_shape.h"
#include "cpu_memory_desc_utils.h"
#include "mkldnn_extension_utils.h"
using namespace InferenceEngine;
using namespace mkldnn;
@@ -54,7 +55,7 @@ void MKLDNNMemory::Create(const memory::dims& dims, memory::data_type data_type,
format = memory::format_tag::any;
}
memory::desc desc = MKLDNNMemoryDesc({dims}, data_type, format);
memory::desc desc = MKLDNNMemoryDesc(MKLDNNExtensionUtils::convertToSizeVector(dims), data_type, format);
Create(desc, data);
}
@@ -89,10 +90,16 @@ void MKLDNNMemory::Create(const mkldnn::memory::desc& desc, const void *data, bo
}
}
void MKLDNNMemory::Create(const MemoryDesc &desc, const void *data, bool pads_zeroing) {
pMemDesc = desc.clone();
Create(mkldnn::memory::desc(MemoryDescUtils::convertToMKLDNNMemoryDesc(desc)), data, pads_zeroing);
}
void MKLDNNMemory::reorderData(const MKLDNNMemory &input, const MKLDNNMemory &output, size_t size) {
if (size != 0)
IE_ASSERT(size <= output.GetDescriptor().get_size());
if (input.GetDesc() == output.GetDesc()) {
if (input.GetDescriptor() == output.GetDescriptor()) {
auto srcPtr = static_cast<uint8_t*>(input.GetPtr());
auto dstPtr = static_cast<uint8_t*>(output.GetPtr());
@@ -118,7 +125,7 @@ void MKLDNNMemory::reorderData(const MKLDNNMemory &input, const MKLDNNMemory &ou
MKLDNNExtensionUtils::DataTypeToIEPrecision(output.GetDataType()), input.GetElementsCount());
MKLDNNMemory tmpMem(output.eng);
tmpMem.Create(input.GetDims(), output.GetDataType(), input.GetDesc().getFormat(), tmpBuff.data());
tmpMem.Create(input.GetDims(), output.GetDataType(), input.GetMKLDNNDesc().getFormat(), tmpBuff.data());
pReorder = std::unique_ptr<mkldnn::reorder>(new mkldnn::reorder(tmpMem.GetPrimitive(), output.GetPrimitive()));
srcMemoryPtr = tmpMem.prim;
@@ -189,8 +196,8 @@ void MKLDNNMemory::FillZero() {
memset(dataPtr, 0, GetSize());
}
memory::format_tag MKLDNNMemory::GetPlainFormat(const memory::dims& dims) {
switch (dims.size()) {
memory::format_tag MKLDNNMemory::GetPlainFormatByRank(size_t rank) {
switch (rank) {
case 0:
case 1:
return memory::format_tag::a;
@@ -222,11 +229,6 @@ InferenceEngine::Layout MKLDNNMemory::GetPlainLayout(const memory::dims& dims) {
}
}
bool MKLDNNMemory::isConsistant(const mkldnn::memory::dims& dims, mkldnn::memory::format_tag format) {
memory::desc attempt(dims, memory::data_type::f32, format, true);
return static_cast<bool>(attempt);
}
Precision MKLDNNMemory::convertToIePrec(memory::data_type dataType) {
return MKLDNNExtensionUtils::DataTypeToIEPrecision(dataType);
}
@@ -262,6 +264,42 @@ std::string MKLDNNMemory::formatToString(memory::format_tag fmt) {
return mkldnn::utils::fmt2str(fmt);
}
void *MKLDNNMemory::GetPtr() const {
auto ptr = static_cast<uint8_t*>(GetData());
auto md = GetDescriptor().data;
mkldnn::impl::memory_desc_wrapper wrapper(md);
ptr += wrapper.offset0() * wrapper.data_type_size();
return ptr;
}
template<>
MKLDNNMemoryDesc MKLDNNMemory::GetDescWithType<MKLDNNMemoryDesc, 0, 0>() const {
if (auto descPtr = dynamic_cast<const MKLDNNMemoryDesc*>(pMemDesc.get())) {
return *descPtr;
} else {
switch (pMemDesc->getType()) {
case (MemoryDescType::Blocked):
return MemoryDescUtils::convertToMKLDNNMemoryDesc(*(pMemDesc->as<BlockedMemoryDesc>()));
default:
IE_THROW() << "Can not convert unsupported memory descriptor";
}
}
}
template<>
BlockedMemoryDesc MKLDNNMemory::GetDescWithType<BlockedMemoryDesc, 0, 0>() const {
if (auto descPtr = dynamic_cast<const BlockedMemoryDesc*>(pMemDesc.get())) {
return *descPtr;
} else {
switch (pMemDesc->getType()) {
case (MemoryDescType::Mkldnn):
return MemoryDescUtils::convertToBlockedDescriptor(*(pMemDesc->as<MKLDNNMemoryDesc>()));
default:
IE_THROW() << "Can not convert unsupported memory descriptor";
}
}
}
bool MKLDNNMemoryDesc::operator==(const MKLDNNMemoryDesc &rhs) const {
return this->desc == rhs.desc;
}
@@ -274,51 +312,42 @@ MKLDNNMemoryDesc::operator mkldnn::memory::desc() const {
return desc;
}
MKLDNNMemoryDesc::MKLDNNMemoryDesc(const mkldnn::memory::dims& dims, mkldnn::memory::data_type dataType,
mkldnn::memory::format_tag format): desc(dims, dataType, mkldnn::memory::format_tag::any) {
MKLDNNMemoryDesc::MKLDNNMemoryDesc(const mkldnn::memory::desc& desc) :
MemoryDesc(Shape(MKLDNNExtensionUtils::convertToSizeVector(desc.dims())), Mkldnn), desc(desc) {
if (desc.data.format_kind == dnnl::impl::format_kind::any)
IE_THROW(Unexpected) << "Memory format any is prohibited!";
}
MKLDNNMemoryDesc::MKLDNNMemoryDesc(const std::vector<size_t>& _dims, mkldnn::memory::data_type dataType, mkldnn::memory::format_tag format)
: MemoryDesc(Shape(_dims), Mkldnn) {
if (format == memory::format_tag::any)
IE_THROW(Unexpected) << "Memory format any is prohibited!";
if (format != memory::format_tag::undef) {
if (format == memory::format_tag::x && dims.size() == 0) {
if (format == memory::format_tag::x && _dims.size() == 0) {
desc = mkldnn::memory::desc(mkldnn::memory::dims(1, 1), dataType, format);
} else {
desc = mkldnn::memory::desc(dims, dataType, format);
desc = mkldnn::memory::desc(MKLDNNExtensionUtils::convertToDnnlDims(_dims), dataType, format);
}
} else {
// Trying to create plain descriptor
// This WA is needed since memory::format_tag doesn't contain plain tag for tensors with rank > 6D
mkldnn::memory::dims strides(dims.size(), 1);
for (int d = dims.size() - 2; d >= 0; d--) {
strides[d] = strides[d + 1] * dims[d + 1];
mkldnn::memory::dims strides(_dims.size(), 1);
for (int d = _dims.size() - 2; d >= 0; d--) {
strides[d] = strides[d + 1] * _dims[d + 1];
}
desc = mkldnn::memory::desc(dims, dataType, strides);
desc = mkldnn::memory::desc(MKLDNNExtensionUtils::convertToDnnlDims(_dims), dataType, strides);
}
}
MKLDNNMemoryDesc::MKLDNNMemoryDesc(const mkldnn::memory::dims& dims, mkldnn::memory::data_type dataType) : desc() {
const auto ndims = dims.size();
MKLDNNMemoryDesc::MKLDNNMemoryDesc(const std::vector<size_t>& _dims, mkldnn::memory::data_type dataType)
: MemoryDesc(Shape(_dims), Mkldnn), desc() {
const auto ndims = _dims.size();
mkldnn::memory::dims plain_strides(ndims, 1);
for (size_t i = 1; i < ndims; i++) {
plain_strides[ndims - i -1] = plain_strides[ndims - i] * dims[ndims - i];
}
desc = {dims, dataType, plain_strides};
}
size_t MKLDNNMemoryDesc::GetElementSize() const {
const auto type = desc.data_type();
switch (type) {
case memory::data_type::f16 :
case memory::data_type::bf16 :
return 2;
case memory::data_type::f32 :
case memory::data_type::s32 :
return 4;
case memory::data_type::s8 :
case memory::data_type::u8 :
case memory::data_type::bin :
return 1;
default:
IE_THROW() << "Unknown data type";
plain_strides[ndims - i -1] = plain_strides[ndims - i] * _dims[ndims - i];
}
desc = {MKLDNNExtensionUtils::convertToDnnlDims(_dims), dataType, plain_strides};
}
static const std::map<int, std::vector<mkldnn::memory::format_tag>> form_tags_by_ndims {
@@ -677,32 +706,92 @@ bool MKLDNNMemoryDesc::isTailCFormat() const {
return is_tailc_strides;
}
bool MKLDNNMemoryDesc::blocksExtended() const {
for (int i = 0; i < desc.data.ndims; i++) {
if (desc.data.dims[i] != desc.data.padded_dims[i])
return true;
}
return false;
}
size_t MKLDNNMemoryDesc::getMemSizeImp() const {
return desc.get_size();
}
size_t MKLDNNMemoryDesc::getElementOffset(size_t elemNumber) const {
mkldnn::impl::memory_desc_wrapper wrapped(desc.data);
return wrapped.off_l(elemNumber);
}
bool MKLDNNMemoryDesc::isCompatible(const MemoryDesc &rhs) const {
if (MemoryDescType::Blocked == rhs.getType()) {
return isCompatible(*(rhs.as<BlockedMemoryDesc>()));
} else if (MemoryDescType::Mkldnn == rhs.getType()) {
return isCompatible(*(rhs.as<MKLDNNMemoryDesc>()));
} else {
return false;
}
}
bool MKLDNNMemoryDesc::isCompatible(const MKLDNNMemoryDesc &rhs) const {
using namespace dnnl;
using namespace impl;
using namespace dnnl::impl::utils;
if (this->desc == rhs.desc) {
return true;
}
mkldnn::impl::memory_desc_wrapper wrappedThis(this->desc.data);
mkldnn::impl::memory_desc_wrapper wrappedRhs(rhs.desc.data);
if (one_of(wrappedThis.format_kind(), format_kind::undef, format_kind::any))
return false;
if (wrappedThis.is_wino_desc() || wrappedThis.is_rnn_packed_desc()) return false;
const auto &blk = wrappedThis.blocking_desc();
const auto &r_blk = wrappedRhs.blocking_desc();
int stride_start = wrappedThis.ndims() >0 && wrappedThis.dims()[0] == 1 ? 1 : 0; //ignore batch axis stride if batch size == 1
// Here is a slightly modified version of mkldnn::impl::memory_desc_wrapper::similar_to() call able to skip specific strides check.
return wrappedThis.ndims() == wrappedRhs.ndims()
&& wrappedThis.format_kind() == wrappedRhs.format_kind()
&& wrappedThis.data_type() == wrappedRhs.data_type()
&& array_cmp(wrappedThis.dims(), wrappedRhs.dims(), wrappedThis.ndims())
&& array_cmp(blk.strides + stride_start, r_blk.strides + stride_start, wrappedThis.ndims() - stride_start)
&& blk.inner_nblks == r_blk.inner_nblks
&& array_cmp(blk.inner_blks, r_blk.inner_blks, blk.inner_nblks)
&& array_cmp(blk.inner_idxs, r_blk.inner_idxs, blk.inner_nblks)
&& array_cmp(wrappedThis.padded_dims(), wrappedRhs.padded_dims(), wrappedRhs.ndims())
&& array_cmp(wrappedThis.padded_offsets(), wrappedRhs.padded_offsets(), wrappedThis.ndims())
&& dimsEqualWeak(wrappedThis.offset0(), wrappedRhs.offset0());
}
/**
* Convert to IE::TensorDesc
* Check compatibility with BlockedMemoryDesc
*
* mkl: IOhw_4i16o4i dims {32, 64, 128, 128}
* strides // the order of outer dims is encoded here
* inner_blks 4 16 4
* inner_idxs 1 0 1
*
* IE tensor desc has more expressive ability. Any oneDNN blocked tensor can be covreted.
* How to convert into IE representation:
* BlockedMemoryDesc desc has more expressive ability.
* How to check compatibility with BlockedMemoryDesc representation:
* 0. Detect a new_outer_order of outer_dims via descending strides.
* 1. IE strides : concatenate strides in new_outer_order and inner strides.
* 2. IE dims : concatenate outer dims in new_outer_order with auto padding and inner blocks
* 3. IE order : concatenate new_outer_order and inner_idxs
* 1. BlockedMemoryDesc strides : concatenate strides in new_outer_order and inner strides.
* 2. BlockedMemoryDesc dims : concatenate outer dims in new_outer_order with auto padding and inner blocks
* 3. BlockedMemoryDesc order : concatenate new_outer_order and inner_idxs
*/
MKLDNNMemoryDesc::operator InferenceEngine::TensorDesc() const {
bool MKLDNNMemoryDesc::isCompatible(const BlockedMemoryDesc &rhs) const {
if (this->getShape() != rhs.getShape() || this->getPrecision() != rhs.getPrecision()) {
return false;
}
const auto dims = desc.dims();
if (desc.data.format_kind == dnnl_format_kind_any)
return TensorDesc {
MKLDNNMemory::convertToIePrec(desc.data_type()),
SizeVector {begin(dims), end(dims)},
Layout::ANY};
if (desc.data.format_kind != dnnl_blocked)
IE_THROW() << "Conversion is not possible";
if (desc.data.format_kind != dnnl_blocked) {
return false;
}
const auto &blk_desc = desc.data.format_desc.blocking;
@@ -731,174 +820,99 @@ MKLDNNMemoryDesc::operator InferenceEngine::TensorDesc() const {
std::iota(outer_order.begin(), outer_order.end(), 0);
std::sort(outer_order.begin(), outer_order.end(),
[&blk_desc, &outer_block_dims] (size_t ind_l, size_t ind_r) {
return (blk_desc.strides[ind_l] > blk_desc.strides[ind_r]) ||
(blk_desc.strides[ind_l] == blk_desc.strides[ind_r] && outer_block_dims[ind_l] > outer_block_dims[ind_r]);
});
return (blk_desc.strides[ind_l] > blk_desc.strides[ind_r]) ||
(blk_desc.strides[ind_l] == blk_desc.strides[ind_r] && outer_block_dims[ind_l] > outer_block_dims[ind_r]);
});
// IE blocked order
// blocked order
// [new_outer_order] U [inner_idxs]
SizeVector ie_blk_order(total_ndims, 0);
std::copy(outer_order.begin(), outer_order.end(), ie_blk_order.begin());
std::copy(blk_desc.inner_idxs, blk_desc.inner_idxs + blk_desc.inner_nblks, ie_blk_order.begin() + dims.size());
SizeVector blk_order(total_ndims, 0);
std::copy(outer_order.begin(), outer_order.end(), blk_order.begin());
std::copy(blk_desc.inner_idxs, blk_desc.inner_idxs + blk_desc.inner_nblks, blk_order.begin() + dims.size());
// IE blocked strides
// [outer_strides via new_outer_order] U [inner_strides]
SizeVector ie_blk_strides(total_ndims, 0);
std::copy(inner_strides.rbegin(), inner_strides.rend(), ie_blk_strides.rbegin());
std::transform(outer_order.begin(), outer_order.end(), ie_blk_strides.begin(),
[&] (size_t i) { return blk_desc.strides[i]; });
if (!dimsEqualWeak(blk_order, rhs.getOrder())) {
return false;
}
// IE blocked dims
//TODO [DS]: undefined offset is also used now as an indicator of undefined strides
if (desc.data.offset0 != Shape::UNDEFINED_DIM) {
// blocked strides
// [outer_strides via new_outer_order] U [inner_strides]
SizeVector blk_strides(total_ndims, 0);
std::copy(inner_strides.rbegin(), inner_strides.rend(), blk_strides.rbegin());
std::transform(outer_order.begin(), outer_order.end(), blk_strides.begin(),
[&](size_t i) { return blk_desc.strides[i]; });
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(blk_strides, rhs.getStrides(), skipAxis)) {
return false;
}
}
// blocked dims
// [dims via new_outer_order with auto pad] U [inner_blk_dims]
SizeVector ie_blk_dims(total_ndims, 0);
SizeVector blk_dims(total_ndims, 0);
std::copy(blk_desc.inner_blks, blk_desc.inner_blks + blk_desc.inner_nblks,
ie_blk_dims.end() - blk_desc.inner_nblks);
std::transform(outer_order.begin(), outer_order.end(), ie_blk_dims.begin(),
blk_dims.end() - blk_desc.inner_nblks);
std::transform(outer_order.begin(), outer_order.end(), blk_dims.begin(),
[&] (size_t i) { return outer_block_dims[i]; });
// IE offset padded to data. Same as for oneDNN
SizeVector ie_blk_offset_to_data {desc.data.padded_offsets, desc.data.padded_offsets + desc.data.ndims};
size_t ie_blk_offset0 = desc.data.offset0;
if (!dimsEqualWeak(blk_dims, rhs.getBlockDims())) {
return false;
}
// TODO: The tensor desc implementation allow to specify offset_to_data for inner blocked dims.
// offset padded to data. Same as for oneDNN
SizeVector blk_offset_to_data {desc.data.padded_offsets, desc.data.padded_offsets + desc.data.ndims};
// TODO: The BlockedMemoryDesc implementation allow to specify offset_to_data for inner blocked dims.
// Which is not obvious behavior. It required offset_to_data.size == total_ndims, so will
// fill it with zero.
ie_blk_offset_to_data.insert(ie_blk_offset_to_data.end(), inner_ndims, 0);
blk_offset_to_data.insert(blk_offset_to_data.end(), inner_ndims, 0);
if (!dimsEqualWeak(blk_offset_to_data, rhs.getOffsetPaddingToData())) {
return false;
}
BlockingDesc ie_blk_desc { ie_blk_dims,
ie_blk_order,
ie_blk_offset0,
ie_blk_offset_to_data,
ie_blk_strides };
TensorDesc res {
MKLDNNMemory::convertToIePrec(desc.data_type()),
SizeVector {begin(dims), end(dims)},
ie_blk_desc };
// TODO: BLOCKED is the most common layout which covers all other permute layout like NHWC.
// But for some cases we have to specify it more correctly.. may be.. or just keep
// auto detected layout in constructor of TensorDesc.
return res;
return dimsEqualWeak(desc.data.offset0, rhs.getOffsetPadding());
}
/**
* Construct from IE::TensorDesc
* @param tDesc
*
* IE IOhw_4i16o4i dims(N) = {32, 64, 128, 128}
* blockedDims {4, 2, 128, 128, 4, 16, 4} // total dims(inner, outermost, auto blocked/padded). Generally sorted by strides.
* strides {8388608, 4194304, 32768, 256, 64, 4, 1} // strides for blockedDims, growing sequence
* order {1, 0, 2, 3, 1, 0, 1} // matching to original dims
*
* All vectors blockedDims/strides/order have same size equals total num of internal blocked dims(inner_dims + outer_dims)
*
* Tensor descriptor filing is not deterministic. It allows any permutation of index which keeps order of
* real dims spliting.
* for {1, 0, 2, 3, 1, 0, 1} we can swap elements [1] <=> [4]
* but not [0]<=>[4] because it breacke spliting original dims into internal blocked dims
* Normalization of representation: Make strides growing but keep layout same as original. Not all
* layout allow us to meet normalize form of tensor desc.
*
* Limitation of conversion first N elements of order should be permutation of [0,1,2 ... N]
*/
MKLDNNMemoryDesc::MKLDNNMemoryDesc(const TensorDesc& tDesc):
desc({}, mkldnn::memory::data_type::undef, mkldnn::memory::format_tag::undef) {
auto dims = tDesc.getDims();
// TODO: implicit conversion of dims is no good...
if (tDesc.getLayout() == Layout::SCALAR) {
desc.data.format_kind = dnnl_blocked;
desc.data.data_type = memory::convert_to_c(MKLDNNMemory::convertToDataType(tDesc.getPrecision()));
desc.data.ndims = 1;
desc.data.dims[0] = 1;
desc.data.padded_dims[0] = 1;
desc.data.format_desc.blocking.strides[0] = 1;
desc.data.padded_offsets[0] = 0;
desc.data.offset0 = tDesc.getBlockingDesc().getOffsetPadding();
return;
}
if (tDesc.getLayout() == Layout::ANY) {
desc.data.format_kind = dnnl_format_kind_any;
desc.data.data_type = memory::convert_to_c(MKLDNNMemory::convertToDataType(tDesc.getPrecision()));
desc.data.ndims = dims.size();
std::copy(dims.begin(), dims.end(), desc.data.dims);
std::copy(dims.begin(), dims.end(), desc.data.padded_dims);
desc.data.offset0 = tDesc.getBlockingDesc().getOffsetPadding();
std::fill(desc.data.padded_offsets, desc.data.padded_offsets + dims.size(), 0);
return;
}
auto ie_blkdDims = tDesc.getBlockingDesc().getBlockDims();
auto ie_order = tDesc.getBlockingDesc().getOrder();
auto ie_offsetsToData = tDesc.getBlockingDesc().getOffsetPaddingToData();
auto ie_strides = tDesc.getBlockingDesc().getStrides();
size_t outer_ndims = dims.size();
size_t inner_ndims = ie_order.size() - dims.size();
bool is_descending_strides = true;
for (int i = 1; i < ie_strides.size(); i++) {
is_descending_strides &= (ie_strides[i-1] >= ie_strides[i]);
}
// TODO: That's strong constrains and can be mitigated. IE::TensorDesc allow to transpose blocked dims
// and may be we can achieve correct "descending strides" form which allow conversion.
if (!is_descending_strides)
IE_THROW() << "Unsupported case for conversion";
std::vector<size_t> outer_order(outer_ndims, outer_ndims + 1); // outer_order[i] is index of stride for i-th dimension
for (size_t i = 0; i < outer_ndims; i++) {
outer_order[ie_order[i]] = i;
}
bool outer_is_correct_permutation_of_n =
std::find(outer_order.begin(), outer_order.end(), outer_ndims + 1) == outer_order.end();
if (!outer_is_correct_permutation_of_n)
IE_THROW() << "Unsupported case for conversion";
bool inner_block_are_dense = one_of(ie_strides.back(), 0, 1); // stride 1 - is dense case, 0 - broad casted
for (int i = outer_ndims; i < ie_strides.size() - 1; i++) {
inner_block_are_dense &= (ie_strides[i] == ie_strides[i+1] * ie_blkdDims[i+1]);
}
if (!inner_block_are_dense)
IE_THROW() << "Unsupported case for conversion";
bool inner_pad_offsets_is_zero = std::all_of(ie_offsetsToData.begin() + outer_ndims, ie_offsetsToData.end(),
[](size_t pad) { return pad == 0; });
if (!inner_pad_offsets_is_zero)
IE_THROW() << "Unsupported case for conversion";
// Fill general memory desc fields
desc.data.format_kind = dnnl_blocked;
desc.data.data_type = memory::convert_to_c(MKLDNNMemory::convertToDataType(tDesc.getPrecision()));
desc.data.ndims = dims.size();
desc.data.offset0 = tDesc.getBlockingDesc().getOffsetPadding();
std::copy(dims.begin(), dims.end(), desc.data.dims);
std::copy(ie_offsetsToData.begin(), ie_offsetsToData.begin() + outer_ndims, desc.data.padded_offsets);
std::fill(desc.data.padded_dims, desc.data.padded_dims + outer_ndims, 1);
for (size_t i = 0; i < ie_order.size(); i++) {
auto idx = ie_order[i];
desc.data.padded_dims[idx] *= ie_blkdDims[i];
}
// Fill blocking desc
auto &dnn_blk_desc = desc.data.format_desc.blocking;
dnn_blk_desc.inner_nblks = inner_ndims;
std::copy(ie_blkdDims.end() - inner_ndims, ie_blkdDims.end(), dnn_blk_desc.inner_blks);
std::copy(ie_order.end() - inner_ndims, ie_order.end(), dnn_blk_desc.inner_idxs);
for (size_t i = 0; i < outer_ndims; i++) {
dnn_blk_desc.strides[i] = ie_strides[outer_order[i]];
bool MKLDNNMemoryDesc::hasLayoutType(LayoutType layoutType) const {
switch (layoutType) {
case LayoutType::ncsp:
return isPlainFormat();
case LayoutType::nspc:
return isTailCFormat();
case LayoutType::nCsp8c:
return isBlockedCFormat(8);
case LayoutType::nCsp16c:
return isBlockedCFormat(16);
default:
return false;
}
}
bool MKLDNNMemoryDesc::blocksExtended() const {
for (int i = 0; i < desc.data.ndims; i++) {
if (desc.data.dims[i] != desc.data.padded_dims[i])
return true;
std::string MKLDNNMemoryDesc::serializeFormat() const {
if (desc.data.format_kind == dnnl_format_kind_wino) {
switch (desc.data.format_desc.wino_desc.wino_format) {
case dnnl_wino_memory_format_t::dnnl_wino_wei_aaOIoi: return "wino_aaOIoi";
case dnnl_wino_memory_format_t::dnnl_wino_wei_aaOio: return "wino_aaOio";
case dnnl_wino_memory_format_t::dnnl_wino_wei_aaOBiOo: return "wino_aaOBiOo";
case dnnl_wino_memory_format_t::dnnl_wino_wei_OBaaIBOIio: return "wino_OBaaIBOIio";
default: return "wino_undef";
}
}
return false;
auto fmt = getFormat();
return mkldnn::utils::fmt2str(fmt);
}
bool MKLDNNMemoryDesc::isDefined() const {
return desc.data.offset0 != Shape::UNDEFINED_DIM;
}
InferenceEngine::Precision MKLDNNMemoryDesc::getPrecision() const {
return MKLDNNExtensionUtils::DataTypeToIEPrecision(desc.data_type());
}
void MKLDNNMemoryDesc::setPrecision(InferenceEngine::Precision prc) {
desc.data.data_type = static_cast<dnnl_data_type_t>(MKLDNNExtensionUtils::IEPrecisionToDataType(prc));
}
} // namespace MKLDNNPlugin
@@ -6,13 +6,18 @@
#include "ie_layouts.h"
#include "mkldnn_dims.h"
#include "cpu_memory_desc.h"
#include "mkldnn_extension_utils.h"
#include <mkldnn.hpp>
#include <mkldnn_types.h>
#include <cpu_shape.h>
#include <cpu_blocked_memory_desc.h>
#include <string>
#include <functional>
#include <memory>
#include <vector>
#include <ie_precision.hpp>
/**
* @file contains a concept classes to work with memory/tensor/blob abstractions on plugin level.
@@ -34,20 +39,15 @@ namespace MKLDNNPlugin {
* Represent internal plugin abstraction of tensor description
*
*/
class MKLDNNMemoryDesc {
class MKLDNNMemoryDesc : public MemoryDesc {
public:
/** Empty constructor - doesn't define any tensor representation */
MKLDNNMemoryDesc(): desc() {}
/** Construct a tensor desc with plain layout format (like ND C array) */
MKLDNNMemoryDesc(const mkldnn::memory::dims& dims, mkldnn::memory::data_type dataType);
MKLDNNMemoryDesc(const std::vector<size_t>& _dims, mkldnn::memory::data_type dataType);
/** Construct a tensor desc with specified layout format tag. Any and Undef is not supported */
MKLDNNMemoryDesc(const mkldnn::memory::dims& dims, mkldnn::memory::data_type dataType, mkldnn::memory::format_tag format);
explicit MKLDNNMemoryDesc(const InferenceEngine::TensorDesc& tDesc);
explicit MKLDNNMemoryDesc(const mkldnn::memory::desc& desc): desc(desc) {}
MKLDNNMemoryDesc(const std::vector<size_t>& _dims, mkldnn::memory::data_type dataType, mkldnn::memory::format_tag format);
explicit MKLDNNMemoryDesc(const mkldnn::memory::desc& desc);
/**
* Try to define original format tag use on creation
@@ -60,8 +60,6 @@ public:
return static_cast<mkldnn::memory::data_type>(desc.data.data_type);
}
size_t GetElementSize() const;
MKLDNNDims getDims() const {
return MKLDNNDims(desc.data.dims, desc.data.ndims);
}
@@ -75,15 +73,38 @@ public:
bool operator != (const MKLDNNMemoryDesc& rhs) const;
operator mkldnn::memory::desc() const;
operator InferenceEngine::TensorDesc() const;
bool isSame(mkldnn::memory::format_tag fmt) const;
dnnl_format_kind_t getFormatKind() const {
return desc.data.format_kind;
}
std::unique_ptr<MemoryDesc> clone() const override {
return MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(*this);
}
bool hasLayoutType(LayoutType layoutType) const override;
std::string serializeFormat() const override;
bool isDefined() const override;
InferenceEngine::Precision getPrecision() const override;
void setPrecision(InferenceEngine::Precision prc) override;
bool isCompatible(const MemoryDesc& rhs) const override;
bool isCompatible(const BlockedMemoryDesc& rhs) const;
bool isCompatible(const MKLDNNMemoryDesc& rhs) const;
private:
size_t getElementOffset(size_t elemNumber) const override;
size_t getMemSizeImp() const override;
bool isPlainFormat() const;
bool isBlockedCFormat(size_t blk_size = UNREACHABLE_DIM) const;
bool isTailCFormat() const;
bool isSame(mkldnn::memory::format_tag fmt) const;
private:
static constexpr size_t UNREACHABLE_DIM = std::numeric_limits<size_t>::max();
mkldnn::memory::desc desc;
@@ -94,6 +115,12 @@ class MKLDNNMemory {
public:
explicit MKLDNNMemory(const mkldnn::engine& eng);
MKLDNNMemory(const MKLDNNMemory&) = delete;
MKLDNNMemory& operator= (const MKLDNNMemory&) = delete;
MKLDNNMemory(MKLDNNMemory&&) = default;
MKLDNNMemory& operator= (MKLDNNMemory&&) = default;
const mkldnn::memory& GetPrimitive() const {
return *prim;
}
@@ -106,10 +133,15 @@ public:
return prim->get_desc();
}
const MKLDNNMemoryDesc GetDesc() const {
return MKLDNNMemoryDesc {prim->get_desc()};
const MemoryDesc& GetDesc() const {
return *pMemDesc;
}
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>
T GetDescWithType() const;
/**
* Return handler of buffer. Real data may starts from some other offset
* @return
@@ -126,12 +158,7 @@ public:
* Like a GetData() but offset is applied.
* @return
*/
void* GetPtr() const {
auto ptr = static_cast<uint8_t*>(GetData());
ptr += GetDescriptor().data.offset0 * GetDesc().GetElementSize();
return ptr;
}
void* GetPtr() const;
mkldnn::memory::data_type GetDataType() const {
return static_cast<mkldnn::memory::data_type>(GetDescriptor().data.data_type);
@@ -145,19 +172,15 @@ public:
return {std::begin(data.dims), std::begin(data.dims) + data.ndims};
}
void Create(const mkldnn::memory::dims& dims, mkldnn::memory::data_type data_type, mkldnn::memory::format_tag format,
const void* data = nullptr);
void Create(const mkldnn::memory::desc& desc, const void* data = nullptr, bool pads_zeroing = true);
void Create(const MemoryDesc& desc, const void* data = nullptr, bool pads_zeroing = true);
// Like a plain format
void SetData(mkldnn::memory::data_type dataType, mkldnn::memory::format_tag format, const void* data, size_t size, bool ftz = true) const;
void SetData(const MKLDNNMemory& memory, size_t size = 0, bool ftz = true) const;
void FillZero();
static mkldnn::memory::format_tag GetPlainFormat(const mkldnn::memory::dims& dims);
static mkldnn::memory::format_tag GetPlainFormatByRank(size_t rank);
static InferenceEngine::Layout GetPlainLayout(const mkldnn::memory::dims& dims);
static bool isConsistant(const mkldnn::memory::dims& dims, mkldnn::memory::format_tag format);
static mkldnn::memory::format_tag Convert(const InferenceEngine::Layout layout);
static InferenceEngine::Precision convertToIePrec(mkldnn::memory::data_type dataType);
static mkldnn::memory::data_type convertToDataType(const InferenceEngine::Precision &precision);
@@ -167,6 +190,17 @@ public:
static void reorderData(const MKLDNNMemory& input, const MKLDNNMemory& output, size_t size = 0);
private:
void Create(const mkldnn::memory::dims& dims, mkldnn::memory::data_type data_type, mkldnn::memory::format_tag format,
const void* data = nullptr);
void Create(const mkldnn::memory::desc& desc, const void* data = nullptr, bool pads_zeroing = true);
const MKLDNNMemoryDesc GetMKLDNNDesc() const {
return MKLDNNMemoryDesc(prim->get_desc());
}
private:
MemoryDescPtr pMemDesc;
std::shared_ptr<mkldnn::memory> prim;
mkldnn::engine eng;
};
@@ -8,6 +8,7 @@
#include "blob_factory.hpp"
#include "mkldnn_memory.h"
#include "nodes/common/cpu_memcpy.h"
#include "cpu_memory_desc_utils.h"
#include <string>
@@ -17,7 +18,7 @@ class MKLDNNVariableState : public InferenceEngine::IVariableStateInternal {
public:
MKLDNNVariableState(std::string name, MKLDNNMemoryPtr storage) :
InferenceEngine::IVariableStateInternal{name} {
state = make_blob_with_precision(MKLDNNMemoryDesc(storage->GetDescriptor()));
state = make_blob_with_precision(MemoryDescUtils::convertToTensorDesc(storage->GetDesc()));
state->allocate();
cpu_memcpy(state->buffer(), storage->GetData(), storage->GetSize());
}
+109 -189
View File
@@ -55,6 +55,7 @@
#include "utils/general_utils.h"
#include "utils/cpu_utils.hpp"
#include "nodes/common/cpu_convert.h"
#include "cpu_memory_desc_utils.h"
using namespace mkldnn;
using namespace MKLDNNPlugin;
@@ -252,20 +253,16 @@ MKLDNNNode::MKLDNNNode(const std::shared_ptr<ngraph::Node>& op, const mkldnn::en
type(TypeFromName(op->get_type_name())), profiling(op->get_friendly_name()) {
algorithm = Algorithm::Undefined;
fusingPort = -1;
const std::string errorPrefix = "Ngraph operation " + std::string(op->get_type_name()) + " with name " + op->get_friendly_name();
for (size_t i = 0; i < op->get_input_size(); i++) {
if (op->get_input_partial_shape(i).is_dynamic())
IE_THROW() << errorPrefix << " has dynamic input shape on " << i << " port, but CPU plug-in supports only static shape";
}
for (size_t i = 0; i < op->get_output_size(); i++) {
if (op->get_output_partial_shape(i).is_dynamic())
IE_THROW() << errorPrefix << " has dynamic output shape on " << i << " port, but CPU plug-in supports only static shape";
}
for (size_t i = 0; i < op->get_input_size(); i++) {
const auto &shape = op->get_input_shape(i);
inDims.emplace_back(ngraph::is_scalar(shape) ? ngraph::Shape{1} : shape);
const auto &shape = op->get_input_partial_shape(i);
bool isScalar = false;
if (shape.rank().is_static()) {
isScalar = shape.rank().get_length() == 0;
}
inputShapes.emplace_back(isScalar ? ngraph::PartialShape{1} : shape);
originalInputPrecisions.emplace_back(details::convertPrecision(op->get_input_element_type(i)));
}
@@ -274,8 +271,13 @@ MKLDNNNode::MKLDNNNode(const std::shared_ptr<ngraph::Node>& op, const mkldnn::en
IE_THROW() << "Node with type '" << typeStr << "' and name '" << name << "' does not have any outputs.";
}
for (size_t i = 0; i < op->get_output_size(); i++) {
const auto &shape = op->get_output_shape(i);
outDims.emplace_back(ngraph::is_scalar(shape) ? ngraph::Shape{1} : shape);
const auto &shape = op->get_output_partial_shape(i);
bool isScalar = false;
if (shape.rank().is_static()) {
isScalar = shape.rank().get_length() == 0;
}
outputShapes.emplace_back(isScalar ? ngraph::PartialShape{1} : shape);
originalOutputPrecisions.emplace_back(details::convertPrecision(op->get_output_element_type(i)));
}
}
@@ -422,9 +424,10 @@ void MKLDNNNode::selectPreferPrimitiveDescriptor(const std::vector<impl_desc_typ
if (inNum < 0 || inNum >= parent_spd->getConfig().outConfs.size()) {
inNum = 0;
}
if (MKLDNNExtensionUtils::initTensorsAreEqual(
getSupportedPrimitiveDescriptors()[i].getConfig().inConfs[j].desc,
parent_spd->getConfig().outConfs[inNum].desc)) {
auto& curDesc = getSupportedPrimitiveDescriptors()[i].getConfig().inConfs[j].desc;
auto& parentDesc = parent_spd->getConfig().outConfs[inNum].desc;
if (curDesc->isCompatible(*parentDesc)) {
equalsLocalFormatCount++;
}
}
@@ -459,9 +462,9 @@ bool MKLDNNNode::canBeInPlace() const {
return false;
}
MKLDNNDims dims = getParentEdgeAt(0)->getDims();
auto inShape = getParentEdgeAt(0)->getShape();
for (size_t cIdx = 0; cIdx < getChildEdges().size(); cIdx++) {
if (getChildEdgeAt(cIdx)->getDims() != dims) {
if (getChildEdgeAt(cIdx)->getShape() != inShape) {
return false;
}
}
@@ -469,7 +472,7 @@ bool MKLDNNNode::canBeInPlace() const {
}
void MKLDNNNode::resolveNotAllocatedEdges() {
const PrimitiveDescInfo *selected_pd = getSelectedPrimitiveDescriptor();
const NodeDesc *selected_pd = getSelectedPrimitiveDescriptor();
if (!selected_pd)
IE_THROW() << "Cannot find selected primitive descriptor for node: " << getName();
for (size_t i = 0; i < getParentEdges().size() && i < selected_pd->getConfig().inConfs.size(); i++) {
@@ -480,7 +483,7 @@ void MKLDNNNode::resolveNotAllocatedEdges() {
auto * memPtr = reinterpret_cast<char*>(parentEdge->getMemory().GetData());
parentEdge->getMemoryPtr().reset(new MKLDNNMemory(getEngine()));
parentEdge->getMemoryPtr()->Create(MKLDNNMemoryDesc(selected_pd->getConfig().inConfs[i].desc), memPtr);
parentEdge->getMemoryPtr()->Create(*selected_pd->getConfig().inConfs[i].desc, memPtr);
parentEdge->changeStatus(MKLDNNEdge::Status::Allocated);
}
@@ -492,7 +495,7 @@ void MKLDNNNode::resolveNotAllocatedEdges() {
auto * memPtr = reinterpret_cast<char*>(childEdge->getMemory().GetData());
childEdge->getMemoryPtr().reset(new MKLDNNMemory(getEngine()));
childEdge->getMemoryPtr()->Create(MKLDNNMemoryDesc(selected_pd->getConfig().outConfs[i].desc), memPtr);
childEdge->getMemoryPtr()->Create(*selected_pd->getConfig().outConfs[i].desc, memPtr);
childEdge->changeStatus(MKLDNNEdge::Status::Allocated);
}
@@ -547,14 +550,14 @@ std::string MKLDNNNode::getPrimitiveDescriptorType() {
// it is mixed precision.
if (selectedPrimitiveDesc) {
if (!selectedPrimitiveDesc->getConfig().inConfs.empty()) {
if (selectedPrimitiveDesc->getConfig().inConfs[0].desc.getPrecision() != InferenceEngine::Precision::U8) {
str_type += "_" + std::string(selectedPrimitiveDesc->getConfig().inConfs[0].desc.getPrecision().name());
if (selectedPrimitiveDesc->getConfig().inConfs[0].desc->getPrecision() != InferenceEngine::Precision::U8) {
str_type += "_" + std::string(selectedPrimitiveDesc->getConfig().inConfs[0].desc->getPrecision().name());
} else {
str_type += "_I8";
}
} else {
if (selectedPrimitiveDesc->getConfig().outConfs[0].desc.getPrecision() != InferenceEngine::Precision::U8) {
str_type += "_" + std::string(selectedPrimitiveDesc->getConfig().outConfs[0].desc.getPrecision().name());
if (selectedPrimitiveDesc->getConfig().outConfs[0].desc->getPrecision() != InferenceEngine::Precision::U8) {
str_type += "_" + std::string(selectedPrimitiveDesc->getConfig().outConfs[0].desc->getPrecision().name());
} else {
str_type += "_I8";
}
@@ -583,7 +586,7 @@ const MKLDNNEdgePtr MKLDNNNode::getChildEdgeAt(size_t idx) const {
}
const std::vector<MKLDNNEdgePtr> MKLDNNNode::getParentEdgesAtPort(size_t idx) const {
if (idx >= inDims.size())
if (idx >= inputShapes.size())
IE_THROW() << "Node " << getName() << " contains less input ports than " << idx;
std::vector<MKLDNNEdgePtr> res;
@@ -597,7 +600,7 @@ const std::vector<MKLDNNEdgePtr> MKLDNNNode::getParentEdgesAtPort(size_t idx) co
}
const std::vector<MKLDNNEdgePtr> MKLDNNNode::getChildEdgesAtPort(size_t idx) const {
if (idx >= outDims.size())
if (idx >= outputShapes.size())
IE_THROW() << "Node " << getName() << " contains less output ports than " << idx;
std::vector<MKLDNNEdgePtr> res;
@@ -611,18 +614,18 @@ const std::vector<MKLDNNEdgePtr> MKLDNNNode::getChildEdgesAtPort(size_t idx) con
}
std::vector<memory::format_tag> MKLDNNNode::getAvailableFormatsForDims(const MKLDNNDims &dims) const {
if (dims.ndims() == 0)
std::vector<memory::format_tag> MKLDNNNode::getAvailableFormatsForDims(const Shape &dims) const {
if (dims.getRank() == 0)
return {memory::format_tag::x};
else if (dims.ndims() == 1)
else if (dims.getRank() == 1)
return {memory::format_tag::x};
else if (dims.ndims() == 2)
else if (dims.getRank() == 2)
return {memory::format_tag::nc};
else if (dims.ndims() == 3)
else if (dims.getRank() == 3)
return {memory::format_tag::tnc, memory::format_tag::ntc};
else if (dims.ndims() == 4)
else if (dims.getRank() == 4)
return {memory::format_tag::nchw, memory::format_tag::nChw8c, memory::format_tag::nChw16c};
else if (dims.ndims() == 5)
else if (dims.getRank() == 5)
return {memory::format_tag::ncdhw, memory::format_tag::nCdhw8c, memory::format_tag::nCdhw16c};
return {memory::format_tag::any};
}
@@ -641,22 +644,22 @@ void MKLDNNNode::initSupportedPrimitiveDescriptors() {
auto itpd = desc.createPrimitiveDescriptorIterator(engine);
while (static_cast<bool>(itpd)) {
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = true;
for (size_t i = 0; i < descInputNumbers(desc); i++) {
InferenceEngine::DataConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = MKLDNNExtensionUtils::getUninitTensorDesc(getSrcMemDesc(itpd, i));
config.inConfs.push_back(dataConfig);
PortConfig portConfig;
portConfig.inPlace = -1;
portConfig.constant = false;
portConfig.desc = MemoryDescUtils::applyUndefinedOffset(*getSrcMemDesc(itpd, i));
config.inConfs.push_back(portConfig);
}
for (size_t i = 0; i < descOutputNumbers(desc); i++) {
InferenceEngine::DataConfig dataConfig;
dataConfig.inPlace = canBeInPlace() ? 0 : -1;
dataConfig.constant = false;
dataConfig.desc = MKLDNNExtensionUtils::getUninitTensorDesc(getDstMemDesc(itpd, i));
config.outConfs.push_back(dataConfig);
PortConfig portConfig;
portConfig.inPlace = canBeInPlace() ? 0 : -1;
portConfig.constant = false;
portConfig.desc = MemoryDescUtils::applyUndefinedOffset(*getDstMemDesc(itpd, i));
config.outConfs.push_back(portConfig);
}
impl_desc_type impl_type = parse_impl_name(itpd.impl_info_str());
@@ -669,15 +672,12 @@ void MKLDNNNode::initSupportedPrimitiveDescriptors() {
void MKLDNNNode::filterSupportedPrimitiveDescriptors() {
// Compare by partial layout descriptor (without particular strides values)
auto areCompatible = [](const TensorDesc& tdesc, mkldnn::memory::format_tag fmt) {
TensorDesc fmt_tdesc = MKLDNNMemoryDesc{
MKLDNNDims(tdesc.getDims()),
MKLDNNExtensionUtils::IEPrecisionToDataType(tdesc.getPrecision()),
fmt};
auto areCompatible = [](const MemoryDesc& desc, mkldnn::memory::format_tag fmt) -> bool {
MKLDNNMemoryDesc fmt_tdesc = MKLDNNMemoryDesc{desc.getShape().getStaticDims(),
MKLDNNExtensionUtils::IEPrecisionToDataType(desc.getPrecision()),
fmt};
auto tmp_partial_tdesc = PartialBlkDesc::extractFrom(fmt_tdesc);
auto actual_partial_tdesc = PartialBlkDesc::extractFrom(tdesc);
return tmp_partial_tdesc == actual_partial_tdesc;
return desc.isCompatible(fmt_tdesc);
};
if (!inputMemoryFormatsFilter.empty() || !outputMemoryFormatsFilter.empty()) {
@@ -689,11 +689,11 @@ void MKLDNNNode::filterSupportedPrimitiveDescriptors() {
bool isSuitableDesc = true;
for (int i = 0; i < inputMemoryFormatsFilter.size(); i++) {
const bool matched = areCompatible(config.inConfs[i].desc, inputMemoryFormatsFilter[i]);
const bool matched = areCompatible(*config.inConfs[i].desc, inputMemoryFormatsFilter[i]);
isSuitableDesc &= matched;
}
for (int i = 0; i < outputMemoryFormatsFilter.size(); i++) {
const bool matched = areCompatible(config.outConfs[i].desc, outputMemoryFormatsFilter[i]);
const bool matched = areCompatible(*config.outConfs[i].desc, outputMemoryFormatsFilter[i]);
isSuitableDesc &= matched;
}
if (!isSuitableDesc) {
@@ -705,22 +705,22 @@ void MKLDNNNode::filterSupportedPrimitiveDescriptors() {
}
}
void MKLDNNNode::initDescriptor(const InferenceEngine::LayerConfig &config) {
void MKLDNNNode::initDescriptor(const NodeConfig& config) {
auto* selectedPD = getSelectedPrimitiveDescriptor();
if (!selectedPD) {
return;
}
std::vector<InferenceEngine::TensorDesc> inDescs;
std::vector<const MemoryDesc*> inDescs;
for (const auto& inConf : config.inConfs)
inDescs.push_back(inConf.desc);
std::vector<InferenceEngine::TensorDesc> outDescs;
inDescs.push_back(inConf.desc.get());
std::vector<const MemoryDesc*> outDescs;
for (const auto& outConf : config.outConfs)
outDescs.push_back(outConf.desc);
createDescriptor({inDescs}, {outDescs});
outDescs.push_back(outConf.desc.get());
createDescriptor(inDescs, outDescs);
std::shared_ptr<mkldnn::primitive_attr> attr = initPrimitiveAttr();
InferenceEngine::LayerConfig rightConfig = selectedPD->getConfig();
NodeConfig rightConfig = selectedPD->getConfig();
size_t selected_count = 0;
for (size_t j = 0; j < descs.size(); j++) {
const auto &desc = descs[j];
@@ -731,10 +731,10 @@ void MKLDNNNode::initDescriptor(const InferenceEngine::LayerConfig &config) {
itpd = desc.createPrimitiveDescriptorIterator(engine, *(attr.get()));
}
while (static_cast<bool>(itpd)) {
InferenceEngine::LayerConfig cfg;
NodeConfig cfg;
cfg.dynBatchSupport = true;
for (size_t i = 0; i < descInputNumbers(desc); i++) {
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = canBeInPlace() ? 0 : -1;
dataConfig.constant = false;
dataConfig.desc = getSrcMemDesc(itpd, i);
@@ -742,7 +742,7 @@ void MKLDNNNode::initDescriptor(const InferenceEngine::LayerConfig &config) {
}
for (size_t i = 0; i < descOutputNumbers(desc); i++) {
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = getDstMemDesc(itpd, i);
@@ -772,23 +772,21 @@ void MKLDNNNode::initDescriptor(const InferenceEngine::LayerConfig &config) {
return;
for (size_t i = 0; i < selectedConfig.inConfs.size(); i++) {
if (selectedConfig.inConfs[i].desc.getLayout() != InferenceEngine::Layout::ANY &&
!MKLDNNExtensionUtils::initTensorsAreEqual(selectedConfig.inConfs[i].desc, config.inConfs[i].desc))
if (!selectedConfig.inConfs[i].desc->isCompatible(*config.inConfs[i].desc))
IE_THROW() << "Incorrect descriptor for node: " << getName();
}
for (size_t i = 0; i < selectedConfig.outConfs.size(); i++) {
if (selectedConfig.outConfs[i].desc.getLayout() != InferenceEngine::Layout::ANY &&
!MKLDNNExtensionUtils::initTensorsAreEqual(selectedConfig.outConfs[i].desc, config.outConfs[i].desc))
if (!selectedConfig.outConfs[i].desc->isCompatible(*config.outConfs[i].desc))
IE_THROW() << "Incorrect descriptor for node: " << getName();
}
rightConfig = config;
}
selectedPD->getConfig() = rightConfig;
selectedPD->setConfig(rightConfig);
}
void MKLDNNNode::prepareMemory(const PrimitiveDescInfo *selected_pd, mkldnn::primitive_desc_iterator& itpd) {
void MKLDNNNode::prepareMemory(const NodeDesc *selected_pd, mkldnn::primitive_desc_iterator& itpd) {
for (size_t i = 0; i < getChildEdges().size(); i++) {
auto &dstMemPtr = getChildEdgeAt(i)->getMemoryPtr();
if (!dstMemPtr || !dstMemPtr->GetPrimitivePtr())
@@ -810,7 +808,8 @@ void MKLDNNNode::prepareMemory(const PrimitiveDescInfo *selected_pd, mkldnn::pri
const auto &internalBlob = internalBlobs[i];
auto create = [&] () {
auto newDesc = MKLDNNMemoryDesc(internalBlob->getTensorDesc());
// TODO [DS]: internal blobs should be removed or rewritten using Memory object
auto newDesc = MemoryDescUtils::convertToMKLDNNMemoryDesc(internalBlob->getTensorDesc());
MKLDNNMemory memory{ engine };
memory.Create(newDesc, internalBlob->buffer());
@@ -951,119 +950,60 @@ const std::vector<impl_desc_type>& MKLDNNNode::getPrimitivesPriority() {
return implPriorities;
}
bool MKLDNNNode::isUninitTensorDesc(const InferenceEngine::TensorDesc& desc) const {
if (desc.getLayout() == InferenceEngine::Layout::ANY)
return true;
if (desc.getBlockingDesc().getOffsetPadding() == std::numeric_limits<size_t>::max())
return true;
for (size_t i = 0; i < desc.getBlockingDesc().getOrder().size(); i++) {
if (desc.getBlockingDesc().getOffsetPaddingToData()[i] == std::numeric_limits<size_t>::max() ||
desc.getBlockingDesc().getStrides()[i] == std::numeric_limits<size_t>::max())
return true;
}
return false;
}
InferenceEngine::TensorDesc MKLDNNNode::getConfiguredInputDesc(const InferenceEngine::LayerConfig& config, size_t idx) const {
if (!isUninitTensorDesc(config.inConfs[idx].desc))
return config.inConfs[idx].desc;
std::unique_ptr<MemoryDesc> MKLDNNNode::getDefinedInputDesc(const NodeConfig &config, size_t idx) const {
int num = getParentEdgeAt(idx)->getInputNum();
auto *selectedPD = getParentEdgeAt(idx)->getParent()->getSelectedPrimitiveDescriptor();
if (!selectedPD)
IE_THROW() << "Cannot get selected primitive descriptor for node: " << getParentEdgeAt(idx)->getParent()->getName();
if (selectedPD->getConfig().outConfs.size() <= num)
num = 0;
if (config.inConfs[idx].desc->isDefined()) {
return config.inConfs[idx].desc->clone();
}
if (config.inConfs[idx].inPlace >= 0) {
return getConfiguredOutputDesc(config, static_cast<size_t>(config.inConfs[idx].inPlace));
return getDefinedOutputDesc(config, static_cast<size_t>(config.inConfs[idx].inPlace));
}
if (num >= 0) {
auto parentConf = selectedPD->getConfig().outConfs[num];
parentConf.desc.setPrecision(config.inConfs[idx].desc.getPrecision());
if (isUninitTensorDesc(parentConf.desc) && parentConf.inPlace >= 0)
parentConf.desc->setPrecision(config.inConfs[idx].desc->getPrecision());
if (!parentConf.desc->isDefined() && parentConf.inPlace >= 0)
getParentEdgeAt(idx)->getParent()->initOptimalPrimitiveDescriptor();
parentConf = getParentEdgeAt(idx)->getParent()->getSelectedPrimitiveDescriptor()->getConfig().outConfs[num];
if (!isUninitTensorDesc(parentConf.desc) &&
MKLDNNExtensionUtils::initTensorsAreEqual(parentConf.desc, config.inConfs[idx].desc)) {
return parentConf.desc;
}
if (config.inConfs[idx].desc.getLayout() == InferenceEngine::Layout::ANY &&
parentConf.desc.getLayout() != InferenceEngine::Layout::ANY) {
return InferenceEngine::TensorDesc(parentConf.desc.getPrecision(),
parentConf.desc.getDims(), {
parentConf.desc.getBlockingDesc().getBlockDims(),
parentConf.desc.getBlockingDesc().getOrder()
});
if (parentConf.desc->isDefined() && parentConf.desc->isCompatible(*config.inConfs[idx].desc)) {
return parentConf.desc->clone();
}
}
if (config.inConfs[idx].desc.getLayout() != InferenceEngine::Layout::ANY) {
return InferenceEngine::TensorDesc(config.inConfs[idx].desc.getPrecision(),
config.inConfs[idx].desc.getDims(), {
config.inConfs[idx].desc.getBlockingDesc().getBlockDims(),
config.inConfs[idx].desc.getBlockingDesc().getOrder()
});
}
return InferenceEngine::TensorDesc(config.inConfs[idx].desc.getPrecision(),
config.inConfs[idx].desc.getDims(),
InferenceEngine::TensorDesc::getLayoutByDims(config.inConfs[idx].desc.getDims()));
return MemoryDescUtils::resetOffset(config.inConfs[idx].desc.get());
}
InferenceEngine::TensorDesc MKLDNNNode::getConfiguredOutputDesc(const InferenceEngine::LayerConfig& config, size_t idx) const {
if (!isUninitTensorDesc(config.outConfs[idx].desc))
return config.outConfs[idx].desc;
std::unique_ptr<MemoryDesc> MKLDNNNode::getDefinedOutputDesc(const NodeConfig &config, size_t idx) const {
int num = getChildEdgeAt(idx)->getOutputNum();
auto *selectedPD = getChildEdgeAt(idx)->getChild()->getSelectedPrimitiveDescriptor();
if (!selectedPD)
IE_THROW() << "Cannot get selected primitive descriptor for node: " << getChildEdgeAt(idx)->getChild()->getName();
if (selectedPD->getConfig().inConfs.size() <= num)
num = 0;
if (config.outConfs[idx].desc->isDefined()) {
return config.outConfs[idx].desc->clone();
}
if (config.outConfs[idx].inPlace >= 0) {
return getConfiguredInputDesc(config, static_cast<size_t>(config.outConfs[idx].inPlace));
return getDefinedInputDesc(config, static_cast<size_t>(config.outConfs[idx].inPlace));
}
if (num >= 0) {
auto childConf = selectedPD->getConfig().inConfs[num];
childConf.desc.setPrecision(config.outConfs[idx].desc.getPrecision());
if (isUninitTensorDesc(childConf.desc) && childConf.inPlace >= 0)
childConf.desc->setPrecision(config.outConfs[idx].desc->getPrecision());
if (!childConf.desc->isDefined() && childConf.inPlace >= 0)
getChildEdgeAt(idx)->getChild()->initOptimalPrimitiveDescriptor();
childConf = getChildEdgeAt(idx)->getChild()->getSelectedPrimitiveDescriptor()->getConfig().inConfs[num];
if (!isUninitTensorDesc(childConf.desc) &&
MKLDNNExtensionUtils::initTensorsAreEqual(childConf.desc, config.outConfs[idx].desc)) {
return childConf.desc;
}
if (config.outConfs[idx].desc.getLayout() == InferenceEngine::Layout::ANY &&
childConf.desc.getLayout() != InferenceEngine::Layout::ANY) {
return InferenceEngine::TensorDesc(childConf.desc.getPrecision(),
childConf.desc.getDims(), {
childConf.desc.getBlockingDesc().getBlockDims(),
childConf.desc.getBlockingDesc().getOrder()
});
if (childConf.desc->isDefined() && childConf.desc->isCompatible(*config.outConfs[idx].desc)) {
return childConf.desc->clone();
}
}
if (config.outConfs[idx].desc.getLayout() != InferenceEngine::Layout::ANY) {
return InferenceEngine::TensorDesc(config.outConfs[idx].desc.getPrecision(),
config.outConfs[idx].desc.getDims(), {
config.outConfs[idx].desc.getBlockingDesc().getBlockDims(),
config.outConfs[idx].desc.getBlockingDesc().getOrder()
});
}
return InferenceEngine::TensorDesc(config.outConfs[idx].desc.getPrecision(),
config.outConfs[idx].desc.getDims(),
InferenceEngine::TensorDesc::getLayoutByDims(config.outConfs[idx].desc.getDims()));
return MemoryDescUtils::resetOffset(config.outConfs[idx].desc.get());
}
void MKLDNNNode::initOptimalPrimitiveDescriptor() {
@@ -1071,17 +1011,13 @@ void MKLDNNNode::initOptimalPrimitiveDescriptor() {
if (selected_pd == nullptr)
IE_THROW() << "Preferable primitive descriptor is not set.";
auto config = selected_pd->getConfig();
if (!isInitConfig(config)) {
if (!isConfigDefined(config)) {
for (size_t i = 0; i < config.inConfs.size(); i++) {
// TensorDescriptor constructor which is called inside getConfiguredInputDesc incorrectly computes offset field.
// What's why MKLDNNMemoryDesc routine is used to reinitialize TD with expected offset values.
config.inConfs[i].desc = MKLDNNMemoryDesc(getConfiguredInputDesc(config, i));
config.inConfs[i].desc = getDefinedInputDesc(config, i);
}
for (size_t i = 0; i < config.outConfs.size(); i++) {
// TensorDescriptor constructor which is called inside getConfiguredOutputDesc incorrectly computes offset field.
// What's why MKLDNNMemoryDesc routine is used to reinitialize TD with expected offset values.
config.outConfs[i].desc = MKLDNNMemoryDesc(getConfiguredOutputDesc(config, i));
config.outConfs[i].desc = getDefinedOutputDesc(config, i);
}
initDescriptor(config);
@@ -1090,38 +1026,22 @@ void MKLDNNNode::initOptimalPrimitiveDescriptor() {
}
}
bool MKLDNNNode::isInitConfig(const InferenceEngine::LayerConfig& config) const {
bool MKLDNNNode::isConfigDefined(const NodeConfig &config) const {
for (const auto& configs : {config.inConfs, config.outConfs}) {
for (const auto &dc : configs) {
if (isUninitTensorDesc(dc.desc))
if (!dc.desc->isDefined())
return false;
}
}
return true;
}
MKLDNNMemoryDesc MKLDNNNode::getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
InferenceEngine::TensorDesc desc = MKLDNNMemoryDesc(primitive_desc_it.src_desc(idx));
if (desc.getLayout() == InferenceEngine::Layout::ANY)
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getParentEdgeAt(idx)->getDims().ToSizeVector(),
desc.getLayout()));
else
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getParentEdgeAt(idx)->getDims().ToSizeVector(),
desc.getBlockingDesc()));
std::unique_ptr<MKLDNNMemoryDesc> MKLDNNNode::getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
return MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(primitive_desc_it.src_desc(idx));
}
MKLDNNMemoryDesc MKLDNNNode::getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
InferenceEngine::TensorDesc desc = MKLDNNMemoryDesc(primitive_desc_it.dst_desc(idx));
if (desc.getLayout() == InferenceEngine::Layout::ANY)
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getChildEdgeAt(idx)->getDims().ToSizeVector(),
desc.getLayout()));
else
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getChildEdgeAt(idx)->getDims().ToSizeVector(),
desc.getBlockingDesc()));
std::unique_ptr<MKLDNNMemoryDesc> MKLDNNNode::getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
return MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(primitive_desc_it.dst_desc(idx));
}
int MKLDNNNode::batchToProcess() {
@@ -1130,15 +1050,15 @@ int MKLDNNNode::batchToProcess() {
int MKLDNNNode::getMaxBatch() {
// FIXME: batch != 0 dims number
if (!inDims.empty()) {
if (inDims[0].ndims())
return inDims[0][0];
if (!inputShapes.empty()) {
if (inputShapes[0].getRank())
return static_cast<int>(inputShapes[0].getStaticDims()[0]);
else
return 1;
}
if (!outDims.empty() && outDims[0].ndims()) {
if (outDims[0].ndims())
return outDims[0][0];
if (!outputShapes.empty()) {
if (outputShapes[0].getRank())
return static_cast<int>(outputShapes[0].getStaticDims()[0]);
else
return 1;
}
@@ -1327,11 +1247,11 @@ bool MKLDNNNode::canBePerformedAsScaleShift(const MKLDNNNode *parentNode) const
}
const auto isBroadcastableToDataInput = [&]() {
const auto dataShape = getParentEdgeAt(fusingPort)->getDims().ToSizeVector();
const auto dataShape = getParentEdgeAt(fusingPort)->getShape().getStaticDims();
for (size_t i = 0; i < getParentEdges().size(); i++) {
if (i == fusingPort)
continue;
auto weightShape = getParentEdgeAt(i)->getDims().ToSizeVector();
auto weightShape = getParentEdgeAt(i)->getShape().getStaticDims();
if (getParentEdgesAtPort(i)[0]->getParent()->getChildEdges().size() != 1 || !isPerTensorOrPerChannelBroadcastable(dataShape, weightShape))
return false;
}
@@ -1404,7 +1324,7 @@ void MKLDNNNode::fillScalesAndShifts(const MKLDNNNode *parentNode, std::vector<f
IE_THROW() << "Can't fill scale and shifts for node: " << getName() << " with type: " << NameFromType(getType());
}
const size_t bufferSize = static_cast<size_t>(outDims[0][outDims[0].ndims() > 1 ? 1 : 0]);
const size_t bufferSize = static_cast<size_t>(outputShapes[0].getStaticDims()[outputShapes[0].getRank() > 1 ? 1 : 0]);
if (align == -1) {
align = bufferSize;
}
+117 -115
View File
@@ -26,8 +26,10 @@
#include <ngraph/ops.hpp>
#include <ngraph/node.hpp>
#include <ie_precision.hpp>
#include <nodes/common/tensor_desc_creator.h>
#include <nodes/common/blocked_desc_creator.h>
#include "cpu_types.h"
#include "cpu_shape.h"
#include "cpu_memory_desc.h"
namespace MKLDNNPlugin {
@@ -203,84 +205,92 @@ static std::string NameFromType(Type type) {
}
}
class PrimitiveDescInfo {
class PortConfigurator {
public:
PrimitiveDescInfo(const InferenceEngine::LayerConfig& conf, impl_desc_type type): config(conf) {
PortConfigurator(MKLDNNPlugin::LayoutType blockedDescType, InferenceEngine::Precision prc, const Shape& shape,
bool constant = false, int inPlace = -1) :
blockedDescCreator(getBlockedDescCreator(blockedDescType)), prc(prc), shape(shape), constant(constant), inPlace(inPlace) {}
PortConfigurator(MKLDNNPlugin::LayoutType blockedDescType, InferenceEngine::Precision prc = InferenceEngine::Precision::UNSPECIFIED,
bool constant = false, int inPlace = -1) :
blockedDescCreator(getBlockedDescCreator(blockedDescType)), prc(prc), constant(constant), inPlace(inPlace) {}
MKLDNNPlugin::BlockedDescCreator::CreatorConstPtr blockedDescCreator;
const InferenceEngine::Precision prc;
const Shape shape;
bool constant = false;
int inPlace = -1;
private:
static MKLDNNPlugin::BlockedDescCreator::CreatorConstPtr getBlockedDescCreator(MKLDNNPlugin::LayoutType blockedDescType) {
auto& creators = MKLDNNPlugin::BlockedDescCreator::getCommonCreators();
if (creators.find(blockedDescType) == creators.end()) {
IE_THROW() << "Cannot find tensor descriptor creator";
}
return creators.at(blockedDescType);
}
};
struct PortConfig {
PortConfig() = default;
PortConfig(const PortConfig& rhs) {
this->constant = rhs.constant;
this->inPlace = rhs.inPlace;
if (rhs.desc) {
this->desc = rhs.desc->clone();
}
}
PortConfig& operator=(const PortConfig& rhs) {
this->constant = rhs.constant;
this->inPlace = rhs.inPlace;
if (rhs.desc) {
this->desc = rhs.desc->clone();
}
return *this;
}
PortConfig(PortConfig&& rhs) = default;
PortConfig& operator=(PortConfig&& rhs) = default;
// TODO [DS]: better to make private and const
bool constant = false;
int inPlace = -1;
std::unique_ptr<MemoryDesc> desc;
};
struct NodeConfig {
bool dynBatchSupport = false;
std::vector<PortConfig> inConfs;
std::vector<PortConfig> outConfs;
};
class NodeDesc {
public:
NodeDesc(const NodeConfig& conf, impl_desc_type type): config(conf) {
implementationType = type;
}
PrimitiveDescInfo(const InferenceEngine::LayerConfig& conf, impl_desc_type type, const std::vector<mkldnn::memory::format_tag>& outFmts): config(conf) {
implementationType = type;
outputLayouts = outFmts;
}
PrimitiveDescInfo(const InferenceEngine::LayerConfig& conf, impl_desc_type type, mkldnn::memory::format_tag outFmt): config(conf) {
implementationType = type;
setOutputLayouts(outFmt);
}
PrimitiveDescInfo(const PrimitiveDescInfo &descInfo) = default;
PrimitiveDescInfo(PrimitiveDescInfo &&descInfo) = default;
PrimitiveDescInfo &operator=(const PrimitiveDescInfo &descInfo) = default;
const InferenceEngine::LayerConfig getConfig() const {
const NodeConfig& getConfig() const {
return config;
}
InferenceEngine::LayerConfig& getConfig() {
return config;
void setConfig(const NodeConfig& config) {
this->config = config;
}
impl_desc_type getImplementationType() const {
return implementationType;
}
const std::vector<mkldnn::memory::format_tag>& getOutputLayouts() const {
return outputLayouts;
}
void setImplementationType(impl_desc_type type) {
implementationType = type;
}
void setOutputLayouts(mkldnn::memory::format_tag outFmt) {
outputLayouts.clear();
for (int i = 0; i < config.outConfs.size(); i++) {
outputLayouts.push_back(outFmt);
}
}
private:
InferenceEngine::LayerConfig config;
NodeConfig config;
impl_desc_type implementationType;
std::vector<mkldnn::memory::format_tag> outputLayouts;
};
class DataConfigurator {
public:
DataConfigurator(MKLDNNPlugin::TensorDescCreatorTypes tensorDescType, InferenceEngine::Precision prc, const InferenceEngine::SizeVector& shape,
bool constant = false, int inplace = -1) :
tensorDescCreator(getTensorDescCreator(tensorDescType)), prc(prc), shape(shape), constant(constant), inplace(inplace) {}
DataConfigurator(MKLDNNPlugin::TensorDescCreatorTypes tensorDescType, InferenceEngine::Precision prc = InferenceEngine::Precision::UNSPECIFIED,
bool constant = false, int inplace = -1) :
tensorDescCreator(getTensorDescCreator(tensorDescType)), prc(prc), shape({}), constant(constant), inplace(inplace) {}
const MKLDNNPlugin::TensorDescCreator::CreatorConstPtr tensorDescCreator;
const InferenceEngine::Precision prc = InferenceEngine::Precision::UNSPECIFIED;
const InferenceEngine::SizeVector shape;
const bool constant = false;
const int inplace = -1;
private:
static MKLDNNPlugin::TensorDescCreator::CreatorConstPtr getTensorDescCreator(MKLDNNPlugin::TensorDescCreatorTypes tensorDescType) {
auto& creators = MKLDNNPlugin::TensorDescCreator::getCommonCreators();
if (creators.find(tensorDescType) == creators.end()) {
IE_THROW() << "Cannot find tensor descriptor creator";
}
return creators.at(tensorDescType);
}
};
class MKLDNNNode {
@@ -426,18 +436,18 @@ public:
return type;
}
const std::vector<PrimitiveDescInfo>& getSupportedPrimitiveDescriptors() const {
const std::vector<NodeDesc>& getSupportedPrimitiveDescriptors() const {
return supportedPrimitiveDescriptors;
}
inline const PrimitiveDescInfo* getSelectedPrimitiveDescriptor() const {
inline const NodeDesc* getSelectedPrimitiveDescriptor() const {
if (selectedPrimitiveDescriptorIndex < 0 ||
selectedPrimitiveDescriptorIndex >= supportedPrimitiveDescriptors.size())
return nullptr;
return &supportedPrimitiveDescriptors[selectedPrimitiveDescriptorIndex];
}
inline PrimitiveDescInfo* getSelectedPrimitiveDescriptor() {
inline NodeDesc* getSelectedPrimitiveDescriptor() {
if (selectedPrimitiveDescriptorIndex < 0 ||
selectedPrimitiveDescriptorIndex >= supportedPrimitiveDescriptors.size())
return nullptr;
@@ -473,9 +483,10 @@ public:
virtual void initOptimalPrimitiveDescriptor();
virtual void getSupportedDescriptors() = 0;
virtual void createDescriptor(const std::vector<InferenceEngine::TensorDesc>& inputDesc,
const std::vector<InferenceEngine::TensorDesc>& outputDesc) {}
virtual void initDescriptor(const InferenceEngine::LayerConfig& config);
// TODO [DS]: Should be moved into Node derivative class
virtual void createDescriptor(const std::vector<const MemoryDesc*>& inputDesc,
const std::vector<const MemoryDesc*>& outputDesc) {}
virtual void initDescriptor(const NodeConfig& config);
virtual bool created() const = 0;
virtual bool created(const MKLDNNExtensionManager::Ptr& extMgr) {
return created();
@@ -489,23 +500,19 @@ public:
template <class PD, class D, typename FPD = bool>
PD createPrimitiveDescriptor(const mkldnn::primitive_attr &attr = mkldnn::primitive_attr()) {
auto descsEqual = [](const std::vector<InferenceEngine::TensorDesc>& srcDescs,
const std::vector<InferenceEngine::DataConfig>& selectedDescs) {
auto descsCompatible = [](const std::vector<MemoryDescPtr>& srcDescs,
const std::vector<PortConfig>& selectedDescs) {
if (srcDescs.empty() && selectedDescs.empty())
return true;
if (srcDescs.empty() || selectedDescs.empty())
return false;
for (size_t i = 0; i < srcDescs.size() && i < selectedDescs.size(); i++) {
if (!(srcDescs[i].getBlockingDesc() == selectedDescs[i].desc.getBlockingDesc() &&
srcDescs[i].getPrecision() == selectedDescs[i].desc.getPrecision() &&
srcDescs[i].getDims() == selectedDescs[i].desc.getDims()) &&
srcDescs[i].getLayout() != InferenceEngine::Layout::ANY)
return false;
return srcDescs[i]->isCompatible(*selectedDescs[i].desc);
}
return true;
};
const PrimitiveDescInfo *selected_pd = getSelectedPrimitiveDescriptor();
const NodeDesc *selected_pd = getSelectedPrimitiveDescriptor();
if (selected_pd == nullptr)
IE_THROW() << "Preferable primitive descriptor is not set for node " << getName() << ".";
@@ -513,19 +520,19 @@ public:
auto itpd = desc.createPrimitiveDescriptorIterator(engine, attr);
while (static_cast<bool>(itpd)) {
std::vector<InferenceEngine::TensorDesc> srcDescs;
std::vector<MemoryDescPtr> srcDescs;
for (size_t i = 0; i < descInputNumbers(desc); i++)
srcDescs.push_back(getSrcMemDesc(itpd, i));
std::vector<InferenceEngine::TensorDesc> dstDescs;
std::vector<MemoryDescPtr> dstDescs;
for (size_t i = 0; i < descOutputNumbers(desc); i++)
dstDescs.push_back(getDstMemDesc(itpd, i));
impl_desc_type impl_type = parse_impl_name(itpd.impl_info_str());
if (impl_type == selected_pd->getImplementationType() &&
descsEqual(srcDescs, selected_pd->getConfig().inConfs) &&
descsEqual(dstDescs, selected_pd->getConfig().outConfs)) {
descsCompatible(srcDescs, selected_pd->getConfig().inConfs) &&
descsCompatible(dstDescs, selected_pd->getConfig().outConfs)) {
prepareMemory(selected_pd, itpd);
PD prim_desc = createPd<PD, D, FPD>(desc);
return {itpd.get()};
@@ -652,10 +659,10 @@ protected:
virtual int getMaxBatch();
virtual InferenceEngine::TensorDesc getConfiguredInputDesc(const InferenceEngine::LayerConfig& config, size_t idx) const;
virtual InferenceEngine::TensorDesc getConfiguredOutputDesc(const InferenceEngine::LayerConfig& config, size_t idx) const;
virtual MKLDNNMemoryDesc getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx);
virtual MKLDNNMemoryDesc getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx);
virtual std::unique_ptr<MemoryDesc> getDefinedInputDesc(const NodeConfig &config, size_t idx) const;
virtual std::unique_ptr<MemoryDesc> getDefinedOutputDesc(const NodeConfig &config, size_t idx) const;
virtual std::unique_ptr<MKLDNNMemoryDesc> getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx);
virtual std::unique_ptr<MKLDNNMemoryDesc> getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx);
/**
* @brief Appends new item into ops list with the information on how the node should be executed as post operation.
@@ -669,8 +676,8 @@ protected:
GetPrimitiveMemoryFormatFunc;
std::vector<GetPrimitiveMemoryFormatFunc> internalBlobDesc;
std::vector<MKLDNNDims> inDims;
std::vector<MKLDNNDims> outDims;
std::vector<Shape> inputShapes;
std::vector<Shape> outputShapes;
std::vector <MKLDNNNodePtr> fusedWith;
std::vector <MKLDNNNodePtr> mergedWith;
@@ -695,12 +702,11 @@ protected:
ConstantType constant = ConstantType::Unknown;
std::vector<InferenceEngine::Blob::Ptr> internalBlobs;
std::vector<MKLDNNMemoryPtr> internalBlobMemory;
std::vector<PrimitiveDescInfo> supportedPrimitiveDescriptors;
std::vector<NodeDesc> supportedPrimitiveDescriptors;
std::unordered_map<int, mkldnn::memory> primArgs;
MKLDNNPrimitive prim;
std::vector<MKLDNNDescriptor> descs;
InferenceEngine::Blob::Ptr ext_scales;
MKLDNNWeightsSharing::Ptr weightCache;
Algorithm algorithm = Algorithm::Undefined;
@@ -712,14 +718,13 @@ protected:
friend class MKLDNNGraphOptimizer;
friend class NodeDumper;
bool isUninitTensorDesc(const InferenceEngine::TensorDesc& desc) const;
bool isInitConfig(const InferenceEngine::LayerConfig& config) const;
void selectPreferPrimitiveDescriptor(const std::vector<impl_desc_type>& priority, bool ignoreConstInputs);
bool isConfigDefined(const NodeConfig &config) const;
virtual bool canBeInPlace() const;
virtual const std::vector<impl_desc_type>& getPrimitivesPriority();
virtual std::vector<mkldnn::memory::format_tag> getAvailableFormatsForDims(const MKLDNNDims& dims) const;
virtual std::vector<mkldnn::memory::format_tag> getAvailableFormatsForDims(const Shape& dims) const;
int batchToProcess();
InferenceEngine::Layout getWeightsLayoutByDims(InferenceEngine::SizeVector dims, bool isGrouped);
@@ -736,42 +741,39 @@ protected:
*/
virtual std::vector<InferenceEngine::Precision> getOutputPrecisions() const;
void addSupportedPrimDesc(const std::vector<DataConfigurator>& inDataConfigurators,
const std::vector<DataConfigurator>& outDataConfigurators,
void addSupportedPrimDesc(const std::vector<PortConfigurator>& inPortConfigs,
const std::vector<PortConfigurator>& outPortConfigs,
impl_desc_type implType,
bool dynBatchSupport = false) {
auto fill_port = [] (const DataConfigurator& dataConfigurator, const InferenceEngine::SizeVector& dims,
InferenceEngine::Precision prc, std::vector<InferenceEngine::DataConfig>& port) -> bool {
// In order to simplify particular node initialization logic we just don't add config in case target shape is not supported by tensorDescCreator.
// This should be suitable for major of scenarios since almost all nodes add `ncsp` tensorDescCreator which supports any shape rank.
if (dims.size() < dataConfigurator.tensorDescCreator->getMinimalRank())
auto fill_port = [] (const PortConfigurator& portConfigurator, const Shape& shape,
InferenceEngine::Precision prc, std::vector<PortConfig>& port) -> bool {
// In order to simplify particular node initialization logic we just don't add config in case target shape is not supported by blockedDescCreator.
// This should be suitable for major of scenarios since almost all nodes add `ncsp` blockedDescCreator which supports any shape rank.
if (shape.getRank() < portConfigurator.blockedDescCreator->getMinimalRank())
return false;
InferenceEngine::DataConfig dataConfig;
dataConfig.inPlace = dataConfigurator.inplace;
dataConfig.constant = dataConfigurator.constant;
PortConfig portConfig;
portConfig.inPlace = portConfigurator.inPlace;
portConfig.constant = portConfigurator.constant;
portConfig.desc = portConfigurator.blockedDescCreator->createUniqueDesc(prc, shape.getStaticDims());
dataConfig.desc = dataConfigurator.tensorDescCreator->createDesc(prc, dims);
port.push_back(dataConfig);
port.push_back(std::move(portConfig));
return true;
};
InferenceEngine::LayerConfig config;
for (size_t i = 0; i < inDataConfigurators.size(); i++) {
auto dims = inDataConfigurators[i].shape.empty() ? getParentEdgesAtPort(i)[0]->getDims().ToSizeVector() : inDataConfigurators[i].shape;
auto prc = inDataConfigurators[i].prc == InferenceEngine::Precision::UNSPECIFIED ? getOriginalInputPrecisionAtPort(i)
: inDataConfigurators[i].prc;
if (!fill_port(inDataConfigurators[i], dims, prc, config.inConfs))
NodeConfig config;
for (size_t i = 0; i < inPortConfigs.size(); i++) {
auto shape = inPortConfigs[i].shape.getRank() == 0 ? getParentEdgesAtPort(i)[0]->getShape() : inPortConfigs[i].shape;
auto prc = inPortConfigs[i].prc == InferenceEngine::Precision::UNSPECIFIED ? getOriginalInputPrecisionAtPort(i) : inPortConfigs[i].prc;
if (!fill_port(inPortConfigs[i], shape, prc, config.inConfs))
return;
}
for (size_t i = 0; i < outDataConfigurators.size(); i++) {
auto dims = outDataConfigurators[i].shape.empty() ? getChildEdgesAtPort(i)[0]->getDims().ToSizeVector() : outDataConfigurators[i].shape;
auto prc = outDataConfigurators[i].prc == InferenceEngine::Precision::UNSPECIFIED ? getOriginalOutputPrecisionAtPort(i)
: outDataConfigurators[i].prc;
if (!fill_port(outDataConfigurators[i], dims, prc, config.outConfs))
for (size_t i = 0; i < outPortConfigs.size(); i++) {
auto dims = outPortConfigs[i].shape.getRank() == 0 ? getChildEdgesAtPort(i)[0]->getShape() : outPortConfigs[i].shape;
auto prc = outPortConfigs[i].prc == InferenceEngine::Precision::UNSPECIFIED ? getOriginalOutputPrecisionAtPort(i) : outPortConfigs[i].prc;
if (!fill_port(outPortConfigs[i], dims, prc, config.outConfs))
return;
}
@@ -817,7 +819,7 @@ private:
return PD(*selected_desc_ptr, engine);
}
void prepareMemory(const PrimitiveDescInfo *selected_pd, mkldnn::primitive_desc_iterator& itpd);
void prepareMemory(const NodeDesc *selected_pd, mkldnn::primitive_desc_iterator& itpd);
enum LOOK { LOOK_UP = 1, LOOK_DOWN = 2 };
ConstantType checkConstant(LOOK look, std::vector<MKLDNNNodePtr>& checkNodes);
};
@@ -1,162 +0,0 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#pragma once
#include <ie_iextension.h>
#include "nodes/list.hpp"
#include "common/tensor_desc_creator.h"
#include "ngraph/descriptor/tensor.hpp"
#include <ie_ngraph_utils.hpp>
#include "cpu_types.h"
#include <string>
#include <vector>
namespace InferenceEngine {
namespace Extensions {
namespace Cpu {
class ExtLayerBase: public ILayerExecImpl {
public:
StatusCode getSupportedConfigurations(std::vector<LayerConfig>& conf, ResponseDesc *resp) noexcept override {
if (!errorMsg.empty()) {
if (resp) {
errorMsg.copy(resp->msg, sizeof(resp->msg) - 1);
}
return GENERAL_ERROR;
}
conf = confs;
return OK;
}
StatusCode init(LayerConfig& config, ResponseDesc *resp) noexcept override {
for (auto& input : config.inConfs) {
for (auto& offset : input.desc.getBlockingDesc().getOffsetPaddingToData()) {
if (offset) {
return GENERAL_ERROR;
}
}
if (input.desc.getBlockingDesc().getOffsetPadding()) {
return GENERAL_ERROR;
}
}
for (auto& output : config.outConfs) {
for (auto& offset : output.desc.getBlockingDesc().getOffsetPaddingToData()) {
if (offset) {
return GENERAL_ERROR;
}
}
if (output.desc.getBlockingDesc().getOffsetPadding()) {
return GENERAL_ERROR;
}
}
return OK;
}
protected:
MKLDNNPlugin::Algorithm getAlgorithm() const {
return algorithm;
}
MKLDNNPlugin::Algorithm algorithm;
class DataConfigurator {
public:
DataConfigurator(MKLDNNPlugin::TensorDescCreatorTypes tensorDescType, Precision prc = Precision::UNSPECIFIED, bool constant = false, int inplace = -1) :
tensorDescCreator(getTensorDescCreator(tensorDescType)), prc(prc), constant(constant), inplace(inplace) {}
DataConfigurator(const MKLDNNPlugin::TensorDescCreator::CreatorConstPtr& tensorDescCreator, Precision prc = Precision::UNSPECIFIED,
bool constant = false, int inplace = -1) : tensorDescCreator(tensorDescCreator), prc(prc), constant(constant), inplace(inplace) {}
const MKLDNNPlugin::TensorDescCreator::CreatorConstPtr tensorDescCreator;
const bool constant = false;
const int inplace = -1;
const Precision prc = Precision::UNSPECIFIED; // By default ngraph node precision is used
private:
static MKLDNNPlugin::TensorDescCreator::CreatorConstPtr getTensorDescCreator(MKLDNNPlugin::TensorDescCreatorTypes tensorDescType) {
auto& creators = MKLDNNPlugin::TensorDescCreator::getCommonCreators();
if (creators.find(tensorDescType) == creators.end()) {
IE_THROW() << "Cannot find tensor descriptor creator";
}
return creators.at(tensorDescType);
}
};
void addConfig(const std::shared_ptr<ngraph::Node>& op,
const std::vector<DataConfigurator>& inDataConfigurators,
const std::vector<DataConfigurator>& outDataConfigurators,
bool dynBatchSupport = false) {
LayerConfig config;
if (inDataConfigurators.size() != op->get_input_size())
IE_THROW() << "Cannot add config for operation " << op->get_friendly_name() << ". Incorrect number of inputs: " <<
"expected: " << op->get_input_size() << ", provided: " << inDataConfigurators.size();
if (outDataConfigurators.size() != op->get_output_size())
IE_THROW() << "Cannot add config for operation " << op->get_friendly_name() << ". Incorrect number of outputs: " <<
"expected: " << op->get_output_size() << ", provided: " << outDataConfigurators.size();
auto fill_port = [] (const DataConfigurator& dataConfigurator, const ngraph::descriptor::Tensor& tensor, std::vector<DataConfig>& port) -> bool {
// In order to simplify particular node initialization logic we just don't add config in case target shape is not supported by tensorDescCreator.
// This should be suitable for major of scenarios since almost all nodes add `ncsp` tensorDescCreator which supports any shape rank.
if (tensor.get_shape().size() < dataConfigurator.tensorDescCreator->getMinimalRank())
return false;
auto precision = dataConfigurator.prc != Precision::UNSPECIFIED ? dataConfigurator.prc : details::convertPrecision(tensor.get_element_type());
DataConfig dataConfig;
dataConfig.inPlace = dataConfigurator.inplace;
dataConfig.constant = dataConfigurator.constant;
dataConfig.desc = dataConfigurator.tensorDescCreator->createDesc(precision, tensor.get_shape());
port.push_back(dataConfig);
return true;
};
for (size_t i = 0; i < inDataConfigurators.size(); i++)
if (!fill_port(inDataConfigurators[i], op->get_input_tensor(i), config.inConfs))
return;
for (size_t i = 0; i < outDataConfigurators.size(); i++)
if (!fill_port(outDataConfigurators[i], op->get_output_tensor(i), config.outConfs))
return;
config.dynBatchSupport = dynBatchSupport;
confs.push_back(config);
}
std::string errorMsg;
std::vector<LayerConfig> confs;
};
template <class IMPL>
class ImplFactory : public ILayerImplFactory {
public:
explicit ImplFactory(const std::shared_ptr<ngraph::Node>& op) : ngraphOp(op) {}
// First implementation has more priority than next
StatusCode getImplementations(std::vector<ILayerImpl::Ptr>& impls, ResponseDesc *resp) noexcept override {
try {
impls.push_back(ILayerImpl::Ptr(new IMPL(ngraphOp)));
} catch (const InferenceEngine::Exception& ex) {
strncpy(resp->msg, ex.what(), sizeof(resp->msg) - 1);
IE_SUPPRESS_DEPRECATED_START
return ex.getStatus() != OK ? ex.getStatus() : GENERAL_ERROR;
IE_SUPPRESS_DEPRECATED_END
}
return OK;
}
protected:
const std::shared_ptr<ngraph::Node> ngraphOp;
};
#define REG_FACTORY_FOR(__prim, __type) \
void __prim ## __type(MKLDNNExtensions * extInstance) { \
using namespace MKLDNNPlugin; \
extInstance->layersFactory.registerNodeIfRequired(MKLDNNPlugin, __type, OV_PP_TOSTRING(__type), ImplFactory<__prim>); \
}
} // namespace Cpu
} // namespace Extensions
} // namespace InferenceEngine
@@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "tensor_desc_creator.h"
#include "blocked_desc_creator.h"
#include <numeric>
using namespace InferenceEngine;
@@ -11,19 +11,19 @@ using namespace MKLDNNPlugin;
namespace {
constexpr size_t channelsPos = 1lu;
class PlainFormatCreator : public TensorDescCreator {
class PlainFormatCreator : public BlockedDescCreator {
public:
InferenceEngine::TensorDesc createDesc(const InferenceEngine::Precision& precision, const InferenceEngine::SizeVector& srcDims) const override {
BlockedMemoryDesc createDesc(const InferenceEngine::Precision& precision, const InferenceEngine::SizeVector& srcDims) const override {
SizeVector order(srcDims.size());
std::iota(order.begin(), order.end(), 0);
return TensorDesc(precision, srcDims, {srcDims, order});
return BlockedMemoryDesc(precision, srcDims, srcDims, order);
}
size_t getMinimalRank() const override { return 0lu; }
};
class PerChannelCreator : public TensorDescCreator {
class PerChannelCreator : public BlockedDescCreator {
public:
InferenceEngine::TensorDesc createDesc(const InferenceEngine::Precision &precision, const InferenceEngine::SizeVector &srcDims) const override {
BlockedMemoryDesc createDesc(const InferenceEngine::Precision &precision, const InferenceEngine::SizeVector &srcDims) const override {
SizeVector order(srcDims.size());
std::iota(order.begin(), order.end(), 0);
SizeVector blkDims = srcDims;
@@ -37,15 +37,15 @@ public:
moveElementBack(blkDims, channelsPos);
}
return TensorDesc(precision, srcDims, {blkDims, order});
return BlockedMemoryDesc(precision, srcDims, blkDims, order);
}
size_t getMinimalRank() const override { return 3lu; }
};
class ChannelBlockedCreator : public TensorDescCreator {
class ChannelBlockedCreator : public BlockedDescCreator {
public:
ChannelBlockedCreator(size_t blockSize) : _blockSize(blockSize) {}
InferenceEngine::TensorDesc createDesc(const InferenceEngine::Precision& precision, const InferenceEngine::SizeVector& srcDims) const override {
BlockedMemoryDesc createDesc(const InferenceEngine::Precision& precision, const InferenceEngine::SizeVector& srcDims) const override {
if (srcDims.size() < 2) {
IE_THROW() << "Can't create blocked tensor descriptor!";
}
@@ -55,10 +55,12 @@ public:
order.push_back(channelsPos);
SizeVector blkDims = srcDims;
blkDims[channelsPos] = blkDims[channelsPos] / _blockSize + (blkDims[channelsPos] % _blockSize ? 1 : 0);
if (Shape::UNDEFINED_DIM != blkDims[channelsPos]) {
blkDims[channelsPos] = blkDims[channelsPos] / _blockSize + (blkDims[channelsPos] % _blockSize ? 1 : 0);
}
blkDims.push_back(_blockSize);
return TensorDesc(precision, srcDims, {blkDims, order});
return BlockedMemoryDesc(precision, srcDims, blkDims, order);
}
size_t getMinimalRank() const override { return 3lu; }
@@ -67,16 +69,16 @@ private:
};
} // namespace
const TensorDescCreator::CreatorsMap& TensorDescCreator::getCommonCreators() {
static const CreatorsMap map{ { TensorDescCreatorTypes::nspc, CreatorConstPtr(new PerChannelCreator) },
{ TensorDescCreatorTypes::nCsp8c, CreatorConstPtr(new ChannelBlockedCreator(8)) },
{ TensorDescCreatorTypes::nCsp16c, CreatorConstPtr(new ChannelBlockedCreator(16)) },
{ TensorDescCreatorTypes::ncsp, CreatorConstPtr(new PlainFormatCreator) } };
const BlockedDescCreator::CreatorsMap& BlockedDescCreator::getCommonCreators() {
static const CreatorsMap map{ { LayoutType::nspc, CreatorConstPtr(new PerChannelCreator) },
{ LayoutType::nCsp8c, CreatorConstPtr(new ChannelBlockedCreator(8)) },
{ LayoutType::nCsp16c, CreatorConstPtr(new ChannelBlockedCreator(16)) },
{ LayoutType::ncsp, CreatorConstPtr(new PlainFormatCreator) } };
return map;
}
std::pair<CreatorsMapFilterConstIterator, CreatorsMapFilterConstIterator>
TensorDescCreator::makeFilteredRange(const CreatorsMap &map, unsigned int rank) {
BlockedDescCreator::makeFilteredRange(const CreatorsMap &map, unsigned int rank) {
auto rankFilter = [rank](const CreatorsMap::value_type& item) {
if (item.second->getMinimalRank() > rank) {
return false;
@@ -90,7 +92,7 @@ TensorDescCreator::makeFilteredRange(const CreatorsMap &map, unsigned int rank)
}
std::pair<CreatorsMapFilterConstIterator, CreatorsMapFilterConstIterator>
TensorDescCreator::makeFilteredRange(const CreatorsMap& map, unsigned rank, const std::vector<TensorDescCreatorTypes>& supportedTypes) {
BlockedDescCreator::makeFilteredRange(const CreatorsMap& map, unsigned rank, const std::vector<LayoutType>& supportedTypes) {
unsigned bitMask = 0ul;
for (auto& item : supportedTypes) {
bitMask |= 1 << static_cast<unsigned>(item);
@@ -112,7 +114,7 @@ TensorDescCreator::makeFilteredRange(const CreatorsMap& map, unsigned rank, cons
}
std::pair<CreatorsMapFilterConstIterator, CreatorsMapFilterConstIterator>
TensorDescCreator::makeFilteredRange(const CreatorsMap &map, TensorDescCreator::Predicate predicate) {
BlockedDescCreator::makeFilteredRange(const CreatorsMap &map, BlockedDescCreator::Predicate predicate) {
auto first = CreatorsMapFilterConstIterator(std::move(predicate), map.begin(), map.end());
auto last = first.end();
return std::make_pair(first, last);
@@ -4,25 +4,19 @@
#pragma once
#include <ie_layouts.h>
#include <functional>
#include "cpu_shape.h"
#include "cpu_blocked_memory_desc.h"
namespace MKLDNNPlugin {
enum class TensorDescCreatorTypes : unsigned {
nspc, // general per channels format
ncsp, // general planar
nCsp8c, // general channels blocked by 8
nCsp16c // general channels blocked by 16
};
class CreatorsMapFilterConstIterator;
class TensorDescCreator {
class BlockedDescCreator {
public:
typedef std::shared_ptr<TensorDescCreator> CreatorPtr;
typedef std::shared_ptr<const TensorDescCreator> CreatorConstPtr;
typedef std::map<TensorDescCreatorTypes, CreatorConstPtr> CreatorsMap;
typedef std::shared_ptr<BlockedDescCreator> CreatorPtr;
typedef std::shared_ptr<const BlockedDescCreator> CreatorConstPtr;
typedef std::map<LayoutType, CreatorConstPtr> CreatorsMap;
typedef std::function<bool(const CreatorsMap::value_type&)> Predicate;
public:
@@ -30,17 +24,20 @@ public:
static std::pair<CreatorsMapFilterConstIterator, CreatorsMapFilterConstIterator>
makeFilteredRange(const CreatorsMap &map, unsigned rank);
static std::pair<CreatorsMapFilterConstIterator, CreatorsMapFilterConstIterator>
makeFilteredRange(const CreatorsMap& map, unsigned rank, const std::vector<TensorDescCreatorTypes>& supportedTypes);
makeFilteredRange(const CreatorsMap& map, unsigned rank, const std::vector<LayoutType>& supportedTypes);
static std::pair<CreatorsMapFilterConstIterator, CreatorsMapFilterConstIterator>
makeFilteredRange(const CreatorsMap& map, Predicate predicate);
virtual InferenceEngine::TensorDesc createDesc(const InferenceEngine::Precision& precision, const InferenceEngine::SizeVector& srcDims) const = 0;
virtual BlockedMemoryDesc createDesc(const InferenceEngine::Precision& precision, const InferenceEngine::SizeVector& srcDims) const = 0;
std::unique_ptr<BlockedMemoryDesc> createUniqueDesc(const InferenceEngine::Precision& precision, const InferenceEngine::SizeVector& srcDims) const {
return MKLDNNPlugin::make_unique<BlockedMemoryDesc>(createDesc(precision, srcDims));
}
virtual size_t getMinimalRank() const = 0;
virtual ~TensorDescCreator() = default;
virtual ~BlockedDescCreator() = default;
};
class CreatorsMapFilterConstIterator {
public:
typedef TensorDescCreator::CreatorsMap::const_iterator Iterator;
typedef BlockedDescCreator::CreatorsMap::const_iterator Iterator;
typedef std::iterator_traits<Iterator>::value_type value_type;
typedef std::iterator_traits<Iterator>::reference reference;
typedef std::iterator_traits<Iterator>::pointer pointer;
@@ -69,19 +69,19 @@ void MKLDNNAdaptivePoolingNode::getSupportedDescriptors() {
if (getChildEdges().size() != (algorithm == AdaptivePoolingMax ? 2 : 1))
IE_THROW() << errorPrefix << "has incorrect number of output edges: " << getParentEdges().size();
auto parentDims = getParentEdgeAt(0)->getDims();
auto childDims = getChildEdgeAt(0)->getDims();
auto parentDims = getParentEdgeAt(0)->getShape().getStaticDims();
auto childDims = getChildEdgeAt(0)->getShape().getStaticDims();
spatialDimsCount = parentDims.ndims() - 2;
spatialDimsCount = parentDims.size() - 2;
if (!one_of(spatialDimsCount, 1, 2, 3)) {
IE_THROW() << errorPrefix << "doesn't support 0th input with rank: " << getParentEdgeAt(0)->getDims().ndims();
IE_THROW() << errorPrefix << "doesn't support 0th input with rank: " << getParentEdgeAt(0)->getShape().getRank();
}
if (getParentEdgeAt(1)->getDims().ndims() != 1) {
IE_THROW() << errorPrefix << "doesn't support 1st input with rank: " << getParentEdgeAt(1)->getDims().ndims();
if (getParentEdgeAt(1)->getShape().getRank() != 1) {
IE_THROW() << errorPrefix << "doesn't support 1st input with rank: " << getParentEdgeAt(1)->getShape().getRank();
}
if (getChildEdgeAt(0)->getDims().ndims() != getParentEdgeAt(0)->getDims().ndims()) {
if (getChildEdgeAt(0)->getShape().getRank() != getParentEdgeAt(0)->getShape().getRank()) {
IE_THROW() << errorPrefix << "must keep data rank";
}
}
@@ -98,20 +98,20 @@ void MKLDNNAdaptivePoolingNode::initSupportedPrimitiveDescriptors() {
config.inConfs.resize(2);
config.outConfs.resize((algorithm == Algorithm::AdaptivePoolingAvg ? 1 : 2));
std::vector<TensorDescCreatorTypes> dataFormats{ TensorDescCreatorTypes::ncsp };
if (getParentEdgeAt(0)->getDims()[1] != 1) {
dataFormats.push_back(TensorDescCreatorTypes::nspc);
dataFormats.push_back(TensorDescCreatorTypes::nCsp16c);
dataFormats.push_back(TensorDescCreatorTypes::nCsp8c);
std::vector<LayoutType> dataFormats{ LayoutType::ncsp };
if (getParentEdgeAt(0)->getShape().getStaticDims()[1] != 1) {
dataFormats.push_back(LayoutType::nspc);
dataFormats.push_back(LayoutType::nCsp16c);
dataFormats.push_back(LayoutType::nCsp8c);
}
for (const auto &df : dataFormats) {
if (algorithm == Algorithm::AdaptivePoolingAvg) {
addSupportedPrimDesc({{df, precision}, {TensorDescCreatorTypes::ncsp, Precision::I32}},
addSupportedPrimDesc({{df, precision}, {LayoutType::ncsp, Precision::I32}},
{{df, precision}},
impl_desc_type::unknown);
} else {
addSupportedPrimDesc({{df, precision}, {TensorDescCreatorTypes::ncsp, Precision::I32}},
{{df, precision}, {TensorDescCreatorTypes::ncsp, Precision::I32}},
addSupportedPrimDesc({{df, precision}, {LayoutType::ncsp, Precision::I32}},
{{df, precision}, {LayoutType::ncsp, Precision::I32}},
impl_desc_type::unknown);
}
}
@@ -134,8 +134,8 @@ void MKLDNNAdaptivePoolingNode::execute(mkldnn::stream strm) {
auto srcBlockDesc = srcMemory0.GetDescriptor().data.format_desc.blocking;
int blockSize = srcBlockDesc.inner_nblks > 0 ? srcBlockDesc.inner_blks[0] : 1;
auto isPlainFmt = srcMemory0.GetDesc().isPlainFormat();
auto isTailCFmt = srcMemory0.GetDesc().isTailCFormat();
auto isPlainFmt = srcMemory0.GetDesc().hasLayoutType(LayoutType::ncsp);
auto isTailCFmt = srcMemory0.GetDesc().hasLayoutType(LayoutType::nspc);
const auto *src = reinterpret_cast<const float *>(getParentEdgeAt(0)->getMemoryPtr()->GetPtr());
const auto *srcPooledSpatialShapes = reinterpret_cast<const int *>(getParentEdgeAt(1)->getMemoryPtr()->GetPtr());
@@ -165,8 +165,8 @@ void MKLDNNAdaptivePoolingNode::execute(mkldnn::stream strm) {
if (!selectedPrimitiveDescriptor)
IE_THROW() << errorPrefix << "doesn't have primitive descriptors.";
auto config = selectedPrimitiveDescriptor->getConfig();
auto srcStrides = config.inConfs[0].desc.getBlockingDesc().getStrides();
auto dstStrides = config.outConfs[0].desc.getBlockingDesc().getStrides();
auto srcStrides = getParentEdgesAtPort(0)[0]->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
auto dstStrides = getChildEdgesAtPort(0)[0]->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
// unified strides array
const size_t tailDimsOffset = (isTailCFmt ? -1 : 0);
@@ -10,7 +10,7 @@
#include "utils/bfloat16.hpp"
#include <mkldnn_selective_build.h>
#include "mkldnn_batch_to_space_node.h"
#include <nodes/common/tensor_desc_creator.h>
#include <nodes/common/blocked_desc_creator.h>
#include <ngraph/opsets/opset2.hpp>
using namespace MKLDNNPlugin;
@@ -67,32 +67,32 @@ void MKLDNNBatchToSpaceNode::initSupportedPrimitiveDescriptors() {
if (supported_precision_sizes.find(precision.size()) == supported_precision_sizes.end())
IE_THROW() << errorPrefix << " has unsupported precision: " << precision.name();
addSupportedPrimDesc({{TensorDescCreatorTypes::nspc, precision},
{TensorDescCreatorTypes::ncsp},
{TensorDescCreatorTypes::ncsp},
{TensorDescCreatorTypes::ncsp}},
{{TensorDescCreatorTypes::nspc, precision}},
addSupportedPrimDesc({{LayoutType::nspc, precision},
{LayoutType::ncsp},
{LayoutType::ncsp},
{LayoutType::ncsp}},
{{LayoutType::nspc, precision}},
impl_desc_type::ref_any);
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, precision},
{TensorDescCreatorTypes::ncsp},
{TensorDescCreatorTypes::ncsp},
{TensorDescCreatorTypes::ncsp}},
{{TensorDescCreatorTypes::ncsp, precision}},
addSupportedPrimDesc({{LayoutType::ncsp, precision},
{LayoutType::ncsp},
{LayoutType::ncsp},
{LayoutType::ncsp}},
{{LayoutType::ncsp, precision}},
impl_desc_type::ref_any);
if (inDims[1] % 8 == 0) {
addSupportedPrimDesc({{TensorDescCreatorTypes::nCsp8c, precision},
{TensorDescCreatorTypes::ncsp},
{TensorDescCreatorTypes::ncsp},
{TensorDescCreatorTypes::ncsp}},
{{TensorDescCreatorTypes::nCsp8c, precision}},
addSupportedPrimDesc({{LayoutType::nCsp8c, precision},
{LayoutType::ncsp},
{LayoutType::ncsp},
{LayoutType::ncsp}},
{{LayoutType::nCsp8c, precision}},
impl_desc_type::ref_any);
}
if (inDims[1] % 16 == 0) {
addSupportedPrimDesc({{TensorDescCreatorTypes::nCsp16c, precision},
{TensorDescCreatorTypes::ncsp},
{TensorDescCreatorTypes::ncsp},
{TensorDescCreatorTypes::ncsp}},
{{TensorDescCreatorTypes::nCsp16c, precision}},
addSupportedPrimDesc({{LayoutType::nCsp16c, precision},
{LayoutType::ncsp},
{LayoutType::ncsp},
{LayoutType::ncsp}},
{{LayoutType::nCsp16c, precision}},
impl_desc_type::ref_any);
}
}
@@ -112,15 +112,16 @@ void MKLDNNBatchToSpaceNode::batchToSpaceKernel() {
const auto *srcData = reinterpret_cast<const T *>(getParentEdgeAt(0)->getMemoryPtr()->GetPtr());
auto *dstData = reinterpret_cast<T *>(getChildEdgeAt(0)->getMemoryPtr()->GetPtr());
const auto layout = getParentEdgeAt(0)->getDesc().getLayout();
const bool blocked = layout != NCHW && layout != NCDHW && layout != NHWC && layout != NDHWC;
auto srcDesc = getParentEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
const bool blocked = srcDesc.hasLayoutType(LayoutType::nCsp8c) || srcDesc.hasLayoutType(LayoutType::nCsp16c);
const auto dimsSize = inDims.size();
auto inShape5D = getShape5D(inDims);
auto outShape5D = getShape5D(outDims);
auto blockShape = getShape5D(blockShapeIn);
if (layout == NHWC || layout == NDHWC) {
if (srcDesc.hasLayoutType(LayoutType::nspc) && one_of(srcDesc.getShape().getRank(), 4, 5)) {
inShape5D.push_back(inShape5D[1]);
inShape5D.erase(inShape5D.begin() + 1);
outShape5D.push_back(outShape5D[1]);
@@ -129,9 +130,11 @@ void MKLDNNBatchToSpaceNode::batchToSpaceKernel() {
blockShape.erase(blockShape.begin() + 1);
}
const size_t blockSize = blocked ? getChildEdgeAt(0)->getDesc().getBlockingDesc().getBlockDims().back() : 1lu;
const size_t blockCountInput = getParentEdgeAt(0)->getDesc().getBlockingDesc().getBlockDims()[1];
const size_t blockCountOutput = getChildEdgeAt(0)->getDesc().getBlockingDesc().getBlockDims()[1];
auto dstDesc = getChildEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
const size_t blockSize = blocked ? dstDesc.getBlockDims().back() : 1lu;
const size_t blockCountInput = srcDesc.getBlockDims()[1];
const size_t blockCountOutput = dstDesc.getBlockDims()[1];
const auto blockRemainder = inShape5D[1] % blockSize;
const auto lastBlock = blockRemainder == 0 ? blockSize : blockRemainder;
@@ -166,7 +169,7 @@ void MKLDNNBatchToSpaceNode::batchToSpaceKernel() {
oAdd[2] = dimsSize == 5 ? bIdx % blockShapeIn[2] - cropsBeginIn[2] : 0lu;
bIdx = dimsSize == 5 ? bIdx / blockShapeIn[2] : bIdx;
oAdd[1] = bIdx % blockShapeIn[1] - cropsBeginIn[1];
if (layout == NHWC || layout == NDHWC) {
if (srcDesc.hasLayoutType(LayoutType::nspc) && one_of(srcDesc.getShape().getRank(), 4, 5)) {
oAdd.push_back(oAdd[1]);
oAdd.erase(oAdd.begin() + 1);
}
@@ -221,12 +224,13 @@ void MKLDNNBatchToSpaceNode::batchToSpaceKernel() {
}
void MKLDNNBatchToSpaceNode::execute(mkldnn::stream strm) {
switch (getParentEdgeAt(0)->getDesc().getPrecision().size()) {
switch (getParentEdgeAt(0)->getMemory().GetDesc().getPrecision().size()) {
case 1: batchToSpaceKernel<PrecisionTrait<Precision::U8>::value_type>(); break;
case 2: batchToSpaceKernel<PrecisionTrait<Precision::U16>::value_type>(); break;
case 4: batchToSpaceKernel<PrecisionTrait<Precision::I32>::value_type>(); break;
default:
IE_THROW() << "BatchToSpace layer does not support precision '" + std::string(getParentEdgeAt(0)->getDesc().getPrecision().name()) + "'";
IE_THROW() << "BatchToSpace layer does not support precision '" <<
std::string(getParentEdgeAt(0)->getMemory().GetDesc().getPrecision().name()) << "'";
}
}
@@ -24,6 +24,10 @@ public:
static bool isSupportedOperation(const std::shared_ptr<ngraph::Node>& op, std::string& errorMessage) noexcept;
private:
template<typename T>
void batchToSpaceKernel();
private:
InferenceEngine::SizeVector inDims;
InferenceEngine::SizeVector outDims;
@@ -31,9 +35,6 @@ private:
std::vector<size_t> cropsBeginIn;
std::string errorPrefix;
template<typename T>
void batchToSpaceKernel();
};
} // namespace MKLDNNPlugin
@@ -942,16 +942,16 @@ void MKLDNNBinaryConvolutionNode::getSupportedDescriptors() {
if (getChildEdges().empty())
IE_THROW() << errorPrefix << "has incorrect number of output edges";
if (getParentEdgeAt(0)->getDims().ndims() != 4) {
IE_THROW() << errorPrefix << "doesn't support 0th input with rank: " << getParentEdgeAt(0)->getDims().ndims();
if (getParentEdgeAt(0)->getShape().getRank() != 4) {
IE_THROW() << errorPrefix << "doesn't support 0th input with rank: " << getParentEdgeAt(0)->getShape().getRank();
}
if (getParentEdgeAt(1)->getDims().ndims() != 4) {
IE_THROW() << errorPrefix << "doesn't support 1st input with rank: " << getParentEdgeAt(1)->getDims().ndims();
if (getParentEdgeAt(1)->getShape().getRank() != 4) {
IE_THROW() << errorPrefix << "doesn't support 1st input with rank: " << getParentEdgeAt(1)->getShape().getRank();
}
if (getChildEdgeAt(0)->getDims().ndims() != 4) {
IE_THROW() << errorPrefix << "doesn't support output with rank: " << getChildEdgeAt(0)->getDims().ndims();
if (getChildEdgeAt(0)->getShape().getRank() != 4) {
IE_THROW() << errorPrefix << "doesn't support output with rank: " << getChildEdgeAt(0)->getShape().getRank();
}
}
@@ -961,7 +961,7 @@ void MKLDNNBinaryConvolutionNode::initSupportedPrimitiveDescriptors() {
setPostOps(attr);
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = false;
config.inConfs.resize(2);
config.inConfs[0].constant = false;
@@ -975,26 +975,38 @@ void MKLDNNBinaryConvolutionNode::initSupportedPrimitiveDescriptors() {
if (implType != impl_desc_type::ref) {
// optimzed implementation
auto outputDataType = withBinarization ? memory::data_type::bin : memory::data_type::f32;
auto weiFormat = implType == impl_desc_type::jit_avx512 ? memory::format_tag::OIhw16o32i : memory::format_tag::OIhw8o32i;
// auto weiFormat = implType == impl_desc_type::jit_avx512 ? memory::format_tag::OhIw16o32i : memory::format_tag::OhIw8o32i;
config.inConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), memory::data_type::bin, memory::format_tag::nhwc);
config.inConfs[1].desc = MKLDNNMemoryDesc(getParentEdgeAt(1)->getDims(), memory::data_type::bin, weiFormat);
config.outConfs[0].desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, memory::format_tag::nhwc);
//activation
auto nspcCreator = BlockedDescCreator::getCommonCreators().at(LayoutType::nspc);
config.inConfs[0].desc = nspcCreator->createUniqueDesc(Precision::BIN, getParentEdgeAt(0)->getShape().getStaticDims());
//weights
size_t weiFirstDimBlockSize = implType == impl_desc_type::jit_avx512 ? 16 : 8; //memory::format_tag::OIhw16o32i : memory::format_tag::OIhw8o32i;
auto weiDims = getParentEdgeAt(1)->getShape().getStaticDims();
std::vector<size_t> weiBlockDims = {div_up(weiDims[0], weiFirstDimBlockSize), div_up(weiDims[1], 32),
weiDims[2], weiDims[3], weiFirstDimBlockSize, 32};
std::vector<size_t> weiOrder = {0, 1, 2, 3, 0, 1};
config.inConfs[1].desc = MKLDNNPlugin::make_unique<BlockedMemoryDesc>(Precision::BIN, weiDims, weiBlockDims, weiOrder);
//result
auto outputPrecision = withBinarization ? Precision::BIN : Precision::FP32;
config.outConfs[0].desc = nspcCreator->createUniqueDesc(outputPrecision, getChildEdgeAt(0)->getShape().getStaticDims());
if (withSum) {
config.inConfs.push_back(config.outConfs[0]);
config.outConfs[0].inPlace = 2;
}
supportedPrimitiveDescriptors.push_back({config, implType, memory::format_tag::nhwc});
supportedPrimitiveDescriptors.push_back({config, implType});
} else {
// reference implementation
auto weiFormat = group > 1 ? memory::format_tag::goihw : memory::format_tag::oihw;
auto weiCreator = BlockedDescCreator::getCommonCreators().at(LayoutType::ncsp);
auto nspcCreator = BlockedDescCreator::getCommonCreators().at(LayoutType::nspc);
config.inConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), memory::data_type::bin, memory::format_tag::nhwc);
config.inConfs[1].desc = MKLDNNMemoryDesc(getParentEdgeAt(1)->getDims(), memory::data_type::bin, weiFormat);
config.outConfs[0].desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), memory::data_type::f32, memory::format_tag::nhwc);
supportedPrimitiveDescriptors.push_back({config, implType, memory::format_tag::nhwc});
config.inConfs[0].desc = nspcCreator->createUniqueDesc(Precision::BIN, getParentEdgeAt(0)->getShape().getStaticDims());
config.inConfs[1].desc = weiCreator->createUniqueDesc(Precision::BIN, getParentEdgeAt(1)->getShape().getStaticDims());
config.outConfs[0].desc = nspcCreator->createUniqueDesc(Precision::FP32, getChildEdgeAt(0)->getShape().getStaticDims());
supportedPrimitiveDescriptors.push_back({config, implType});
}
}
@@ -1003,11 +1015,9 @@ void MKLDNNBinaryConvolutionNode::createPrimitive() {
if (!selectedPrimitiveDescriptor)
IE_THROW() << "CPU binary convolution with name '" << getName() << "' doesn't have primitive descriptors.";
auto config = selectedPrimitiveDescriptor->getConfig();
auto srcDims = config.inConfs[0].desc.getDims();
auto weiDims = config.inConfs[1].desc.getDims();
auto dstDims = config.outConfs[0].desc.getDims();
auto srcDims = getParentEdgeAt(0)->getShape().getStaticDims();
auto weiDims = getParentEdgeAt(1)->getShape().getStaticDims();
auto dstDims = getChildEdgeAt(0)->getShape().getStaticDims();
auto implType = selectedPrimitiveDescriptor->getImplementationType();
@@ -1061,9 +1071,12 @@ void MKLDNNBinaryConvolutionNode::createPrimitive() {
jcp.nb_oc_blocking = nstl::min(implType == impl_desc_type::jit_sse42 ? 2 : implType == impl_desc_type::jit_avx2 ? 4 : 6, jcp.nb_oc);
jcp.dst_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(config.outConfs[0].desc.getPrecision());
jcp.typesize_in = config.inConfs[0].desc.getPrecision() == Precision::BIN ? 1 : config.inConfs[0].desc.getPrecision().size();
jcp.typesize_out = config.outConfs[0].desc.getPrecision() == Precision::BIN ? 1 : config.outConfs[0].desc.getPrecision().size();
auto srcPrecision = getParentEdgeAt(0)->getMemory().GetDesc().getPrecision();
auto dstPrecision = getChildEdgeAt(0)->getMemory().GetDesc().getPrecision();
jcp.dst_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(dstPrecision);
jcp.typesize_in = srcPrecision == Precision::BIN ? 1 : srcPrecision.size();
jcp.typesize_out = dstPrecision == Precision::BIN ? 1 : dstPrecision.size();
int r_pad_no_tail = nstl::max(0, (jcp.ow - jcp.ur_w_tail - 1) * jcp.stride_w
+ (jcp.kw - 1) * (jcp.dilate_w + 1) - (jcp.iw + jcp.l_pad - 1));
@@ -1281,30 +1294,28 @@ void MKLDNNBinaryConvolutionNode::execute(mkldnn::stream strm) {
auto weights = reinterpret_cast<const uint8_t*>(weightsMemory->GetPtr());
auto dst = reinterpret_cast<uint8_t*>(dstMemory->GetPtr());
auto srcDesc = getParentEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
std::vector<size_t> srcStride(srcDesc.getStrides().size());
for (int i = 0; i < srcStride.size(); i++) {
srcStride[srcDesc.getOrder()[i]] = srcDesc.getStrides()[i];
}
auto weiDesc = getParentEdgeAt(1)->getMemory().GetDescWithType<BlockedMemoryDesc>();
std::vector<size_t> weightsStride(weiDesc.getShape().getRank());
for (int i = 0; i < weightsStride.size(); i++) {
weightsStride[weiDesc.getOrder()[i]] = weiDesc.getStrides()[i];
}
auto dstDesc = getChildEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
std::vector<size_t> dstStride(dstDesc.getStrides().size());
for (int i = 0; i < dstStride.size(); i++) {
dstStride[dstDesc.getOrder()[i]] = dstDesc.getStrides()[i];
}
auto selectedPrimitiveDescriptor = getSelectedPrimitiveDescriptor();
if (!selectedPrimitiveDescriptor)
IE_THROW() << "CPU binary convolution with name '" << getName() << "' doesn't have primitive descriptors.";
auto config = selectedPrimitiveDescriptor->getConfig();
auto srcBlockDesc = config.inConfs[0].desc.getBlockingDesc();
std::vector<size_t> srcStride(srcBlockDesc.getStrides().size());
for (int i = 0; i < srcStride.size(); i++) {
srcStride[srcBlockDesc.getOrder()[i]] = srcBlockDesc.getStrides()[i];
}
auto weiBlockDesc = config.inConfs[1].desc.getBlockingDesc();
std::vector<size_t> weightsStride(config.inConfs[1].desc.getDims().size());
for (int i = 0; i < weightsStride.size(); i++) {
weightsStride[weiBlockDesc.getOrder()[i]] = weiBlockDesc.getStrides()[i];
}
auto dstBlockDesc = config.outConfs[0].desc.getBlockingDesc();
std::vector<size_t> dstStride(dstBlockDesc.getStrides().size());
for (int i = 0; i < dstStride.size(); i++) {
dstStride[dstBlockDesc.getOrder()[i]] = dstBlockDesc.getStrides()[i];
}
auto implType = selectedPrimitiveDescriptor->getImplementationType();
if (implType != impl_desc_type::ref) {
executeOptimized(src, weights, dst, srcStride, weightsStride, dstStride);
@@ -10,7 +10,7 @@
#include "utils/bfloat16.hpp"
#include <mkldnn_selective_build.h>
#include "mkldnn_broadcast_node.h"
#include <nodes/common/tensor_desc_creator.h>
#include <nodes/common/blocked_desc_creator.h>
#include <ngraph/opsets/opset1.hpp>
#include "common/cpu_memcpy.h"
@@ -60,18 +60,20 @@ void MKLDNNBroadcastNode::initSupportedPrimitiveDescriptors() {
Precision prec = getOriginalInputPrecisionAtPort(BROADCAST_INPUT);
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, prec},
{TensorDescCreatorTypes::ncsp, Precision::I32}},
{{TensorDescCreatorTypes::ncsp, prec}},
addSupportedPrimDesc({{LayoutType::ncsp, prec},
{LayoutType::ncsp, Precision::I32}},
{{LayoutType::ncsp, prec}},
impl_desc_type::ref_any);
}
void MKLDNNBroadcastNode::execute(mkldnn::stream strm) {
size_t shape_size = (getParentEdgeAt(BROADCAST_SHAPE)->getDesc().getDims())[0];
SizeVector dst_dims = getChildEdgeAt(0)->getDesc().getDims();
SizeVector src_dims = getParentEdgeAt(BROADCAST_INPUT)->getDesc().getDims();
SizeVector srcStrides = getParentEdgeAt(BROADCAST_INPUT)->getDesc().getBlockingDesc().getStrides();
size_t data_size = getParentEdgeAt(BROADCAST_INPUT)->getDesc().getPrecision().size();
size_t shape_size = (getParentEdgeAt(BROADCAST_SHAPE)->getMemory().GetDesc().getShape().getStaticDims())[0];
SizeVector dst_dims = getChildEdgeAt(0)->getMemory().GetDesc().getShape().getStaticDims();
SizeVector src_dims = getParentEdgeAt(BROADCAST_INPUT)->getMemory().GetDesc().getShape().getStaticDims();
auto srcDesc = getParentEdgeAt(BROADCAST_INPUT)->getMemory().GetDescWithType<BlockedMemoryDesc>();
SizeVector srcStrides = srcDesc.getStrides();
size_t data_size = srcDesc.getPrecision().size();
if (!src_dims.size())
src_dims = SizeVector(1, 1);
@@ -86,7 +88,8 @@ void MKLDNNBroadcastNode::execute(mkldnn::stream strm) {
IE_THROW() << "Output tensor dimension is smaller then input tensor dimension";
}
InferenceEngine::SizeVector dstStrides = getChildEdgeAt(0)->getDesc().getBlockingDesc().getStrides();
auto dstDesc = getChildEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
InferenceEngine::SizeVector dstStrides = dstDesc.getStrides();
InferenceEngine::SizeVector src_aligned(dst_dims.size());
InferenceEngine::SizeVector srcStrides_aligned(dst_dims.size());
size_t prefix_size = dst_dims.size() - src_dims.size();
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <vector>
#include <algorithm>
@@ -82,9 +80,9 @@ void MKLDNNBucketizeNode::initSupportedPrimitiveDescriptors() {
output_precision = Precision::I32;
}
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, input_precision},
{TensorDescCreatorTypes::ncsp, boundaries_precision}},
{{TensorDescCreatorTypes::ncsp, output_precision}},
addSupportedPrimDesc({{LayoutType::ncsp, input_precision},
{LayoutType::ncsp, boundaries_precision}},
{{LayoutType::ncsp, output_precision}},
impl_desc_type::ref_any);
}
@@ -21,7 +21,8 @@
#include "mkldnn_eltwise_node.h"
#include <limits>
#include "common/cpu_memcpy.h"
#include "common/tensor_desc_creator.h"
#include "common/blocked_desc_creator.h"
#include <cpu_memory_desc_utils.h>
using namespace mkldnn;
using namespace MKLDNNPlugin;
@@ -61,19 +62,19 @@ MKLDNNConcatNode::MKLDNNConcatNode(const std::shared_ptr<ngraph::Node>& op, cons
}
void MKLDNNConcatNode::getSupportedDescriptors() {
auto& firstParentDims = getParentEdgeAt(0)->getDims();
auto& firstParentDims = getParentEdgeAt(0)->getShape().getStaticDims();
for (size_t i = 1; i < getParentEdges().size(); i++) {
auto& dims = getParentEdgeAt(i)->getDims();
auto& dims = getParentEdgeAt(i)->getShape().getStaticDims();
bool incorrectDims = false;
for (size_t j = 0; j < firstParentDims.ndims(); j++) {
for (size_t j = 0; j < firstParentDims.size(); j++) {
if (j == axis)
continue;
if (dims.ndims() != firstParentDims.ndims() || firstParentDims[j] != dims[j]) {
if (dims.size() != firstParentDims.size() || firstParentDims[j] != dims[j]) {
incorrectDims = true;
break;
}
}
if (incorrectDims || firstParentDims.ndims() == 0) {
if (incorrectDims || firstParentDims.size() == 0) {
IE_THROW() << "Incorrect input dimensions for concat node " << getName();
}
}
@@ -100,19 +101,19 @@ void MKLDNNConcatNode::initSupportedPrimitiveDescriptors() {
// Concat supports only equal precisions for inputs and output
outputPrecision = inputPrecision;
auto& dstDims = getChildEdgeAt(0)->getDims();
std::vector<TensorDescCreatorTypes> tdCreatorTypes = {TensorDescCreatorTypes::ncsp, TensorDescCreatorTypes::nspc};
auto& dstDims = getChildEdgeAt(0)->getShape().getStaticDims();
std::vector<LayoutType> tdCreatorTypes = {LayoutType::ncsp, LayoutType::nspc};
// check if blocked layouts are available the channels size should be evenly divided by the block size to avoid slow oneDNN ref implementation
if (dstDims.ndims() > channelAxis) {
for (auto item : { std::make_pair(8lu, TensorDescCreatorTypes::nCsp8c), std::make_pair(16lu, TensorDescCreatorTypes::nCsp16c)}) {
SizeVector blkDims = dstDims.ToSizeVector();
if (dstDims.size() > channelAxis) {
for (auto item : { std::make_pair(8lu, LayoutType::nCsp8c), std::make_pair(16lu, LayoutType::nCsp16c)}) {
SizeVector blkDims = dstDims;
if (blkDims[channelAxis] % item.first)
continue;
bool blocked = true;
for (size_t i = 0; i < getParentEdges().size(); i++) {
auto& srcDims = getParentEdgeAt(i)->getDims();
auto& srcDims = getParentEdgeAt(i)->getShape().getStaticDims();
if (srcDims[channelAxis] % item.first) {
blocked = false;
break;
@@ -126,28 +127,27 @@ void MKLDNNConcatNode::initSupportedPrimitiveDescriptors() {
std::vector<size_t> pdIndexesToReuse;
auto& creatorsMap = TensorDescCreator::getCommonCreators();
auto itrRange = TensorDescCreator::makeFilteredRange(creatorsMap, static_cast<unsigned>(dstDims.ndims()), tdCreatorTypes);
auto& creatorsMap = BlockedDescCreator::getCommonCreators();
auto itrRange = BlockedDescCreator::makeFilteredRange(creatorsMap, static_cast<unsigned>(dstDims.size()), tdCreatorTypes);
for (auto itr = itrRange.first; itr != itrRange.second; ++itr) {
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = true;
config.outConfs.resize(1);
config.outConfs[0].inPlace = -1;
config.outConfs[0].constant = false;
config.outConfs[0].desc = itr->second->createDesc(outputPrecision, dstDims.ToSizeVector());
memory::format_tag outFmt = MKLDNNMemoryDesc(config.outConfs[0].desc).getFormat();
config.outConfs[0].desc = itr->second->createUniqueDesc(outputPrecision, dstDims);
config.inConfs.resize(getParentEdges().size());
for (size_t i = 0; i < getParentEdges().size(); ++i) {
config.inConfs[i].inPlace = -1;
config.inConfs[i].constant = false;
config.inConfs[i].desc = MKLDNNExtensionUtils::getUninitTensorDesc(
itr->second->createDesc(inputPrecision, getParentEdgeAt(i)->getDims().ToSizeVector()));
config.inConfs[i].desc = MemoryDescUtils::applyUndefinedOffset(
itr->second->createDesc(inputPrecision, getParentEdgeAt(i)->getShape().getStaticDims()));
}
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::ref, outFmt);
if (itr->first != TensorDescCreatorTypes::nspc) {
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::ref);
if (itr->first != LayoutType::nspc) {
pdIndexesToReuse.push_back(supportedPrimitiveDescriptors.size() - 1);
}
}
@@ -161,8 +161,8 @@ void MKLDNNConcatNode::initSupportedPrimitiveDescriptors() {
const auto& refConfig = supportedPrimitiveDescriptors[refPdIndex].getConfig();
auto config = refConfig;
const auto& order = refConfig.outConfs[0].desc.getBlockingDesc().getOrder();
const auto& blkDims = refConfig.outConfs[0].desc.getBlockingDesc().getBlockDims();
const auto &order = refConfig.outConfs[0].desc->as<BlockedMemoryDesc>()->getOrder();
const auto &blkDims = refConfig.outConfs[0].desc->as<BlockedMemoryDesc>()->getBlockDims();
auto numOfDim = blkDims.size();
SizeVector offsets(numOfDim, 0lu);
@@ -178,17 +178,16 @@ void MKLDNNConcatNode::initSupportedPrimitiveDescriptors() {
}
}
config.outConfs[0].desc = TensorDesc(outputPrecision, dstDims.ToSizeVector(), {blkDims, order, offset, offsets, strides});
memory::format_tag outFmt = MKLDNNMemoryDesc(config.outConfs[0].desc).getFormat();
config.outConfs[0].desc = MKLDNNPlugin::make_unique<BlockedMemoryDesc>(outputPrecision, dstDims, blkDims, order, offset, offsets, strides);
for (size_t i = 0; i < getParentEdges().size(); i++) {
const auto& srcBlkDims = refConfig.inConfs[i].desc.getBlockingDesc().getBlockDims();
const auto& dims = refConfig.inConfs[i].desc.getDims();
const auto& srcBlkDims = refConfig.inConfs[i].desc->as<BlockedMemoryDesc>()->getBlockDims();
const auto& dims = refConfig.inConfs[i].desc->getShape().getStaticDims();
config.inConfs[i].inPlace = 0;
config.inConfs[i].desc = TensorDesc(inputPrecision, dims, {srcBlkDims, order, offset, offsets, strides});
config.inConfs[i].desc = MKLDNNPlugin::make_unique<BlockedMemoryDesc>(inputPrecision, dims, srcBlkDims, order, offset, offsets, strides);
}
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown, outFmt);
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown);
}
}
@@ -210,7 +209,9 @@ void MKLDNNConcatNode::selectOptimalPrimitiveDescriptor() {
canOptimize = false;
}
std::map<PartialBlkDesc, size_t> formatFrequency;
std::map<LayoutType, size_t> formatFrequency;
std::vector<LayoutType> supportedLayouts = {LayoutType::ncsp, LayoutType::nspc, LayoutType::nCsp8c, LayoutType::nCsp16c};
for (size_t i = 0; i < getParentEdges().size(); i++) {
auto parentEdge = getParentEdgeAt(i);
auto parent = parentEdge->getParent();
@@ -224,10 +225,11 @@ void MKLDNNConcatNode::selectOptimalPrimitiveDescriptor() {
if (outputIndex < 0 || outputIndex >= parent_config.outConfs.size())
IE_THROW() << "Cannot find index of output node";
const auto &port_desc = parent_config.outConfs[outputIndex].desc;
if (port_desc.getLayout() == Layout::ANY)
continue;
auto partial_format_desc = PartialBlkDesc::extractFrom(port_desc);
formatFrequency[partial_format_desc] += 1;
for (auto& item : supportedLayouts) {
if (port_desc->hasLayoutType(item)) {
formatFrequency[item] += 1;
}
}
}
for (size_t i = 0; i < getChildEdges().size(); i++) {
auto childEdge = getChildEdgeAt(i);
@@ -241,37 +243,47 @@ void MKLDNNConcatNode::selectOptimalPrimitiveDescriptor() {
if (inputIndex < 0 || inputIndex >= config.inConfs.size())
IE_THROW() << "Cannot find index of output node";
const auto &port_desc = config.inConfs[inputIndex].desc;
if (port_desc.getLayout() == Layout::ANY)
continue;
auto partial_format_desc = PartialBlkDesc::extractFrom(port_desc);
formatFrequency[partial_format_desc] += 1;
for (auto& item : supportedLayouts) {
if (port_desc->hasLayoutType(item)) {
formatFrequency[item] += 1;
}
}
}
size_t maxCount = 0;
auto outDims = getChildEdgeAt(0)->getDims().ToSizeVector();
auto convertTo = PartialBlkDesc::makePlain(outDims);
auto outDims = getChildEdgeAt(0)->getShape().getStaticDims();
LayoutType convertTo = LayoutType::ncsp;
for (auto &it : formatFrequency) {
if (it.second > maxCount) {
maxCount = it.second;
convertTo = it.first;
} else if (it.second == maxCount) {
if (isInQuantizedGraph && it.first == PartialBlkDesc::makeTailC(outDims)) {
if (isInQuantizedGraph && it.first == LayoutType::nspc) {
convertTo = it.first;
} else if (it.first == PartialBlkDesc::makeCBlocked(outDims, 8) || it.first == PartialBlkDesc::makeCBlocked(outDims, 16)) {
} else if (it.first == LayoutType::nCsp8c || it.first == LayoutType::nCsp16c) {
convertTo = it.first;
}
}
}
if (convertTo.isAutoExtendedWith(outDims))
convertTo = PartialBlkDesc::makePlain(outDims);
for (size_t i = 0; i < getParentEdges().size(); i++) {
if (convertTo.isAutoExtendedWith(getParentEdgeAt(i)->getDims().ToSizeVector()))
convertTo = PartialBlkDesc::makePlain(outDims);
for (auto& item : { std::make_pair(8lu, LayoutType::nCsp8c), std::make_pair(16lu, LayoutType::nCsp16c) }) {
if (convertTo == item.second) {
if (outDims[1] % item.first != 0) {
convertTo = LayoutType::ncsp;
break;
}
for (size_t i = 0; i < getParentEdges().size(); i++) {
auto& inpDims = getParentEdgeAt(i)->getShape().getStaticDims();
if (inpDims[1] % item.first != 0) {
convertTo = LayoutType::ncsp;
break;
}
}
}
}
for (size_t i = 0; i < supportedPrimitiveDescriptors.size(); ++i) {
if (PartialBlkDesc::extractFrom(supportedPrimitiveDescriptors[i].getConfig().outConfs[0].desc) == convertTo) {
if (supportedPrimitiveDescriptors[i].getConfig().outConfs[0].desc->hasLayoutType(convertTo)) {
if (IMPLICATION(supportedPrimitiveDescriptors[i].getImplementationType() == impl_desc_type::unknown, canOptimize)) {
canSelectPrimitive.push_back(i);
}
@@ -283,7 +295,7 @@ void MKLDNNConcatNode::selectOptimalPrimitiveDescriptor() {
return;
}
// if there are more then one PD with similar data layouts - select the optimized one
// if there are more than one PD with similar data layouts - select the optimized one
for (auto indx : canSelectPrimitive) {
if (supportedPrimitiveDescriptors[indx].getImplementationType() == impl_desc_type::unknown) {
selectPrimitiveDescriptorByIndex(static_cast<int>(indx));
@@ -321,7 +333,7 @@ void MKLDNNConcatNode::createPrimitive() {
IE_THROW() << "Preferable primitive descriptor is not set.";
//check if selected Tensor descriptor has nspc layout and concat axis is C
if (axis == channelAxis && getChildEdgeAt(0)->getMemory().GetDesc().isTailCFormat()) {
if (axis == channelAxis && getChildEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nspc)) {
canOptimizeNspc = true;
return;
}
@@ -337,8 +349,8 @@ void MKLDNNConcatNode::createPrimitive() {
}
auto desc = srcMemPtr->GetDescriptor();
auto dims = getParentEdgeAt(i)->getDims();
for (size_t j = 0; j < dims.ndims(); j++) {
auto& dims = getParentEdgeAt(i)->getShape().getStaticDims();
for (size_t j = 0; j < dims.size(); j++) {
desc.data.dims[j] = dims[j];
}
@@ -346,8 +358,8 @@ void MKLDNNConcatNode::createPrimitive() {
}
auto desc = getChildEdgeAt(0)->getMemory().GetDescriptor();
auto dims = getChildEdgeAt(0)->getDims();
for (size_t i = 0; i < dims.ndims(); i++) {
auto& dims = getChildEdgeAt(0)->getShape().getStaticDims();
for (size_t i = 0; i < dims.size(); i++) {
desc.data.dims[i] = dims[i];
desc.data.padded_dims[i] = dims[i];
}
@@ -370,79 +382,77 @@ void MKLDNNConcatNode::initOptimalPrimitiveDescriptor() {
if (selected_pd == nullptr)
IE_THROW() << "Preferable primitive descriptor is not set.";
if (!isOptimized()) {
if (!isOptimized()) {
MKLDNNNode::initOptimalPrimitiveDescriptor();
auto config = selected_pd->getConfig();
if (!isInitConfig(config)) {
if (!isConfigDefined(config)) {
for (size_t i = 0; i < config.inConfs.size(); i++) {
config.inConfs[i].desc = getConfiguredInputDesc(config, i);
config.inConfs[i].desc = getDefinedInputDesc(config, i);
// Concat doesn't support different precision on inputs
config.inConfs[i].desc.setPrecision(inputPrecision);
config.inConfs[i].desc->setPrecision(inputPrecision);
}
for (size_t i = 0; i < config.outConfs.size(); i++) {
config.outConfs[i].desc = getConfiguredOutputDesc(config, i);
config.outConfs[i].desc.setPrecision(outputPrecision);
config.outConfs[i].desc = getDefinedOutputDesc(config, i);
config.outConfs[i].desc->setPrecision(outputPrecision);
}
initDescriptor(config);
}
return;
}
auto config = selected_pd->getConfig();
if (isInitConfig(config))
if (isConfigDefined(config))
return;
for (size_t i = 0; i < config.outConfs.size(); i++) {
if (!isUninitTensorDesc(config.outConfs[i].desc))
if (config.outConfs[i].desc->isDefined())
continue;
int num = getChildEdgeAt(i)->getOutputNum();
if (num >= 0) {
auto childConf = getChildEdgeAt(i)->getChild()->getSelectedPrimitiveDescriptor()->getConfig().inConfs[num];
childConf.desc.setPrecision(config.outConfs[i].desc.getPrecision());
childConf.desc->setPrecision(config.outConfs[i].desc->getPrecision());
if (getChildEdgeAt(i)->getChild()->getSelectedPrimitiveDescriptor()) {
if (isUninitTensorDesc(childConf.desc) && childConf.inPlace >= 0)
if (!childConf.desc->isDefined() && childConf.inPlace >= 0)
getChildEdgeAt(i)->getChild()->initOptimalPrimitiveDescriptor();
if (!isUninitTensorDesc(childConf.desc) &&
MKLDNNExtensionUtils::initTensorsAreEqual(childConf.desc, config.outConfs[i].desc)) {
config.outConfs[i].desc = childConf.desc;
if (childConf.desc->isDefined() && childConf.desc->isCompatible(*config.outConfs[i].desc)) {
config.outConfs[i].desc = childConf.desc->clone();
continue;
}
}
}
config.outConfs[i].desc = InferenceEngine::TensorDesc(config.outConfs[i].desc.getPrecision(),
config.outConfs[i].desc.getDims(), {
config.outConfs[i].desc.getBlockingDesc().getBlockDims(),
config.outConfs[i].desc.getBlockingDesc().getOrder()
});
// reset undefined offsets
config.outConfs[i].desc = MemoryDescUtils::resetOffset(config.outConfs[i].desc.get());
}
auto firstOutBlockingDesc = MemoryDescUtils::convertToBlockedDescriptor(*config.outConfs[0].desc);
size_t offset = 0;
for (size_t i = 0; i < config.inConfs.size(); i++) {
config.inConfs[i].desc = InferenceEngine::TensorDesc(config.inConfs[i].desc.getPrecision(),
config.inConfs[i].desc.getDims(), {
config.inConfs[i].desc.getBlockingDesc().getBlockDims(),
config.inConfs[i].desc.getBlockingDesc().getOrder(),
config.outConfs[0].desc.getBlockingDesc().getOffsetPadding() + offset,
config.outConfs[0].desc.getBlockingDesc().getOffsetPaddingToData(),
config.outConfs[0].desc.getBlockingDesc().getStrides()
});
auto inpBlockingDesc = MemoryDescUtils::convertToBlockedDescriptor(*config.inConfs[i].desc);
config.inConfs[i].desc = MKLDNNPlugin::make_unique<BlockedMemoryDesc>(inpBlockingDesc.getPrecision(),
inpBlockingDesc.getShape().getStaticDims(),
inpBlockingDesc.getBlockDims(),
inpBlockingDesc.getOrder(),
firstOutBlockingDesc.getOffsetPadding() + offset,
firstOutBlockingDesc.getOffsetPaddingToData(),
firstOutBlockingDesc.getStrides());
size_t axisSize = 1;
if (config.inConfs[0].desc.getLayout() == Layout::NHWC) {
// This is more general and works for any "direct" Layout (such as nchw or nhwc), but it doesn't work for nchw8c
size_t realAxis = inverseOrder(config.inConfs[0].desc.getBlockingDesc().getOrder(), axis);
for (size_t j = realAxis; j < config.inConfs[i].desc.getBlockingDesc().getBlockDims().size(); j++) {
size_t jj = config.inConfs[0].desc.getBlockingDesc().getOrder()[j];
axisSize *= config.inConfs[i].desc.getBlockingDesc().getBlockDims()[jj];
auto firstInpBlockingDesc = MemoryDescUtils::convertToBlockedDescriptor(*config.inConfs[0].desc);
if (firstInpBlockingDesc.hasLayoutType(LayoutType::nspc)) {
// This is more general and works for any "direct" Layout (such as nchw or nhwc), but it doesn't work for blocked
size_t realAxis = inverseOrder(firstInpBlockingDesc.getOrder(), axis);
for (size_t j = realAxis; j < inpBlockingDesc.getBlockDims().size(); j++) {
size_t jj = firstInpBlockingDesc.getOrder()[j];
axisSize *= inpBlockingDesc.getBlockDims()[jj];
}
} else {
// This works for nchw and nchw8c/nchw16c
for (size_t j = axis; j < config.inConfs[i].desc.getBlockingDesc().getBlockDims().size(); j++) {
axisSize *= config.inConfs[i].desc.getBlockingDesc().getBlockDims()[j];
for (size_t j = axis; j < inpBlockingDesc.getBlockDims().size(); j++) {
axisSize *= inpBlockingDesc.getBlockDims()[j];
}
}
offset += axisSize;
@@ -470,7 +480,7 @@ void MKLDNNConcatNode::execute(mkldnn::stream strm) {
}
InferenceEngine::Precision MKLDNNConcatNode::getRuntimePrecision() const {
return MKLDNNExtensionUtils::getMaxPrecision(getInputPrecisions());
return getMaxPrecision(getInputPrecisions());
}
void MKLDNNConcatNode::execNspcSpecCase() {
@@ -18,6 +18,7 @@
#include <ngraph/ops.hpp>
#include <cpu/x64/jit_generator.hpp>
#include "common/cpu_convert.h"
#include <cpu_memory_desc_utils.h>
using namespace mkldnn;
using namespace MKLDNNPlugin;
@@ -68,7 +69,7 @@ MKLDNNConvolutionNode::MKLDNNConvolutionNode(const std::shared_ptr<ngraph::Node>
biasesDims = { groupOC };
for (int i = 0; i < convolutionOp->get_strides().size(); i++) {
stride.push_back(static_cast<ptrdiff_t>(convolutionOp->get_strides()[i]));
stride.push_back(convolutionOp->get_strides()[i]);
}
for (int i = 0; i < convolutionOp->get_dilations().size(); i++) {
dilation.push_back(static_cast<ptrdiff_t>(convolutionOp->get_dilations()[i]) - 1);
@@ -90,7 +91,7 @@ MKLDNNConvolutionNode::MKLDNNConvolutionNode(const std::shared_ptr<ngraph::Node>
biasesDims = {groupOC * groupNum};
for (int i = 0; i < groupConvolutionOp->get_strides().size(); i++) {
stride.push_back(static_cast<ptrdiff_t>(groupConvolutionOp->get_strides()[i]));
stride.push_back(groupConvolutionOp->get_strides()[i]);
}
for (int i = 0; i < groupConvolutionOp->get_dilations().size(); i++) {
dilation.push_back(static_cast<ptrdiff_t>(groupConvolutionOp->get_dilations()[i]) - 1);
@@ -142,17 +143,6 @@ void MKLDNNConvolutionNode::getSupportedDescriptors() {
(withBiases ? (getParentEdgeAt(2)->getParent()->isConstant() && getParentEdgeAt(2)->getParent()->getType() == Input) : true);
}
if (isWinograd()) {
internalBlobDesc.emplace_back([&](primitive_desc_iterator &primitive_desc_it, size_t idx) -> MKLDNNMemoryDesc {
return MKLDNNMemoryDesc(primitive_desc_it.weights_desc(0));
});
internalBlobDesc.emplace_back([&](primitive_desc_iterator &primitive_desc_it, size_t idx) -> MKLDNNMemoryDesc {
if (!withBiases)
return MKLDNNMemoryDesc();
return MKLDNNMemoryDesc(primitive_desc_it.weights_desc(1));
});
}
withSum = false;
int expectedInputEdgesNum = static_cast<int>(getOriginalInputsNumber());
for (int i = 0; i < fusedWith.size(); i++) {
@@ -169,36 +159,6 @@ void MKLDNNConvolutionNode::getSupportedDescriptors() {
}
}
// we can't convert winograd memory descriptor to TensorDesc, so we removed weight and bias edges and put data into internalBlobs
if (isWinograd()) {
std::vector<MKLDNNEdgePtr> edgesToRemove;
internalBlobs.push_back(createInternalBlob(weightDims, 1, isGrouped));
edgesToRemove.push_back(getParentEdgeAt(1));
if (withBiases) {
internalBlobs.push_back(createInternalBlob(biasesDims, 2));
edgesToRemove.push_back(getParentEdgeAt(2));
}
if (expectedInputEdgesNum - getOriginalInputsNumber() > 0) {
size_t reconnectPort = 1;
for (size_t startPort = 2 + (withBiases ? 1 : 0); startPort < expectedInputEdgesNum; startPort++) {
getParentEdgeAt(startPort)->setChildPort(reconnectPort);
reconnectPort++;
}
}
for (size_t i = 0; i < edgesToRemove.size(); i++) {
removeEdge(edgesToRemove[i]);
}
expectedInputEdgesNum -= getOriginalInputsNumber() - 1;
if (withBiases) {
inDims.erase(inDims.begin() + 2);
}
inDims.erase(inDims.begin() + 1);
}
auto inputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(getOriginalInputPrecisionAtPort(0));
if (!inputZeroPoints.empty())
inputDataType = memory::data_type::u8;
@@ -234,7 +194,7 @@ void MKLDNNConvolutionNode::getSupportedDescriptors() {
if (getChildEdges().empty())
IE_THROW() << "Incorrect number of output edges for layer " << getName();
int ndims = getParentEdgesAtPort(0)[0]->getDims().ndims();
int ndims = getParentEdgesAtPort(0)[0]->getShape().getRank();
MKLDNNDims weightsDims = MKLDNNDims(weightDims);
withDWConv = isFusedWith(Convolution);
@@ -242,10 +202,14 @@ void MKLDNNConvolutionNode::getSupportedDescriptors() {
for (int i = 0; i < fusedWith.size(); i++) {
auto *convolutionNode = dynamic_cast<MKLDNNConvolutionNode *>(fusedWith[i].get());
if (convolutionNode) {
dw_conv_ih = convolutionNode->inDims[0][convolutionNode->inDims[0].ndims() - 2];
dw_conv_iw = convolutionNode->inDims[0][convolutionNode->inDims[0].ndims() - 1];
dw_conv_oc = convolutionNode->outDims[0][1];
const auto &dwWeightsDims = convolutionNode->inDims[1].ToSizeVector();
auto& inActivationDims = convolutionNode->inputShapes[0].getStaticDims();
dw_conv_ih = inActivationDims[convolutionNode->inputShapes[0].getRank() - 2];
dw_conv_iw = inActivationDims[convolutionNode->inputShapes[0].getRank() - 1];
auto& outDims = convolutionNode->outputShapes[0].getStaticDims();
dw_conv_oc = outDims[1];
const auto &dwWeightsDims = convolutionNode->inputShapes[1].getStaticDims();
dw_conv_kernel.push_back(dwWeightsDims[dwWeightsDims.size() - 1]);
dw_conv_kernel.push_back(dwWeightsDims[dwWeightsDims.size() - 2]);
dw_conv_strides = convolutionNode->getStride();
@@ -263,8 +227,8 @@ void MKLDNNConvolutionNode::getSupportedDescriptors() {
for (int j = 0; j < paddingR.size(); j++) {
int with_group = isGrouped ? 1 : 0;
int krn = weightsDims[with_group + 2 + j];
int src = getParentEdgeAt(0)->getDims()[2 + j];
int dst = getChildEdgeAt(0)->getDims()[2 + j];
int src = getParentEdgeAt(0)->getShape().getStaticDims()[2 + j];
int dst = getChildEdgeAt(0)->getShape().getStaticDims()[2 + j];
krn = (krn - 1)*(dilation[j] + 1) + 1;
int calc_dst = (src - krn + paddingL[j]) / stride[j] + 1;
@@ -273,18 +237,18 @@ void MKLDNNConvolutionNode::getSupportedDescriptors() {
}
}
MKLDNNMemoryDesc in_candidate, out_candidate;
MemoryDescPtr in_candidate, out_candidate;
if (canBeExecutedInInt8()) {
// We have to extend convolution_x8s8s32x from oneDNN to support BF16 output data type
if (outputDataType == memory::data_type::bf16)
outputDataType = memory::data_type::f32;
if (eltwisePrecision == Precision::BF16)
eltwisePrecision = Precision::FP32;
in_candidate = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, ndims == 5 ? memory::format_tag::ndhwc
: memory::format_tag::nhwc);
out_candidate = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, ndims == 5 ? memory::format_tag::ndhwc
: memory::format_tag::nhwc);
createDescriptor({in_candidate}, {out_candidate});
in_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(0)->getShape().getStaticDims(),
inputDataType, ndims == 5 ? memory::format_tag::ndhwc : memory::format_tag::nhwc);
out_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getChildEdgeAt(0)->getShape().getStaticDims(),
outputDataType, ndims == 5 ? memory::format_tag::ndhwc : memory::format_tag::nhwc);
createDescriptor({ in_candidate.get() }, { out_candidate.get() });
} else {
inputDataType = (getOriginalInputPrecisionAtPort(0) == Precision::BF16
&& !(isDepthWise() && ndims == 5)) ? memory::data_type::bf16 : memory::data_type::f32;
@@ -321,33 +285,36 @@ void MKLDNNConvolutionNode::getSupportedDescriptors() {
memory::format_tag nCsp16c = ndims == 4 ? memory::format_tag::nChw16c : memory::format_tag::nCdhw16c;
memory::format_tag nCsp8c = ndims == 4 ? memory::format_tag::nChw8c : memory::format_tag::nCdhw8c;
auto inputDims = getParentEdgeAt(0)->getShape().getStaticDims();
auto outputDims = getChildEdgeAt(0)->getShape().getStaticDims();
if (IC == 1 && groupOC == 1) {
in_candidate = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, ncsp);
out_candidate = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, ncsp);
createDescriptor({in_candidate}, {out_candidate});
in_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(inputDims, inputDataType, ncsp);
out_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(outputDims, outputDataType, ncsp);
createDescriptor({ in_candidate.get() }, { out_candidate.get() });
} else if (IC < 4) {
in_candidate = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, ncsp);
out_candidate = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, nCsp16c);
createDescriptor({in_candidate}, {out_candidate});
out_candidate = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, nCsp8c);
createDescriptor({in_candidate}, {out_candidate});
in_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(inputDims, inputDataType, ncsp);
out_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(outputDims, outputDataType, nCsp16c);
createDescriptor({ in_candidate.get() }, { out_candidate.get() });
out_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(outputDims, outputDataType, nCsp8c);
createDescriptor({ in_candidate.get() }, { out_candidate.get() });
} else {
in_candidate = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, nCsp16c);
out_candidate = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, nCsp16c);
createDescriptor({in_candidate}, {out_candidate});
in_candidate = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, nCsp8c);
out_candidate = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, nCsp8c);
createDescriptor({in_candidate}, {out_candidate});
in_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(inputDims, inputDataType, nCsp16c);
out_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(outputDims, outputDataType, nCsp16c);
createDescriptor({ in_candidate.get() }, { out_candidate.get() });
in_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(inputDims, inputDataType, nCsp8c);
out_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(outputDims, outputDataType, nCsp8c);
createDescriptor({ in_candidate.get() }, { out_candidate.get() });
}
in_candidate = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, ncsp);
out_candidate = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, ncsp);
createDescriptor({in_candidate}, {out_candidate});
in_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(inputDims, inputDataType, ncsp);
out_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(outputDims, outputDataType, ncsp);
createDescriptor({ in_candidate.get() }, { out_candidate.get() });
if (inputDataType != memory::data_type::bf16 && isNspcAvailable()) {
in_candidate = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, nspc);
out_candidate = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, nspc);
createDescriptor({in_candidate}, {out_candidate});
in_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(inputDims, inputDataType, nspc);
out_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(outputDims, outputDataType, nspc);
createDescriptor({ in_candidate.get() }, { out_candidate.get() });
}
}
}
@@ -422,15 +389,18 @@ void MKLDNNConvolutionNode::initSupportedPrimitiveDescriptors() {
continue;
auto itpd = desc.createPrimitiveDescriptorIterator(getEngine(), attr);
while (static_cast<bool>(itpd)) {
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = true;
for (size_t i = 0; i < descInputNumbers(desc); i++) {
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = getSrcMemDesc(itpd, i);
if (!isGrouped)
dataConfig.desc = MKLDNNExtensionUtils::getUninitTensorDesc(dataConfig.desc);
auto srcDesc = getSrcMemDesc(itpd, i);
if (isGrouped || srcDesc->getFormatKind() != dnnl_format_kind_t::dnnl_blocked)
dataConfig.desc = std::move(srcDesc);
else
dataConfig.desc = MemoryDescUtils::applyUndefinedOffset(*srcDesc);
config.inConfs.push_back(dataConfig);
}
@@ -438,34 +408,38 @@ void MKLDNNConvolutionNode::initSupportedPrimitiveDescriptors() {
auto weightsPrc = MKLDNNExtensionUtils::IEPrecisionToDataType(dw_conv_in_dt == mkldnn_u8 ? Precision::I8 : Precision::FP32);
auto biasPrc = memory::data_type::f32;
MKLDNNDims dwWeightsDims({dw_conv_oc, (ptrdiff_t)1, (ptrdiff_t)1, dw_conv_kernel[Y_AXIS], dw_conv_kernel[X_AXIS]});
MKLDNNDims dwBiasesDims({dw_conv_oc});
std::vector<size_t> dwWeightsDims({dw_conv_oc, 1, 1, dw_conv_kernel[Y_AXIS], dw_conv_kernel[X_AXIS]});
std::vector<size_t> dwBiasesDims({dw_conv_oc});
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = MKLDNNMemoryDesc(dwWeightsDims, weightsPrc, memory::format_tag::Goihw8g);
dataConfig.desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(dwWeightsDims, weightsPrc, memory::format_tag::Goihw8g);
config.inConfs.push_back(dataConfig);
dataConfig.desc = MKLDNNMemoryDesc(dwBiasesDims, biasPrc, memory::format_tag::x);
dataConfig.desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(dwBiasesDims, biasPrc, memory::format_tag::x);
config.inConfs.push_back(dataConfig);
}
for (size_t i = 0; i < descOutputNumbers(desc); i++) {
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
if (withSum) {
dataConfig.inPlace = getParentEdges().size() - 1;
}
dataConfig.constant = false;
dataConfig.desc = getDstMemDesc(itpd, i);
if (!isGrouped)
dataConfig.desc = MKLDNNExtensionUtils::getUninitTensorDesc(dataConfig.desc);
auto dstDesc = getDstMemDesc(itpd, i);
if (isGrouped || dstDesc->getFormatKind() != dnnl_format_kind_t::dnnl_blocked)
dataConfig.desc = std::move(dstDesc);
else
dataConfig.desc = MemoryDescUtils::applyUndefinedOffset(*dstDesc);
config.outConfs.push_back(dataConfig);
if (withSum) {
dataConfig.inPlace = -1;
dataConfig.desc.setPrecision(eltwisePrecision);
dataConfig.desc->setPrecision(eltwisePrecision);
config.inConfs.push_back(dataConfig);
}
}
@@ -506,9 +480,10 @@ bool MKLDNNConvolutionNode::created() const {
return getType() == Convolution;
}
void MKLDNNConvolutionNode::createDescriptor(const std::vector<InferenceEngine::TensorDesc> &inputDesc,
const std::vector<InferenceEngine::TensorDesc> &outputDesc) {
TensorDesc inDesc = inputDesc[0], outDesc = outputDesc[0];
void MKLDNNConvolutionNode::createDescriptor(const std::vector<const MemoryDesc*>& inputDesc,
const std::vector<const MemoryDesc*>& outputDesc) {
auto inDesc = MemoryDescUtils::convertToMKLDNNMemoryDesc(*inputDesc[0]);
auto outDesc = MemoryDescUtils::convertToMKLDNNMemoryDesc(*outputDesc[0]);
memory::data_type wdt = MKLDNNExtensionUtils::IEPrecisionToDataType(inDesc.getPrecision());
memory::data_type bdt = memory::data_type::f32;
@@ -517,12 +492,9 @@ void MKLDNNConvolutionNode::createDescriptor(const std::vector<InferenceEngine::
wdt = memory::data_type::s8;
}
MKLDNNMemoryDesc in_candidate(inDesc);
MKLDNNMemoryDesc out_candidate(outDesc);
MKLDNNDims blocked_weightDims(weightDims);
MKLDNNDims blocked_biasesDims(biasesDims);
MKLDNNMemoryDesc wgh_candidate{blocked_weightDims, wdt, memory::format_tag::any};
mkldnn::memory::desc wgh_candidate(blocked_weightDims, wdt, memory::format_tag::any);
std::vector<mkldnn::algorithm> algorithms;
@@ -534,17 +506,17 @@ void MKLDNNConvolutionNode::createDescriptor(const std::vector<InferenceEngine::
try {
std::shared_ptr<mkldnn::convolution_forward::desc> conv_desc;
if (withBiases) {
MKLDNNMemoryDesc bias_candidate{blocked_biasesDims, bdt, memory::format_tag::any};
mkldnn::memory::desc bias_candidate(blocked_biasesDims, bdt, memory::format_tag::any);
conv_desc.reset(new convolution_forward::desc(prop_kind::forward_scoring, alg,
in_candidate, wgh_candidate, bias_candidate, out_candidate,
inDesc, wgh_candidate, bias_candidate, outDesc,
mkldnn::memory::dims(stride.begin(), stride.end()),
mkldnn::memory::dims(dilation.begin(), dilation.end()),
mkldnn::memory::dims(paddingL.begin(), paddingL.end()),
mkldnn::memory::dims(paddingR.begin(), paddingR.end())));
} else {
conv_desc.reset(new convolution_forward::desc(prop_kind::forward_scoring, alg,
in_candidate, wgh_candidate, out_candidate,
inDesc, wgh_candidate, outDesc,
mkldnn::memory::dims(stride.begin(), stride.end()),
mkldnn::memory::dims(dilation.begin(), dilation.end()),
mkldnn::memory::dims(paddingL.begin(), paddingL.end()),
@@ -570,7 +542,7 @@ void MKLDNNConvolutionNode::addZeroPoints(mkldnn::primitive_attr& attr) const {
}
}
void MKLDNNConvolutionNode::initDescriptor(const InferenceEngine::LayerConfig& config) {
void MKLDNNConvolutionNode::initDescriptor(const NodeConfig& config) {
auto* selectedPD = getSelectedPrimitiveDescriptor();
if (!selectedPD) {
return;
@@ -590,14 +562,14 @@ void MKLDNNConvolutionNode::initDescriptor(const InferenceEngine::LayerConfig& c
// }
if (isStridedBlobsSupported) {
createDescriptor({config.inConfs[0].desc}, {config.outConfs[0].desc});
createDescriptor({config.inConfs[0].desc.get()}, {config.outConfs[0].desc.get()});
}
mkldnn::primitive_attr attr;
addZeroPoints(attr);
setPostOps(attr);
InferenceEngine::LayerConfig rightConfig = selectedPD->getConfig();
auto rightConfig = selectedPD->getConfig();
size_t selected_count = 0;
bool containJitImpl = false;
@@ -608,10 +580,10 @@ void MKLDNNConvolutionNode::initDescriptor(const InferenceEngine::LayerConfig& c
continue;
auto itpd = desc.createPrimitiveDescriptorIterator(getEngine(), attr);
while (static_cast<bool>(itpd)) {
InferenceEngine::LayerConfig cfg;
NodeConfig cfg;
cfg.dynBatchSupport = true;
for (size_t j = 0; j < descInputNumbers(desc); j++) {
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = getSrcMemDesc(itpd, j);
@@ -622,27 +594,27 @@ void MKLDNNConvolutionNode::initDescriptor(const InferenceEngine::LayerConfig& c
auto weightsPrc = MKLDNNExtensionUtils::IEPrecisionToDataType(dw_conv_in_dt == mkldnn_u8 ? Precision::I8 : Precision::FP32);
auto biasPrc = memory::data_type::f32;
MKLDNNDims dwWeightsDims({dw_conv_oc, (ptrdiff_t)1, (ptrdiff_t)1, dw_conv_kernel[Y_AXIS], dw_conv_kernel[X_AXIS]});
MKLDNNDims dwBiasesDims({dw_conv_oc});
std::vector<size_t> dwWeightsDims({dw_conv_oc, 1, 1, dw_conv_kernel[Y_AXIS], dw_conv_kernel[X_AXIS]});
std::vector<size_t> dwBiasesDims({dw_conv_oc});
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = MKLDNNMemoryDesc(dwWeightsDims, weightsPrc, memory::format_tag::Goihw8g);
dataConfig.desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(dwWeightsDims, weightsPrc, memory::format_tag::Goihw8g);
cfg.inConfs.push_back(dataConfig);
dataConfig.desc = MKLDNNMemoryDesc(dwBiasesDims, biasPrc, memory::format_tag::x);
dataConfig.desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(dwBiasesDims, biasPrc, memory::format_tag::x);
cfg.inConfs.push_back(dataConfig);
}
for (size_t j = 0; j < descOutputNumbers(desc); j++) {
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = getDstMemDesc(itpd, j);
if (withSum) {
auto eltwiseConfig = dataConfig;
eltwiseConfig.desc.setPrecision(eltwisePrecision);
eltwiseConfig.desc->setPrecision(eltwisePrecision);
cfg.inConfs.push_back(eltwiseConfig);
dataConfig.inPlace = getParentEdges().size() - 1;
}
@@ -669,7 +641,7 @@ void MKLDNNConvolutionNode::initDescriptor(const InferenceEngine::LayerConfig& c
break;
}
}
selectedPD->getConfig() = rightConfig;
selectedPD->setConfig(rightConfig);
}
void MKLDNNConvolutionNode::filterSupportedPrimitiveDescriptors() {
@@ -730,44 +702,17 @@ bool MKLDNNConvolutionNode::isPossibleToSkipInitConfig(MKLDNNDescriptor &desc) c
auto dstMemDesc = MKLDNNMemoryDesc {convDesc->data.dst_desc};
auto srcDataType = convDesc->data.src_desc.data_type;
auto dstDataType = convDesc->data.dst_desc.data_type;
bool isPlanarFloatConv = srcMemDesc.isPlainFormat()
&& dstMemDesc.isPlainFormat()
bool isPlanarFloatConv = srcMemDesc.hasLayoutType(LayoutType::ncsp)
&& dstMemDesc.hasLayoutType(LayoutType::ncsp)
&& srcDataType == memory::data_type::f32
&& dstDataType == memory::data_type::f32;
return !isPossibleJitPlanar && isPlanarFloatConv;
}
MKLDNNMemoryDesc MKLDNNConvolutionNode::getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
InferenceEngine::TensorDesc desc = idx > 0 ? MKLDNNMemoryDesc(primitive_desc_it.weights_desc(idx - 1))
: MKLDNNMemoryDesc(primitive_desc_it.src_desc(idx));
if (desc.getLayout() == InferenceEngine::Layout::ANY) {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getParentEdgeAt(idx)->getDims().ToSizeVector(),
desc.getLayout()));
} else {
if (getParentEdgeAt(idx)->getDims().ToSizeVector().size() != *std::max_element(desc.getBlockingDesc().getOrder().begin(),
desc.getBlockingDesc().getOrder().end()) + 1) {
auto old_dims = getParentEdgeAt(idx)->getDims().ToSizeVector();
auto new_dims = InferenceEngine::SizeVector({groupNum, div_up(old_dims[0], groupNum)});
for (int i = 1; i < old_dims.size(); i++) {
new_dims.push_back(old_dims[i]);
}
auto td = InferenceEngine::TensorDesc(desc.getPrecision(),
new_dims,
desc.getBlockingDesc());
if (new_dims.size() == desc.getBlockingDesc().getBlockDims().size()) {
td.setLayout(BLOCKED);
}
return MKLDNNMemoryDesc(td);
} else {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getParentEdgeAt(idx)->getDims().ToSizeVector(),
desc.getBlockingDesc()));
}
}
std::unique_ptr<MKLDNNMemoryDesc> MKLDNNConvolutionNode::getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
auto desc = idx > 0 ? MKLDNNMemoryDesc(primitive_desc_it.weights_desc(idx - 1)) : MKLDNNMemoryDesc(primitive_desc_it.src_desc(idx));
return MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(std::move(desc));
}
bool MKLDNNConvolutionNode::canFuse(const MKLDNNNodePtr& node) const {
@@ -775,11 +720,11 @@ bool MKLDNNConvolutionNode::canFuse(const MKLDNNNodePtr& node) const {
}
const mkldnn::memory& MKLDNNConvolutionNode::getWeights() const {
return isWinograd() ? internalBlobMemory[0]->GetPrimitive() : getParentEdgeAt(1)->getMemory().GetPrimitive();
return getParentEdgeAt(1)->getMemory().GetPrimitive();
}
const mkldnn::memory& MKLDNNConvolutionNode::getBias() const {
return isWinograd() ? internalBlobMemory[1]->GetPrimitive() : getParentEdgeAt(2)->getMemory().GetPrimitive();
return getParentEdgeAt(2)->getMemory().GetPrimitive();
}
InferenceEngine::Precision MKLDNNConvolutionNode::getRuntimePrecision() const {
@@ -793,7 +738,7 @@ InferenceEngine::Precision MKLDNNConvolutionNode::getRuntimePrecision() const {
}
}
return MKLDNNExtensionUtils::getMaxPrecision(inputPrecisions);
return getMaxPrecision(inputPrecisions);
}
bool MKLDNNConvolutionNode::isNspcAvailable() const {
@@ -810,8 +755,8 @@ bool MKLDNNConvolutionNode::isNspcAvailable() const {
}
// A bunch of heuristics are designed to cut off not optimal nspc convolution applications
auto inpDims = getParentEdgeAt(0)->getDims().ToSizeVector();
auto outDims = getChildEdgeAt(0)->getDims().ToSizeVector();
auto inpDims = getParentEdgeAt(0)->getShape().getStaticDims();
auto outDims = getChildEdgeAt(0)->getShape().getStaticDims();
auto ndims = inpDims.size();
if (isDepthWise()) {
@@ -20,9 +20,9 @@ public:
static bool isSupportedOperation(const std::shared_ptr<ngraph::Node>& op, std::string& errorMessage) noexcept;
void getSupportedDescriptors() override;
void createDescriptor(const std::vector<InferenceEngine::TensorDesc>& inputDesc,
const std::vector<InferenceEngine::TensorDesc>& outputDesc) override;
void initDescriptor(const InferenceEngine::LayerConfig& config) override;
void createDescriptor(const std::vector<const MemoryDesc*>& inputDesc,
const std::vector<const MemoryDesc*>& outputDesc) override;
void initDescriptor(const NodeConfig& config) override;
void createPrimitive() override;
void selectOptimalPrimitiveDescriptor() override;
void initSupportedPrimitiveDescriptors() override;
@@ -32,13 +32,13 @@ public:
return false;
}
InferenceEngine::Precision getRuntimePrecision() const override;
MKLDNNMemoryDesc getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
std::unique_ptr<MKLDNNMemoryDesc> getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
const mkldnn::memory& getWeights() const;
const mkldnn::memory& getBias() const;
size_t descInputNumbers(MKLDNNDescriptor desc) override {
return static_cast<size_t>(isWinograd() ? 1 : getOriginalInputsNumber());
return getOriginalInputsNumber();
}
bool canBeExecutedInInt8() const;
@@ -49,7 +49,7 @@ public:
std::vector<int32_t> outputCompensation;
const InferenceEngine::SizeVector &getWeightDims() { return weightDims; }
const std::vector<ptrdiff_t> &getStride() { return stride; }
const std::vector<size_t> &getStride() { return stride; }
const std::vector<ptrdiff_t> &getDilation() { return dilation; }
const std::vector<ptrdiff_t> &getPaddingL() { return paddingL; }
const std::vector<ptrdiff_t> &getPaddingR() { return paddingR; }
@@ -77,18 +77,18 @@ private:
bool withDWConv;
bool isGrouped;
bool isPrimitivesPriorityDefined = false;
std::vector<ptrdiff_t> stride;
std::vector<size_t> stride;
std::vector<ptrdiff_t> dilation;
std::vector<ptrdiff_t> paddingL;
std::vector<ptrdiff_t> paddingR;
InferenceEngine::SizeVector weightDims;
InferenceEngine::SizeVector biasesDims;
ptrdiff_t dw_conv_oc;
ptrdiff_t dw_conv_ih;
ptrdiff_t dw_conv_iw;
std::vector<ptrdiff_t> dw_conv_kernel;
std::vector<ptrdiff_t> dw_conv_strides;
size_t dw_conv_oc;
size_t dw_conv_ih;
size_t dw_conv_iw;
std::vector<size_t> dw_conv_kernel;
std::vector<size_t> dw_conv_strides;
mkldnn::memory::data_type dw_conv_in_dt;
size_t groupNum;
@@ -5,7 +5,7 @@
#include <mkldnn_extension_utils.h>
#include "mkldnn_convert_node.h"
#include "common/cpu_convert.h"
#include "common/tensor_desc_creator.h"
#include "common/blocked_desc_creator.h"
#include <ngraph/opsets/opset1.hpp>
using namespace mkldnn;
@@ -38,9 +38,9 @@ MKLDNNConvertNode::MKLDNNConvertNode(const std::shared_ptr<ngraph::Node>& op, co
MKLDNNConvertNode::MKLDNNConvertNode(const InferenceEngine::SizeVector &dims, const InferenceEngine::Precision &inPrc, const InferenceEngine::Precision &outPrc,
const std::string &nodeName, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache)
: MKLDNNNode("Convert", nodeName, eng, cache) {
inDims.emplace_back(dims);
inputShapes.emplace_back(dims);
addOriginalInputPrecision(inPrc);
outDims.emplace_back(dims);
outputShapes.emplace_back(dims);
addOriginalOutputPrecision(outPrc);
errorPrefix = "Convert node with name '" + getName() + "'";
@@ -49,10 +49,10 @@ MKLDNNConvertNode::MKLDNNConvertNode(const InferenceEngine::SizeVector &dims, co
void MKLDNNConvertNode::getSupportedDescriptors() {
// if tensor descriptors are set via setDescs method we need to update the inDims/outDims data
// from correspond tensor descriptors.
if (outDims.empty() && output && output->getLayout() != InferenceEngine::Layout::ANY)
outDims.push_back(MKLDNNDims(output->getDims()));
if (inDims.empty() && input && input->getLayout() != InferenceEngine::Layout::ANY)
inDims.push_back(MKLDNNDims(input->getDims()));
if (outputShapes.empty())
outputShapes.push_back(output->getShape());
if (inputShapes.empty())
inputShapes.push_back(input->getShape());
if (getParentEdges().size() != 1)
IE_THROW() << errorPrefix << " has incorrect number of input edges";
if (getChildEdges().empty())
@@ -63,39 +63,40 @@ void MKLDNNConvertNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
LayerConfig config;
DataConfig dataIn;
DataConfig dataConfigOut;
NodeConfig config;
PortConfig dataIn;
PortConfig dataConfigOut;
config.dynBatchSupport = false;
// if input and output pointers are not null, then the inp/output tensor descriptors were set using setDescs method, so
// they should be used as the actual descriptors.
if (input && input->getLayout() != InferenceEngine::Layout::ANY && output && output->getLayout() != InferenceEngine::Layout::ANY) {
dataIn.desc = *input;
if (input && output) {
dataIn.desc = input->clone();
config.inConfs.push_back(dataIn);
const auto& blockingDesc = config.inConfs[0].desc.getBlockingDesc(); // inp/out layouts must be the same
dataConfigOut.desc = TensorDesc(output->getPrecision(), input->getDims(), blockingDesc);
// inp/out layouts must be the same
dataConfigOut.desc = config.inConfs[0].desc->clone();
dataConfigOut.desc->setPrecision(output->getPrecision());
config.outConfs.push_back(dataConfigOut);
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown, MKLDNNMemoryDesc(config.outConfs.front().desc).getFormat());
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown);
} else if (getOriginalInputsNumber() == 1 && getOriginalOutputsNumber() == 1) {
const SizeVector& insDims = getParentEdgeAt(0)->getDims().ToSizeVector();
const Shape& insShape = getParentEdgeAt(0)->getShape();
auto insPrecision = getOriginalInputPrecisionAtPort(0);
const SizeVector& outputDims = getChildEdgeAt(0)->getDims().ToSizeVector();
const Shape& outputShape = getChildEdgeAt(0)->getShape();
auto outPrecision = getOriginalOutputPrecisionAtPort(0);
config.inConfs.push_back(dataIn);
config.outConfs.push_back(dataConfigOut);
auto creators = TensorDescCreator::getCommonCreators();
auto range = TensorDescCreator::makeFilteredRange(creators, insDims.size());
auto creators = BlockedDescCreator::getCommonCreators();
auto range = BlockedDescCreator::makeFilteredRange(creators, insShape.getRank());
for (auto itr = range.first; itr != range.second; ++itr) {
config.inConfs[0].desc = itr->second->createDesc(insPrecision, insDims);
config.outConfs[0].desc = itr->second->createDesc(outPrecision, outputDims);
config.inConfs[0].desc = MKLDNNPlugin::make_unique<BlockedMemoryDesc>(itr->second->createDesc(insPrecision, insShape.getDims()));
config.outConfs[0].desc = MKLDNNPlugin::make_unique<BlockedMemoryDesc>(itr->second->createDesc(outPrecision, outputShape.getDims()));
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown, MKLDNNMemoryDesc(config.outConfs.front().desc).getFormat());
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown);
}
} else {
IE_THROW() << errorPrefix << " has incorrect number of input/output edges";
@@ -121,7 +122,7 @@ void MKLDNNConvertNode::execute(mkldnn::stream strm) {
void* srcPtr = parentMem.GetPtr();
void* dstPtr = childMem.GetPtr();
cpu_convert(srcPtr, dstPtr, getParentEdgeAt(0)->getDesc().getPrecision(), getChildEdgeAt(0)->getDesc().getPrecision(), parentMem.GetElementsCount());
cpu_convert(srcPtr, dstPtr, parentMem.GetDesc().getPrecision(), childMem.GetDesc().getPrecision(), parentMem.GetElementsCount());
}
bool MKLDNNConvertNode::created() const {
@@ -30,19 +30,19 @@ public:
// In that case the Convert node is instantiated with default CNNLayer and inp/out tensor descriptors are set via this method.
// This is useful if the Convert node is added to the graph as an auxiliary operation at the MKLDNNGraph
// initialization stage.
void setDescs(const InferenceEngine::TensorDesc& input, const InferenceEngine::TensorDesc& output) {
this->input.reset(new InferenceEngine::TensorDesc(input));
this->output.reset(new InferenceEngine::TensorDesc(output));
void setDescs(const MemoryDesc& input, const MemoryDesc& output) {
this->input = input.clone();
this->output = output.clone();
}
std::shared_ptr<const InferenceEngine::TensorDesc> getInput() const { return input; }
std::shared_ptr<const InferenceEngine::TensorDesc> getOutput() const { return output; }
const MemoryDesc& getInput() const { return *input; }
const MemoryDesc& getOutput() const { return *output; }
static bool isSupportedOperation(const std::shared_ptr<ngraph::Node>& op, std::string& errorMessage) noexcept;
private:
std::shared_ptr<InferenceEngine::TensorDesc> input;
std::shared_ptr<InferenceEngine::TensorDesc> output;
std::unique_ptr<MemoryDesc> input;
std::unique_ptr<MemoryDesc> output;
std::string errorPrefix;
};
@@ -1,7 +1,6 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <vector>
@@ -59,9 +58,9 @@ void MKLDNNCTCGreedyDecoderNode::initSupportedPrimitiveDescriptors() {
if (seqLenPrecision != Precision::FP32 && seqLenPrecision != Precision::BF16)
IE_THROW() << errorPrefix << "has unsupported 'sequence_length' input precision: " << seqLenPrecision;
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
@@ -70,9 +69,9 @@ void MKLDNNCTCGreedyDecoderNode::execute(mkldnn::stream strm) {
const float* sequenceMask = reinterpret_cast<const float *>(getParentEdgeAt(SEQUENCE_LENGTH_INDEX)->getMemoryPtr()->GetPtr());
float* outputSequences = reinterpret_cast<float *>(getChildEdgesAtPort(0)[0]->getMemoryPtr()->GetPtr());
const size_t T = getParentEdgeAt(DATA_INDEX)->getDims()[0];
const size_t B = getParentEdgeAt(DATA_INDEX)->getDims()[1];
const int C = getParentEdgeAt(DATA_INDEX)->getDims()[2];
const size_t T = getParentEdgeAt(DATA_INDEX)->getShape().getStaticDims()[0];
const size_t B = getParentEdgeAt(DATA_INDEX)->getShape().getStaticDims()[1];
const int C = getParentEdgeAt(DATA_INDEX)->getShape().getStaticDims()[2];
const size_t BC = B * C;
const size_t CB1 = C * (B - 1);
@@ -1,7 +1,6 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <vector>
@@ -58,15 +57,15 @@ void MKLDNNCTCGreedyDecoderSeqLenNode::initSupportedPrimitiveDescriptors() {
if (seqLenPrecision != Precision::I32 && seqLenPrecision != Precision::I64)
IE_THROW() << errorPrefix << "has unsupported 'sequence_length' input precision: " << seqLenPrecision;
std::vector<DataConfigurator> inDataConf;
std::vector<PortConfigurator> inDataConf;
inDataConf.reserve(getOriginalInputsNumber());
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, Precision::FP32);
inDataConf.emplace_back(LayoutType::ncsp, Precision::FP32);
for (int i = 1; i < getOriginalInputsNumber(); ++i)
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, Precision::I32);
inDataConf.emplace_back(LayoutType::ncsp, Precision::I32);
addSupportedPrimDesc(inDataConf,
{{TensorDescCreatorTypes::ncsp, Precision::I32},
{TensorDescCreatorTypes::ncsp, Precision::I32}},
{{LayoutType::ncsp, Precision::I32},
{LayoutType::ncsp, Precision::I32}},
impl_desc_type::ref_any);
}
@@ -76,13 +75,13 @@ void MKLDNNCTCGreedyDecoderSeqLenNode::execute(mkldnn::stream strm) {
int* decodedClasses = reinterpret_cast<int *>(getChildEdgesAtPort(DECODED_CLASSES_INDEX)[0]->getMemoryPtr()->GetPtr());
int* decodedClassesLength = reinterpret_cast<int *>(getChildEdgesAtPort(DECODED_CLASSES_LENGTH_INDEX)[0]->getMemoryPtr()->GetPtr());
const size_t B = getParentEdgeAt(DATA_INDEX)->getDims()[0];;
const size_t T = getParentEdgeAt(DATA_INDEX)->getDims()[1];;
const int C = getParentEdgeAt(DATA_INDEX)->getDims()[2];;
const size_t B = getParentEdgeAt(DATA_INDEX)->getShape().getStaticDims()[0];;
const size_t T = getParentEdgeAt(DATA_INDEX)->getShape().getStaticDims()[1];;
const int C = getParentEdgeAt(DATA_INDEX)->getShape().getStaticDims()[2];;
const size_t TC = T * C;
int blankIndex = C - 1;
if (inDims.size() > BLANK_INDEX)
if (inputShapes.size() > BLANK_INDEX)
blankIndex = (reinterpret_cast<const int *>(getParentEdgeAt(BLANK_INDEX)->getMemoryPtr()->GetPtr()))[0];
size_t workAmount = 0;
@@ -91,7 +90,7 @@ void MKLDNNCTCGreedyDecoderSeqLenNode::execute(mkldnn::stream strm) {
std::string errorMsg = errorPrefix
+ ". Sequence length " + std::to_string(sequenceLengths[b])
+ " cannot be greater than according decoded classes dimension size "
+ std::to_string(getChildEdgesAtPort(DECODED_CLASSES_INDEX)[0]->getDims()[1]);
+ std::to_string(getChildEdgesAtPort(DECODED_CLASSES_INDEX)[0]->getShape().getStaticDims()[1]);
IE_THROW() << errorMsg;
}
workAmount += sequenceLengths[b];
@@ -46,14 +46,14 @@ void MKLDNNCTCLossNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
std::vector<DataConfigurator> inDataConf;
std::vector<PortConfigurator> inDataConf;
inDataConf.reserve(getOriginalInputsNumber());
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, Precision::FP32);
inDataConf.emplace_back(LayoutType::ncsp, Precision::FP32);
for (int i = 1; i < getOriginalInputsNumber(); ++i)
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, Precision::I32);
inDataConf.emplace_back(LayoutType::ncsp, Precision::I32);
addSupportedPrimDesc(inDataConf,
{{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
@@ -66,12 +66,12 @@ void MKLDNNCTCLossNode::execute(mkldnn::stream strm) {
const int* labelsLength = reinterpret_cast<const int *>(getParentEdgeAt(3)->getMemoryPtr()->GetPtr());
float* dstData = reinterpret_cast<float *>(getChildEdgesAtPort(0)[0]->getMemoryPtr()->GetPtr());
const size_t batchNum = getParentEdgeAt(0)->getDims()[0];
const size_t maxTime = getParentEdgeAt(0)->getDims()[1];
const size_t classesNum = getParentEdgeAt(0)->getDims()[2];
const size_t batchNum = getParentEdgeAt(0)->getShape().getStaticDims()[0];
const size_t maxTime = getParentEdgeAt(0)->getShape().getStaticDims()[1];
const size_t classesNum = getParentEdgeAt(0)->getShape().getStaticDims()[2];
int blankIndex = classesNum - 1;
if (inDims.size() > 4) {
if (inputShapes.size() > 4) {
blankIndex = reinterpret_cast<const int *>(getParentEdgeAt(4)->getMemoryPtr()->GetPtr())[0];
}
@@ -2,7 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "list.hpp"
#include "base.hpp"
#include <string>
#include <vector>
@@ -78,20 +77,20 @@ void MKLDNNCumSumNode::initSupportedPrimitiveDescriptors() {
IE_THROW() << errorPrefix << " has unsupported 'axis' input precision: " << axisTensorPrec.name();
}
std::vector<DataConfigurator> inDataConf;
std::vector<PortConfigurator> inDataConf;
inDataConf.reserve(getOriginalInputsNumber());
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, dataPrecision);
inDataConf.emplace_back(LayoutType::ncsp, dataPrecision);
for (int i = 1; i < getOriginalInputsNumber(); ++i)
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, Precision::I32);
inDataConf.emplace_back(LayoutType::ncsp, Precision::I32);
addSupportedPrimDesc(inDataConf,
{{TensorDescCreatorTypes::ncsp, dataPrecision}},
{{LayoutType::ncsp, dataPrecision}},
impl_desc_type::ref_any);
}
void MKLDNNCumSumNode::execute(mkldnn::stream strm) {
if (inDims.size() == numOfInputs)
axis = getAxis(getParentEdgeAt(AXIS)->getBlob(), getParentEdgeAt(CUM_SUM_DATA)->getBlob());
if (inputShapes.size() == numOfInputs)
axis = getAxis(getParentEdgeAt(AXIS)->getMemory(), getParentEdgeAt(CUM_SUM_DATA)->getMemory());
switch (dataPrecision) {
case Precision::I8 : {
@@ -134,7 +133,7 @@ template <typename dataType>
void MKLDNNCumSumNode::exec() {
const auto *input = reinterpret_cast<const dataType *>(getParentEdgeAt(CUM_SUM_DATA)->getMemoryPtr()->GetPtr());
auto *output = reinterpret_cast<dataType *>(getChildEdgesAtPort(0)[0]->getMemoryPtr()->GetPtr());
const std::vector<size_t> strides = getParentEdgeAt(CUM_SUM_DATA)->getDesc().getBlockingDesc().getStrides();
const std::vector<size_t> strides = getParentEdgeAt(CUM_SUM_DATA)->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
if (reverse) {
if (exclusive) {
@@ -248,18 +247,18 @@ inline size_t MKLDNNCumSumNode::getStartOffset(const std::vector<size_t> &forSta
return startOffset;
}
size_t MKLDNNCumSumNode::getAxis(const Blob::CPtr& _axis, const Blob::CPtr& _data) const {
const auto& axisPrecision = _axis->getTensorDesc().getPrecision();
const int64_t dataShapeSize = static_cast<int64_t>(_data->getTensorDesc().getDims().size());
size_t MKLDNNCumSumNode::getAxis(const MKLDNNMemory& _axis, const MKLDNNMemory& _data) const {
const auto& axisPrecision = _axis.GetDesc().getPrecision();
const int64_t dataShapeSize = static_cast<int64_t>(_data.GetDesc().getShape().getRank());
int64_t axisValueFromBlob;
switch (axisPrecision) {
case Precision::I32 : {
const auto *axisPtr = _axis->cbuffer().as<const int32_t *>();
const auto *axisPtr = reinterpret_cast<const int32_t *>(_axis.GetPtr());
axisValueFromBlob = static_cast<int64_t>(axisPtr[0]);
break;
}
case Precision::I64 : {
const auto *axisPtr = _axis->cbuffer().as<const int64_t *>();
const auto *axisPtr = reinterpret_cast<const int64_t *>(_axis.GetPtr());
axisValueFromBlob = axisPtr[0];
break;
}
@@ -34,7 +34,7 @@ private:
inline size_t getStartOffset(const std::vector<size_t> &forStartOffset, const std::vector<size_t>& strides) const;
size_t getAxis(const InferenceEngine::Blob::CPtr& _axis, const InferenceEngine::Blob::CPtr& _data) const;
size_t getAxis(const MKLDNNMemory& _axis, const MKLDNNMemory& _data) const;
enum { CUM_SUM_DATA, AXIS, numOfInputs };
bool exclusive;
@@ -16,6 +16,7 @@
#include <ngraph/opsets/opset1.hpp>
#include <cpu/x64/cpu_isa_traits.hpp>
#include <nodes/common/cpu_memcpy.h>
#include <cpu_memory_desc_utils.h>
using namespace mkldnn;
using namespace MKLDNNPlugin;
@@ -108,10 +109,10 @@ InferenceEngine::Blob::Ptr MKLDNNDeconvolutionNode::createWeiBlobAsIO(InferenceE
// So we disconnect constant node containing weights from the graph and then don't use it.
if (getParentEdges().size() == 3) {
removeEdge(getParentEdgeAt(2));
inDims.erase(inDims.begin() + 2);
inputShapes.erase(inputShapes.begin() + 2);
}
removeEdge(getParentEdgeAt(1));
inDims.erase(inDims.begin() + 1);
inputShapes.erase(inputShapes.begin() + 1);
InferenceEngine::SizeVector dimsForBlockedDesc{dims};
std::swap(dimsForBlockedDesc[withGroups + 0], dimsForBlockedDesc[withGroups + 1]);
@@ -151,7 +152,7 @@ bool MKLDNNDeconvolutionNode::canBeExecutedInInt8() const {
if (!withGroups && stride.back() > 3)
return false;
if (!impl::cpu::x64::mayiuse(impl::cpu::x64::avx512_common)) {
auto inDims = getChildEdgeAt(0)->getDims().ToSizeVector();
auto inDims = getChildEdgeAt(0)->getShape().getStaticDims();
// heuristicConst = 2^26
// heuristicParam = IC^2 * SP
auto heuristicConst = 67108864;
@@ -230,8 +231,8 @@ void MKLDNNDeconvolutionNode::getSupportedDescriptors() {
for (int i = 0; i < paddingR.size(); i++) {
int with_group = getAlgorithm() == DeconvolutionGrouped ? 1 : 0;
int krn = weightDims[with_group + 2 + i];
int src = getChildEdgeAt(0)->getDims()[2 + i];
int dst = getParentEdgeAt(0)->getDims()[2 + i];
int src = getChildEdgeAt(0)->getShape().getStaticDims()[2 + i];
int dst = getParentEdgeAt(0)->getShape().getStaticDims()[2 + i];
krn = (krn - 1)*(dilation[i] + 1) + 1;
int calc_dst = (src - krn + paddingL[i]) / stride[i] + 1;
@@ -242,15 +243,15 @@ void MKLDNNDeconvolutionNode::getSupportedDescriptors() {
// WA: if int8 deconvolution is supported, we create internal weights blob in IO format
std::swap(weightDims[withGroups + 0], weightDims[withGroups + 1]);
internalBlobs.push_back(createWeiBlobAsIO(weightDims));
auto format = getParentEdgeAt(0)->getDims().ndims() == 5 ? dnnl::memory::format_tag::ndhwc : dnnl::memory::format_tag::nhwc;
MKLDNNMemoryDesc in_candidate(getParentEdgeAt(0)->getDims(), inputDataType, format);
MKLDNNMemoryDesc out_candidate(getChildEdgeAt(0)->getDims(), outputDataType, format);
createDescriptor({in_candidate}, {out_candidate});
auto format = getParentEdgeAt(0)->getShape().getRank() == 5 ? dnnl::memory::format_tag::ndhwc : dnnl::memory::format_tag::nhwc;
MKLDNNMemoryDesc in_candidate(getParentEdgeAt(0)->getShape().getStaticDims(), inputDataType, format);
MKLDNNMemoryDesc out_candidate(getChildEdgeAt(0)->getShape().getStaticDims(), outputDataType, format);
createDescriptor({&in_candidate}, {&out_candidate});
} else {
for (auto format : getAvailableFormatsForDims(getParentEdgeAt(0)->getDims())) {
MKLDNNMemoryDesc in_candidate(getParentEdgeAt(0)->getDims(), inputDataType, format);
MKLDNNMemoryDesc out_candidate(getChildEdgeAt(0)->getDims(), outputDataType, format);
createDescriptor({in_candidate}, {out_candidate});
for (auto format : getAvailableFormatsForDims(getParentEdgeAt(0)->getShape())) {
MKLDNNMemoryDesc in_candidate(getParentEdgeAt(0)->getShape().getStaticDims(), inputDataType, format);
MKLDNNMemoryDesc out_candidate(getChildEdgeAt(0)->getShape().getStaticDims(), outputDataType, format);
createDescriptor({&in_candidate}, {&out_candidate});
}
}
setPostOps(attr);
@@ -346,10 +347,10 @@ void MKLDNNDeconvolutionNode::createPrimitive() {
}
}
void MKLDNNDeconvolutionNode::createDescriptor(const std::vector<InferenceEngine::TensorDesc> &inputDesc,
const std::vector<InferenceEngine::TensorDesc> &outputDesc) {
MKLDNNMemoryDesc in_candidate(inputDesc[0]);
MKLDNNMemoryDesc out_candidate(outputDesc[0]);
void MKLDNNDeconvolutionNode::createDescriptor(const std::vector<const MemoryDesc*> &inputDesc,
const std::vector<const MemoryDesc*> &outputDesc) {
const MKLDNNMemoryDesc in_candidate = MemoryDescUtils::convertToMKLDNNMemoryDesc(*inputDesc[0]);
const MKLDNNMemoryDesc out_candidate = MemoryDescUtils::convertToMKLDNNMemoryDesc(*outputDesc[0]);
// grouping and autoblicking is not compatible
if ((withGroups && !isDW) && (in_candidate.blocksExtended() || out_candidate.blocksExtended()))
@@ -361,7 +362,7 @@ void MKLDNNDeconvolutionNode::createDescriptor(const std::vector<InferenceEngine
if (isInt8) {
MKLDNNDims weightsDims = MKLDNNDims(weightDims);
MKLDNNMemoryDesc wgh_candidate{weightsDims, memory::data_type::s8, memory::format_tag::any};
mkldnn::memory::desc wgh_candidate(weightsDims, memory::data_type::s8, memory::format_tag::any);
std::shared_ptr<mkldnn::deconvolution_forward::desc> deconv_desc;
deconv_desc.reset(new deconvolution_forward::desc(prop_kind::forward_inference, mkldnn::algorithm::deconvolution_direct,
in_candidate, wgh_candidate, out_candidate,
@@ -370,7 +371,7 @@ void MKLDNNDeconvolutionNode::createDescriptor(const std::vector<InferenceEngine
descs.emplace_back(deconv_desc);
} else {
MKLDNNDims weightsDims = MKLDNNDims(weightDims);
MKLDNNMemoryDesc wgh_candidate{weightsDims, in_candidate.getDataType(), memory::format_tag::any};
mkldnn::memory::desc wgh_candidate(weightsDims, in_candidate.getDataType(), memory::format_tag::any);
for (auto alg : {mkldnn::algorithm::convolution_winograd, mkldnn::algorithm::convolution_direct}) {
std::shared_ptr<mkldnn::convolution_forward::desc> conv_desc;
conv_desc.reset(new convolution_forward::desc(prop_kind::forward_inference, alg,
@@ -399,52 +400,21 @@ void MKLDNNDeconvolutionNode::createDescriptor(const std::vector<InferenceEngine
}
}
MKLDNNMemoryDesc MKLDNNDeconvolutionNode::getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
std::unique_ptr<MKLDNNMemoryDesc> MKLDNNDeconvolutionNode::getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
if (idx == 2) {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(getOriginalInputPrecisionAtPort(2),
getParentEdgeAt(2)->getDims().ToSizeVector(),
TensorDesc::getLayoutByDims(getParentEdgeAt(2)->getDims().ToSizeVector())));
auto dataType = MKLDNNExtensionUtils::IEPrecisionToDataType(getOriginalInputPrecisionAtPort(2));
return MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(2)->getShape().getStaticDims(), dataType,
MKLDNNMemory::GetPlainFormatByRank(getParentEdgeAt(2)->getShape().getRank()));
}
InferenceEngine::TensorDesc desc = idx > 0 ? MKLDNNMemoryDesc(primitive_desc_it.weights_desc(idx - 1))
MKLDNNMemoryDesc desc = idx > 0 ? MKLDNNMemoryDesc(primitive_desc_it.weights_desc(idx - 1))
: isInt8 ? MKLDNNMemoryDesc(primitive_desc_it.src_desc(idx)) : MKLDNNMemoryDesc(primitive_desc_it.diff_dst_desc(idx));
if (desc.getLayout() == InferenceEngine::Layout::ANY) {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getParentEdgeAt(idx)->getDims().ToSizeVector(),
desc.getLayout()));
} else {
if (getParentEdgeAt(idx)->getDims().ToSizeVector().size() != *std::max_element(desc.getBlockingDesc().getOrder().begin(),
desc.getBlockingDesc().getOrder().end()) + 1) {
auto old_dims = getParentEdgeAt(idx)->getDims().ToSizeVector();
auto new_dims = weightDims;
auto td = InferenceEngine::TensorDesc(desc.getPrecision(),
new_dims,
desc.getBlockingDesc());
if (new_dims.size() == desc.getBlockingDesc().getBlockDims().size()) {
td.setLayout(BLOCKED);
}
return MKLDNNMemoryDesc(td);
} else {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getParentEdgeAt(idx)->getDims().ToSizeVector(),
desc.getBlockingDesc()));
}
}
return MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(std::move(desc));
}
MKLDNNMemoryDesc MKLDNNDeconvolutionNode::getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
InferenceEngine::TensorDesc desc = isInt8 ? MKLDNNMemoryDesc(primitive_desc_it.dst_desc(idx))
: MKLDNNMemoryDesc(primitive_desc_it.diff_src_desc(idx));
if (desc.getLayout() == InferenceEngine::Layout::ANY)
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getChildEdgeAt(idx)->getDims().ToSizeVector(),
desc.getLayout()));
else
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getChildEdgeAt(idx)->getDims().ToSizeVector(),
desc.getBlockingDesc()));
std::unique_ptr<MKLDNNMemoryDesc> MKLDNNDeconvolutionNode::getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
return isInt8 ? MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(primitive_desc_it.dst_desc(idx)) :
MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(primitive_desc_it.diff_src_desc(idx));
}
InferenceEngine::Precision MKLDNNDeconvolutionNode::getRuntimePrecision() const {
@@ -458,7 +428,7 @@ InferenceEngine::Precision MKLDNNDeconvolutionNode::getRuntimePrecision() const
}
}
return MKLDNNExtensionUtils::getMaxPrecision(inputPrecisions);
return getMaxPrecision(inputPrecisions);
}
REG_MKLDNN_PRIM_FOR(MKLDNNDeconvolutionNode, Deconvolution);
@@ -17,8 +17,8 @@ public:
MKLDNNDeconvolutionNode(const std::shared_ptr<ngraph::Node>& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache);
void getSupportedDescriptors() override;
void createDescriptor(const std::vector<InferenceEngine::TensorDesc>& inputDesc,
const std::vector<InferenceEngine::TensorDesc>& outputDesc) override;
void createDescriptor(const std::vector<const MemoryDesc*>& inputDesc,
const std::vector<const MemoryDesc*>& outputDesc) override;
void createPrimitive() override;
void filterSupportedPrimitiveDescriptors() override;
void filterSupportedDescriptors();
@@ -31,8 +31,8 @@ public:
return static_cast<size_t>(getParentEdges().size());
}
MKLDNNMemoryDesc getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
MKLDNNMemoryDesc getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
std::unique_ptr<MKLDNNMemoryDesc> getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
std::unique_ptr<MKLDNNMemoryDesc> getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
InferenceEngine::Precision getRuntimePrecision() const override;
@@ -785,20 +785,20 @@ void MKLDNNDeformableConvolutionNode::getSupportedDescriptors() {
if (getChildEdges().empty())
IE_THROW() << errorPrefix << "has incorrect number of output edges";
if (getParentEdgeAt(0)->getDims().ndims() != 4) {
if (getParentEdgeAt(0)->getShape().getRank() != 4) {
IE_THROW() << "Deformable convolution layer. Unsupported mode. Only 4D blobs are supported as input.";
}
if (getParentEdgeAt(1)->getDims().ndims() != 4) {
IE_THROW() << errorPrefix << "doesn't support 1st input with rank: " << getParentEdgeAt(1)->getDims().ndims();
if (getParentEdgeAt(1)->getShape().getRank() != 4) {
IE_THROW() << errorPrefix << "doesn't support 1st input with rank: " << getParentEdgeAt(1)->getShape().getRank();
}
if (getParentEdgeAt(2)->getDims().ndims() != 4) {
IE_THROW() << errorPrefix << "doesn't support 2nd input with rank: " << getParentEdgeAt(2)->getDims().ndims();
if (getParentEdgeAt(2)->getShape().getRank() != 4) {
IE_THROW() << errorPrefix << "doesn't support 2nd input with rank: " << getParentEdgeAt(2)->getShape().getRank();
}
if (getChildEdgeAt(0)->getDims().ndims() != 4) {
IE_THROW() << errorPrefix << "doesn't support output with rank: " << getChildEdgeAt(0)->getDims().ndims();
if (getChildEdgeAt(0)->getShape().getRank() != 4) {
IE_THROW() << errorPrefix << "doesn't support output with rank: " << getChildEdgeAt(0)->getShape().getRank();
}
}
@@ -806,7 +806,7 @@ void MKLDNNDeformableConvolutionNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = false;
config.inConfs.resize(3);
config.inConfs[0].constant = false;
@@ -838,20 +838,26 @@ void MKLDNNDeformableConvolutionNode::initSupportedPrimitiveDescriptors() {
auto weiFormat = group > 1 ? mayiuse(avx512_common) ? memory::format_tag::gOIhw16i16o : memory::format_tag::gOIhw8i8o
: mayiuse(avx512_common) ? memory::format_tag::OIhw16i16o : memory::format_tag::OIhw8i8o;
config.inConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), memory::data_type::f32, dataFormat);
config.inConfs[1].desc = MKLDNNMemoryDesc(getParentEdgeAt(1)->getDims(), memory::data_type::f32, offFormat);
config.inConfs[2].desc = MKLDNNMemoryDesc(getParentEdgeAt(2)->getDims(), memory::data_type::f32, weiFormat);
config.outConfs[0].desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), memory::data_type::f32, dataFormat);
supportedPrimitiveDescriptors.push_back({config, impl_type, dataFormat});
config.inConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(0)->getShape().getStaticDims(),
memory::data_type::f32, dataFormat);
config.inConfs[1].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(1)->getShape().getStaticDims(),
memory::data_type::f32, offFormat);
config.inConfs[2].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(2)->getShape().getStaticDims(),
memory::data_type::f32, weiFormat);
config.outConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getChildEdgeAt(0)->getShape().getStaticDims(),
memory::data_type::f32, dataFormat);
supportedPrimitiveDescriptors.push_back({config, impl_type});
} else {
// reference implementation
auto weiFormat = group > 1 ? memory::format_tag::goihw : memory::format_tag::oihw;
config.inConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), memory::data_type::f32, memory::format_tag::nchw);
config.inConfs[1].desc = MKLDNNMemoryDesc(getParentEdgeAt(1)->getDims(), memory::data_type::f32, memory::format_tag::nchw);
config.inConfs[2].desc = MKLDNNMemoryDesc(getParentEdgeAt(2)->getDims(), memory::data_type::f32, memory::format_tag::oihw);
config.outConfs[0].desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), memory::data_type::f32, memory::format_tag::nchw);
supportedPrimitiveDescriptors.push_back({config, impl_type, weiFormat});
config.inConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(0)->getShape().getStaticDims(), memory::data_type::f32,
memory::format_tag::nchw);
config.inConfs[1].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(1)->getShape().getStaticDims(), memory::data_type::f32,
memory::format_tag::nchw);
config.inConfs[2].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(2)->getShape().getStaticDims(), memory::data_type::f32,
memory::format_tag::oihw);
config.outConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getChildEdgeAt(0)->getShape().getStaticDims(), memory::data_type::f32,
memory::format_tag::nchw);
supportedPrimitiveDescriptors.push_back({config, impl_type});
}
}
@@ -861,9 +867,9 @@ void MKLDNNDeformableConvolutionNode::createPrimitive() {
IE_THROW() << "CPU deformable convolution with name '" << getName() << "' doesn't have primitive descriptors.";
auto config = selectedPrimitiveDescriptor->getConfig();
auto srcDims = config.inConfs[0].desc.getDims();
auto weiDims = config.inConfs[2].desc.getDims();
auto dstDims = config.outConfs[0].desc.getDims();
auto srcDims = getParentEdgeAt(0)->getShape().getStaticDims();
auto weiDims = getParentEdgeAt(2)->getShape().getStaticDims();
auto dstDims = getChildEdgeAt(0)->getShape().getStaticDims();
jcp.dg = deformable_group;
@@ -1062,25 +1068,20 @@ void MKLDNNDeformableConvolutionNode::execute(mkldnn::stream strm) {
const auto *weights = reinterpret_cast<const float *>(srcMemory2.GetPtr());
float *dst = reinterpret_cast<float *>(dstMemory.GetPtr());
auto selectedPrimitiveDescriptor = getSelectedPrimitiveDescriptor();
if (!selectedPrimitiveDescriptor)
IE_THROW() << "CPU deformable convolution with name '" << getName() << "' doesn't have primitive descriptors.";
auto config = selectedPrimitiveDescriptor->getConfig();
auto src_block_desc = config.inConfs[0].desc.getBlockingDesc();
auto src_block_desc = getParentEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
std::vector<size_t> src_strides(src_block_desc.getStrides().size());
for (int i = 0; i < src_strides.size(); i++) {
src_strides[src_block_desc.getOrder()[i]] = src_block_desc.getStrides()[i];
}
auto dst_block_desc = config.outConfs[0].desc.getBlockingDesc();
auto dst_block_desc = getChildEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
std::vector<size_t> dst_strides(dst_block_desc.getStrides().size());
for (int i = 0; i < dst_strides.size(); i++) {
dst_strides[dst_block_desc.getOrder()[i]] = dst_block_desc.getStrides()[i];
}
auto off_strides = config.inConfs[1].desc.getBlockingDesc().getStrides();
auto wei_strides = config.inConfs[2].desc.getBlockingDesc().getStrides();
auto off_strides = getParentEdgeAt(1)->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
auto wei_strides = getParentEdgeAt(2)->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
if (def_conv_kernel) {
executeOptimized(src, offsets, weights, dst, src_strides, off_strides, dst_strides);
@@ -1094,7 +1095,7 @@ bool MKLDNNDeformableConvolutionNode::created() const {
}
InferenceEngine::Precision MKLDNNDeformableConvolutionNode::getRuntimePrecision() const {
return MKLDNNExtensionUtils::getMaxPrecision(getInputPrecisions());
return getMaxPrecision(getInputPrecisions());
}
REG_MKLDNN_PRIM_FOR(MKLDNNDeformableConvolutionNode, DeformableConvolution);
@@ -6,7 +6,7 @@
#include <cpu/x64/jit_generator.hpp>
#include <mkldnn_extension_utils.h>
#include "common/tensor_desc_creator.h"
#include "common/blocked_desc_creator.h"
#include <utils/general_utils.h>
#include <ngraph/opsets/opset1.hpp>
@@ -58,7 +58,7 @@ MKLDNNDepthToSpaceNode::MKLDNNDepthToSpaceNode(const std::shared_ptr<ngraph::Nod
if (blockSize == 0)
THROW_ERROR << "has incorrect block_size parameter is zero!";
size_t nSpatialDims = inDims[0].ndims() - 2;
size_t nSpatialDims = inputShapes[0].getRank() - 2;
blockStep = static_cast<size_t>(std::pow(blockSize, nSpatialDims));
} else {
IE_THROW(NotImplemented) << errorMessage;
@@ -66,13 +66,13 @@ MKLDNNDepthToSpaceNode::MKLDNNDepthToSpaceNode(const std::shared_ptr<ngraph::Nod
}
void MKLDNNDepthToSpaceNode::getSupportedDescriptors() {
SizeVector srcDims = inDims[0].ToSizeVector();
SizeVector srcDims = inputShapes[0].getStaticDims();
if (srcDims.size() < 3)
THROW_ERROR << "has incorrect number of input dimensions";
if (srcDims.size() > 5)
THROW_ERROR << "doesn't support dimensions with rank greater than 5";
SizeVector dstDims = outDims[0].ToSizeVector();
SizeVector dstDims = outputShapes[0].getStaticDims();
if (srcDims.size() != dstDims.size())
THROW_ERROR << "has incorrect number of input/output dimensions";
@@ -99,8 +99,8 @@ void MKLDNNDepthToSpaceNode::initSupportedPrimitiveDescriptors() {
return;
InferenceEngine::Precision precision = getOriginalInputPrecisionAtPort(0);
auto srcDims = getParentEdgeAt(0)->getDims();
const size_t nDims = srcDims.ndims();
auto srcDims = getParentEdgeAt(0)->getShape().getStaticDims();
const size_t nDims = srcDims.size();
impl_desc_type impl_type;
if (mayiuse(impl::cpu::x64::avx512_common)) {
@@ -113,7 +113,7 @@ void MKLDNNDepthToSpaceNode::initSupportedPrimitiveDescriptors() {
impl_type = impl_desc_type::ref;
}
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = true;
config.inConfs.resize(1);
config.outConfs.resize(1);
@@ -122,27 +122,27 @@ void MKLDNNDepthToSpaceNode::initSupportedPrimitiveDescriptors() {
config.outConfs[0].inPlace = -1;
config.outConfs[0].constant = false;
std::vector<TensorDescCreatorTypes> supportedTypes;
std::vector<LayoutType> supportedTypes;
if (nDims > 2) {
auto canUseBlocked = [=](const size_t block) {
return srcDims[1] % block == 0 && (srcDims[1] / block) % blockStep == 0 &&
(mode == Mode::DEPTH_FIRST ? block % blockStep == 0 : true);
};
supportedTypes.push_back(TensorDescCreatorTypes::nspc);
supportedTypes.push_back(LayoutType::nspc);
if (canUseBlocked(8lu))
supportedTypes.push_back(TensorDescCreatorTypes::nCsp8c);
supportedTypes.push_back(LayoutType::nCsp8c);
if (canUseBlocked(16lu))
supportedTypes.push_back(TensorDescCreatorTypes::nCsp16c);
supportedTypes.push_back(LayoutType::nCsp16c);
}
supportedTypes.push_back(TensorDescCreatorTypes::ncsp);
auto creators = TensorDescCreator::getCommonCreators();
auto range = TensorDescCreator::makeFilteredRange(creators, nDims, supportedTypes);
supportedTypes.push_back(LayoutType::ncsp);
auto creators = BlockedDescCreator::getCommonCreators();
auto range = BlockedDescCreator::makeFilteredRange(creators, nDims, supportedTypes);
for (auto itr = range.first; itr != range.second; ++itr) {
config.inConfs[0].desc = itr->second->createDesc(precision, getParentEdgeAt(0)->getDims().ToSizeVector());
config.outConfs[0].desc = itr->second->createDesc(precision, getChildEdgeAt(0)->getDims().ToSizeVector());
supportedPrimitiveDescriptors.emplace_back(config, impl_type, MKLDNNMemoryDesc(config.outConfs.front().desc).getFormat());
config.inConfs[0].desc = itr->second->createUniqueDesc(precision, getParentEdgeAt(0)->getShape().getStaticDims());
config.outConfs[0].desc = itr->second->createUniqueDesc(precision, getChildEdgeAt(0)->getShape().getStaticDims());
supportedPrimitiveDescriptors.emplace_back(config, impl_type);
}
}
@@ -156,18 +156,19 @@ void MKLDNNDepthToSpaceNode::createPrimitive() {
if (getSelectedPrimitiveDescriptor() == nullptr)
THROW_ERROR << "has unidentified preferable primitive descriptor";
SizeVector srcDims = getParentEdgeAt(0)->getBlob()->getTensorDesc().getDims();
SizeVector dstDims = getChildEdgeAt(0)->getBlob()->getTensorDesc().getDims();
SizeVector srcDims = getParentEdgeAt(0)->getShape().getStaticDims();
SizeVector dstDims = getChildEdgeAt(0)->getShape().getStaticDims();
size_t nDims = srcDims.size();
const size_t nSpatialDims = nDims - 2;
const bool isBlocked = getParentEdgeAt(0)->getMemory().GetDesc().isBlockedCFormat();
const bool isBlocked = getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nCsp8c) ||
getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nCsp16c);
const size_t reshapedRank = nDims + nSpatialDims + static_cast<int>(isBlocked) + static_cast<int>(isBlocked && mode == Mode::DEPTH_FIRST);
const size_t lastIdx = reshapedRank - 1;
size_t firstSpatialOrder = 2;
PermuteParams params;
params.data_size = getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc.getPrecision().size();
params.data_size = getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc->getPrecision().size();
params.order.resize(reshapedRank, 0);
params.src_block_order.resize(reshapedRank);
params.dst_block_order.resize(reshapedRank);
@@ -193,8 +194,8 @@ void MKLDNNDepthToSpaceNode::createPrimitive() {
};
if (isBlocked) {
SizeVector srcBlockedDims = getParentEdgeAt(0)->getDesc().getBlockingDesc().getBlockDims();
SizeVector dstBlockedDims = getChildEdgeAt(0)->getDesc().getBlockingDesc().getBlockDims();
SizeVector srcBlockedDims = getParentEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>().getBlockDims();
SizeVector dstBlockedDims = getChildEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>().getBlockDims();
size_t orderShiftForBlocks, orderShiftForDims;
if (mode == Mode::BLOCKS_FIRST) {
@@ -223,7 +224,7 @@ void MKLDNNDepthToSpaceNode::createPrimitive() {
}
reshapeAndSetPermOrder(orderShiftForDims, orderShiftForBlocks, firstSpatialOrder, srcBlockedDims);
} else if (getParentEdgeAt(0)->getMemory().GetDesc().isTailCFormat()) {
} else if (getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nspc)) {
srcDims.push_back(srcDims[1]);
dstDims.push_back(dstDims[1]);
srcDims.erase(srcDims.begin() + 1);
@@ -1,7 +1,6 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <vector>
@@ -116,13 +115,13 @@ void MKLDNNDetectionOutputNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
std::vector<DataConfigurator> inDataConf;
std::vector<PortConfigurator> inDataConf;
inDataConf.reserve(getOriginalInputsNumber());
for (int i = 0; i < getOriginalInputsNumber(); ++i)
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, Precision::FP32);
inDataConf.emplace_back(LayoutType::ncsp, Precision::FP32);
addSupportedPrimDesc(inDataConf,
{{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
@@ -132,12 +131,12 @@ void MKLDNNDetectionOutputNode::execute(mkldnn::stream strm) {
const float *loc_data = reinterpret_cast<const float *>(getParentEdgeAt(idx_location)->getMemoryPtr()->GetPtr());
const float *conf_data = reinterpret_cast<const float *>(getParentEdgeAt(idx_confidence)->getMemoryPtr()->GetPtr());
const float *prior_data = reinterpret_cast<const float *>(getParentEdgeAt(idx_priors)->getMemoryPtr()->GetPtr());
const float *arm_conf_data = inDims.size() > 3 ?
const float *arm_conf_data = inputShapes.size() > 3 ?
reinterpret_cast<const float *>(getParentEdgeAt(idx_arm_confidence)->getMemoryPtr()->GetPtr()) : nullptr;
const float *arm_loc_data = inDims.size() > 4 ?
const float *arm_loc_data = inputShapes.size() > 4 ?
reinterpret_cast<const float *>(getParentEdgeAt(idx_arm_location)->getMemoryPtr()->GetPtr()) : nullptr;
const int N = getParentEdgeAt(idx_confidence)->getDims()[0];
const int N = getParentEdgeAt(idx_confidence)->getShape().getStaticDims()[0];
float *decoded_bboxes_data = _decoded_bboxes.data();
float *reordered_conf_data = _reordered_conf.data();
@@ -286,8 +285,8 @@ void MKLDNNDetectionOutputNode::execute(mkldnn::stream strm) {
}
}
const int num_results = getChildEdgesAtPort(0)[0]->getDims()[2];
const int DETECTION_SIZE = getChildEdgesAtPort(0)[0]->getDims()[3];
const int num_results = getChildEdgesAtPort(0)[0]->getShape().getStaticDims()[2];
const int DETECTION_SIZE = getChildEdgesAtPort(0)[0]->getShape().getStaticDims()[3];
if (DETECTION_SIZE != 7) {
IE_THROW() << NOT_IMPLEMENTED;
}
@@ -300,7 +299,7 @@ void MKLDNNDetectionOutputNode::execute(mkldnn::stream strm) {
else
dst_data_size = N * _num_classes * _num_priors * DETECTION_SIZE * sizeof(float);
if (dst_data_size > getChildEdgesAtPort(0)[0]->getBlob()->byteSize()) {
if (dst_data_size > getChildEdgesAtPort(0)[0]->getMemory().GetSize()) {
IE_THROW() << OUT_OF_BOUNDS;
}
memset(dst_data, 0, dst_data_size);
@@ -48,20 +48,20 @@ MKLDNNDFTNode::MKLDNNDFTNode(const std::shared_ptr<ngraph::Node>& op, const mkld
}
/* Data */
inputShape = inDims[DATA_INDEX].ToSizeVector();
inputShape = inputShapes[DATA_INDEX].getStaticDims();
if (inputShape.size() < 2) {
IE_THROW() << layerErrorPrefix << " has invalid 'data' input tensor with rank: " << inputShape.size();
}
/* Axes */
const auto axesRank = inDims[AXES_INDEX].ndims();
const auto axesRank = inputShapes[AXES_INDEX].getRank();
if (axesRank != 1) {
IE_THROW() << layerErrorPrefix << " has invalid 'axes' input tensor with rank: " << axesRank;
}
/* Signal size */
if (inputsNumber > SIGNAL_SIZE_INDEX) {
const auto signalSizeRank = inDims[SIGNAL_SIZE_INDEX].ndims();
const auto signalSizeRank = inputShapes[SIGNAL_SIZE_INDEX].getRank();
if (signalSizeRank != 1) {
IE_THROW() << layerErrorPrefix << " has invalid 'signal_size' input tensor with rank: " << signalSizeRank;
}
@@ -93,12 +93,12 @@ void MKLDNNDFTNode::initSupportedPrimitiveDescriptors() {
}
}
std::vector<DataConfigurator> inDataConfigurators({{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::I32}});
std::vector<PortConfigurator> inDataConfigurators({{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::I32}});
if (getOriginalInputsNumber() > SIGNAL_SIZE_INDEX)
inDataConfigurators.push_back({TensorDescCreatorTypes::ncsp, Precision::I32});
inDataConfigurators.push_back({LayoutType::ncsp, Precision::I32});
addSupportedPrimDesc(inDataConfigurators, {{TensorDescCreatorTypes::ncsp, Precision::FP32}}, impl_desc_type::ref_any);
addSupportedPrimDesc(inDataConfigurators, {{LayoutType::ncsp, Precision::FP32}}, impl_desc_type::ref_any);
}
namespace {
@@ -225,7 +225,7 @@ void copyDataToOutputWithSignalSize(const float* input, const std::vector<size_t
void MKLDNNDFTNode::execute(mkldnn::stream strm) {
auto axesEdge = getParentEdgeAt(AXES_INDEX);
const auto* axesStartPtr = reinterpret_cast<const int32_t*>(axesEdge->getMemoryPtr()->GetPtr());
axes = std::vector<int32_t>(axesStartPtr, axesStartPtr + axesEdge->getDims()[0]);
axes = std::vector<int32_t>(axesStartPtr, axesStartPtr + axesEdge->getShape().getStaticDims()[0]);
for (auto& axis : axes) {
if (axis < 0) {
axis += inputShape.size() - 1;
@@ -233,7 +233,7 @@ void MKLDNNDFTNode::execute(mkldnn::stream strm) {
}
std::sort(axes.begin(), axes.end());
outputShape = getChildEdgeAt(0)->getDims().ToSizeVector();
outputShape = getChildEdgeAt(0)->getShape().getStaticDims();
for (size_t axis : axes) {
size_t nComplex = outputShape[axis];
// FFT uses different twiddle factors
@@ -247,8 +247,8 @@ void MKLDNNDFTNode::execute(mkldnn::stream strm) {
const auto *input = reinterpret_cast<const float*>(inputDataEdge->getMemoryPtr()->GetPtr());
auto *output = reinterpret_cast<float*>(outputDataEdge->getMemoryPtr()->GetPtr());
auto inputStrides = inputDataEdge->getDesc().getBlockingDesc().getStrides();
auto outputStrides = outputDataEdge->getDesc().getBlockingDesc().getStrides();
auto inputStrides = inputDataEdge->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
auto outputStrides = outputDataEdge->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
if (inputShape != outputShape) {
copyDataToOutputWithSignalSize(input, inputShape, inputStrides, output, outputShape, outputStrides);
} else {
@@ -257,7 +257,7 @@ void MKLDNNDFTNode::execute(mkldnn::stream strm) {
}
// 1d case
if (inputDataEdge->getDesc().getDims().size() == 2) {
if (inputDataEdge->getShape().getRank() == 2) {
size_t nComplex = outputShape[0];
if (IsPowerOfTwo(nComplex)) {
fft(output, nComplex * 2, true);
@@ -125,11 +125,11 @@ struct jit_uni_eltwise_generic : public MKLDNNPlugin::jit_uni_eltwise_kernel, pu
if (eltwiseNode.getFusedWith()[i].get()->getType() == Eltwise) {
post_op_emitters.push_back(create_eltwise_emitter(*eltwiseNode.getFusedWith()[i].get(), exec_prc));
} else if (eltwiseNode.getFusedWith()[i].get()->getType() == FakeQuantize) {
auto fakeQuantizeNode = dynamic_cast<MKLDNNFakeQuantizeNode*>(eltwiseNode.getFusedWith()[i].get());
fakeQuantizeNode->appendPostOps(post_ops);
auto fakeQuantizeNode = dynamic_cast<MKLDNNFakeQuantizeNode*>(eltwiseNode.getFusedWith()[i].get());
fakeQuantizeNode->appendPostOps(post_ops);
quantization_injectors.push_back(std::make_shared<jit_uni_quantization_injector_f32<isa>>(
this, post_ops.get()->entry_[post_ops.len() - 1], vmm_d_weights, vmm_d_bias, reg_d_weights, reg_d_bias));
quantization_injectors.push_back(std::make_shared<jit_uni_quantization_injector_f32<isa>>(
this, post_ops.get()->entry_[post_ops.len() - 1], vmm_d_weights, vmm_d_bias, reg_d_weights, reg_d_bias));
}
}
@@ -965,9 +965,9 @@ size_t MKLDNNEltwiseNode::getOpInputsNum() const {
}
bool MKLDNNEltwiseNode::isWithBroadcast() {
auto oDims = outDims[0].ToSizeVector();
for (size_t i = 0; i < inDims.size(); i++) {
auto iDims = inDims[i].ToSizeVector();
auto oDims = outputShapes[0].getStaticDims();
for (size_t i = 0; i < inputShapes.size(); i++) {
auto iDims = inputShapes[i].getStaticDims();
if (iDims != oDims)
return true;
}
@@ -1080,10 +1080,10 @@ void MKLDNNEltwiseNode::initSupportedPrimitiveDescriptors() {
Blocked
};
auto initDesc = [&] (LayoutType lt) -> PrimitiveDescInfo {
auto createMemoryDesc = [lt](MKLDNNEdgePtr edge, Precision prc, size_t offset) -> TensorDesc {
if (lt == ChannelsFirst && edge->getDims().ndims() != 1) {
auto dims = edge->getDims().ToSizeVector();
auto initDesc = [&] (LayoutType lt) -> NodeDesc {
auto createMemoryDesc = [lt](MKLDNNEdgePtr edge, Precision prc, size_t offset) -> std::unique_ptr<BlockedMemoryDesc> {
if (lt == ChannelsFirst && edge->getShape().getRank() != 1) {
auto dims = edge->getShape().getStaticDims();
auto ndims = dims.size();
std::vector<size_t> order(ndims);
std::iota(order.begin(), order.end(), 0);
@@ -1097,11 +1097,11 @@ void MKLDNNEltwiseNode::initSupportedPrimitiveDescriptors() {
blocks[i] = dims[order[i]];
}
return TensorDesc(prc, edge->getDims().ToSizeVector(), {blocks, order, offset});
} else if (lt == Blocked && edge->getDims().ndims() != 1 && edge->getDims()[1] != 1) {
return MKLDNNPlugin::make_unique<BlockedMemoryDesc>(prc, edge->getShape().getStaticDims(), blocks, order, offset);
} else if (lt == Blocked && edge->getShape().getRank() != 1 && edge->getShape().getStaticDims()[1] != 1) {
size_t blockSize = mayiuse(x64::avx512_common) ? 16 : 8;
std::vector<size_t> blocks = edge->getDims().ToSizeVector();
std::vector<size_t> blocks = edge->getShape().getStaticDims();
std::vector<size_t> order(blocks.size());
std::iota(order.begin(), order.end(), 0);
@@ -1109,37 +1109,38 @@ void MKLDNNEltwiseNode::initSupportedPrimitiveDescriptors() {
blocks.push_back(blockSize);
order.push_back(1);
return TensorDesc(prc, edge->getDims().ToSizeVector(), {blocks, order, offset});
return MKLDNNPlugin::make_unique<BlockedMemoryDesc>(prc, edge->getShape().getStaticDims(), blocks, order, offset);
} else {
std::vector<size_t> blocks = edge->getDims().ToSizeVector();
std::vector<size_t> blocks = edge->getShape().getStaticDims();
std::vector<size_t> order(blocks.size());
std::iota(order.begin(), order.end(), 0);
return TensorDesc(prc, edge->getDims().ToSizeVector(), {blocks, order, offset});
return MKLDNNPlugin::make_unique<BlockedMemoryDesc>(prc, edge->getShape().getStaticDims(), blocks, order, offset);
}
};
size_t offset = std::numeric_limits<size_t>::max();
InferenceEngine::LayerConfig config;
config.dynBatchSupport = getChildEdgeAt(0)->getDims().ndims() > 1 && getChildEdgeAt(0)->getDims() == getParentEdgeAt(0)->getDims();
NodeConfig config;
config.dynBatchSupport = getChildEdgeAt(0)->getShape().getRank() > 1 && getChildEdgeAt(0)->getShape() ==
getParentEdgeAt(0)->getShape();
for (size_t i = 0; i < getParentEdges().size(); i++) {
InferenceEngine::DataConfig dataConfig;
dataConfig.inPlace = (!i && canBeInPlace() && inputPrecisions[i] == outputPrecision) ? 0 : -1;
dataConfig.constant = false;
PortConfig portConfig;
portConfig.inPlace = (!i && canBeInPlace() && inputPrecisions[i] == outputPrecision) ? 0 : -1;
portConfig.constant = false;
dataConfig.desc = createMemoryDesc(getParentEdgeAt(i), inputPrecisions[i], offset);
portConfig.desc = createMemoryDesc(getParentEdgeAt(i), inputPrecisions[i], offset);
config.inConfs.push_back(dataConfig);
config.inConfs.push_back(portConfig);
}
InferenceEngine::DataConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
PortConfig portConfig;
portConfig.inPlace = -1;
portConfig.constant = false;
dataConfig.desc = createMemoryDesc(getChildEdgeAt(0), outputPrecision, offset);
portConfig.desc = createMemoryDesc(getChildEdgeAt(0), outputPrecision, offset);
config.outConfs.push_back(dataConfig);
config.outConfs.push_back(portConfig);
impl_desc_type impl_type;
if (mayiuse(x64::avx512_common)) {
@@ -1155,18 +1156,20 @@ void MKLDNNEltwiseNode::initSupportedPrimitiveDescriptors() {
return {config, impl_type};
};
bool isChannelsFirstApplicable = one_of(getChildEdgeAt(0)->getDims().ndims(), 1, 2, 4, 5);
bool isChannelsFirstApplicable = one_of(getChildEdgeAt(0)->getShape().getRank(), 1, 2, 4, 5);
for (size_t i = 0; i < getParentEdges().size(); i++) {
isChannelsFirstApplicable = isChannelsFirstApplicable && one_of(getParentEdgeAt(i)->getDims().ndims(), 1, 2, 4, 5);
isChannelsFirstApplicable = isChannelsFirstApplicable && implication(getParentEdgeAt(i)->getDims().ndims() != 1,
getChildEdgeAt(0)->getDims().ndims() == getParentEdgeAt(i)->getDims().ndims());
isChannelsFirstApplicable = isChannelsFirstApplicable && one_of(getParentEdgeAt(i)->getShape().getRank(), 1, 2, 4, 5);
isChannelsFirstApplicable = isChannelsFirstApplicable && implication(getParentEdgeAt(i)->getShape().getRank() != 1,
getChildEdgeAt(0)->getShape().getRank() ==
getParentEdgeAt(i)->getShape().getRank());
}
bool isBlockedApplicable = one_of(getChildEdgeAt(0)->getDims().ndims(), 1, 4, 5);
bool isBlockedApplicable = one_of(getChildEdgeAt(0)->getShape().getRank(), 1, 4, 5);
for (size_t i = 0; i < getParentEdges().size(); i++) {
isBlockedApplicable = isBlockedApplicable && one_of(getParentEdgeAt(i)->getDims().ndims(), 1, 4, 5);
isBlockedApplicable = isBlockedApplicable && implication(getParentEdgeAt(i)->getDims().ndims() != 1,
getChildEdgeAt(0)->getDims().ndims() == getParentEdgeAt(i)->getDims().ndims());
isBlockedApplicable = isBlockedApplicable && one_of(getParentEdgeAt(i)->getShape().getRank(), 1, 4, 5);
isBlockedApplicable = isBlockedApplicable && implication(getParentEdgeAt(i)->getShape().getRank() != 1,
getChildEdgeAt(0)->getShape().getRank() ==
getParentEdgeAt(i)->getShape().getRank());
}
if (isChannelsFirstApplicable)
@@ -1177,9 +1180,7 @@ void MKLDNNEltwiseNode::initSupportedPrimitiveDescriptors() {
}
void MKLDNNEltwiseNode::createPrimitive() {
auto config = getSelectedPrimitiveDescriptor()->getConfig();
auto initDims = [this, config](size_t maxInputSize) {
auto initDims = [this](size_t maxInputSize) {
size_t inputNum = getParentEdges().size();
dims_in.resize(inputNum);
@@ -1189,8 +1190,9 @@ void MKLDNNEltwiseNode::createPrimitive() {
dims_out.resize(maxInputSize, 1);
auto outBlockingDesc = getChildEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
std::vector<size_t> order(maxInputSize);
auto outOrder = config.outConfs[0].desc.getBlockingDesc().getOrder();
auto outOrder = outBlockingDesc.getOrder();
for (size_t i = 0; i < order.size(); i++) {
if (i < order.size() - outOrder.size())
order[i] = i;
@@ -1198,17 +1200,18 @@ void MKLDNNEltwiseNode::createPrimitive() {
order[i] = outOrder[i - (order.size() - outOrder.size())] + (order.size() - outOrder.size());
}
size_t outRank = config.outConfs[0].desc.getBlockingDesc().getBlockDims().size();
size_t outRank = outBlockingDesc.getBlockDims().size();
for (int i = 0; i < outRank; i++) {
dims_out[dims_out.size() - 1 - i] = config.outConfs[0].desc.getBlockingDesc().getBlockDims()[outRank - 1 - i];
dims_out[dims_out.size() - 1 - i] = outBlockingDesc.getBlockDims()[outRank - 1 - i];
}
for (int i = 0; i < inputNum; i++) {
size_t inRank = config.inConfs[i].desc.getBlockingDesc().getBlockDims().size();
auto inBlockingDesc = getParentEdgeAt(i)->getMemory().GetDescWithType<BlockedMemoryDesc>();
size_t inRank = inBlockingDesc.getBlockDims().size();
// WA to normalize blocked and planar layouts
auto inOrder = config.inConfs[i].desc.getBlockingDesc().getOrder();
size_t startOff = outOrder.size() != config.outConfs[0].desc.getDims().size() &&
auto inOrder = inBlockingDesc.getOrder();
size_t startOff = outOrder.size() != outBlockingDesc.getShape().getRank() &&
outOrder[outOrder.size() - 1] != inOrder[inOrder.size() - 1] ? 1 : 0;
// WA to handle nspc layout with 1D tensors
@@ -1217,7 +1220,7 @@ void MKLDNNEltwiseNode::createPrimitive() {
}
for (int j = 0; j < inRank; j++) {
dims_in[i][dims_in[i].size() - 1 - j - startOff] = config.inConfs[i].desc.getBlockingDesc().getBlockDims()[inRank - 1 - j];
dims_in[i][dims_in[i].size() - 1 - j - startOff] = inBlockingDesc.getBlockDims()[inRank - 1 - j];
}
}
@@ -1229,13 +1232,13 @@ void MKLDNNEltwiseNode::createPrimitive() {
}
};
auto initOffsets = [this, config](size_t maxInputSize) {
auto initOffsets = [this](size_t maxInputSize) {
size_t inputNum = getParentEdges().size();
offsets_out.resize(maxInputSize, 1);
offset_out_calc(offsets_out, dims_out);
for (int j = 0; j < maxInputSize; j++) {
offsets_out[j] *= config.outConfs[0].desc.getPrecision().size();
offsets_out[j] *= getChildEdgeAt(0)->getMemory().GetDesc().getPrecision().size();
}
offsets_in.resize(inputNum);
@@ -1243,7 +1246,7 @@ void MKLDNNEltwiseNode::createPrimitive() {
offsets_in[i].resize(maxInputSize, 1);
offset_in_calc(offsets_in[i], dims_in[i], dims_out);
for (int j = 0; j < maxInputSize; j++) {
offsets_in[i][j] *= config.inConfs[i].desc.getPrecision().size();
offsets_in[i][j] *= getParentEdgeAt(i)->getMemory().GetDesc().getPrecision().size();
}
}
@@ -1287,10 +1290,11 @@ void MKLDNNEltwiseNode::createPrimitive() {
}
};
tensorRank = std::max(static_cast<size_t>(optimalTensorRank), config.outConfs[0].desc.getBlockingDesc().getBlockDims().size());
auto outBlockingDesc = getChildEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
tensorRank = std::max(static_cast<size_t>(optimalTensorRank), outBlockingDesc.getBlockDims().size());
initDims(tensorRank);
auto outOrder = config.outConfs[0].desc.getBlockingDesc().getOrder();
auto outOrder = outBlockingDesc.getOrder();
size_t oc_size = 0;
offsets_oc.resize(tensorRank, 0);
if (isFusedWith(FakeQuantize)) {
@@ -1310,7 +1314,7 @@ void MKLDNNEltwiseNode::createPrimitive() {
fullWorkAmount *= dims_out[i];
}
isDynBatchEnabled = config.dynBatchSupport;
isDynBatchEnabled = getSelectedPrimitiveDescriptor()->getConfig().dynBatchSupport;
size_t minimalConcurrency = parallel_get_max_threads();
size_t minimalJitWorkAmount = 256;
@@ -1320,7 +1324,7 @@ void MKLDNNEltwiseNode::createPrimitive() {
bool hasDifferentDims = false;
while (currentJitWorkAmount < minimalJitWorkAmount && currentJitWorkAmount < fullWorkAmount &&
// we shouldn't collapse batch dimension in case dynamic batch is enabled
(!isDynBatchEnabled || (config.outConfs[0].desc.getBlockingDesc().getBlockDims().size() - collapsedDims > 2))) {
(!isDynBatchEnabled || (outBlockingDesc.getBlockDims().size() - collapsedDims > 2))) {
if (dims_out.size() - collapsedDims - 2 < 0)
break;
@@ -1372,22 +1376,24 @@ void MKLDNNEltwiseNode::createPrimitive() {
}
}
batchDimIdx = tensorRank - config.outConfs[0].desc.getBlockingDesc().getBlockDims().size() + collapsedDims;
batchDimIdx = tensorRank - outBlockingDesc.getBlockDims().size() + collapsedDims;
schedulerWorkAmount = fullWorkAmount / dims_out[dims_out.size() - 1];
initOffsets(tensorRank);
jep.inputs_number = config.inConfs.size();
const size_t inpuPortsCount = getSelectedPrimitiveDescriptor()->getConfig().inConfs.size();
jep.inputs_number = inpuPortsCount;
jep.input_size = tensorRank;
for (int i = 0; i < config.inConfs.size(); i++) {
for (int i = 0; i < inpuPortsCount; i++) {
jep.src_size[i] = dims_in[i][dims_in[i].size() - 1];
jep.src_prc[i] = config.inConfs[i].desc.getPrecision();
jep.src_prc[i] = getParentEdgesAtPort(i).front()->getMemory().GetDesc().getPrecision();
}
jep.dst_size = dims_out[dims_out.size() - 1];
jep.dst_prc = config.outConfs[0].desc.getPrecision();
jep.dst_prc = getChildEdgesAtPort(0).front()->getMemory().GetDesc().getPrecision();
for (int i = 0; i < config.inConfs.size(); i++) {
for (int i = 0; i < inpuPortsCount; i++) {
jep.src_offsets[i] = offsets_in[i];
}
jep.dst_offsets = offsets_out;
@@ -1415,13 +1421,13 @@ void MKLDNNEltwiseNode::initOptimalPrimitiveDescriptor() {
if (selected_pd == nullptr)
IE_THROW() << "Preferable primitive descriptor is not set.";
auto config = selected_pd->getConfig();
if (!isInitConfig(config)) {
if (!isConfigDefined(config)) {
for (size_t i = 0; i < config.inConfs.size(); i++) {
config.inConfs[i].desc = getConfiguredInputDesc(config, i);
config.inConfs[i].desc = std::move(getDefinedInputDesc(config, i));
}
for (size_t i = 0; i < config.outConfs.size(); i++) {
config.outConfs[i].desc = getConfiguredOutputDesc(config, i);
config.outConfs[i].desc = std::move(getDefinedOutputDesc(config, i));
}
initDescriptor(config);
@@ -1641,13 +1647,13 @@ bool MKLDNNEltwiseNode::canBeInPlace() const {
}
}
return getParentEdgesAtPort(0)[0].get()->getDims() == getChildEdgesAtPort(0)[0].get()->getDims();
return getParentEdgesAtPort(0)[0].get()->getShape() == getChildEdgesAtPort(0)[0].get()->getShape();
}
void MKLDNNEltwiseNode::fuseInto(MKLDNNNodePtr& parentNode) {
// Handling Convolution custom Add node fusing case which is processed via dnnl append_sum() API.
specialConvolutionAddFusing = (parentNode->getType() == Convolution || parentNode->getType() == BinaryConvolution) && getAlgorithm() == EltwiseAdd &&
getParentEdgesAtPort(0)[0]->getDims().ToSizeVector() == getParentEdgesAtPort(1)[0]->getDims().ToSizeVector();
getParentEdgesAtPort(0)[0]->getShape() == getParentEdgesAtPort(1)[0]->getShape();
if (!specialConvolutionAddFusing && canBePerformedAsScaleShift(parentNode.get())) {
fillScalesAndShifts(parentNode.get(), scales, shifts, 16);
}
@@ -1770,7 +1776,7 @@ InferenceEngine::Precision MKLDNNEltwiseNode::getRuntimePrecision() const {
}
}
return MKLDNNExtensionUtils::getMaxPrecision(inputPrecisions);
return getMaxPrecision(inputPrecisions);
}
REG_MKLDNN_PRIM_FOR(MKLDNNEltwiseNode, Eltwise);
@@ -62,15 +62,15 @@ void MKLDNNEmbeddingBagOffsetSumNode::initSupportedPrimitiveDescriptors() {
IE_THROW() << logPrefix << "has unsupported precision: " << inDataPrecision.name();
}
std::vector<DataConfigurator> inDataConfigurators({{TensorDescCreatorTypes::ncsp, inDataPrecision},
{TensorDescCreatorTypes::ncsp, Precision::I32},
{TensorDescCreatorTypes::ncsp, Precision::I32}});
std::vector<PortConfigurator> inDataConfigurators({{LayoutType::ncsp, inDataPrecision},
{LayoutType::ncsp, Precision::I32},
{LayoutType::ncsp, Precision::I32}});
if (getOriginalInputsNumber() > DEFAULT_INDEX_IDX)
inDataConfigurators.push_back({TensorDescCreatorTypes::ncsp, Precision::I32});
inDataConfigurators.push_back({LayoutType::ncsp, Precision::I32});
if (getOriginalInputsNumber() > PER_SAMPLE_WEIGHTS_IDX)
inDataConfigurators.push_back({TensorDescCreatorTypes::ncsp, inDataPrecision});
inDataConfigurators.push_back({LayoutType::ncsp, inDataPrecision});
addSupportedPrimDesc(inDataConfigurators, {{TensorDescCreatorTypes::ncsp, inDataPrecision}}, impl_desc_type::ref_any);
addSupportedPrimDesc(inDataConfigurators, {{LayoutType::ncsp, inDataPrecision}}, impl_desc_type::ref_any);
}
void MKLDNNEmbeddingBagOffsetSumNode::initFromInputs() {
@@ -122,7 +122,8 @@ void MKLDNNEmbeddingBagOffsetSumNode::execute(mkldnn::stream strm) {
if (_withWeights)
weightsData = reinterpret_cast<const uint8_t *>(getParentEdgeAt(PER_SAMPLE_WEIGHTS_IDX)->getMemoryPtr()->GetPtr());
MKLDNNEmbeddingBagSumNode::execute(srcData, weightsData, dstData, getParentEdgeAt(0)->getDesc(), getChildEdgeAt(0)->getDesc());
MKLDNNEmbeddingBagSumNode::execute(srcData, weightsData, dstData, getParentEdgeAt(0)->getMemory().GetDesc().getPrecision(),
getParentEdgeAt(0)->getShape().getStaticDims(), getChildEdgeAt(0)->getShape().getStaticDims());
}
bool MKLDNNEmbeddingBagOffsetSumNode::created() const {
@@ -58,12 +58,12 @@ void MKLDNNEmbeddingBagPackedSumNode::initSupportedPrimitiveDescriptors() {
IE_THROW() << logPrefix << "has unsupported precision: " << inDataPrecision.name();
}
std::vector<DataConfigurator> inDataConfigurators({{TensorDescCreatorTypes::ncsp, inDataPrecision},
{TensorDescCreatorTypes::ncsp, Precision::I32}});
std::vector<PortConfigurator> inDataConfigurators({{LayoutType::ncsp, inDataPrecision},
{LayoutType::ncsp, Precision::I32}});
if (getOriginalInputsNumber() > PER_SAMPLE_WEIGHTS_IDX)
inDataConfigurators.push_back({TensorDescCreatorTypes::ncsp, inDataPrecision});
inDataConfigurators.push_back({LayoutType::ncsp, inDataPrecision});
addSupportedPrimDesc(inDataConfigurators, {{TensorDescCreatorTypes::ncsp, inDataPrecision}}, impl_desc_type::ref_any);
addSupportedPrimDesc(inDataConfigurators, {{LayoutType::ncsp, inDataPrecision}}, impl_desc_type::ref_any);
}
void MKLDNNEmbeddingBagPackedSumNode::initFromInputs() {
@@ -89,7 +89,8 @@ void MKLDNNEmbeddingBagPackedSumNode::execute(mkldnn::stream strm) {
if (_withWeights)
weightsData = reinterpret_cast<const uint8_t *>(getParentEdgeAt(PER_SAMPLE_WEIGHTS_IDX)->getMemoryPtr()->GetPtr());
MKLDNNEmbeddingBagSumNode::execute(srcData, weightsData, dstData, getParentEdgeAt(0)->getDesc(), getChildEdgeAt(0)->getDesc());
MKLDNNEmbeddingBagSumNode::execute(srcData, weightsData, dstData, getParentEdgeAt(0)->getMemory().GetDesc().getPrecision(),
getParentEdgeAt(0)->getShape().getStaticDims(), getChildEdgeAt(0)->getShape().getStaticDims());
}
bool MKLDNNEmbeddingBagPackedSumNode::created() const {
@@ -44,13 +44,12 @@ MKLDNNEmbeddingBagSumNode::MKLDNNEmbeddingBagSumNode(
template<typename T>
void MKLDNNEmbeddingBagSumNode::processData(const T* srcData, const T* weightsData, T* dstData,
const InferenceEngine::TensorDesc& srcDesc, const InferenceEngine::TensorDesc& dstDesc) {
const InferenceEngine::SizeVector& inDataDims, const InferenceEngine::SizeVector& outDataDims) {
std::string msgPrefix = std::string("Node EmbeddingBagSum with name '") + _layerName + "' ";
initFromInputs();
const auto& inDataDims = srcDesc.getDims();
const size_t outputBagsNum = dstDesc.getDims()[0];
const size_t outputBagsNum = outDataDims[0];
auto threadBody = [&](const int ithr, const int nthr) {
size_t start(0lu), end(0lu);
@@ -115,27 +114,27 @@ void MKLDNNEmbeddingBagSumNode::processData(const T* srcData, const T* weightsDa
parallel_nt(0, threadBody);
}
void MKLDNNEmbeddingBagSumNode::execute(const uint8_t* srcData, const uint8_t* weightsData, uint8_t* dstData,
const InferenceEngine::TensorDesc& srcDesc, const InferenceEngine::TensorDesc& dstDesc) {
switch (srcDesc.getPrecision()) {
void MKLDNNEmbeddingBagSumNode::execute(const uint8_t* srcData, const uint8_t* weightsData, uint8_t* dstData, const InferenceEngine::Precision &srcPrc,
const InferenceEngine::SizeVector& inDims, const InferenceEngine::SizeVector& outDims) {
switch (srcPrc) {
case Precision::FP32: {
return processData<PrecisionTrait<Precision::FP32>::value_type>(reinterpret_cast<const float*>(srcData),
reinterpret_cast<const float*>(weightsData), reinterpret_cast<float*>(dstData), srcDesc, dstDesc);
reinterpret_cast<const float*>(weightsData), reinterpret_cast<float*>(dstData), inDims, outDims);
}
case Precision::I8: {
return processData<PrecisionTrait<Precision::I8>::value_type>(reinterpret_cast<const int8_t*>(srcData),
reinterpret_cast<const int8_t*>(weightsData), reinterpret_cast<int8_t*>(dstData), srcDesc, dstDesc);
reinterpret_cast<const int8_t*>(weightsData), reinterpret_cast<int8_t*>(dstData), inDims, outDims);
}
case Precision::U8: {
return processData<PrecisionTrait<Precision::U8>::value_type>(srcData, weightsData, dstData, srcDesc, dstDesc);
return processData<PrecisionTrait<Precision::U8>::value_type>(srcData, weightsData, dstData, inDims, outDims);
}
case Precision::I32: {
return processData<PrecisionTrait<Precision::I32>::value_type>(reinterpret_cast<const int32_t*>(srcData),
reinterpret_cast<const int32_t*>(weightsData), reinterpret_cast<int32_t*>(dstData), srcDesc, dstDesc);
reinterpret_cast<const int32_t*>(weightsData), reinterpret_cast<int32_t*>(dstData), inDims, outDims);
}
default: {
IE_THROW() << "EmbeddingBagSum layer does not support precision '"
+ std::string(srcDesc.getPrecision().name()) + "'";
+ std::string(srcPrc.name()) + "'";
}
}
}
@@ -21,8 +21,8 @@ public:
size_t perSampleWeightsIdx,
size_t defaultIndexIdx);
void execute(const uint8_t* srcData, const uint8_t* weightsData, uint8_t* dstData,
const InferenceEngine::TensorDesc& srcDesc, const InferenceEngine::TensorDesc& dstDesc);
void execute(const uint8_t* srcData, const uint8_t* weightsData, uint8_t* dstData, const InferenceEngine::Precision &srcPrc,
const InferenceEngine::SizeVector& inDims, const InferenceEngine::SizeVector& outDims);
~MKLDNNEmbeddingBagSumNode() = default;
@@ -37,7 +37,7 @@ protected:
template<typename T>
void processData(const T* srcData, const T* weightsData, T* dstData,
const InferenceEngine::TensorDesc& srcDesc, const InferenceEngine::TensorDesc& dstDesc);
const InferenceEngine::SizeVector& inDataDims, const InferenceEngine::SizeVector& outDataDims);
const size_t EMB_TABLE_IDX = 0lu;
const size_t INDICES_IDX;
@@ -62,21 +62,21 @@ void MKLDNNEmbeddingSegmentsSumNode::initSupportedPrimitiveDescriptors() {
IE_THROW() << logPrefix << "has unsupported precision: " << inDataPrecision.name();
}
std::vector<DataConfigurator> inDataConfigurators({{TensorDescCreatorTypes::ncsp, inDataPrecision},
{TensorDescCreatorTypes::ncsp, Precision::I32},
{TensorDescCreatorTypes::ncsp, Precision::I32},
{TensorDescCreatorTypes::ncsp, Precision::I32}});
std::vector<PortConfigurator> inDataConfigurators({{LayoutType::ncsp, inDataPrecision},
{LayoutType::ncsp, Precision::I32},
{LayoutType::ncsp, Precision::I32},
{LayoutType::ncsp, Precision::I32}});
if (getOriginalInputsNumber() > DEFAULT_INDEX_IDX)
inDataConfigurators.push_back({TensorDescCreatorTypes::ncsp, Precision::I32});
inDataConfigurators.push_back({LayoutType::ncsp, Precision::I32});
if (getOriginalInputsNumber() > PER_SAMPLE_WEIGHTS_IDX)
inDataConfigurators.push_back({TensorDescCreatorTypes::ncsp, inDataPrecision});
inDataConfigurators.push_back({LayoutType::ncsp, inDataPrecision});
addSupportedPrimDesc(inDataConfigurators, {{TensorDescCreatorTypes::ncsp, inDataPrecision}}, impl_desc_type::ref_any);
addSupportedPrimDesc(inDataConfigurators, {{LayoutType::ncsp, inDataPrecision}}, impl_desc_type::ref_any);
}
void MKLDNNEmbeddingSegmentsSumNode::initFromInputs() {
indices_ = reinterpret_cast<const int *>(getParentEdgeAt(INDICES_IDX)->getMemoryPtr()->GetPtr());
indicesSize_ = getParentEdgeAt(INDICES_IDX)->getBlob()->size();
indicesSize_ = getParentEdgeAt(INDICES_IDX)->getShape().getElementsCount();
segmentIds_ = reinterpret_cast<const int *>(getParentEdgeAt(SEGMENT_ID_IDX)->getMemoryPtr()->GetPtr());
@@ -124,7 +124,8 @@ void MKLDNNEmbeddingSegmentsSumNode::execute(mkldnn::stream strm) {
if (_withWeights)
weightsData = reinterpret_cast<const uint8_t *>(getParentEdgeAt(PER_SAMPLE_WEIGHTS_IDX)->getMemoryPtr()->GetPtr());
MKLDNNEmbeddingBagSumNode::execute(srcData, weightsData, dstData, getParentEdgeAt(0)->getDesc(), getChildEdgeAt(0)->getDesc());
MKLDNNEmbeddingBagSumNode::execute(srcData, weightsData, dstData, getParentEdgeAt(0)->getMemory().GetDesc().getPrecision(),
getParentEdgeAt(0)->getShape().getStaticDims(), getChildEdgeAt(0)->getShape().getStaticDims());
}
bool MKLDNNEmbeddingSegmentsSumNode::created() const {
@@ -1,7 +1,6 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <vector>
@@ -253,22 +252,22 @@ void MKLDNNExperimentalDetectronDetectionOutputNode::initSupportedPrimitiveDescr
if (!supportedPrimitiveDescriptors.empty())
return;
std::vector<DataConfigurator> inDataConf;
std::vector<PortConfigurator> inDataConf;
inDataConf.reserve(getOriginalInputsNumber());
for (int i = 0; i < getOriginalInputsNumber(); ++i)
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, Precision::FP32);
inDataConf.emplace_back(LayoutType::ncsp, Precision::FP32);
addSupportedPrimDesc(inDataConf,
{{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::I32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::I32},
{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
void MKLDNNExperimentalDetectronDetectionOutputNode::execute(mkldnn::stream strm) {
const int rois_num = getParentEdgeAt(INPUT_ROIS)->getDims()[0];
assert(classes_num_ == static_cast<int>(getParentEdgeAt(INPUT_SCORES)->getDims()[1]));
assert(4 * classes_num_ == static_cast<int>(getParentEdgeAt(INPUT_DELTAS)->getDims()[1]));
const int rois_num = getParentEdgeAt(INPUT_ROIS)->getShape().getStaticDims()[0];
assert(classes_num_ == static_cast<int>(getParentEdgeAt(INPUT_SCORES)->getShape().getStaticDims()[1]));
assert(4 * classes_num_ == static_cast<int>(getParentEdgeAt(INPUT_DELTAS)->getShape().getStaticDims()[1]));
const auto* boxes = reinterpret_cast<const float *>(getParentEdgeAt(INPUT_ROIS)->getMemoryPtr()->GetPtr());
const auto* deltas = reinterpret_cast<const float *>(getParentEdgeAt(INPUT_DELTAS)->getMemoryPtr()->GetPtr());
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <cstring>
#include <cassert>
#include <cmath>
@@ -313,36 +311,36 @@ void MKLDNNExperimentalDetectronGenerateProposalsSingleImageNode::initSupportedP
if (!supportedPrimitiveDescriptors.empty())
return;
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
void MKLDNNExperimentalDetectronGenerateProposalsSingleImageNode::execute(mkldnn::stream strm) {
try {
if (inDims.size() != 4 || outDims.size() != 2) {
if (inputShapes.size() != 4 || outputShapes.size() != 2) {
IE_THROW() << "Incorrect number of input or output edges!";
}
size_t anchor_dims_size = 1;
for (size_t i = 0; i < getParentEdgeAt(INPUT_ANCHORS)->getDims().ToSizeVector().size(); i++) {
anchor_dims_size *= getParentEdgeAt(INPUT_ANCHORS)->getDims().ToSizeVector()[i];
for (size_t i = 0; i < getParentEdgeAt(INPUT_ANCHORS)->getShape().getRank(); i++) {
anchor_dims_size *= getParentEdgeAt(INPUT_ANCHORS)->getShape().getStaticDims()[i];
}
size_t deltas_dims_size = 1;
for (size_t i = 0; i < getParentEdgeAt(INPUT_DELTAS)->getDims().ToSizeVector().size(); i++) {
deltas_dims_size *= getParentEdgeAt(INPUT_DELTAS)->getDims().ToSizeVector()[i];
for (size_t i = 0; i < getParentEdgeAt(INPUT_DELTAS)->getShape().getRank(); i++) {
deltas_dims_size *= getParentEdgeAt(INPUT_DELTAS)->getShape().getStaticDims()[i];
}
if (anchor_dims_size != deltas_dims_size)
IE_THROW() << "'Anchors' blob size for ONNXProposal is incompatible with 'deltas' blob size!";
size_t score_dims_size = 1;
for (size_t i = 0; i < getParentEdgeAt(INPUT_SCORES)->getDims().ToSizeVector().size(); i++) {
score_dims_size *= getParentEdgeAt(INPUT_SCORES)->getDims().ToSizeVector()[i];
for (size_t i = 0; i < getParentEdgeAt(INPUT_SCORES)->getShape().getRank(); i++) {
score_dims_size *= getParentEdgeAt(INPUT_SCORES)->getShape().getStaticDims()[i];
}
if (deltas_dims_size != (4 * score_dims_size))
IE_THROW() << "'Deltas' blob size for ONNXProposal is incompatible with 'scores' blob size!";
@@ -356,11 +354,11 @@ void MKLDNNExperimentalDetectronGenerateProposalsSingleImageNode::execute(mkldnn
float *p_roi_item = reinterpret_cast<float *>(getChildEdgesAtPort(OUTPUT_ROIS)[0]->getMemoryPtr()->GetPtr());
float *p_roi_score_item = reinterpret_cast<float *>(getChildEdgesAtPort(OUTPUT_SCORES)[0]->getMemoryPtr()->GetPtr());
const int anchors_num = getParentEdgeAt(INPUT_SCORES)->getDims()[0];
const int anchors_num = getParentEdgeAt(INPUT_SCORES)->getShape().getStaticDims()[0];
// bottom shape: (num_anchors) x H x W
const int bottom_H = getParentEdgeAt(INPUT_DELTAS)->getDims()[1];
const int bottom_W = getParentEdgeAt(INPUT_DELTAS)->getDims()[2];
const int bottom_H = getParentEdgeAt(INPUT_DELTAS)->getShape().getStaticDims()[1];
const int bottom_W = getParentEdgeAt(INPUT_DELTAS)->getShape().getStaticDims()[2];
// input image height & width
const float img_H = p_img_info_cpu[0];
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <ngraph/opsets/opset6.hpp>
@@ -55,22 +53,22 @@ void MKLDNNExperimentalDetectronPriorGridGeneratorNode::initSupportedPrimitiveDe
if (!supportedPrimitiveDescriptors.empty())
return;
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
void MKLDNNExperimentalDetectronPriorGridGeneratorNode::execute(mkldnn::stream strm) {
const int num_priors_ = getParentEdgeAt(INPUT_PRIORS)->getDims()[0];
assert(getParentEdgeAt(INPUT_PRIORS)->getDims()[1] == 4);
const int num_priors_ = getParentEdgeAt(INPUT_PRIORS)->getShape().getStaticDims()[0];
assert(getParentEdgeAt(INPUT_PRIORS)->getShape().getStaticDims()[1] == 4);
// Execute
const int layer_width = grid_w_ ? grid_w_ : getParentEdgeAt(INPUT_FEATUREMAP)->getDims()[3];
const int layer_height = grid_h_ ? grid_h_ : getParentEdgeAt(INPUT_FEATUREMAP)->getDims()[2];
const float step_w = stride_w_ ? stride_w_ : static_cast<float>(getParentEdgeAt(INPUT_IMAGE)->getDims()[3]) / layer_width;
const float step_h = stride_h_ ? stride_h_ : static_cast<float>(getParentEdgeAt(INPUT_IMAGE)->getDims()[2]) / layer_height;
const int layer_width = grid_w_ ? grid_w_ : getParentEdgeAt(INPUT_FEATUREMAP)->getShape().getStaticDims()[3];
const int layer_height = grid_h_ ? grid_h_ : getParentEdgeAt(INPUT_FEATUREMAP)->getShape().getStaticDims()[2];
const float step_w = stride_w_ ? stride_w_ : static_cast<float>(getParentEdgeAt(INPUT_IMAGE)->getShape().getStaticDims()[3]) / layer_width;
const float step_h = stride_h_ ? stride_h_ : static_cast<float>(getParentEdgeAt(INPUT_IMAGE)->getShape().getStaticDims()[2]) / layer_height;
const auto *bottom_data_0 = reinterpret_cast<const float *>(getParentEdgeAt(0)->getMemoryPtr()->GetPtr());
auto *top_data_0 = reinterpret_cast<float *>(getChildEdgesAtPort(OUTPUT_ROIS)[0]->getMemoryPtr()->GetPtr());
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <vector>
#include <algorithm>
@@ -341,27 +339,27 @@ void MKLDNNExperimentalDetectronROIFeatureExtractorNode::initSupportedPrimitiveD
if (!supportedPrimitiveDescriptors.empty())
return;
std::vector<DataConfigurator> inDataConf;
std::vector<PortConfigurator> inDataConf;
inDataConf.reserve(getOriginalInputsNumber());
for (int i = 0; i < getOriginalInputsNumber(); ++i)
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, Precision::FP32);
inDataConf.emplace_back(LayoutType::ncsp, Precision::FP32);
addSupportedPrimDesc(inDataConf,
{{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
void MKLDNNExperimentalDetectronROIFeatureExtractorNode::execute(mkldnn::stream strm) {
const int levels_num = inDims.size() - INPUT_FEATURES_START;
const int num_rois = getParentEdgeAt(INPUT_ROIS)->getDims()[0];
const int channels_num = getParentEdgeAt(INPUT_FEATURES_START)->getDims()[1];
const int levels_num = inputShapes.size() - INPUT_FEATURES_START;
const int num_rois = getParentEdgeAt(INPUT_ROIS)->getShape().getStaticDims()[0];
const int channels_num = getParentEdgeAt(INPUT_FEATURES_START)->getShape().getStaticDims()[1];
const int feaxels_per_roi = pooled_height_ * pooled_width_ * channels_num;
auto *input_rois = reinterpret_cast<const float *>(getParentEdgeAt(INPUT_ROIS)->getMemoryPtr()->GetPtr());
auto *output_rois_features = reinterpret_cast<float *>(getChildEdgesAtPort(OUTPUT_ROI_FEATURES)[0]->getMemoryPtr()->GetPtr());
float *output_rois = nullptr;
if (OUTPUT_ROIS < outDims.size()) {
if (OUTPUT_ROIS < outputShapes.size()) {
output_rois = reinterpret_cast<float *>(getChildEdgesAtPort(OUTPUT_ROIS)[0]->getMemoryPtr()->GetPtr());
}
@@ -381,8 +379,8 @@ void MKLDNNExperimentalDetectronROIFeatureExtractorNode::execute(mkldnn::stream
const int level_rois_num = rois_per_level[i + 1] - level_rois_offset;
if (level_rois_num > 0) {
auto *featuremap = reinterpret_cast<const float *>(getParentEdgeAt(INPUT_FEATURES_START + i)->getMemoryPtr()->GetPtr());
const int featuremap_height = getParentEdgeAt(INPUT_FEATURES_START + i)->getDims()[2];
const int featuremap_width = getParentEdgeAt(INPUT_FEATURES_START + i)->getDims()[3];
const int featuremap_height = getParentEdgeAt(INPUT_FEATURES_START + i)->getShape().getStaticDims()[2];
const int featuremap_width = getParentEdgeAt(INPUT_FEATURES_START + i)->getShape().getStaticDims()[3];
ROIAlignForward_cpu_kernel<float>(feaxels_per_roi * level_rois_num,
featuremap,
1.0f / pyramid_scales_[i],
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <vector>
#include <algorithm>
@@ -51,14 +49,14 @@ void MKLDNNExperimentalDetectronTopKROIsNode::initSupportedPrimitiveDescriptors(
if (!supportedPrimitiveDescriptors.empty())
return;
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
void MKLDNNExperimentalDetectronTopKROIsNode::execute(mkldnn::stream strm) {
const int input_rois_num = getParentEdgeAt(INPUT_ROIS)->getDims()[0];
const int input_rois_num = getParentEdgeAt(INPUT_ROIS)->getShape().getStaticDims()[0];
const int top_rois_num = (std::min)(max_rois_num_, input_rois_num);
auto *input_rois = reinterpret_cast<const float *>(getParentEdgeAt(INPUT_ROIS)->getMemoryPtr()->GetPtr());
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <cstring>
#include <string>
#include <cmath>
@@ -411,8 +409,8 @@ void MKLDNNExtractImagePatchesNode::initSupportedPrimitiveDescriptors() {
if (_supported_precisions_sizes.find(precision.size()) == _supported_precisions_sizes.end())
IE_THROW() << errorPrefix << "has unsupported precision: " << precision.name();
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, precision}},
{{TensorDescCreatorTypes::ncsp, precision}},
addSupportedPrimDesc({{LayoutType::ncsp, precision}},
{{LayoutType::ncsp, precision}},
impl_desc_type::ref_any);
}
@@ -421,12 +419,12 @@ void MKLDNNExtractImagePatchesNode::execute(mkldnn::stream strm) {
char *dst_data = reinterpret_cast<char *>(getChildEdgesAtPort(0)[0]->getMemoryPtr()->GetPtr());
const size_t dtype_size = getOriginalInputPrecisionAtPort(0).size();
const auto& inDims = getParentEdgeAt(0)->getDims().ToSizeVector();
const auto& inDims = getParentEdgeAt(0)->getShape().getStaticDims();
const size_t IC = inDims[1];
const size_t IH = inDims[2];
const size_t IW = inDims[3];
const auto& outDims = getChildEdgesAtPort(0)[0]->getDims().ToSizeVector();
const auto& outDims = getChildEdgesAtPort(0)[0]->getShape().getStaticDims();
const size_t OB = outDims[0];
const size_t OH = outDims[2];
const size_t OW = outDims[3];
@@ -436,8 +434,8 @@ void MKLDNNExtractImagePatchesNode::execute(mkldnn::stream strm) {
const size_t RH = _rates[0], RW = _rates[1];
const size_t PT = _pad_top, PL = _pad_left;
const std::vector<size_t> istrides = getParentEdgeAt(0)->getDesc().getBlockingDesc().getStrides();
const std::vector<size_t> ostrides = getChildEdgesAtPort(0)[0]->getDesc().getBlockingDesc().getStrides();
const std::vector<size_t> istrides = getParentEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
const std::vector<size_t> ostrides = getChildEdgesAtPort(0)[0]->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
const std::vector<size_t> ostrides_partial = {ostrides[0], KW * IC * ostrides[1], IC * ostrides[1], ostrides[1]};
if (extract_image_patches_kernel) {
@@ -19,6 +19,7 @@
#include "ie_parallel.hpp"
#include <ngraph/opsets/opset1.hpp>
#include <cpu_memory_desc_utils.h>
// Quantization ranges validation is switched off by default in order to avoid regressions on user side
// #define VALIDATE_QUANTIZATION_RANGES
@@ -219,7 +220,7 @@ struct jit_uni_quantization_kernel : public jit_uni_quantize_kernel, public jit_
this->preamble();
if (jqp_.src_layout == Layout::CHW || jqp_.src_layout == Layout::NCHW || jqp_.src_layout == Layout::NCDHW)
if (jqp_.is_planar)
compute_planar();
else
compute_generic();
@@ -1090,31 +1091,23 @@ MKLDNNFakeQuantizeNode::MKLDNNFakeQuantizeNode(const std::shared_ptr<ngraph::Nod
}
}
std::vector<mkldnn::memory::format_tag> MKLDNNFakeQuantizeNode::getDataFormats() const {
std::vector<LayoutType> MKLDNNFakeQuantizeNode::getDataFormats() const {
// Special case for first FQ in the network
if (getParentEdgesAtPort(0)[0]->getDims()[getAxis()] == 3) {
return { MKLDNNMemory::GetPlainFormat(getParentEdgesAtPort(0)[0]->getDims()) };
if (getParentEdgesAtPort(0)[0]->getShape().getStaticDims()[getAxis()] == 3) {
return { LayoutType::ncsp };
} else {
if (isBinarization()) {
return {memory::format_tag::nhwc};
return { LayoutType::nspc };
} else {
switch (getParentEdgesAtPort(0)[0]->getDims().ndims()) {
case 4:
if (getAxis() == 1) {
auto blkFormat = mayiuse(cpu::x64::avx512_common) ? memory::format_tag::nChw16c : memory::format_tag::nChw8c;
return {blkFormat, memory::format_tag::nhwc, memory::format_tag::nchw};
} else {
return {memory::format_tag::nchw};
}
case 5:
if (getAxis() == 1) {
auto blkFormat = mayiuse(cpu::x64::avx512_common) ? memory::format_tag::nCdhw16c : memory::format_tag::nCdhw8c;
return {blkFormat, memory::format_tag::ndhwc, memory::format_tag::ncdhw};
} else {
return {memory::format_tag::ncdhw};
}
default:
return {MKLDNNMemory::GetPlainFormat(getParentEdgesAtPort(0)[0]->getDims())};
if (one_of(getParentEdgesAtPort(0)[0]->getShape().getRank(), 4, 5)) {
if (getAxis() == 1) {
auto blkFormat = mayiuse(cpu::x64::avx512_common) ? LayoutType::nCsp16c : LayoutType::nCsp8c;
return { blkFormat, LayoutType::nspc, LayoutType::ncsp };
} else {
return { LayoutType::ncsp };
}
} else {
return { LayoutType::ncsp };
}
}
}
@@ -1147,12 +1140,12 @@ void MKLDNNFakeQuantizeNode::getSupportedDescriptors() {
IE_THROW() << errorPrefix << "has unsupported number of parent edges at port " << i;
}
if (getParentEdgesAtPort(0)[0]->getDims().ndims() != getChildEdgesAtPort(0)[0]->getDims().ndims()) {
if (getParentEdgesAtPort(0)[0]->getShape().getRank() != getChildEdgesAtPort(0)[0]->getShape().getRank()) {
IE_THROW() << errorPrefix << "has different ranks for input and output tensors";
}
if (isBinarization()) {
if (getParentEdgesAtPort(0)[0]->getDims().ndims() != 4ul) {
if (getParentEdgesAtPort(0)[0]->getShape().getRank() != 4ul) {
IE_THROW() << errorPrefix << "doesn't support input/output rank != 4";
}
}
@@ -1189,47 +1182,52 @@ void MKLDNNFakeQuantizeNode::initSupportedPrimitiveDescriptors() {
}
}
auto inputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(getInputPrecision());
auto outputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(getOutputPrecision());
for (auto& fmt : getDataFormats()) {
LayerConfig config;
NodeConfig config;
config.dynBatchSupport = true;
for (size_t i = 0; i < getParentEdges().size(); i++) {
DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
if (i == 0) {
dataConfig.desc = MKLDNNMemoryDesc(getParentEdgeAt(i)->getDims(), inputDataType, fmt);
auto descCreator = BlockedDescCreator::getCommonCreators().at(fmt);
dataConfig.desc = descCreator->createUniqueDesc(getInputPrecision(), getParentEdgeAt(i)->getShape().getStaticDims());
} else {
dataConfig.desc = MKLDNNMemoryDesc(getParentEdgeAt(i)->getDims(), memory::data_type::f32,
MKLDNNMemory::GetPlainFormat(getParentEdgeAt(i)->getDims()));
auto descCreator = BlockedDescCreator::getCommonCreators().at(LayoutType::ncsp);
dataConfig.desc = descCreator->createUniqueDesc(Precision::FP32, getParentEdgeAt(i)->getShape().getStaticDims());
}
config.inConfs.push_back(dataConfig);
}
DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, fmt);
auto descCreator = BlockedDescCreator::getCommonCreators().at(fmt);
dataConfig.desc = descCreator->createUniqueDesc(getOutputPrecision(), getChildEdgeAt(0)->getShape().getStaticDims());
config.outConfs.push_back(dataConfig);
supportedPrimitiveDescriptors.push_back({config, impl_type, fmt});
supportedPrimitiveDescriptors.push_back({config, impl_type});
}
}
void MKLDNNFakeQuantizeNode::createPrimitive() {
auto config = getSelectedPrimitiveDescriptor()->getConfig();
auto inDims = config.inConfs[0].desc.getDims();
auto inDims = config.inConfs[0].desc->getShape().getStaticDims();
jqp.c = inDims.size() > 1 ? inDims[1] : 1;
jqp.src_prc = config.inConfs[0].desc.getPrecision();
jqp.src_prc = config.inConfs[0].desc->getPrecision();
jqp.wei_prc = Precision::FP32;
jqp.dst_prc = config.outConfs[0].desc.getPrecision();
jqp.dst_prc = config.outConfs[0].desc->getPrecision();
jqp.src_layout = config.inConfs[0].desc.getLayout();
auto srcDesc = getParentEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
jqp.s_str = srcDesc.getStrides();
auto dstDesc = getChildEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
jqp.d_str = dstDesc.getStrides();
jqp.is_planar = srcDesc.hasLayoutType(LayoutType::ncsp) && one_of(srcDesc.getShape().getRank(), 3, 4, 5);
jqp.op_type = getAlgorithm();
@@ -1258,7 +1256,7 @@ void MKLDNNFakeQuantizeNode::createPrimitive() {
if (quantize_kernel)
quantize_kernel->create_ker();
size_t axisSize = getParentEdgeAt(0)->getDims()[getAxis()];
size_t axisSize = getParentEdgeAt(0)->getShape().getStaticDims()[getAxis()];
size_t axisPaddedSize = rnd_up(axisSize, 16);
MKLDNNMemoryDesc weightsDataDesc = {{(uint32_t)axisPaddedSize}, memory::data_type::f32, memory::format_tag::x};
@@ -1297,12 +1295,11 @@ void MKLDNNFakeQuantizeNode::executeReference() {
auto src = reinterpret_cast<const float *>(srcMemory->GetPtr());
auto config = getSelectedPrimitiveDescriptor()->getConfig();
auto srcDims = config.inConfs[0].desc.getDims();
auto dstDims = config.outConfs[0].desc.getDims();
auto srcDims = srcMemory->GetDesc().getShape().getStaticDims();
auto dstDims = dstMemory->GetDesc().getShape().getStaticDims();
auto s_str = config.inConfs[0].desc.getBlockingDesc().getStrides();
auto d_str = config.outConfs[0].desc.getBlockingDesc().getStrides();
auto s_str = jqp.s_str;
auto d_str = jqp.d_str;
const int N = srcDims[0];
const int C = srcDims.size() > 1 ? srcDims[1] : 1;
@@ -1419,10 +1416,9 @@ void MKLDNNFakeQuantizeNode::executeBinarization() {
auto thresholds = reinterpret_cast<const float*>(internalBlobMemory[0]->GetData());
auto output_mask = reinterpret_cast<const float*>(internalBlobMemory[1]->GetData());
auto config = getSelectedPrimitiveDescriptor()->getConfig();
auto src_dims = config.inConfs[0].desc.getDims();
auto src_dims = srcMemory->GetDesc().getShape().getStaticDims();
std::vector<size_t> s_str = config.inConfs[0].desc.getBlockingDesc().getStrides();
std::vector<size_t> s_str = jqp.s_str;
size_t tmp = s_str[s_str.size() - 1];
for (int i = s_str.size() - 1; i > 1; i--) {
s_str[i] = s_str[i - 1];
@@ -1463,24 +1459,23 @@ void MKLDNNFakeQuantizeNode::executeQuantization() {
auto output_scale = reinterpret_cast<const float*>(internalBlobMemory[4]->GetData());
auto output_shift = reinterpret_cast<const float*>(internalBlobMemory[5]->GetData());
auto config = getSelectedPrimitiveDescriptor()->getConfig();
auto srcDims = config.inConfs[0].desc.getDims();
auto& srcDesc = srcMemory->GetDesc();
auto srcDims = srcDesc.getShape().getStaticDims();
bool is_blk_format = jqp.src_layout != Layout::NHWC && jqp.src_layout != Layout::NDHWC;
int blk_size = (jqp.src_layout == Layout::CHW ||
jqp.src_layout == Layout::NCHW ||
jqp.src_layout == Layout::NCDHW) ? 1 : mayiuse(cpu::x64::avx512_common) ? 16 : 8;
bool is_blk_format = !srcDesc.hasLayoutType(LayoutType::nspc) && one_of(srcDesc.getShape().getRank(), 4, 5);
int blk_size = (srcDesc.hasLayoutType(LayoutType::ncsp) && one_of(srcDesc.getShape().getRank(), 3, 4, 5))
? 1 : mayiuse(cpu::x64::avx512_common) ? 16 : 8;
auto src_type_size = jqp.src_prc.size();
auto dst_type_size = jqp.dst_prc.size();
std::vector<size_t> s_str = config.inConfs[0].desc.getBlockingDesc().getStrides();
auto s_str = jqp.s_str;
if (jqp.src_layout == BLOCKED) {
if (is_blk_format) {
s_str[1] /= blk_size;
}
if (jqp.src_layout == Layout::NHWC || jqp.src_layout == Layout::NDHWC) {
if (srcDesc.hasLayoutType(LayoutType::nspc) && one_of(srcDesc.getShape().getRank(), 4, 5)) {
size_t tmp = s_str[s_str.size() - 1];
for (int i = s_str.size() - 1; i > 1; i--) {
s_str[i] = s_str[i - 1];
@@ -1495,7 +1490,7 @@ void MKLDNNFakeQuantizeNode::executeQuantization() {
const int H = srcDims.size() == 3 ? srcDims[2] : srcDims.size() > 3 ? srcDims[srcDims.size() - 2] : 1;
const int W = srcDims.size() > 3 ? srcDims[srcDims.size() - 1] : 1;
if (jqp.src_layout == Layout::CHW) {
if (srcDesc.hasLayoutType(LayoutType::ncsp) && srcDesc.getShape().getRank() == 3) {
parallel_nd(N, CB, D, [&](int n, int cb, int d) {
auto arg = jit_quantize_call_args();
@@ -1542,7 +1537,7 @@ void MKLDNNFakeQuantizeNode::executeQuantization() {
arg.src_step = is_blk_format ? (size_t) blk_size * src_type_size : (size_t) C * src_type_size;
arg.dst_step = is_blk_format ? (size_t) blk_size * dst_type_size : (size_t) C * dst_type_size;
arg.block_size = (is_blk_format && jqp.src_layout != Layout::NC) ? (size_t) blk_size : nstl::min(blk_size, C - c);
arg.block_size = (is_blk_format && srcDims.size() != 2) ? (size_t) blk_size : nstl::min(blk_size, C - c);
arg.work_amount = (size_t) W;
(*quantize_kernel)(&arg);
@@ -17,12 +17,14 @@ namespace MKLDNNPlugin {
struct jit_quantize_params {
int c;
bool is_planar;
InferenceEngine::Precision src_prc;
InferenceEngine::Precision wei_prc;
InferenceEngine::Precision dst_prc;
InferenceEngine::Layout src_layout;
std::vector<size_t> s_str;
std::vector<size_t> d_str;
Algorithm op_type;
};
@@ -109,7 +111,7 @@ public:
private:
void init() override;
std::vector<mkldnn::memory::format_tag> getDataFormats() const;
std::vector<LayoutType> getDataFormats() const;
void executeReference();
void executeBinarization();
void executeQuantization();
@@ -12,6 +12,7 @@
#include <mkldnn_extension_utils.h>
#include <mkldnn.hpp>
#include "utils/general_utils.h"
#include <cpu_memory_desc_utils.h>
using namespace mkldnn;
using namespace MKLDNNPlugin;
@@ -50,18 +51,18 @@ MKLDNNFullyConnectedNode::MKLDNNFullyConnectedNode(const std::shared_ptr<ngraph:
}
}
std::vector<memory::format_tag> MKLDNNFullyConnectedNode::getAvailableFormatsForDims(const MKLDNNDims &dims) const {
if (dims.ndims() == 0)
std::vector<memory::format_tag> MKLDNNFullyConnectedNode::getAvailableFormatsForDims(const Shape &dims) const {
if (dims.getRank() == 0)
return {memory::format_tag::x};
else if (dims.ndims() == 1)
else if (dims.getRank() == 1)
return {memory::format_tag::x};
else if (dims.ndims() == 2)
else if (dims.getRank() == 2)
return {memory::format_tag::nc};
else if (dims.ndims() == 3)
else if (dims.getRank() == 3)
return {memory::format_tag::tnc};
else if (dims.ndims() == 4)
else if (dims.getRank() == 4)
return {memory::format_tag::nChw8c, memory::format_tag::nChw16c, memory::format_tag::nhwc, memory::format_tag::nchw};
else if (dims.ndims() == 5)
else if (dims.getRank() == 5)
return {memory::format_tag::nCdhw8c, memory::format_tag::nCdhw16c, memory::format_tag::ndhwc, memory::format_tag::ncdhw};
return {memory::format_tag::any};
}
@@ -100,23 +101,23 @@ void MKLDNNFullyConnectedNode::getSupportedDescriptors() {
outputDataType = memory::data_type::bf16;
}
MKLDNNDims inDims = getParentEdgeAt(0)->getDims();
MKLDNNDims outDims = getChildEdgeAt(0)->getDims();
const auto inDims = getParentEdgeAt(0)->getShape().getStaticDims();
const auto outDims = getChildEdgeAt(0)->getShape().getStaticDims();
if (inDims.ndims() == 3) {
if (inDims.size() == 3) {
weightsDims = InferenceEngine::SizeVector({static_cast<size_t>(outDims[2]), static_cast<size_t>(inDims[2])});
} else {
weightsDims.push_back(outDims[1]);
for (int i = 1; i < inDims.ndims(); i++)
for (int i = 1; i < inDims.size(); i++)
weightsDims.push_back(inDims[i]);
}
biasesDims.push_back(weightsDims[0]);
for (auto format : getAvailableFormatsForDims(inDims)) {
MKLDNNMemoryDesc in_candidate(inDims, inputDataType, format);
MKLDNNMemoryDesc out_candidate(outDims, outputDataType, memory::format_tag::any);
for (auto format : getAvailableFormatsForDims(getParentEdgeAt(0)->getShape())) {
auto in_candidate = mkldnn::memory::desc(MKLDNNExtensionUtils::convertToDnnlDims(inDims), inputDataType, format);
auto out_candidate = mkldnn::memory::desc(MKLDNNExtensionUtils::convertToDnnlDims(outDims), outputDataType, mkldnn::memory::format_tag::any);
createDescriptor({in_candidate}, {out_candidate});
createDescriptorInternal(in_candidate, out_candidate);
}
}
@@ -236,35 +237,40 @@ std::shared_ptr<mkldnn::primitive_attr> MKLDNNFullyConnectedNode::initPrimitiveA
return attr;
}
void MKLDNNFullyConnectedNode::createDescriptor(const std::vector<InferenceEngine::TensorDesc> &inputDesc,
const std::vector<InferenceEngine::TensorDesc> &outputDesc) {
TensorDesc inDesc = inputDesc[0], outDesc = outputDesc[0];
// WA: creation MKLDNNMemoryDesc with format == any is prohibited
// so we create mkldnn::memory::desc directly
// we need specific method and can't remove createDescriptor from base class because its used into initDescriptor
void MKLDNNFullyConnectedNode::createDescriptorInternal(const mkldnn::memory::desc &inputDesc,
const mkldnn::memory::desc &outputDesc) {
auto in_candidate = inputDesc;
auto out_candidate = outputDesc;
mkldnn::memory::data_type wdt = MKLDNNExtensionUtils::IEPrecisionToDataType(inDesc.getPrecision());
mkldnn::memory::data_type bdt = MKLDNNExtensionUtils::IEPrecisionToDataType(inDesc.getPrecision());
if (inDesc.getPrecision() == Precision::BF16) {
mkldnn::memory::data_type wdt = in_candidate.data_type();
mkldnn::memory::data_type bdt = out_candidate.data_type();
if (in_candidate.data_type() == mkldnn::memory::data_type::bf16) {
bdt = mkldnn::memory::data_type::f32;
} else if (inDesc.getPrecision() == Precision::U8 || inDesc.getPrecision() == Precision::I8) {
} else if (in_candidate.data_type() == mkldnn::memory::data_type::u8 || in_candidate.data_type() == mkldnn::memory::data_type::s8) {
wdt = memory::data_type::s8;
if (withBiases)
bdt = MKLDNNExtensionUtils::IEPrecisionToDataType(getOriginalInputPrecisionAtPort(BIAS_ID));
}
if (inDesc.getDims().size() == 3) {
auto inDims = inDesc.getDims();
auto outDims = outDesc.getDims();
InferenceEngine::SizeVector normalizedInDims = {inDims[0] * inDims[1], inDims[2]};
InferenceEngine::SizeVector normalizedOutDims = {outDims[0] * outDims[1], outDims[2]};
inDesc = InferenceEngine::TensorDesc(inDesc.getPrecision(), normalizedInDims, TensorDesc::getLayoutByDims(normalizedInDims));
outDesc = InferenceEngine::TensorDesc(outDesc.getPrecision(), normalizedOutDims, TensorDesc::getLayoutByDims(normalizedOutDims));
if (in_candidate.dims().size() == 3) {
auto inDims = in_candidate.dims();
auto outDims = out_candidate.dims();
auto normalizedInDims = {inDims[0] * inDims[1], inDims[2]};
auto normalizedOutDims = {outDims[0] * outDims[1], outDims[2]};
in_candidate = mkldnn::memory::desc(normalizedInDims, in_candidate.data_type(),
MKLDNNMemory::GetPlainFormatByRank(normalizedInDims.size()));
out_candidate = mkldnn::memory::desc(normalizedOutDims, out_candidate.data_type(),
MKLDNNMemory::GetPlainFormatByRank(normalizedOutDims.size()));
}
MKLDNNMemoryDesc in_candidate(inDesc);
MKLDNNMemoryDesc out_candidate(outDesc);
MKLDNNMemoryDesc wgh_candidate(MKLDNNDims(weightsDims), wdt, mkldnn::memory::format_tag::any);
mkldnn::memory::desc wgh_candidate(MKLDNNDims(weightsDims), wdt, mkldnn::memory::format_tag::any);
if (withBiases) {
MKLDNNMemoryDesc bias_candidate(MKLDNNDims(inDims[BIAS_ID]), bdt, memory::format_tag::any);
mkldnn::memory::desc bias_candidate(MKLDNNExtensionUtils::convertToDnnlDims(inputShapes[BIAS_ID].getStaticDims()), bdt,
mkldnn::memory::format_tag::any);
MKLDNNDescriptor desc(std::shared_ptr<inner_product_forward::desc>(
new inner_product_forward::desc(prop_kind::forward_scoring, in_candidate, wgh_candidate,
bias_candidate, out_candidate)));
@@ -277,40 +283,28 @@ void MKLDNNFullyConnectedNode::createDescriptor(const std::vector<InferenceEngin
}
}
MKLDNNMemoryDesc MKLDNNFullyConnectedNode::getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
InferenceEngine::TensorDesc desc = idx > 0 ? MKLDNNMemoryDesc(primitive_desc_it.weights_desc(idx - 1))
: MKLDNNMemoryDesc(primitive_desc_it.src_desc(idx));
if (desc.getLayout() == InferenceEngine::Layout::ANY) {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getParentEdgeAt(idx)->getDims().ToSizeVector(),
desc.getLayout()));
} else if (getParentEdgeAt(idx)->getDims().ndims() == 3) {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getParentEdgeAt(idx)->getDims().ToSizeVector(),
TensorDesc::getLayoutByDims(getParentEdgeAt(idx)->getDims().ToSizeVector())));
} else {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getParentEdgeAt(idx)->getDims().ToSizeVector(),
desc.getBlockingDesc()));
}
void MKLDNNFullyConnectedNode::createDescriptor(const std::vector<const MemoryDesc*> &inputDesc,
const std::vector<const MemoryDesc*> &outputDesc) {
createDescriptorInternal(MemoryDescUtils::convertToMKLDNNMemoryDesc(*inputDesc[0]), MemoryDescUtils::convertToMKLDNNMemoryDesc(*outputDesc[0]));
}
MKLDNNMemoryDesc MKLDNNFullyConnectedNode::getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
InferenceEngine::TensorDesc desc = MKLDNNMemoryDesc(primitive_desc_it.dst_desc(idx));
if (desc.getLayout() == InferenceEngine::Layout::ANY) {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getChildEdgeAt(idx)->getDims().ToSizeVector(),
desc.getLayout()));
} else if (getChildEdgeAt(idx)->getDims().ndims() == 3) {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getChildEdgeAt(idx)->getDims().ToSizeVector(),
TensorDesc::getLayoutByDims(getChildEdgeAt(idx)->getDims().ToSizeVector())));
} else {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(desc.getPrecision(),
getChildEdgeAt(idx)->getDims().ToSizeVector(),
desc.getBlockingDesc()));
std::unique_ptr<MKLDNNMemoryDesc> MKLDNNFullyConnectedNode::getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
auto desc = idx > 0 ? MKLDNNMemoryDesc(primitive_desc_it.weights_desc(idx - 1)) : MKLDNNMemoryDesc(primitive_desc_it.src_desc(idx));
if (getParentEdgeAt(idx)->getShape().getRank() == 3) {
desc = MKLDNNMemoryDesc(getParentEdgeAt(idx)->getShape().getStaticDims(), MKLDNNExtensionUtils::IEPrecisionToDataType(desc.getPrecision()),
MKLDNNMemory::GetPlainFormatByRank(getParentEdgeAt(idx)->getShape().getRank()));
}
return MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(std::move(desc));
}
std::unique_ptr<MKLDNNMemoryDesc> MKLDNNFullyConnectedNode::getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
auto desc = MKLDNNMemoryDesc(primitive_desc_it.dst_desc(idx));
if (getChildEdgeAt(idx)->getShape().getRank() == 3) {
desc = MKLDNNMemoryDesc(getChildEdgeAt(idx)->getShape().getStaticDims(), MKLDNNExtensionUtils::IEPrecisionToDataType(desc.getPrecision()),
MKLDNNMemory::GetPlainFormatByRank(getChildEdgeAt(idx)->getShape().getRank()));
}
return MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(std::move(desc));
}
InferenceEngine::Precision MKLDNNFullyConnectedNode::getRuntimePrecision() const {
@@ -324,7 +318,7 @@ InferenceEngine::Precision MKLDNNFullyConnectedNode::getRuntimePrecision() const
}
}
return MKLDNNExtensionUtils::getMaxPrecision(inputPrecisions);
return getMaxPrecision(inputPrecisions);
}
REG_MKLDNN_PRIM_FOR(MKLDNNFullyConnectedNode, FullyConnected);
@@ -16,7 +16,7 @@ class MKLDNNFullyConnectedNode : public MKLDNNNode {
public:
MKLDNNFullyConnectedNode(const std::shared_ptr<ngraph::Node>& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache);
std::vector<mkldnn::memory::format_tag> getAvailableFormatsForDims(const MKLDNNDims &dims) const override;
std::vector<mkldnn::memory::format_tag> getAvailableFormatsForDims(const Shape &dims) const override;
void getSupportedDescriptors() override;
void createPrimitive() override;
void execute(mkldnn::stream strm) override;
@@ -27,15 +27,15 @@ public:
}
const std::vector<impl_desc_type>& getPrimitivesPriority() override;
void createDescriptor(const std::vector<InferenceEngine::TensorDesc>& inputDesc,
const std::vector<InferenceEngine::TensorDesc>& outputDesc) override;
void createDescriptor(const std::vector<const MemoryDesc*>& inputDesc,
const std::vector<const MemoryDesc*>& outputDesc) override;
size_t descInputNumbers(MKLDNNDescriptor desc) override {
return static_cast<size_t>(getOriginalInputsNumber());
}
MKLDNNMemoryDesc getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
MKLDNNMemoryDesc getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
std::unique_ptr<MKLDNNMemoryDesc> getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
std::unique_ptr<MKLDNNMemoryDesc> getDstMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
InferenceEngine::Precision getRuntimePrecision() const override;
@@ -47,6 +47,9 @@ protected:
std::shared_ptr<mkldnn::primitive_attr> initPrimitiveAttr();
private:
void createDescriptorInternal(const mkldnn::memory::desc &inputDesc,
const mkldnn::memory::desc &outputDesc);
InferenceEngine::SizeVector weightsDims;
InferenceEngine::SizeVector biasesDims;
@@ -86,9 +86,9 @@ void MKLDNNGatherElementsNode::initSupportedPrimitiveDescriptors() {
dataTypeSize_ = inDataPrecision.size();
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, inDataPrecision},
{TensorDescCreatorTypes::ncsp, Precision::I32}},
{{TensorDescCreatorTypes::ncsp, inDataPrecision}},
addSupportedPrimDesc({{LayoutType::ncsp, inDataPrecision},
{LayoutType::ncsp, Precision::I32}},
{{LayoutType::ncsp, inDataPrecision}},
impl_desc_type::ref_any);
}
@@ -98,7 +98,7 @@ void MKLDNNGatherElementsNode::directExecution() {
const auto *indices = reinterpret_cast<const int *>(getParentEdgeAt(indicesIndex_)->getMemoryPtr()->GetPtr());
auto *dstData = reinterpret_cast<dataType *>(getChildEdgeAt(0)->getMemoryPtr()->GetPtr());
const int outSize = getChildEdgeAt(0)->getBlob()->size();
const int outSize = getChildEdgeAt(0)->getShape().getElementsCount();
auto threadBody = [&](const int ithr, const int nthr) {
int start(0lu), end(0lu);
splitter(outSize, nthr, ithr, start, end);
@@ -89,9 +89,9 @@ void MKLDNNGatherNDNode::initSupportedPrimitiveDescriptors() {
_dataTypeSize = inDataPrecision.size();
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, inDataPrecision},
{TensorDescCreatorTypes::ncsp, Precision::I32}},
{{TensorDescCreatorTypes::ncsp, inDataPrecision}},
addSupportedPrimDesc({{LayoutType::ncsp, inDataPrecision},
{LayoutType::ncsp, Precision::I32}},
{{LayoutType::ncsp, inDataPrecision}},
impl_desc_type::ref_any);
}
@@ -101,10 +101,11 @@ void MKLDNNGatherNDNode::gatherElementwise() {
const auto *indices = reinterpret_cast<const int *>(getParentEdgeAt(_indicesIndex)->getMemoryPtr()->GetPtr());
auto *dstData = reinterpret_cast<dataType *>(getChildEdgeAt(0)->getMemoryPtr()->GetPtr());
auto strides = getParentEdgeAt(_dataIndex)->getDesc().getBlockingDesc().getStrides();
auto strides = getParentEdgeAt(_dataIndex)->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
const size_t* srcMultipliers = strides.data() + _batchDims;
const size_t cycles = getChildEdgeAt(0)->getBlob()->byteSize() / (sizeof(dataType) * _batchNum);
const size_t cycles = getChildEdgeAt(0)->getShape().getElementsCount() *
getChildEdgeAt(0)->getMemory().GetDesc().getPrecision().size() / (sizeof(dataType) * _batchNum);
const size_t CS = cycles * _sliceRank;
const size_t CB = cycles * _blockSize;
const size_t workAmount = _batchNum * cycles;
@@ -149,11 +150,11 @@ void MKLDNNGatherNDNode::gatherBlocks() {
std::vector<size_t> srcMultipliers(_sliceRank);
for (size_t i = 0; i < _sliceRank ; i++)
srcMultipliers[i] = _dataTypeSize * getParentEdgeAt(_dataIndex)->getDesc().getBlockingDesc().getStrides()[i + _batchDims];
srcMultipliers[i] = _dataTypeSize * getParentEdgeAt(_dataIndex)->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides()[i + _batchDims];
const size_t batchStep = _batchStep * _dataTypeSize;
const size_t dataStep = _blockSize * _dataTypeSize;
const size_t cycles = getChildEdgeAt(0)->getBlob()->byteSize() / (dataStep * _batchNum);
const size_t cycles = getChildEdgeAt(0)->getMemory().GetSize() / (dataStep * _batchNum);
const size_t CS = cycles * _sliceRank;
const size_t CB = cycles * dataStep;
const size_t workAmount = _batchNum * cycles;
@@ -75,10 +75,10 @@ void MKLDNNGatherNode::initSupportedPrimitiveDescriptors() {
return;
Precision dataPrecision = getOriginalInputPrecisionAtPort(GATHER_DATA);
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, dataPrecision},
{TensorDescCreatorTypes::ncsp, Precision::I32},
{TensorDescCreatorTypes::ncsp, Precision::I32}},
{{TensorDescCreatorTypes::ncsp, dataPrecision}},
addSupportedPrimDesc({{LayoutType::ncsp, dataPrecision},
{LayoutType::ncsp, Precision::I32},
{LayoutType::ncsp, Precision::I32}},
{{LayoutType::ncsp, dataPrecision}},
impl_desc_type::ref_any);
}
@@ -92,10 +92,10 @@ void MKLDNNGatherNode::createPrimitive() {
if (getSelectedPrimitiveDescriptor() == nullptr)
IE_THROW() << errorPrefix_ << " has unidentified preferable primitive descriptor.";
const SizeVector srcDims = getParentEdgeAt(GATHER_DATA)->getDims().ToSizeVector();
const SizeVector idxDims = getParentEdgeAt(GATHER_INDEXES)->getDims().ToSizeVector();
const SizeVector dstDims = getChildEdgeAt(0)->getDims().ToSizeVector();
dataSize = getParentEdgeAt(GATHER_DATA)->getDesc().getPrecision().size();
const SizeVector srcDims = getParentEdgeAt(GATHER_DATA)->getShape().getStaticDims();
const SizeVector idxDims = getParentEdgeAt(GATHER_INDEXES)->getShape().getStaticDims();
const SizeVector dstDims = getChildEdgeAt(0)->getShape().getStaticDims();
dataSize = getParentEdgeAt(GATHER_DATA)->getMemory().GetDesc().getPrecision().size();
indexRange = srcDims[axis];
batchSize = std::accumulate(srcDims.begin(), srcDims.begin() + batchDims, 1, std::multiplies<size_t>());
@@ -1,7 +1,6 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <vector>
@@ -66,11 +65,11 @@ void MKLDNNGatherTreeNode::initSupportedPrimitiveDescriptors() {
IE_THROW() << errorPrefix << " has incorrect input/output data precision. Must be the same.";
}
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, precision},
{TensorDescCreatorTypes::ncsp, precision},
{TensorDescCreatorTypes::ncsp, precision},
{TensorDescCreatorTypes::ncsp, precision}},
{{TensorDescCreatorTypes::ncsp, precision}},
addSupportedPrimDesc({{LayoutType::ncsp, precision},
{LayoutType::ncsp, precision},
{LayoutType::ncsp, precision},
{LayoutType::ncsp, precision}},
{{LayoutType::ncsp, precision}},
impl_desc_type::ref_any);
}
@@ -85,16 +84,16 @@ template<typename DATA_T>
void MKLDNNGatherTreeNode::gatherTreeKernel() noexcept {
const auto *step_idx = reinterpret_cast<DATA_T *>(getParentEdgeAt(GATHER_TREE_STEP_IDX)->getMemoryPtr()->GetPtr());
const auto * const parent_idx = reinterpret_cast<DATA_T *>(getParentEdgeAt(GATHER_TREE_PARENT_IDX)->getMemoryPtr()->GetPtr());
const size_t parent_idx_size = getParentEdgeAt(GATHER_TREE_PARENT_IDX)->getDims().size()
- getParentEdgeAt(GATHER_TREE_PARENT_IDX)->getDesc().getBlockingDesc().getOffsetPadding();
const size_t parent_idx_size = getParentEdgeAt(GATHER_TREE_PARENT_IDX)->getShape().getElementsCount()
- getParentEdgeAt(GATHER_TREE_PARENT_IDX)->getMemory().GetDescWithType<BlockedMemoryDesc>().getOffsetPadding();
const auto *max_seq_len = reinterpret_cast<DATA_T *>(getParentEdgeAt(GATHER_TREE_MAX_SEQ_LEN)->getMemoryPtr()->GetPtr());
auto end_token = (reinterpret_cast<DATA_T *>(getParentEdgeAt(GATHER_TREE_END_TOKEN)->getMemoryPtr()->GetPtr()))[0];
auto * final_idx = reinterpret_cast<DATA_T *>(getChildEdgesAtPort(0)[0]->getMemoryPtr()->GetPtr());
SizeVector step_idx_dims = getParentEdgeAt(GATHER_TREE_STEP_IDX)->getDims().ToSizeVector();
SizeVector parent_idx_dims = getParentEdgeAt(GATHER_TREE_PARENT_IDX)->getDims().ToSizeVector();
SizeVector max_seq_len_dims = getParentEdgeAt(GATHER_TREE_MAX_SEQ_LEN)->getDims().ToSizeVector();
SizeVector final_idx_dims = getChildEdgesAtPort(0)[0]->getDims().ToSizeVector();
SizeVector step_idx_dims = getParentEdgeAt(GATHER_TREE_STEP_IDX)->getShape().getStaticDims();
SizeVector parent_idx_dims = getParentEdgeAt(GATHER_TREE_PARENT_IDX)->getShape().getStaticDims();
SizeVector max_seq_len_dims = getParentEdgeAt(GATHER_TREE_MAX_SEQ_LEN)->getShape().getStaticDims();
SizeVector final_idx_dims = getChildEdgesAtPort(0)[0]->getShape().getStaticDims();
int32_t max_time = step_idx_dims[0];
const size_t batch_size = step_idx_dims[1];
const size_t beam_width = step_idx_dims[2];
@@ -8,6 +8,7 @@
#include <vector>
#include <string>
#include <blob_factory.hpp>
#include "cpu_memory_desc_utils.h"
using namespace mkldnn;
using namespace MKLDNNPlugin;
@@ -22,6 +23,42 @@ void MKLDNNGenericNode::getSupportedDescriptors() {
}
}
NodeConfig MKLDNNGenericNode::convertLayerToNodeConfig(const InferenceEngine::LayerConfig &layerConfig) {
NodeConfig config;
config.dynBatchSupport = layerConfig.dynBatchSupport;
config.inConfs.resize(layerConfig.inConfs.size());
for (size_t i = 0; i < layerConfig.inConfs.size(); i++) {
config.inConfs[i].inPlace = layerConfig.inConfs[i].inPlace;
config.inConfs[i].constant = layerConfig.inConfs[i].constant;
config.inConfs[i].desc = MemoryDescUtils::convertToMKLDNNMemoryDesc(layerConfig.inConfs[i].desc).clone();
}
config.outConfs.resize(layerConfig.outConfs.size());
for (size_t i = 0; i < layerConfig.outConfs.size(); i++) {
config.outConfs[i].inPlace = layerConfig.outConfs[i].inPlace;
config.outConfs[i].constant = layerConfig.outConfs[i].constant;
config.outConfs[i].desc = MemoryDescUtils::convertToMKLDNNMemoryDesc(layerConfig.outConfs[i].desc).clone();
}
return config;
}
InferenceEngine::LayerConfig MKLDNNGenericNode::convertNodeToLayerConfig(const NodeConfig &nodeConfig) {
InferenceEngine::LayerConfig config;
config.dynBatchSupport = nodeConfig.dynBatchSupport;
config.inConfs.resize(nodeConfig.inConfs.size());
for (size_t i = 0; i < nodeConfig.inConfs.size(); i++) {
config.inConfs[i].inPlace = nodeConfig.inConfs[i].inPlace;
config.inConfs[i].constant = nodeConfig.inConfs[i].constant;
config.inConfs[i].desc = MemoryDescUtils::convertToTensorDesc(*nodeConfig.inConfs[i].desc);
}
config.outConfs.resize(nodeConfig.outConfs.size());
for (size_t i = 0; i < nodeConfig.outConfs.size(); i++) {
config.outConfs[i].inPlace = nodeConfig.outConfs[i].inPlace;
config.outConfs[i].constant = nodeConfig.outConfs[i].constant;
config.outConfs[i].desc = MemoryDescUtils::convertToTensorDesc(*nodeConfig.outConfs[i].desc);
}
return config;
}
void MKLDNNGenericNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
@@ -35,7 +72,7 @@ void MKLDNNGenericNode::initSupportedPrimitiveDescriptors() {
}
for (auto& config : configs) {
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown);
supportedPrimitiveDescriptors.emplace_back(convertLayerToNodeConfig(config), impl_desc_type::unknown);
}
}
if (impls.empty()) {
@@ -109,9 +146,9 @@ void MKLDNNGenericNode::execLayer() {
std::vector<InferenceEngine::Blob::Ptr> inputs;
std::vector<InferenceEngine::Blob::CPtr> constInputs;
std::vector<InferenceEngine::TensorDesc> inputDescs;
std::vector<InferenceEngine::SizeVector> outputShapes;
std::vector<InferenceEngine::SizeVector> execOutputShapes;
for (size_t i = 0; i < getParentEdges().size(); i++) {
auto inputBlob = getParentEdgeAt(i)->getBlob();
auto inputBlob = MemoryDescUtils::interpretAsBlob(getParentEdgeAt(i)->getMemory());
inputs.push_back(inputBlob);
constInputs.push_back(inputBlob);
if (isDynBatch && dynBatchLim >= inputs[inputs.size() - 1]->getTensorDesc().getDims()[0]) {
@@ -137,14 +174,14 @@ void MKLDNNGenericNode::execLayer() {
}
}
std::vector<InferenceEngine::Blob::Ptr> outputs;
for (size_t i = 0; i < outDims.size(); i++) {
for (size_t i = 0; i < outputShapes.size(); i++) {
if (isDynBatch) {
auto out_edge = getChildEdgesAtPort(i)[0];
auto td = out_edge->getBlob()->getTensorDesc();
td.setDims(outputShapes[i]);
auto td = MemoryDescUtils::convertToTensorDesc(out_edge->getMemory().GetDesc());
td.setDims(execOutputShapes[i]);
outputs.push_back(make_blob_with_precision(td, out_edge->getMemory().GetData()));
} else {
outputs.push_back(getChildEdgesAtPort(i)[0]->getBlob());
outputs.push_back(MemoryDescUtils::interpretAsBlob(getChildEdgesAtPort(i)[0]->getMemory()));
}
}
InferenceEngine::ResponseDesc resp;
@@ -154,8 +191,8 @@ void MKLDNNGenericNode::execLayer() {
}
}
void MKLDNNGenericNode::initDescriptor(const InferenceEngine::LayerConfig &config) {
InferenceEngine::LayerConfig rightConfig = config;
void MKLDNNGenericNode::initDescriptor(const NodeConfig &config) {
NodeConfig rightConfig = config;
InferenceEngine::StatusCode rc;
InferenceEngine::ResponseDesc resp;
@@ -190,14 +227,15 @@ void MKLDNNGenericNode::initDescriptor(const InferenceEngine::LayerConfig &confi
impls.clear();
impls.emplace_back(selectedImpl);
rc = impls[0]->init(rightConfig, &resp);
auto ieConfig = convertNodeToLayerConfig(rightConfig);
rc = impls[0]->init(ieConfig, &resp);
if (rc != InferenceEngine::OK) {
IE_THROW() << resp.msg;
}
rightConfig = convertLayerToNodeConfig(ieConfig);
auto descriptor = getSelectedPrimitiveDescriptor();
if (descriptor != nullptr) {
descriptor->getConfig() = rightConfig;
descriptor->setConfig(rightConfig);
}
bool isConst = !rightConfig.inConfs.empty() || !rightConfig.outConfs.empty();
for (const auto &inConf : rightConfig.inConfs) {
@@ -29,12 +29,15 @@ public:
return false;
}
void initDescriptor(const InferenceEngine::LayerConfig& config) override;
void initDescriptor(const NodeConfig& config) override;
void execLayer();
void cleanup() override;
protected:
NodeConfig convertLayerToNodeConfig(const InferenceEngine::LayerConfig &layerConfig);
InferenceEngine::LayerConfig convertNodeToLayerConfig(const NodeConfig &nodeConfig);
InferenceEngine::ILayerImplFactory::Ptr extFactory;
std::vector<InferenceEngine::ILayerExecImpl::Ptr> impls;
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <ngraph/opsets/opset1.hpp>
@@ -46,8 +44,8 @@ void MKLDNNGRNNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32, false, 0}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32, false, 0}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32, false, 0}},
{{LayoutType::ncsp, Precision::FP32, false, 0}},
impl_desc_type::ref_any);
}
@@ -55,7 +53,7 @@ void MKLDNNGRNNode::execute(mkldnn::stream strm) {
const float* src_data = reinterpret_cast<const float *>(getParentEdgeAt(0)->getMemoryPtr()->GetPtr());
float* dst_data = reinterpret_cast<float *>(getChildEdgesAtPort(0)[0]->getMemoryPtr()->GetPtr());
SizeVector dims = getParentEdgeAt(0)->getDims().ToSizeVector();
SizeVector dims = getParentEdgeAt(0)->getShape().getStaticDims();
int N = static_cast<int>((dims.size() > 0) ? dims[0] : 1);
int C = static_cast<int>((dims.size() > 1) ? dims[1] : 1);
@@ -246,7 +246,7 @@ MKLDNNInputNode::MKLDNNInputNode(const std::shared_ptr<ngraph::Node>& op, const
}
void MKLDNNInputNode::cloneBlobIfRequired() {
MKLDNNDims dims(constOp->get_shape().empty() ? ngraph::Shape(1, 1) : constOp->get_shape());
std::vector<size_t> dims(constOp->get_shape().empty() ? ngraph::Shape(1, 1) : constOp->get_shape());
const auto prec = convertPrecision(constOp->get_element_type());
const size_t size = dims.size();
MKLDNNMemoryDesc memDesc(dims, MKLDNNExtensionUtils::IEPrecisionToDataType(prec));
@@ -349,15 +349,15 @@ void MKLDNNInputNode::cloneBlobIfRequired() {
}
}
MKLDNNInputNode::MKLDNNInputNode(const InferenceEngine::SizeVector &dims, const InferenceEngine::Precision &prc, const std::string &name,
MKLDNNInputNode::MKLDNNInputNode(const Shape& shape, const InferenceEngine::Precision &prc, const std::string &name,
const std::string &type, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache)
: MKLDNNNode(type, name, eng, cache) {
constant = ConstantType::NoConst;
if (getType() == Input) {
outDims.emplace_back(dims);
outputShapes.emplace_back(shape);
addOriginalOutputPrecision(prc);
} else if (getType() == Output) {
inDims.emplace_back(dims);
inputShapes.emplace_back(shape);
addOriginalInputPrecision(prc);
}
}
@@ -388,42 +388,29 @@ void MKLDNNInputNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
LayerConfig config;
config.dynBatchSupport = true;
std::vector<PortConfigurator> inPortConfs;
std::vector<PortConfigurator> outPortConfs;
if (getType() == Input || getType() == MemoryInput) {
precision = getOriginalOutputPrecisionAtPort(0);
if (precision == Precision::U16 || isMeanImage) {
precision = Precision::FP32;
}
DataConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
auto outputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(precision);
auto mem_tdesc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType);
dataConfig.desc = mem_tdesc;
config.outConfs.push_back(dataConfig);
// ReadValue operation expects constant input
outPortConfs.push_back({LayoutType::ncsp, precision});
if (!getParentEdges().empty()) {
DataConfig inConfig;
inConfig.inPlace = -1;
inConfig.constant = true;
inConfig.desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType);
config.inConfs.push_back(inConfig);
inPortConfs.push_back({LayoutType::ncsp, precision, true});
}
} else if (getType() == Output) {
precision = getOriginalInputPrecisionAtPort(0);
if (precision == Precision::U16) precision = Precision::FP32;
DataConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
auto inputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(precision);
auto mem_tdesc = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType);
dataConfig.desc = mem_tdesc;
config.inConfs.push_back(dataConfig);
inPortConfs.push_back({LayoutType::ncsp, precision});
}
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown);
addSupportedPrimDesc(inPortConfs,
outPortConfs,
impl_desc_type::unknown);
}
void MKLDNNInputNode::createPrimitive() {
@@ -440,7 +427,7 @@ void MKLDNNInputNode::createPrimitive() {
<< " from node " << getParentEdgeAt(i)->getParent()->getName() << ".";
}
const PrimitiveDescInfo *selected_pd = getSelectedPrimitiveDescriptor();
const NodeDesc *selected_pd = getSelectedPrimitiveDescriptor();
if (selected_pd == nullptr)
IE_THROW() << "Preferable primitive descriptor is not set for node " << getName() << ".";
}
@@ -14,7 +14,7 @@ namespace MKLDNNPlugin {
class MKLDNNInputNode : public MKLDNNNode {
public:
MKLDNNInputNode(const std::shared_ptr<ngraph::Node>& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache);
MKLDNNInputNode(const InferenceEngine::SizeVector &dims, const InferenceEngine::Precision &prc, const std::string &name,
MKLDNNInputNode(const Shape& shape, const InferenceEngine::Precision &prc, const std::string &name,
const std::string &type, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache);
void getSupportedDescriptors() override;
@@ -1829,7 +1829,7 @@ void MKLDNNInterpolateNode::getSupportedDescriptors() {
if (getChildEdges().empty())
IE_THROW() << errorPrefix << " has incorrect number of output edges";
srcDim = getParentEdgeAt(DATA_ID)->getDims().ToSizeVector();
srcDim = getParentEdgeAt(DATA_ID)->getShape().getStaticDims();
int dataRank = srcDim.size();
// get pad
@@ -1868,7 +1868,7 @@ void MKLDNNInterpolateNode::getSupportedDescriptors() {
} else {
srcDimPad = srcDim;
}
dstDim = getChildEdgeAt(0)->getDims().ToSizeVector();
dstDim = getChildEdgeAt(0)->getShape().getStaticDims();
}
void MKLDNNInterpolateNode::initSupportedPrimitiveDescriptors() {
@@ -1902,7 +1902,7 @@ void MKLDNNInterpolateNode::initSupportedPrimitiveDescriptors() {
inputPrec = inputPrecision;
outputPrec = outputPrecision;
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = false;
if (isAxesSpecified) {
config.inConfs.resize(4);
@@ -1916,22 +1916,26 @@ void MKLDNNInterpolateNode::initSupportedPrimitiveDescriptors() {
auto axesType = MKLDNNExtensionUtils::IEPrecisionToDataType(Precision::I32);
auto pushDesc = [&](memory::format_tag dataFormat, impl_desc_type implDetail) {
config.inConfs[DATA_ID].desc = MKLDNNMemoryDesc(getParentEdgeAt(DATA_ID)->getDims(), inputDataType, dataFormat);
config.inConfs[TARGET_SHAPE_ID].desc = MKLDNNMemoryDesc(getParentEdgeAt(TARGET_SHAPE_ID)->getDims(), targetShapeType, memory::format_tag::x);
config.inConfs[SCALES_ID].desc = MKLDNNMemoryDesc(getParentEdgeAt(SCALES_ID)->getDims(), scalesType, memory::format_tag::x);
config.inConfs[DATA_ID].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(DATA_ID)->getShape().getStaticDims(),
inputDataType, dataFormat);
config.inConfs[TARGET_SHAPE_ID].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(TARGET_SHAPE_ID)->getShape().getStaticDims(),
targetShapeType, memory::format_tag::x);
config.inConfs[SCALES_ID].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(SCALES_ID)->getShape().getStaticDims(), scalesType,
memory::format_tag::x);
if (isAxesSpecified)
config.inConfs[AXES_ID].desc = MKLDNNMemoryDesc(getParentEdgeAt(AXES_ID)->getDims(), axesType, memory::format_tag::x);
config.outConfs[0].desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, dataFormat);
supportedPrimitiveDescriptors.push_back({config, implDetail, dataFormat});
config.inConfs[AXES_ID].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(AXES_ID)->getShape().getStaticDims(), axesType,
memory::format_tag::x);
config.outConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getChildEdgeAt(0)->getShape().getStaticDims(), outputDataType, dataFormat);
supportedPrimitiveDescriptors.push_back({config, implDetail});
};
auto channels = getParentEdgeAt(DATA_ID)->getDims().ndims() > 1 ? getParentEdgeAt(DATA_ID)->getDims()[1] : 1;
auto channels = getParentEdgeAt(DATA_ID)->getShape().getRank() > 1 ? getParentEdgeAt(DATA_ID)->getShape().getStaticDims()[1] : 1;
if (!mayiuse(cpu::x64::sse41) || mode == InterpolateMode::linear) {
pushDesc(MKLDNNMemory::GetPlainFormat(getParentEdgeAt(DATA_ID)->getDims()), ref);
pushDesc(MKLDNNMemory::GetPlainFormatByRank(getParentEdgeAt(DATA_ID)->getShape().getRank()), ref);
} else {
// blk and by_channel JIT kernel on sse41 or above machine
if (getParentEdgeAt(DATA_ID)->getDims().ndims() == 4) {
if (getParentEdgeAt(DATA_ID)->getShape().getRank() == 4) {
if (mayiuse(cpu::x64::avx512_common)) {
pushDesc(memory::format_tag::nhwc, jit_avx512);
if (channels != 1)
@@ -1945,7 +1949,7 @@ void MKLDNNInterpolateNode::initSupportedPrimitiveDescriptors() {
if (channels != 1)
pushDesc(memory::format_tag::nChw8c, jit_sse42);
}
} else if (getParentEdgeAt(DATA_ID)->getDims().ndims() == 5 && mode != InterpolateMode::cubic) {
} else if (getParentEdgeAt(DATA_ID)->getShape().getRank() == 5 && mode != InterpolateMode::cubic) {
if (mayiuse(cpu::x64::avx512_common)) {
pushDesc(memory::format_tag::ndhwc, jit_avx512);
if (channels != 1)
@@ -1963,7 +1967,7 @@ void MKLDNNInterpolateNode::initSupportedPrimitiveDescriptors() {
// planar for 1.ref on machine without sse41(if no sse41, canFuse() is false). 2.JIT kernel for f32 && avx2(gather).(with fuse)
if (mayiuse(cpu::x64::avx2) && inputPrec == Precision::FP32) {
pushDesc(MKLDNNMemory::GetPlainFormat(getParentEdgeAt(DATA_ID)->getDims()), jit_avx2);
pushDesc(MKLDNNMemory::GetPlainFormatByRank(getParentEdgeAt(DATA_ID)->getShape().getRank()), jit_avx2);
}
}
}
@@ -1989,11 +1993,10 @@ void MKLDNNInterpolateNode::createPrimitive() {
if (getSelectedPrimitiveDescriptor() == nullptr)
IE_THROW() << errorPrefix << " did not set preferable primitive descriptor";
auto selectedPD = getSelectedPrimitiveDescriptor();
auto jcp = jit_interpolate_config_params();
jcp.mode = mode;
jcp.src_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(selectedPD->getConfig().inConfs[0].desc.getPrecision());
jcp.dst_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(selectedPD->getConfig().outConfs[0].desc.getPrecision());
jcp.src_dt = getParentEdgeAt(0)->getMemory().GetDataType();
jcp.dst_dt = getChildEdgeAt(0)->getMemory().GetDataType();
jcp.src_data_size = MKLDNNExtensionUtils::sizeOfDataType(jcp.src_dt);
jcp.dst_data_size = MKLDNNExtensionUtils::sizeOfDataType(jcp.dst_dt);
jcp.indices_size = sizeof(int);
@@ -2008,9 +2011,10 @@ void MKLDNNInterpolateNode::createPrimitive() {
jcp.ID = srcDimPad5d[2];
jcp.spatial_dim_size = spatialDimSize;
if (getChildEdgeAt(0)->getMemory().GetDesc().isPlainFormat()) {
if (getChildEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::ncsp)) {
jcp.layout = InterpolateLayoutType::planar;
} else if (getChildEdgeAt(0)->getMemory().GetDesc().isBlockedCFormat()) {
} else if (getChildEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nCsp8c) ||
getChildEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nCsp16c)) {
jcp.layout = InterpolateLayoutType::block;
} else {
jcp.layout = InterpolateLayoutType::by_channel;
@@ -64,8 +64,8 @@ void MKLDNNLogSoftmaxNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
@@ -6,6 +6,7 @@
#include <string>
#include <mkldnn_extension_utils.h>
#include <ngraph/opsets/opset1.hpp>
#include <cpu_memory_desc_utils.h>
using namespace MKLDNNPlugin;
using namespace InferenceEngine;
@@ -88,19 +89,20 @@ void MKLDNNLrnNode::getSupportedDescriptors() {
precision = InferenceEngine::Precision::FP32;
auto inputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(precision);
auto parentDims = getParentEdgeAt(0)->getDims();
const auto &parentShape = getParentEdgeAt(0)->getShape();
const auto parentStaticDims = parentShape.getStaticDims();
for (auto format : getAvailableFormatsForDims(parentDims)) {
MKLDNNMemoryDesc in_candidate(parentDims, inputDataType, format);
createDescriptor({in_candidate}, {});
for (auto format : getAvailableFormatsForDims(parentShape)) {
auto in_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(parentStaticDims, inputDataType, format);
createDescriptor({in_candidate.get()}, {});
}
}
MKLDNNMemoryDesc MKLDNNLrnNode::getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
std::unique_ptr<MKLDNNMemoryDesc> MKLDNNLrnNode::getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) {
if (idx > 0) {
return MKLDNNMemoryDesc(InferenceEngine::TensorDesc(getOriginalInputPrecisions()[idx],
getParentEdgeAt(idx)->getDims().ToSizeVector(),
TensorDesc::getLayoutByDims(getParentEdgeAt(idx)->getDims().ToSizeVector())));
return MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(idx)->getShape().getStaticDims(),
MKLDNNExtensionUtils::IEPrecisionToDataType(getOriginalInputPrecisions()[idx]),
MKLDNNMemory::GetPlainFormatByRank(getParentEdgeAt(idx)->getShape().getRank()));
} else {
return MKLDNNNode::getSrcMemDesc(primitive_desc_it, idx);
}
@@ -123,12 +125,12 @@ bool MKLDNNLrnNode::created() const {
return getType() == Lrn;
}
void MKLDNNLrnNode::createDescriptor(const std::vector<InferenceEngine::TensorDesc> &inputDesc,
const std::vector<InferenceEngine::TensorDesc> &outputDesc) {
void MKLDNNLrnNode::createDescriptor(const std::vector<const MemoryDesc*> &inputDesc,
const std::vector<const MemoryDesc*> &outputDesc) {
mkldnn::algorithm alg = isAcrossMaps ? mkldnn::algorithm::lrn_across_channels : mkldnn::algorithm::lrn_within_channel;
MKLDNNMemoryDesc in_candidate(inputDesc[0]);
MKLDNNDescriptor desc(std::shared_ptr<mkldnn::lrn_forward::desc>(
new mkldnn::lrn_forward::desc(mkldnn::prop_kind::forward_scoring, alg, in_candidate, size, alpha, beta, k)));
new mkldnn::lrn_forward::desc(mkldnn::prop_kind::forward_scoring, alg, MemoryDescUtils::convertToMKLDNNMemoryDesc(*inputDesc[0]),
size, alpha, beta, k)));
descs.push_back(desc);
}
@@ -17,12 +17,12 @@ public:
MKLDNNLrnNode(const std::shared_ptr<ngraph::Node>& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache);
void getSupportedDescriptors() override;
void createDescriptor(const std::vector<InferenceEngine::TensorDesc>& inputDesc,
const std::vector<InferenceEngine::TensorDesc>& outputDesc) override;
void createDescriptor(const std::vector<const MemoryDesc*>& inputDesc,
const std::vector<const MemoryDesc*>& outputDesc) override;
size_t descInputNumbers(MKLDNNDescriptor desc) override {
return static_cast<size_t>(getOriginalInputsNumber());
}
MKLDNNMemoryDesc getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
std::unique_ptr<MKLDNNMemoryDesc> getSrcMemDesc(mkldnn::primitive_desc_iterator &primitive_desc_it, size_t idx) override;
void createPrimitive() override;
bool created() const override;
bool canBeInPlace() const override {
@@ -49,18 +49,18 @@ void MKLDNNMathNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
std::vector<DataConfigurator> inDataConf;
std::vector<PortConfigurator> inDataConf;
inDataConf.reserve(getOriginalInputsNumber());
for (int i = 0; i < getOriginalInputsNumber(); ++i)
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, Precision::FP32);
inDataConf.emplace_back(LayoutType::ncsp, Precision::FP32);
addSupportedPrimDesc(inDataConf,
{{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
void MKLDNNMathNode::execute(mkldnn::stream strm) {
size_t dataSize = getChildEdgeAt(0)->getBlob()->size();
size_t dataSize = getChildEdgeAt(0)->getShape().getElementsCount();
const float *src_data = reinterpret_cast<const float *>(getParentEdgeAt(0)->getMemoryPtr()->GetPtr());
float* dst_data = reinterpret_cast<float *>(getChildEdgeAt(0)->getMemoryPtr()->GetPtr());
@@ -70,14 +70,14 @@ void MKLDNNMatMulNode::getSupportedDescriptors() {
if (getChildEdges().empty())
IE_THROW() << errorPrefix << " has incorrect number of output edges for layer " << getName();
auto inDims0 = getParentEdgeAt(0)->getDims();
auto inDims1 = getParentEdgeAt(1)->getDims();
auto outDims = getChildEdgeAt(0)->getDims();
auto inDims0 = getParentEdgeAt(0)->getShape().getStaticDims();
auto inDims1 = getParentEdgeAt(1)->getShape().getStaticDims();
auto outDims = getChildEdgeAt(0)->getShape().getStaticDims();
if (inDims0.ndims() != inDims1.ndims() || inDims0.ndims() != outDims.ndims())
if (inDims0.size() != inDims1.size() || inDims0.size() != outDims.size())
IE_THROW() << errorPrefix << " has invalid dims count";
int nDims = inDims0.ndims();
int nDims = inDims0.size();
xAxis = nDims - 1;
yAxis = nDims - 2;
auto xAxis0 = transposeA ? yAxis : xAxis;
@@ -135,22 +135,22 @@ void MKLDNNMatMulNode::initSupportedPrimitiveDescriptors() {
auto inputDataType1 = MKLDNNExtensionUtils::IEPrecisionToDataType(inPrec1);
auto outputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(InferenceEngine::Precision::FP32);
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = true;
auto createDataConfig = [](const MKLDNNDims& dims, memory::data_type dataType) -> InferenceEngine::DataConfig {
InferenceEngine::DataConfig dataConfig;
auto createDataConfig = [](const std::vector<size_t>& dims, memory::data_type dataType) -> PortConfig {
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = MKLDNNMemoryDesc(dims, dataType, MKLDNNMemory::GetPlainFormat(dims));
dataConfig.desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(dims, dataType, MKLDNNMemory::GetPlainFormatByRank(dims.size()));
return dataConfig;
};
config.inConfs.push_back(createDataConfig(getParentEdgeAt(0)->getDims(), inputDataType0));
config.inConfs.push_back(createDataConfig(getParentEdgeAt(1)->getDims(), inputDataType1));
config.outConfs.push_back(createDataConfig(getChildEdgeAt(0)->getDims(), outputDataType));
config.inConfs.push_back(createDataConfig(getParentEdgeAt(0)->getShape().getStaticDims(), inputDataType0));
config.inConfs.push_back(createDataConfig(getParentEdgeAt(1)->getShape().getStaticDims(), inputDataType1));
config.outConfs.push_back(createDataConfig(getChildEdgeAt(0)->getShape().getStaticDims(), outputDataType));
supportedPrimitiveDescriptors.push_back(PrimitiveDescInfo(config, impl_desc_type::gemm_any, MKLDNNMemory::GetPlainFormat(getChildEdgeAt(0)->getDims())));
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::gemm_any);
}
void MKLDNNMatMulNode::initOptimalPrimitiveDescriptor() {
@@ -158,8 +158,9 @@ void MKLDNNMatMulNode::initOptimalPrimitiveDescriptor() {
if (selected_pd == nullptr)
IE_THROW() << errorPrefix << " did not set preferable primitive descriptor";
auto config = selected_pd->getConfig();
if (isInitConfig(config))
return;
if (isConfigDefined(config))
return;
MKLDNNNode::initOptimalPrimitiveDescriptor();
@@ -206,7 +207,7 @@ void MKLDNNMatMulNode::createPrimitive() {
params.shift1 = params.M * params.N * params.MB2;
params.shift2 = params.M * params.N;
runtimePrecision = getParentEdgeAt(0)->getDesc().getPrecision();
runtimePrecision = getParentEdgeAt(0)->getMemory().GetDesc().getPrecision();
}
inline void process_gemm(char transa, char transb, int M, int N, int K, float alpha, const float *A, int lda,
@@ -301,13 +302,13 @@ bool MKLDNNMatMulNode::created() const {
}
int MKLDNNMatMulNode::getMaxBatch() {
if (!outDims.empty())
return outDims[0][0];
if (!outputShapes.empty())
return outputShapes[0].getStaticDims()[0];
return 0;
}
InferenceEngine::Precision MKLDNNMatMulNode::getRuntimePrecision() const {
return MKLDNNExtensionUtils::getMaxPrecision(getInputPrecisions());
return getMaxPrecision(getInputPrecisions());
}
REG_MKLDNN_PRIM_FOR(MKLDNNMatMulNode, MatMul);
@@ -10,7 +10,6 @@
#include <string>
#include <vector>
#include "base.hpp"
#include "ie_parallel.hpp"
#include "ngraph/opsets/opset8.hpp"
#include "ngraph_ops/nms_static_shape_ie.hpp"
@@ -63,17 +62,19 @@ MKLDNNMatrixNmsNode::MKLDNNMatrixNmsNode(const std::shared_ptr<ngraph::Node>& op
if (getOriginalOutputsNumber() != 3)
IE_THROW() << errorPrefix << "has incorrect number of output edges: " << getOriginalOutputsNumber();
if (!(inDims[NMS_BOXES][0] == inDims[NMS_SCORES][0] && inDims[NMS_BOXES][1] == inDims[NMS_SCORES][2])) {
const SizeVector& boxes_dims = inputShapes[NMS_BOXES].getStaticDims();
const SizeVector& scores_dims = inputShapes[NMS_SCORES].getStaticDims();
if (!(boxes_dims[0] == scores_dims[0] && boxes_dims[1] == scores_dims[2])) {
IE_THROW() << errorPrefix << "has incompatible 'boxes' and 'scores' input dmensions";
}
const SizeVector& boxes_dims = op->get_input_shape(NMS_BOXES);
m_numBatches = boxes_dims[0];
m_numBoxes = boxes_dims[1];
if (boxes_dims.size() != 3)
IE_THROW() << errorPrefix << "has unsupported 'boxes' input rank: " << boxes_dims.size();
if (boxes_dims[2] != 4)
IE_THROW() << errorPrefix << "has unsupported 'boxes' input 3rd dimension size: " << boxes_dims[2];
const SizeVector& scores_dims = op->get_input_shape(NMS_SCORES);
m_numClasses = scores_dims[1];
if (scores_dims.size() != 3)
IE_THROW() << errorPrefix << "has unsupported 'scores' input rank: " << scores_dims.size();
@@ -154,11 +155,11 @@ void MKLDNNMatrixNmsNode::initSupportedPrimitiveDescriptors() {
checkPrecision(getOriginalOutputPrecisionAtPort(NMS_SELECTED_OUTPUTS), supportedFloatPrecision, "selected_outputs", outType);
checkPrecision(getOriginalOutputPrecisionAtPort(NMS_VALID_OUTPUTS), supportedIntOutputPrecision, "valid_outputs", outType);
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::I32},
{TensorDescCreatorTypes::ncsp, Precision::I32}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::I32},
{LayoutType::ncsp, Precision::I32}},
impl_desc_type::ref_any);
}
@@ -60,13 +60,14 @@ void MKLDNNMemoryOutputNode::initSupportedPrimitiveDescriptors() {
InferenceEngine::Precision precision = getOriginalInputPrecisionAtPort(0);
auto inputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(precision);
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = true;
config.inConfs.resize(1);
config.inConfs[0].inPlace = -1;
config.inConfs[0].constant = false;
config.inConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, MKLDNNMemory::GetPlainFormat(getParentEdgeAt(0)->getDims()));
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown, memory::format_tag::any);
config.inConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(0)->getShape().getStaticDims(), inputDataType,
MKLDNNMemory::GetPlainFormatByRank(getParentEdgeAt(0)->getShape().getRank()));
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown);
}
void MKLDNNMemoryOutputNode::execute(mkldnn::stream strm) {
@@ -105,8 +106,7 @@ MKLDNNMemoryInputNode::MKLDNNMemoryInputNode(const std::shared_ptr<ngraph::Node>
void MKLDNNMemoryInputNode::createPrimitive() {
MKLDNNInputNode::createPrimitive();
auto mem_desc = getChildEdgeAt(0)->getMemoryPtr()->GetDescriptor();
dataStore->Create(mem_desc);
dataStore->Create(getChildEdgeAt(0)->getMemory().GetDesc());
// default memory state is zero filled
dataStore->FillZero();
@@ -119,7 +119,7 @@ void MKLDNNMemoryInputNode::createPrimitive() {
* @param src source memory object
*/
inline
static void simple_copy(MKLDNNMemory& dst, const MKLDNNMemory& src) {
static void simple_copy(const MKLDNNMemory& dst, const MKLDNNMemory& src) {
auto srcPtr = static_cast<uint8_t*>(src.GetPtr());
auto dstPtr = static_cast<uint8_t*>(dst.GetPtr());
auto srcSizeInByte = src.GetSize();
@@ -146,11 +146,10 @@ void MKLDNNMemoryInputNode::storeState(const MKLDNNMemory &new_state) {
}
void MKLDNNMemoryInputNode::execute(mkldnn::stream strm) {
auto dst_mem = getChildEdgeAt(0)->getMemory();
// TODO: Should be simple call of:
// dst_mem.SetData(dataStore, false);
// But because of performance reason we use simple manual copy
simple_copy(dst_mem, *dataStore);
simple_copy(getChildEdgeAt(0)->getMemory(), *dataStore);
}
MKLDNNMemoryNodeVirtualEdge::Holder* MKLDNNMemoryNodeVirtualEdge::registerInput(MKLDNNMemoryInputNode * node) {
@@ -15,7 +15,6 @@
#include <utility>
#include <vector>
#include "base.hpp"
#include "ie_parallel.hpp"
#include "utils/general_utils.h"
@@ -75,13 +74,13 @@ MKLDNNMultiClassNmsNode::MKLDNNMultiClassNmsNode(const std::shared_ptr<ngraph::N
nms_eta = atrri.nms_eta;
normalized = atrri.normalized;
const SizeVector& boxes_dims = inDims[NMS_BOXES].ToSizeVector();
const SizeVector& boxes_dims = inputShapes[NMS_BOXES].getStaticDims();
if (boxes_dims.size() != 3)
IE_THROW() << errorPrefix << "has unsupported 'boxes' input rank: " << boxes_dims.size();
if (boxes_dims[2] != 4)
IE_THROW() << errorPrefix << "has unsupported 'boxes' input 3rd dimension size: " << boxes_dims[2];
const SizeVector& scores_dims = inDims[NMS_SCORES].ToSizeVector();
const SizeVector& scores_dims = inputShapes[NMS_SCORES].getStaticDims();
if (scores_dims.size() != 3)
IE_THROW() << errorPrefix << "has unsupported 'scores' input rank: " << scores_dims.size();
@@ -90,7 +89,7 @@ MKLDNNMultiClassNmsNode::MKLDNNMultiClassNmsNode(const std::shared_ptr<ngraph::N
if (boxes_dims[1] != scores_dims[2])
IE_THROW() << errorPrefix << " num_boxes is different in 'boxes' and 'scores' inputs";
const SizeVector& valid_outputs_dims = outDims[NMS_SELECTEDNUM].ToSizeVector();
const SizeVector& valid_outputs_dims = outputShapes[NMS_SELECTEDNUM].getStaticDims();
if (valid_outputs_dims.size() != 1)
IE_THROW() << errorPrefix << "has unsupported 'valid_outputs' output rank: " << valid_outputs_dims.size();
if (valid_outputs_dims[0] != boxes_dims[0]) // valid_outputs_dims[0] != num_batches
@@ -100,10 +99,10 @@ MKLDNNMultiClassNmsNode::MKLDNNMultiClassNmsNode(const std::shared_ptr<ngraph::N
void MKLDNNMultiClassNmsNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
const SizeVector& boxes_dims = inDims[NMS_BOXES].ToSizeVector();
const SizeVector& boxes_dims = inputShapes[NMS_BOXES].getStaticDims();
num_batches = boxes_dims[0];
num_boxes = boxes_dims[1];
const SizeVector& scores_dims = inDims[NMS_SCORES].ToSizeVector();
const SizeVector& scores_dims = inputShapes[NMS_SCORES].getStaticDims();
num_classes = scores_dims[1];
numFiltBox.resize(num_batches, std::vector<size_t>(num_classes)); // batches
numBoxOffset.resize(num_batches);
@@ -124,11 +123,11 @@ void MKLDNNMultiClassNmsNode::initSupportedPrimitiveDescriptors() {
checkPrecision(getOriginalOutputPrecisionAtPort(NMS_SELECTEDOUTPUTS), supportedFloatPrecision, "selected_outputs", outType);
checkPrecision(getOriginalOutputPrecisionAtPort(NMS_SELECTEDNUM), supportedIntOutputPrecision, "selected_num", outType);
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::I32},
{TensorDescCreatorTypes::ncsp, Precision::I32}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::I32},
{LayoutType::ncsp, Precision::I32}},
impl_desc_type::ref_any);
}
@@ -136,7 +135,7 @@ void MKLDNNMultiClassNmsNode::execute(mkldnn::stream strm) {
const float* boxes = reinterpret_cast<const float*>(getParentEdgeAt(NMS_BOXES)->getMemoryPtr()->GetPtr());
const float* scores = reinterpret_cast<const float*>(getParentEdgeAt(NMS_SCORES)->getMemoryPtr()->GetPtr());
auto dims_boxes = getParentEdgeAt(NMS_BOXES)->getDesc().getDims();
auto dims_boxes = getParentEdgeAt(NMS_BOXES)->getMemory().GetDesc().getShape().getStaticDims();
if (max_output_boxes_per_class == 0)
return;
@@ -147,8 +146,8 @@ void MKLDNNMultiClassNmsNode::execute(mkldnn::stream strm) {
int* selected_num = reinterpret_cast<int*>(getChildEdgesAtPort(NMS_SELECTEDNUM)[0]->getMemoryPtr()->GetPtr());
auto boxesStrides = getParentEdgeAt(NMS_BOXES)->getDesc().getBlockingDesc().getStrides();
auto scoresStrides = getParentEdgeAt(NMS_SCORES)->getDesc().getBlockingDesc().getStrides();
auto boxesStrides = getParentEdgeAt(NMS_BOXES)->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
auto scoresStrides = getParentEdgeAt(NMS_SCORES)->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
if ((nms_eta >= 0) && (nms_eta < 1)) {
nmsWithEta(boxes, scores, boxesStrides, scoresStrides);
@@ -233,7 +232,7 @@ void MKLDNNMultiClassNmsNode::execute(mkldnn::stream strm) {
});
}
const size_t selectedBoxesNum = getChildEdgeAt(NMS_SELECTEDINDICES)->getDesc().getDims()[0];
const size_t selectedBoxesNum = getChildEdgeAt(NMS_SELECTEDINDICES)->getMemory().GetDesc().getShape().getStaticDims()[0];
const size_t validOutputs = std::min(startOffset, selectedBoxesNum);
std::vector<size_t> m_selected_num;
@@ -733,7 +733,7 @@ void MKLDNNMVNNode::initSupportedPrimitiveDescriptors() {
!getParentEdgeAt(0)->getParent()->isConstant();
const size_t inputsNum = getParentEdges().size();
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = false;
config.inConfs.resize(inputsNum);
config.outConfs.resize(1);
@@ -742,17 +742,15 @@ void MKLDNNMVNNode::initSupportedPrimitiveDescriptors() {
config.inConfs[0].inPlace = -1;
config.outConfs[0].inPlace = canBeInplace ? 0 : -1;
if (inputsNum == 2) {
const auto dims = getParentEdgeAt(1)->getDims().ToSizeVector();
config.inConfs[1].desc = TensorDesc(Precision::I32,
dims,
TensorDesc::getLayoutByDims(dims));
config.inConfs[1].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(1)->getShape().getStaticDims(), memory::data_type::s32,
MKLDNNMemory::GetPlainFormatByRank(getParentEdgeAt(1)->getShape().getRank()));
config.inConfs[1].constant = true;
}
auto pushDesc = [&](memory::format_tag format, impl_desc_type impl_type) {
config.inConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, format);
config.outConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), outputDataType, format);
supportedPrimitiveDescriptors.push_back({config, impl_type, format});
config.inConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(0)->getShape().getStaticDims(), inputDataType, format);
config.outConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(0)->getShape().getStaticDims(), outputDataType, format);
supportedPrimitiveDescriptors.push_back({config, impl_type});
};
impl_desc_type impl_type;
@@ -768,22 +766,22 @@ void MKLDNNMVNNode::initSupportedPrimitiveDescriptors() {
if (mayiuse(cpu::x64::sse41)) {
// nspc
if (getParentEdgeAt(0)->getDims().ndims() == 4) {
if (getParentEdgeAt(0)->getShape().getRank() == 4) {
pushDesc(memory::format_tag::nhwc, impl_type);
} else if (getParentEdgeAt(0)->getDims().ndims() == 5) {
} else if (getParentEdgeAt(0)->getShape().getRank() == 5) {
pushDesc(memory::format_tag::ndhwc, impl_type);
}
// blk
if (impl_desc_type::jit_avx512 == impl_type) {
if (getParentEdgeAt(0)->getDims().ndims() == 4) {
if (getParentEdgeAt(0)->getShape().getRank() == 4) {
pushDesc(memory::format_tag::nChw16c, impl_type);
} else if (getParentEdgeAt(0)->getDims().ndims() == 5) {
} else if (getParentEdgeAt(0)->getShape().getRank() == 5) {
pushDesc(memory::format_tag::nCdhw16c, impl_type);
}
} else if (impl_desc_type::jit_avx2 == impl_type || impl_desc_type::jit_sse42 == impl_type) {
if (getParentEdgeAt(0)->getDims().ndims() == 4) {
if (getParentEdgeAt(0)->getShape().getRank() == 4) {
pushDesc(memory::format_tag::nChw8c, impl_type);
} else if (getParentEdgeAt(0)->getDims().ndims() == 5) {
} else if (getParentEdgeAt(0)->getShape().getRank() == 5) {
pushDesc(memory::format_tag::nCdhw8c, impl_type);
}
}
@@ -792,7 +790,7 @@ void MKLDNNMVNNode::initSupportedPrimitiveDescriptors() {
// planar
if (canBeInplace)
config.inConfs[0].inPlace = 0;
pushDesc(MKLDNNMemory::GetPlainFormat(getChildEdgeAt(0)->getDims()), impl_type);
pushDesc(MKLDNNMemory::GetPlainFormatByRank(getChildEdgeAt(0)->getShape().getRank()), impl_type);
}
void MKLDNNMVNNode::createPrimitive() {
@@ -805,15 +803,15 @@ void MKLDNNMVNNode::createPrimitive() {
if (getSelectedPrimitiveDescriptor() == nullptr)
IE_THROW() << "Preferable primitive descriptor is not set.";
const SizeVector in_dims = getParentEdgeAt(0)->getDims().ToSizeVector();
const SizeVector in_dims = getParentEdgeAt(0)->getShape().getStaticDims();
transformTo5DCase(in_dims);
auto selectedPD = getSelectedPrimitiveDescriptor();
auto jcp = jit_mvn_config_params();
jcp.src_prc = selectedPD->getConfig().inConfs[0].desc.getPrecision();
jcp.dst_prc = selectedPD->getConfig().outConfs[0].desc.getPrecision();
jcp.src_prc = selectedPD->getConfig().inConfs[0].desc->getPrecision();
jcp.dst_prc = selectedPD->getConfig().outConfs[0].desc->getPrecision();
jcp.src_data_size = MKLDNNExtensionUtils::sizeOfDataType(MKLDNNExtensionUtils::IEPrecisionToDataType(jcp.src_prc));
jcp.dst_data_size = MKLDNNExtensionUtils::sizeOfDataType(MKLDNNExtensionUtils::IEPrecisionToDataType(jcp.dst_prc));
jcp.planar_layout = MKLDNNMemory::GetPlainLayout(getChildEdgeAt(0)->getDims()) == selectedPD->getConfig().inConfs[0].desc.getLayout();
jcp.planar_layout = selectedPD->getConfig().inConfs[0].desc->hasLayoutType(LayoutType::ncsp);
jcp.normalize_variance = normalizeVariance_;
jcp.across_channels = acrossChannels_;
int N = 0;
@@ -913,13 +911,12 @@ void MKLDNNMVNNode::execute(mkldnn::stream strm) {
uint8_t *dst_data = reinterpret_cast<uint8_t*>(dstMemPtr->GetPtr());
uint8_t *src_data = reinterpret_cast<uint8_t*>(srcMemPtr->GetPtr());
auto dim = getParentEdgeAt(0)->getDesc().getDims();
auto dim = getParentEdgeAt(0)->getShape().getStaticDims();
if (mayiuse(cpu::x64::sse41)) {
if (!mvn_mean_kernel || (normalizeVariance_ && !mvn_variance_kernel) || !mvn_kernel) {
IE_THROW() << "MVN layer with name '" << getName() << "' doesn't create kernel to execute on sse41 above platform.";
}
Layout layout = getParentEdgeAt(0)->getDesc().getLayout();
if (layout == C || layout == NC || layout == CHW || layout == NCHW || layout == NCDHW) {
if (getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::ncsp)) {
mvn_pln(src_data, dst_data, dim);
} else {
mvn_blk(src_data, dst_data, dim);
@@ -1173,10 +1170,7 @@ void MKLDNNMVNNode::mvn_blk(const uint8_t* src_data, uint8_t* dst_data, const Si
size_t N = 1; size_t C = 1; size_t D = 1; size_t H = 1; size_t W = 1;
std::tie(N, C, D, H, W) = shape5D;
bool is_nhwc = false;
Layout layout = getParentEdgeAt(0)->getDesc().getLayout();
if (layout == NHWC || layout == NDHWC)
is_nhwc = true;
bool is_nhwc = getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nspc);
size_t CB = div_up(C, blk_size);
@@ -1407,7 +1401,7 @@ bool MKLDNNMVNNode::canFuse(const MKLDNNNodePtr& node) const {
}
// limit post ops to unary when shape transformed on channel
// 1D only fused with unary
int inputRank = getParentEdgeAt(0)->getDims().ndims();
int inputRank = getParentEdgeAt(0)->getShape().getRank();
bool unaryEltwise = one_of(node->getAlgorithm(), EltwiseRelu, EltwiseGelu, EltwiseElu, EltwiseSigmoid, EltwiseClamp, EltwiseTanh,
EltwiseSwish, EltwiseHswish, EltwiseMish, EltwiseHsigmoid, EltwiseRoundHalfToEven,
EltwiseRoundHalfAwayFromZero, EltwiseAbs, EltwiseSqrt, EltwiseSoftRelu);
@@ -114,18 +114,18 @@ void MKLDNNNonMaxSuppressionNode::initSupportedPrimitiveDescriptors() {
checkOutput(outputShape_SELECTEDINDICES, supportedIntOutputPrecision, "selected_indices", NMS_SELECTEDINDICES);
checkOutput(outputShape_SELECTEDSCORES, supportedFloatPrecision, "selected_scores", NMS_SELECTEDSCORES);
std::vector<DataConfigurator> inDataConf;
std::vector<PortConfigurator> inDataConf;
inDataConf.reserve(getOriginalInputsNumber());
for (int i = 0; i < getOriginalInputsNumber(); ++i) {
Precision inPrecision = i == NMS_MAXOUTPUTBOXESPERCLASS ? Precision::I32 : Precision::FP32;
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, inPrecision);
inDataConf.emplace_back(LayoutType::ncsp, inPrecision);
}
std::vector<DataConfigurator> outDataConf;
std::vector<PortConfigurator> outDataConf;
outDataConf.reserve(getOriginalOutputsNumber());
for (int i = 0; i < getOriginalOutputsNumber(); ++i) {
Precision outPrecision = i == NMS_SELECTEDSCORES ? Precision::FP32 : Precision::I32;
outDataConf.emplace_back(TensorDescCreatorTypes::ncsp, outPrecision);
outDataConf.emplace_back(LayoutType::ncsp, outPrecision);
}
addSupportedPrimDesc(inDataConf, outDataConf, impl_desc_type::ref_any);
@@ -135,24 +135,24 @@ void MKLDNNNonMaxSuppressionNode::execute(mkldnn::stream strm) {
const float *boxes = reinterpret_cast<const float *>(getParentEdgeAt(NMS_BOXES)->getMemoryPtr()->GetPtr());
const float *scores = reinterpret_cast<const float *>(getParentEdgeAt(NMS_SCORES)->getMemoryPtr()->GetPtr());
max_output_boxes_per_class = outDims.size() > NMS_SELECTEDSCORES ? 0 : num_boxes;
if (inDims.size() > NMS_MAXOUTPUTBOXESPERCLASS) {
max_output_boxes_per_class = outputShapes.size() > NMS_SELECTEDSCORES ? 0 : num_boxes;
if (inputShapes.size() > NMS_MAXOUTPUTBOXESPERCLASS) {
max_output_boxes_per_class = reinterpret_cast<int *>(getParentEdgeAt(NMS_MAXOUTPUTBOXESPERCLASS)->getMemoryPtr()->GetPtr())[0];
}
if (max_output_boxes_per_class == 0)
return;
iou_threshold = outDims.size() > NMS_SELECTEDSCORES ? 0.0f : 1.0f;
if (inDims.size() > NMS_IOUTHRESHOLD)
iou_threshold = outputShapes.size() > NMS_SELECTEDSCORES ? 0.0f : 1.0f;
if (inputShapes.size() > NMS_IOUTHRESHOLD)
iou_threshold = reinterpret_cast<float *>(getParentEdgeAt(NMS_IOUTHRESHOLD)->getMemoryPtr()->GetPtr())[0];
score_threshold = 0.0f;
if (inDims.size() > NMS_SCORETHRESHOLD)
if (inputShapes.size() > NMS_SCORETHRESHOLD)
score_threshold = reinterpret_cast<float *>(getParentEdgeAt(NMS_SCORETHRESHOLD)->getMemoryPtr()->GetPtr())[0];
soft_nms_sigma = 0.0f;
if (inDims.size() > NMS_SOFTNMSSIGMA)
if (inputShapes.size() > NMS_SOFTNMSSIGMA)
soft_nms_sigma = reinterpret_cast<float *>(getParentEdgeAt(NMS_SOFTNMSSIGMA)->getMemoryPtr()->GetPtr())[0];
scale = 0.0f;
if (soft_nms_sigma > 0.0) {
@@ -162,15 +162,15 @@ void MKLDNNNonMaxSuppressionNode::execute(mkldnn::stream strm) {
int *selected_indices = reinterpret_cast<int *>(getChildEdgesAtPort(NMS_SELECTEDINDICES)[0]->getMemoryPtr()->GetPtr());
float *selected_scores = nullptr;
if (outDims.size() > NMS_SELECTEDSCORES)
if (outputShapes.size() > NMS_SELECTEDSCORES)
selected_scores = reinterpret_cast<float *>(getChildEdgesAtPort(NMS_SELECTEDSCORES)[0]->getMemoryPtr()->GetPtr());
int *valid_outputs = nullptr;
if (outDims.size() > NMS_VALIDOUTPUTS)
if (outputShapes.size() > NMS_VALIDOUTPUTS)
valid_outputs = reinterpret_cast<int *>(getChildEdgesAtPort(NMS_VALIDOUTPUTS)[0]->getMemoryPtr()->GetPtr());
auto boxesStrides = getParentEdgeAt(NMS_BOXES)->getDesc().getBlockingDesc().getStrides();
auto scoresStrides = getParentEdgeAt(NMS_SCORES)->getDesc().getBlockingDesc().getStrides();
auto boxesStrides = getParentEdgeAt(NMS_BOXES)->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
auto scoresStrides = getParentEdgeAt(NMS_SCORES)->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
std::vector<filteredBoxes> filtBoxes(max_output_boxes_per_class * num_batches * num_classes);
@@ -205,10 +205,10 @@ void MKLDNNNonMaxSuppressionNode::execute(mkldnn::stream strm) {
});
}
const size_t selectedBoxesNum = getChildEdgesAtPort(NMS_SELECTEDINDICES)[0]->getDims()[0];
const size_t selectedBoxesNum = getChildEdgesAtPort(NMS_SELECTEDINDICES)[0]->getShape().getStaticDims()[0];
const size_t validOutputs = std::min(filtBoxes.size(), selectedBoxesNum);
int selectedIndicesStride = getChildEdgesAtPort(NMS_SELECTEDINDICES)[0]->getDesc().getBlockingDesc().getStrides()[0];
int selectedIndicesStride = getChildEdgesAtPort(NMS_SELECTEDINDICES)[0]->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides()[0];
int *selectedIndicesPtr = selected_indices;
float *selectedScoresPtr = selected_scores;
@@ -218,7 +218,7 @@ void MKLDNNNonMaxSuppressionNode::execute(mkldnn::stream strm) {
selectedIndicesPtr[1] = filtBoxes[idx].class_index;
selectedIndicesPtr[2] = filtBoxes[idx].box_index;
selectedIndicesPtr += selectedIndicesStride;
if (outDims.size() > NMS_SELECTEDSCORES) {
if (outputShapes.size() > NMS_SELECTEDSCORES) {
selectedScoresPtr[0] = static_cast<float>(filtBoxes[idx].batch_index);
selectedScoresPtr[1] = static_cast<float>(filtBoxes[idx].class_index);
selectedScoresPtr[2] = static_cast<float>(filtBoxes[idx].score);
@@ -226,10 +226,10 @@ void MKLDNNNonMaxSuppressionNode::execute(mkldnn::stream strm) {
}
}
std::fill(selectedIndicesPtr, selectedIndicesPtr + (selectedBoxesNum - idx) * selectedIndicesStride, -1);
if (outDims.size() > NMS_SELECTEDSCORES) {
if (outputShapes.size() > NMS_SELECTEDSCORES) {
std::fill(selectedScoresPtr, selectedScoresPtr + (selectedBoxesNum - idx) * selectedIndicesStride, -1.f);
}
if (outDims.size() > NMS_VALIDOUTPUTS)
if (outputShapes.size() > NMS_VALIDOUTPUTS)
*valid_outputs = static_cast<int>(validOutputs);
}
@@ -717,7 +717,7 @@ void MKLDNNNormalizeL2Node::getSupportedDescriptors() {
if (getChildEdges().empty())
IE_THROW() << errorPrefix << " has incorrect number of output edges: " << getChildEdges().size();
if (getParentEdgeAt(0)->getDims().ndims() > 4 || getParentEdgeAt(0)->getDims().ndims() < 2) {
if (getParentEdgeAt(0)->getShape().getRank() > 4 || getParentEdgeAt(0)->getShape().getRank() < 2) {
IE_THROW() << errorPrefix << "has invalid input shape. Normalize supports from 2D to 4D blobs.";
}
}
@@ -759,21 +759,22 @@ void MKLDNNNormalizeL2Node::initSupportedPrimitiveDescriptors() {
bool canBeInplace = src_data_size == dst_data_size && getParentEdgeAt(DATA)->getParent()->getChildEdges().size() == 1;
LayerConfig config;
NodeConfig config;
config.dynBatchSupport = false;
config.inConfs.resize(2);
config.outConfs.resize(1);
config.outConfs[0].inPlace = canBeInplace ? 0 : -1;
auto pushDesc = [&](memory::format_tag format) {
config.inConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(DATA)->getDims(), inputDataType, format);
config.inConfs[1].desc = MKLDNNMemoryDesc(getParentEdgeAt(AXES)->getDims(), memory::data_type::s32, memory::format_tag::x);
config.outConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(DATA)->getDims(), outputDataType, format);
supportedPrimitiveDescriptors.push_back({config, impl_desc_type::unknown, format});
config.inConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(DATA)->getShape().getStaticDims(), inputDataType, format);
config.inConfs[1].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(AXES)->getShape().getStaticDims(), memory::data_type::s32,
memory::format_tag::x);
config.outConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(DATA)->getShape().getStaticDims(), outputDataType, format);
supportedPrimitiveDescriptors.push_back({config, impl_desc_type::unknown});
};
// only plain layout support when w/o sse42
if (getParentEdgeAt(DATA)->getDims().ndims() == 4 && !cornerCase) {
if (getParentEdgeAt(DATA)->getShape().getRank() == 4 && !cornerCase) {
if (mayiuse(cpu::x64::sse41)) {
pushDesc(memory::format_tag::nhwc);
if (mayiuse(cpu::x64::avx512_common)) {
@@ -785,7 +786,7 @@ void MKLDNNNormalizeL2Node::initSupportedPrimitiveDescriptors() {
}
if (canBeInplace)
config.inConfs[0].inPlace = 0;
pushDesc(MKLDNNMemory::GetPlainFormat(getChildEdgeAt(DATA)->getDims()));
pushDesc(MKLDNNMemory::GetPlainFormatByRank(getChildEdgeAt(DATA)->getShape().getRank()));
}
bool MKLDNNNormalizeL2Node::canFuse(const MKLDNNNodePtr& node) const {
@@ -826,22 +827,23 @@ void MKLDNNNormalizeL2Node::createPrimitive() {
if (!cornerCase) {
auto selectedPD = getSelectedPrimitiveDescriptor();
jcp.src_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(selectedPD->getConfig().inConfs[0].desc.getPrecision());
jcp.dst_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(selectedPD->getConfig().outConfs[0].desc.getPrecision());
jcp.src_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(selectedPD->getConfig().inConfs[0].desc->getPrecision());
jcp.dst_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(selectedPD->getConfig().outConfs[0].desc->getPrecision());
jcp.src_data_size = MKLDNNExtensionUtils::sizeOfDataType(jcp.src_dt);
jcp.dst_data_size = MKLDNNExtensionUtils::sizeOfDataType(jcp.dst_dt);
jcp.is_nchw = jcp.is_nhwc = jcp.is_blk = false;
if (getParentEdgeAt(0)->getMemory().GetDesc().isPlainFormat()) {
if (getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::ncsp)) {
jcp.is_nchw = true;
} else if (getParentEdgeAt(0)->getMemory().GetDesc().isBlockedCFormat()) {
} else if (getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nCsp16c) ||
getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nCsp8c)) {
jcp.is_blk = true;
} else {
jcp.is_nhwc = true;
}
jcp.across_spatial = across_spatial;
auto dims = getParentEdgeAt(0)->getDesc().getDims();
auto dims = getParentEdgeAt(0)->getShape().getStaticDims();
size_t dims_size = dims.size();
jcp.n = (dims_size > 0) ? dims[0] : 1lu;
jcp.c = (dims_size > 1) ? dims[1] : 1lu;
@@ -907,7 +909,7 @@ void MKLDNNNormalizeL2Node::execute(mkldnn::stream strm) {
const uint8_t *src_ptr = reinterpret_cast<const uint8_t*>(srcMemPtr->GetPtr());
uint8_t *dst_ptr = reinterpret_cast<uint8_t*>(dstMemPtr->GetPtr());
auto dims = getParentEdgeAt(DATA)->getDesc().getDims();
auto dims = getParentEdgeAt(DATA)->getShape().getStaticDims();
NormalizeContext ctx = {
*this,
@@ -10,7 +10,7 @@
#include "utils/bfloat16.hpp"
#include <mkldnn_selective_build.h>
#include "mkldnn_one_hot_node.h"
#include <nodes/common/tensor_desc_creator.h>
#include <nodes/common/blocked_desc_creator.h>
#include <ngraph/opsets/opset1.hpp>
#include "common/cpu_memcpy.h"
@@ -89,11 +89,11 @@ void MKLDNNOneHotNode::initSupportedPrimitiveDescriptors() {
}
output_precision = getOriginalOutputPrecisionAtPort(0);
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, input_precision},
{TensorDescCreatorTypes::ncsp, input_precision},
{TensorDescCreatorTypes::ncsp, output_precision},
{TensorDescCreatorTypes::ncsp, output_precision}},
{{TensorDescCreatorTypes::ncsp, output_precision}},
addSupportedPrimDesc({{LayoutType::ncsp, input_precision},
{LayoutType::ncsp, input_precision},
{LayoutType::ncsp, output_precision},
{LayoutType::ncsp, output_precision}},
{{LayoutType::ncsp, output_precision}},
impl_desc_type::ref_any);
}
@@ -125,13 +125,13 @@ void MKLDNNOneHotNode::one_hot(size_t prefix_size, size_t suffix_size) {
void MKLDNNOneHotNode::execute(mkldnn::stream strm) {
std::size_t prefix_size = 1;
auto input_dims = getParentEdgeAt(0)->getDesc().getDims();
auto input_dims = getParentEdgeAt(0)->getShape().getStaticDims();
std::size_t actual_axis = (axis == -1) ? src_dims.size() : axis;
for (size_t i = 0; i < actual_axis; ++i)
prefix_size *= input_dims[i];
std::size_t suffix_size = getParentEdgeAt(0)->getBlob()->size() / prefix_size;
std::size_t suffix_size = getParentEdgeAt(0)->getShape().getElementsCount() / prefix_size;
OneHotContext ctx = {this, prefix_size, suffix_size};
OV_SWITCH(MKLDNNPlugin, OneHotExecute, ctx, output_precision.size(),
@@ -92,8 +92,8 @@ void MKLDNNPadNode::getSupportedDescriptors() {
if (getChildEdges().empty())
IE_THROW() << errorPrefix << "Incorrect number of output edges";
const SizeVector srcDims = getParentEdgeAt(DATA_ID)->getDims().ToSizeVector();
const SizeVector dstDims = getChildEdgeAt(DATA_ID)->getDims().ToSizeVector();
const SizeVector srcDims = getParentEdgeAt(DATA_ID)->getShape().getStaticDims();
const SizeVector dstDims = getChildEdgeAt(DATA_ID)->getShape().getStaticDims();
if (srcDims.size() != dstDims.size() || padsBegin.size() != srcDims.size() || padsEnd.size() != srcDims.size())
IE_THROW() << errorPrefix << " has incorrect number of input/output dimensions!";
@@ -122,22 +122,26 @@ void MKLDNNPadNode::initSupportedPrimitiveDescriptors() {
precision = precision.is_float() ? InferenceEngine::Precision::FP32 : InferenceEngine::Precision::I32;
auto dataType = MKLDNNExtensionUtils::IEPrecisionToDataType(precision);
auto srcDims = getParentEdgeAt(DATA_ID)->getDims();
int numOfDims = srcDims.ToSizeVector().size();
auto srcDims = getParentEdgeAt(DATA_ID)->getShape().getStaticDims();
int numOfDims = srcDims.size();
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = false;
config.inConfs.resize(isPadValueSpecified ? 4 : 3);
config.outConfs.resize(1);
auto pushSupportedPrimitiveDescriptor = [&](memory::format_tag memoryFormat) {
config.inConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(DATA_ID)->getDims(), dataType, memoryFormat);
config.inConfs[1].desc = MKLDNNMemoryDesc(getParentEdgeAt(PADS_BEGIN_ID)->getDims(), memory::data_type::s32, memory::format_tag::x);
config.inConfs[2].desc = MKLDNNMemoryDesc(getParentEdgeAt(PADS_END_ID)->getDims(), memory::data_type::s32, memory::format_tag::x);
config.inConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(DATA_ID)->getShape().getStaticDims(), dataType,
memoryFormat);
config.inConfs[1].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(PADS_BEGIN_ID)->getShape().getStaticDims(),
memory::data_type::s32, memory::format_tag::x);
config.inConfs[2].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(PADS_END_ID)->getShape().getStaticDims(),
memory::data_type::s32, memory::format_tag::x);
if (isPadValueSpecified)
config.inConfs[3].desc = MKLDNNMemoryDesc(getParentEdgeAt(PAD_VALUE_ID)->getDims(), memory::data_type::f32, memory::format_tag::x);
config.outConfs[0].desc = MKLDNNMemoryDesc(getChildEdgeAt(DATA_ID)->getDims(), dataType, memoryFormat);
supportedPrimitiveDescriptors.push_back({config, impl_desc_type::ref, memoryFormat});
config.inConfs[3].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(PAD_VALUE_ID)->getShape().getStaticDims(),
memory::data_type::f32, memory::format_tag::x);
config.outConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getChildEdgeAt(DATA_ID)->getShape().getStaticDims(), dataType, memoryFormat);
supportedPrimitiveDescriptors.push_back({config, impl_desc_type::ref});
};
if (numOfDims == 4)
@@ -145,7 +149,7 @@ void MKLDNNPadNode::initSupportedPrimitiveDescriptors() {
else if (numOfDims == 5)
pushSupportedPrimitiveDescriptor(mkldnn::memory::format_tag::ndhwc);
pushSupportedPrimitiveDescriptor(MKLDNNMemory::GetPlainFormat(getParentEdgeAt(0)->getDims()));
pushSupportedPrimitiveDescriptor(MKLDNNMemory::GetPlainFormatByRank(getParentEdgeAt(0)->getShape().getRank()));
auto canUseBlocked = [=](const size_t blockSize) {
return (padMode == CONSTANT && padsBegin[1] % blockSize == 0 && padsEnd[1] % blockSize == 0) ||
@@ -175,10 +179,11 @@ void MKLDNNPadNode::createPrimitive() {
if (getSelectedPrimitiveDescriptor() == nullptr)
IE_THROW() << "Preferable primitive descriptor for Pad " << getName() << " is not set.";
params.sizeData = this->getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc.getPrecision().size();
params.sizeData = this->getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc->getPrecision().size();
params.srcDims = getParentEdgeAt(0)->getDesc().getBlockingDesc().getBlockDims();
params.dstDims = getChildEdgeAt(0)->getDesc().getBlockingDesc().getBlockDims();
const auto inBlkDesc = getParentEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
params.srcDims = inBlkDesc.getBlockDims();
params.dstDims = getChildEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>().getBlockDims();
size_t nDims = params.srcDims.size();
params.srcStrides.resize(nDims, 1);
@@ -188,13 +193,14 @@ void MKLDNNPadNode::createPrimitive() {
params.dstStrides[i] = params.dstStrides[i + 1] * params.dstDims[i + 1];
}
if (getParentEdgeAt(0)->getMemory().GetDesc().isBlockedCFormat()) {
if (getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nCsp16c) ||
getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nCsp8c)) {
padsBegin[1] /= params.srcDims[params.srcDims.size() - 1];
padsEnd[1] /= params.srcDims[params.srcDims.size() - 1];
padsBegin.push_back(0);
padsEnd.push_back(0);
} else {
auto order = getParentEdgeAt(0)->getDesc().getBlockingDesc().getOrder();
auto order = inBlkDesc.getOrder();
std::vector<unsigned int> newPadsBegin(padsBegin.size(), 0), newPadsEnd(padsEnd.size(), 0);
for (size_t i = 0; i < padsBegin.size(); ++i) {
newPadsBegin[i] = padsBegin[order[i]];
@@ -304,7 +310,7 @@ void MKLDNNPadNode::padConstant() {
auto selectedPrimitiveDescriptor = getSelectedPrimitiveDescriptor();
if (!selectedPrimitiveDescriptor)
IE_THROW() << "CPU Pad node with name '" << getName() << "' doesn't have primitive descriptors.";
InferenceEngine::Precision precision = selectedPrimitiveDescriptor->getConfig().inConfs[0].desc.getPrecision();
InferenceEngine::Precision precision = selectedPrimitiveDescriptor->getConfig().inConfs[0].desc->getPrecision();
OV_SWITCH(MKLDNNPlugin, PadConstantEmitter, this, precision,
OV_CASE(InferenceEngine::Precision::FP32, float),
OV_CASE(InferenceEngine::Precision::I32, int32_t),
@@ -13,6 +13,7 @@
#include <mkldnn_types.h>
#include <mkldnn_extension_utils.h>
#include <utils/general_utils.h>
#include <cpu_memory_desc_utils.h>
using namespace mkldnn;
using namespace MKLDNNPlugin;
@@ -60,18 +61,18 @@ MKLDNNPoolingNode::MKLDNNPoolingNode(const std::shared_ptr<ngraph::Node>& op, co
}
}
std::vector<memory::format_tag> MKLDNNPoolingNode::getAvailableFormatsForDims(const MKLDNNDims &dims) const {
if (dims.ndims() == 0)
std::vector<memory::format_tag> MKLDNNPoolingNode::getAvailableFormatsForDims(const Shape &dims) const {
if (dims.getRank() == 0)
return {memory::format_tag::x};
else if (dims.ndims() == 1)
else if (dims.getRank() == 1)
return {memory::format_tag::x};
else if (dims.ndims() == 2)
else if (dims.getRank() == 2)
return {memory::format_tag::nc};
else if (dims.ndims() == 3)
else if (dims.getRank() == 3)
return {memory::format_tag::tnc, memory::format_tag::ntc};
else if (dims.ndims() == 4)
else if (dims.getRank() == 4)
return {memory::format_tag::nChw8c, memory::format_tag::nChw16c, memory::format_tag::nhwc, memory::format_tag::nchw};
else if (dims.ndims() == 5)
else if (dims.getRank() == 5)
return {memory::format_tag::nCdhw8c, memory::format_tag::nCdhw16c, memory::format_tag::ndhwc, memory::format_tag::ncdhw};
return {memory::format_tag::any};
}
@@ -112,15 +113,17 @@ void MKLDNNPoolingNode::getSupportedDescriptors() {
effective_pad_begin = data_pad_begin;
effective_pad_end.resize(data_pad_end.size());
auto parentDims = getParentEdgeAt(0)->getDims();
auto childDims = getChildEdgeAt(0)->getDims();
if ((parentDims.ndims() < 4) || (parentDims.ndims() > 5))
auto parentDims = getParentEdgeAt(0)->getShape().getStaticDims();
auto childDims = getChildEdgeAt(0)->getShape().getStaticDims();
const size_t inputRank = getParentEdgeAt(0)->getShape().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 = getParentEdgeAt(0)->getDims()[2 + i];
int dst = getChildEdgeAt(0)->getDims()[2 + i];
int src = getParentEdgeAt(0)->getShape().getStaticDims()[2 + i];
int dst = getChildEdgeAt(0)->getShape().getStaticDims()[2 + i];
int calc_dst = (src - krn + data_pad_begin[i]) / stride[i] + 1;
effective_pad_end[i] = (dst - calc_dst) * stride[i];
@@ -130,24 +133,28 @@ void MKLDNNPoolingNode::getSupportedDescriptors() {
if (outputDataType == memory::data_type::bf16)
outputDataType = memory::data_type::f32;
// i8 layers supports only ndhwc and nhwc layouts
MKLDNNMemoryDesc in_candidate{parentDims, inputDataType, parentDims.ndims() == 5 ? memory::format_tag::ndhwc : memory::format_tag::nhwc};
MKLDNNMemoryDesc out_candidate{childDims, outputDataType, parentDims.ndims() == 5 ? memory::format_tag::ndhwc : memory::format_tag::nhwc};
createDescriptor({ in_candidate }, { out_candidate });
} else if ((parentDims.ndims() == 4 || parentDims.ndims() == 5) && parentDims[1] == 1) {
const auto in_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(parentDims, inputDataType, inputRank == 5 ?
memory::format_tag::ndhwc : memory::format_tag::nhwc);
const auto out_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(childDims, outputDataType, inputRank == 5 ?
memory::format_tag::ndhwc : memory::format_tag::nhwc);
createDescriptor({ in_candidate.get() }, { out_candidate.get() });
} else if ((inputRank == 4 || inputRank == 5) && parentDims[1] == 1) {
// WA. We should force planar layout since it provides better performance
MKLDNNMemoryDesc in_candidate{parentDims, inputDataType, parentDims.ndims() == 5 ? memory::format_tag::ncdhw : memory::format_tag::nchw};
MKLDNNMemoryDesc out_candidate{childDims, outputDataType, parentDims.ndims() == 5 ? memory::format_tag::ncdhw : memory::format_tag::nchw};
createDescriptor({ in_candidate }, { out_candidate });
const auto in_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(parentDims, inputDataType, inputRank == 5 ?
memory::format_tag::ncdhw : memory::format_tag::nchw);
const auto out_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(childDims, outputDataType, inputRank == 5 ?
memory::format_tag::ncdhw : memory::format_tag::nchw);
createDescriptor({ in_candidate.get() }, { out_candidate.get() });
} else {
if (inputDataType != memory::data_type::bf16) {
inputDataType = memory::data_type::f32;
outputDataType = memory::data_type::f32;
}
// It doesn't support any format
for (auto format : getAvailableFormatsForDims(parentDims)) {
MKLDNNMemoryDesc in_candidate{parentDims, inputDataType, format};
MKLDNNMemoryDesc out_candidate{childDims, outputDataType, format};
createDescriptor({in_candidate}, {out_candidate});
for (auto format : getAvailableFormatsForDims(getParentEdgeAt(0)->getShape())) {
const auto in_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(parentDims, inputDataType, format);
const auto out_candidate = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(childDims, outputDataType, format);
createDescriptor({in_candidate.get()}, {out_candidate.get()});
}
}
}
@@ -172,10 +179,10 @@ bool MKLDNNPoolingNode::created() const {
return getType() == Pooling;
}
void MKLDNNPoolingNode::createDescriptor(const std::vector<InferenceEngine::TensorDesc> &inputDesc,
const std::vector<InferenceEngine::TensorDesc> &outputDesc) {
MKLDNNMemoryDesc in_candidate(inputDesc[0]);
MKLDNNMemoryDesc out_candidate(outputDesc[0]);
void MKLDNNPoolingNode::createDescriptor(const std::vector<const MemoryDesc*> &inputDesc,
const std::vector<const MemoryDesc*> &outputDesc) {
MKLDNNMemoryDesc in_candidate = MemoryDescUtils::convertToMKLDNNMemoryDesc(*inputDesc[0]);
MKLDNNMemoryDesc out_candidate = MemoryDescUtils::convertToMKLDNNMemoryDesc(*outputDesc[0]);
mkldnn::algorithm alg;
if (algorithm == PoolingAvg) {
@@ -240,21 +247,23 @@ void MKLDNNPoolingNode::initSupportedPrimitiveDescriptors() {
for (auto& desc : descs) {
auto itpd = desc.createPrimitiveDescriptorIterator(getEngine(), attr);
while (static_cast<bool>(itpd)) {
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = true;
for (size_t i = 0; i < descInputNumbers(desc); i++) {
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = MKLDNNExtensionUtils::getUninitTensorDesc(getSrcMemDesc(itpd, i));
dataConfig.desc = MemoryDescUtils::applyUndefinedOffset(*getSrcMemDesc(itpd, i));
dataConfig.desc = getSrcMemDesc(itpd, i);
config.inConfs.push_back(dataConfig);
}
for (size_t i = 0; i < descOutputNumbers(desc); i++) {
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = canBeInPlace() ? 0 : -1;
dataConfig.constant = false;
dataConfig.desc = MKLDNNExtensionUtils::getUninitTensorDesc(getDstMemDesc(itpd, i));
dataConfig.desc = MemoryDescUtils::applyUndefinedOffset(*getDstMemDesc(itpd, i));
dataConfig.desc = getDstMemDesc(itpd, i);
config.outConfs.push_back(dataConfig);
}
impl_desc_type impl_type = parse_impl_name(itpd.impl_info_str());
@@ -266,23 +275,23 @@ void MKLDNNPoolingNode::initSupportedPrimitiveDescriptors() {
}
}
void MKLDNNPoolingNode::initDescriptor(const InferenceEngine::LayerConfig &config) {
void MKLDNNPoolingNode::initDescriptor(const NodeConfig& config) {
auto* selectedPD = getSelectedPrimitiveDescriptor();
if (!selectedPD) {
return;
}
std::vector<InferenceEngine::TensorDesc> inDescs;
std::vector<const MemoryDesc*> inDescs;
for (const auto& inConf : config.inConfs)
inDescs.push_back(inConf.desc);
std::vector<InferenceEngine::TensorDesc> outDescs;
inDescs.push_back(inConf.desc.get());
std::vector<const MemoryDesc*> outDescs;
for (const auto& outConf : config.outConfs)
outDescs.push_back(outConf.desc);
outDescs.push_back(outConf.desc.get());
createDescriptor({inDescs}, {outDescs});
mkldnn::primitive_attr attr;
setPostOps(attr);
InferenceEngine::LayerConfig rightConfig = selectedPD->getConfig();
NodeConfig rightConfig = selectedPD->getConfig();
size_t selected_count = 0;
for (size_t j = 0; j < descs.size(); j++) {
const auto &desc = descs[j];
@@ -291,10 +300,10 @@ void MKLDNNPoolingNode::initDescriptor(const InferenceEngine::LayerConfig &confi
itpd = desc.createPrimitiveDescriptorIterator(getEngine(), attr);
while (itpd) {
InferenceEngine::LayerConfig cfg;
NodeConfig cfg;
cfg.dynBatchSupport = true;
for (size_t i = 0; i < descInputNumbers(desc); i++) {
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = canBeInPlace() ? 0 : -1;
dataConfig.constant = false;
dataConfig.desc = getSrcMemDesc(itpd, i);
@@ -302,7 +311,7 @@ void MKLDNNPoolingNode::initDescriptor(const InferenceEngine::LayerConfig &confi
}
for (size_t i = 0; i < descOutputNumbers(desc); i++) {
InferenceEngine::DataConfig dataConfig;
PortConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = getDstMemDesc(itpd, i);
@@ -332,20 +341,18 @@ void MKLDNNPoolingNode::initDescriptor(const InferenceEngine::LayerConfig &confi
return;
for (size_t i = 0; i < selectedConfig.inConfs.size(); i++) {
if (selectedConfig.inConfs[i].desc.getLayout() != InferenceEngine::Layout::ANY &&
!MKLDNNExtensionUtils::initTensorsAreEqual(selectedConfig.inConfs[i].desc, config.inConfs[i].desc))
if (!selectedConfig.inConfs[i].desc->isCompatible(*config.inConfs[i].desc))
IE_THROW() << "Incorrect descriptor for node: " << getName();
}
for (size_t i = 0; i < selectedConfig.outConfs.size(); i++) {
if (selectedConfig.outConfs[i].desc.getLayout() != InferenceEngine::Layout::ANY &&
!MKLDNNExtensionUtils::initTensorsAreEqual(selectedConfig.outConfs[i].desc, config.outConfs[i].desc))
if (!selectedConfig.outConfs[i].desc->isCompatible(*config.outConfs[i].desc))
IE_THROW() << "Incorrect descriptor for node: " << getName();
}
rightConfig = config;
}
selectedPD->getConfig() = rightConfig;
selectedPD->setConfig(rightConfig);
}
void MKLDNNPoolingNode::setPostOps(mkldnn::primitive_attr &attr, bool initWeights) {
@@ -16,12 +16,12 @@ class MKLDNNPoolingNode : public MKLDNNNode {
public:
MKLDNNPoolingNode(const std::shared_ptr<ngraph::Node>& op, const mkldnn::engine& eng, MKLDNNWeightsSharing::Ptr &cache);
void createDescriptor(const std::vector<InferenceEngine::TensorDesc>& inputDesc,
const std::vector<InferenceEngine::TensorDesc>& outputDesc) override;
std::vector<mkldnn::memory::format_tag> getAvailableFormatsForDims(const MKLDNNDims &dims) const override;
void createDescriptor(const std::vector<const MemoryDesc*>& inputDesc,
const std::vector<const MemoryDesc*>& outputDesc) override;
std::vector<mkldnn::memory::format_tag> getAvailableFormatsForDims(const Shape &dims) const override;
void getSupportedDescriptors() override;
void initSupportedPrimitiveDescriptors() override;
void initDescriptor(const InferenceEngine::LayerConfig &config) override;
void initDescriptor(const NodeConfig& config) override;
void createPrimitive() override;
bool created() const override;
bool canBeInPlace() const override {
@@ -1,7 +1,6 @@
// Copyright (C) 2018-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <vector>
@@ -141,17 +140,17 @@ void MKLDNNProposalNode::initSupportedPrimitiveDescriptors() {
return;
if (store_prob) {
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
} else {
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
}
@@ -166,8 +165,8 @@ void MKLDNNProposalNode::execute(mkldnn::stream strm) {
if (store_prob)
outProbData = reinterpret_cast <float *>(getChildEdgesAtPort(PROBABILITIES_OUT_IDX)[0]->getMemoryPtr()->GetPtr());
auto inProbDims = getParentEdgeAt(0)->getDims().ToSizeVector();
const size_t imgInfoSize = getParentEdgeAt(2)->getDims()[0];
auto inProbDims = getParentEdgeAt(0)->getShape().getStaticDims();
const size_t imgInfoSize = getParentEdgeAt(2)->getShape().getStaticDims()[0];
// input image height & width
const float imgHeight = imgInfoData[0];
@@ -12,7 +12,7 @@
#include <ngraph/opsets/opset1.hpp>
#include "mkldnn_psroi_pooling_node.h"
#include <cpu/x64/jit_generator.hpp>
#include <nodes/common/tensor_desc_creator.h>
#include <nodes/common/blocked_desc_creator.h>
using namespace MKLDNNPlugin;
using namespace InferenceEngine;
@@ -139,27 +139,27 @@ void MKLDNNPSROIPoolingNode::initSupportedPrimitiveDescriptors() {
auto dataPrecision = getOriginalInputPrecisionAtPort(0) == Precision::BF16 ? Precision::BF16 : Precision::FP32;
if (getAlgorithm() == Algorithm::PSROIPoolingAverage || getAlgorithm() == Algorithm::PSROIPoolingBilinear) {
std::vector<std::pair<TensorDescCreatorTypes, TensorDescCreatorTypes>> dataFomats{
{TensorDescCreatorTypes::ncsp, TensorDescCreatorTypes::ncsp},
{TensorDescCreatorTypes::nspc, TensorDescCreatorTypes::nspc},
{TensorDescCreatorTypes::nCsp16c, TensorDescCreatorTypes::nCsp16c},
{TensorDescCreatorTypes::nCsp8c, TensorDescCreatorTypes::nCsp8c}
std::vector<std::pair<LayoutType, LayoutType>> dataFomats{
{LayoutType::ncsp, LayoutType::ncsp},
{LayoutType::nspc, LayoutType::nspc},
{LayoutType::nCsp16c, LayoutType::nCsp16c},
{LayoutType::nCsp8c, LayoutType::nCsp8c}
};
for (const auto &df : dataFomats) {
addSupportedPrimDesc({{df.first, dataPrecision}, {TensorDescCreatorTypes::ncsp, Precision::FP32}},
addSupportedPrimDesc({{df.first, dataPrecision}, {LayoutType::ncsp, Precision::FP32}},
{{df.second, dataPrecision}},
impl_type);
}
} else if (getAlgorithm() == Algorithm::PSROIPoolingBilinearDeformable && noTrans) {
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, dataPrecision}, {TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, dataPrecision}},
addSupportedPrimDesc({{LayoutType::ncsp, dataPrecision}, {LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, dataPrecision}},
impl_type);
} else if (getAlgorithm() == Algorithm::PSROIPoolingBilinearDeformable) {
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, dataPrecision},
{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, dataPrecision}},
addSupportedPrimDesc({{LayoutType::ncsp, dataPrecision},
{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, dataPrecision}},
impl_type);
}
}
@@ -182,19 +182,18 @@ inline float bilinearInterp(const inputType* data, const float x, const float y,
return value;
}
void MKLDNNPSROIPoolingNode::unpackParams(const TensorDesc& srcDesc, const TensorDesc& dstDesc,
void MKLDNNPSROIPoolingNode::unpackParams(const BlockedMemoryDesc& srcDesc, const BlockedMemoryDesc& dstDesc,
int& hInputStride, int& wInputStride,
int& hOutputStride, int& wOutputStride,
Layout& inFmt, Layout& outFmt,
int& inBlockSize, int& outBlockSize,
int& outBlockCount,
unsigned long& inputChannelsPadding, unsigned long& outputChannelsPadding) {
inFmt = srcDesc.getLayout();
outFmt = dstDesc.getLayout();
int expectedInBlockDimsSize = (inFmt == Layout::BLOCKED ? 5 : 4);
int expectedOutBlockDimsSize = (outFmt == Layout::BLOCKED ? 5 : 4);
auto inBlkDims = srcDesc.getBlockingDesc().getBlockDims();
auto outBlkDims = dstDesc.getBlockingDesc().getBlockDims();
const bool inpIsBlk = srcDesc.hasLayoutType(LayoutType::nCsp16c) || srcDesc.hasLayoutType(LayoutType::nCsp8c);
const bool outIsBlk = dstDesc.hasLayoutType(LayoutType::nCsp16c) || dstDesc.hasLayoutType(LayoutType::nCsp8c);
int expectedInBlockDimsSize = (inpIsBlk ? 5 : 4);
int expectedOutBlockDimsSize = (outIsBlk ? 5 : 4);
auto inBlkDims = srcDesc.getBlockDims();
auto outBlkDims = dstDesc.getBlockDims();
if (inBlkDims.size() != expectedInBlockDimsSize)
IE_THROW() << errorPrefix << " has unexpected size of blocking dims in input (given " << inBlkDims.size() << ", expected "
<< expectedInBlockDimsSize << ")";
@@ -202,15 +201,15 @@ void MKLDNNPSROIPoolingNode::unpackParams(const TensorDesc& srcDesc, const Tenso
IE_THROW() << errorPrefix << " has unexpected size of blocking dims in output (given " << outBlkDims.size() << ", expected "
<< expectedOutBlockDimsSize << ")";
inBlockSize = (inFmt == Layout::BLOCKED ? srcDesc.getBlockingDesc().getBlockDims()[4] : 1);
outBlockSize = (outFmt == Layout::BLOCKED ? dstDesc.getBlockingDesc().getBlockDims()[4] : 1);
inputChannelsPadding = srcDesc.getBlockingDesc().getBlockDims()[1] * inBlockSize;
outputChannelsPadding = dstDesc.getBlockingDesc().getBlockDims()[1] * outBlockSize;
inBlockSize = (inpIsBlk ? srcDesc.getBlockDims()[4] : 1);
outBlockSize = (outIsBlk ? dstDesc.getBlockDims()[4] : 1);
inputChannelsPadding = srcDesc.getBlockDims()[1] * inBlockSize;
outputChannelsPadding = dstDesc.getBlockDims()[1] * outBlockSize;
outBlockCount = outputChannelsPadding / outBlockSize;
int hOutStrIndex = 0, wOutStrIndex = 0, hInStrIndex = 0, wInStrIndex = 0;
const auto& outOrder = dstDesc.getBlockingDesc().getOrder();
const auto& inOrder = srcDesc.getBlockingDesc().getOrder();
const auto& outOrder = dstDesc.getOrder();
const auto& inOrder = srcDesc.getOrder();
for (int i = 0; i < outOrder.size(); i++) {
if (outOrder[i] == 2) hOutStrIndex = i;
if (outOrder[i] == 3) wOutStrIndex = i;
@@ -219,21 +218,20 @@ void MKLDNNPSROIPoolingNode::unpackParams(const TensorDesc& srcDesc, const Tenso
if (inOrder[i] == 2) hInStrIndex = i;
if (inOrder[i] == 3) wInStrIndex = i;
}
hInputStride = srcDesc.getBlockingDesc().getStrides()[hInStrIndex];
wInputStride = srcDesc.getBlockingDesc().getStrides()[wInStrIndex];
hOutputStride = dstDesc.getBlockingDesc().getStrides()[hOutStrIndex];
wOutputStride = dstDesc.getBlockingDesc().getStrides()[wOutStrIndex];
hInputStride = srcDesc.getStrides()[hInStrIndex];
wInputStride = srcDesc.getStrides()[wInStrIndex];
hOutputStride = dstDesc.getStrides()[hOutStrIndex];
wOutputStride = dstDesc.getStrides()[wOutStrIndex];
}
template <typename inputType, typename outputType>
void MKLDNNPSROIPoolingNode::executeAverage(const inputType *srcData, outputType *dstData, const float *bottomRois,
const int n, const int roiBatchInd,
const TensorDesc& srcDesc, const TensorDesc& dstDesc) {
Layout inFmt, outFmt;
const BlockedMemoryDesc& srcDesc, const BlockedMemoryDesc& dstDesc) {
int inBlockSize, outBlockSize, outBlockCount, hInputStride, wInputStride, hOutputStride, wOutputStride;
unsigned long inputChannelsPadding, outputChannelsPadding;
unpackParams(srcDesc, dstDesc, hInputStride, wInputStride, hOutputStride, wOutputStride,
inFmt, outFmt, inBlockSize, outBlockSize, outBlockCount, inputChannelsPadding, outputChannelsPadding);
inBlockSize, outBlockSize, outBlockCount, inputChannelsPadding, outputChannelsPadding);
const float roiStartW = static_cast<float>(round(bottomRois[1])) * spatialScale;
const float roiStartH = static_cast<float>(round(bottomRois[2])) * spatialScale;
const float roiEndW = static_cast<float>(round(bottomRois[3] + 1.0f)) * spatialScale;
@@ -273,7 +271,7 @@ void MKLDNNPSROIPoolingNode::executeAverage(const inputType *srcData, outputType
dstData[dstIndex] = outSum / binArea;
}
};
if (inFmt == Layout::NHWC) {
if (srcDesc.hasLayoutType(LayoutType::nspc)) {
parallel_for2d(nh, nw, [&](int h, int w) {
const int binOffsetOutput = n * nc * nh * nw;
const int binOffsetInput = roiBatchInd * channels * height * width;
@@ -282,10 +280,10 @@ void MKLDNNPSROIPoolingNode::executeAverage(const inputType *srcData, outputType
avgPsroi(c, h, w, 0, 0, binOffsetInput + gc, binOffsetOutput + c);
}
});
} else if (inFmt == Layout::NCHW) {
} else if (srcDesc.hasLayoutType(LayoutType::ncsp)) {
parallel_for3d(nc, nh, nw, [&](int c, int h, int w) {
const int gc = (c * groupSize + h) * groupSize + w;
const int outputBlockResidual = (outFmt == Layout::NCHW ? 0 : c % inBlockSize);
const int outputBlockResidual = (dstDesc.hasLayoutType(LayoutType::ncsp) ? 0 : c % inBlockSize);
const int outputBlockIdx = (c / outBlockSize) * outBlockSize;
const int binOffsetInput = (roiBatchInd * inputChannelsPadding + gc) * height * width;
const int binOffsetOutput = (n * outputChannelsPadding + outputBlockIdx) * nh * nw;
@@ -297,8 +295,8 @@ void MKLDNNPSROIPoolingNode::executeAverage(const inputType *srcData, outputType
int cEnd = (blkIdx == outBlockCount - 1 ? nc : cStart + outBlockSize);
for (int c = cStart; c < cEnd; c++) {
const int gc = (c * groupSize + h) * groupSize + w;
const int inputBlockResidual = (inFmt == Layout::NCHW ? 0 : gc % inBlockSize);
const int outputBlockResidual = (outFmt == Layout::NCHW ? 0 : c % inBlockSize);
const int inputBlockResidual = (srcDesc.hasLayoutType(LayoutType::ncsp) ? 0 : gc % inBlockSize);
const int outputBlockResidual = (dstDesc.hasLayoutType(LayoutType::ncsp) ? 0 : c % inBlockSize);
const int inputBlockIdx = (gc / inBlockSize) * inBlockSize;
const int outputBlockIdx = (c / outBlockSize) * outBlockSize;
const int binOffsetInput = (roiBatchInd * inputChannelsPadding + inputBlockIdx) * height * width;
@@ -312,12 +310,11 @@ void MKLDNNPSROIPoolingNode::executeAverage(const inputType *srcData, outputType
template <typename inputType, typename outputType>
void MKLDNNPSROIPoolingNode::executeBilinear(const inputType *srcData, outputType *dstData, const float *bottomRois,
const int currentRoi, const int roiBatchInd,
const TensorDesc& srcDesc, const TensorDesc& dstDesc) {
Layout inFmt, outFmt;
const BlockedMemoryDesc& srcDesc, const BlockedMemoryDesc& dstDesc) {
int inBlockSize, outBlockSize, outBlockCount, hInputStride, wInputStride, hOutputStride, wOutputStride;
unsigned long inputChannelsPadding, outputChannelsPadding;
unpackParams(srcDesc, dstDesc, hInputStride, wInputStride, hOutputStride, wOutputStride,
inFmt, outFmt, inBlockSize, outBlockSize, outBlockCount, inputChannelsPadding, outputChannelsPadding);
inBlockSize, outBlockSize, outBlockCount, inputChannelsPadding, outputChannelsPadding);
const float roiStartW = bottomRois[1] * spatialScale;
const float roiStartH = bottomRois[2] * spatialScale;
const float roiEndW = bottomRois[3] * spatialScale;
@@ -340,13 +337,14 @@ void MKLDNNPSROIPoolingNode::executeBilinear(const inputType *srcData, outputTyp
const float inY = nh > 1 ? (h * heightScale + boxYmin * (height - 1)) : 0.5f * (boxYmin + boxYmax) * (height - 1);
for (size_t binX = 0; binX < spatialBinsX; binX++) {
size_t gc = c + (binY * spatialBinsX + binX) * nc;
if (inFmt == Layout::NHWC) {
if (srcDesc.hasLayoutType(LayoutType::nspc)) {
binOffIn = roiBatchInd * channels * height * width + gc;
inBlkRes = 0;
} else { // nchw, nChw16c, nChw8c
const int inputBlockIdx = (gc / inBlockSize) * inBlockSize;
binOffIn = (roiBatchInd * inputChannelsPadding + inputBlockIdx) * height * width;
inBlkRes = (inFmt == Layout::BLOCKED ? gc % inBlockSize : 0);
inBlkRes = ((srcDesc.hasLayoutType(LayoutType::nCsp16c) || srcDesc.hasLayoutType(LayoutType::nCsp8c))
? gc % inBlockSize : 0);
}
const auto *bottomData = srcData + binOffIn;
@@ -386,14 +384,14 @@ void MKLDNNPSROIPoolingNode::executeBilinear(const inputType *srcData, outputTyp
dstData[dstIndex] = accum;
};
if (inFmt == Layout::NHWC) {
if (srcDesc.hasLayoutType(LayoutType::nspc)) {
const int binOffsetOutput = currentRoi * nc * nh * nw;
parallel_for2d(nh, nw, [&](int h, int w) {
for (int c = 0; c < nc; c++) {
bilinearPsroi(c, h, w, 0, binOffsetOutput + c);
}
});
} else if (inFmt == Layout::NCHW) {
} else if (srcDesc.hasLayoutType(LayoutType::ncsp)) {
parallel_for3d(nc, nh, nw, [&](int c, int h, int w) {
bilinearPsroi(c, h, w, 0, (currentRoi * outputChannelsPadding + c) * binCount);
});
@@ -404,7 +402,8 @@ void MKLDNNPSROIPoolingNode::executeBilinear(const inputType *srcData, outputTyp
for (int c = cStart; c < cEnd; c++) {
const int outputBlockIdx = (c / inBlockSize) * inBlockSize;
const int binOffsetOutput = (currentRoi * outputChannelsPadding + outputBlockIdx) * binCount;
const int outputBlockResidual = (inFmt == Layout::BLOCKED ? c % inBlockSize : 0);
const int outputBlockResidual = ((srcDesc.hasLayoutType(LayoutType::nCsp16c) || srcDesc.hasLayoutType(LayoutType::nCsp8c))
? c % inBlockSize : 0);
bilinearPsroi(c, h, w, outputBlockResidual, binOffsetOutput);
}
});
@@ -480,8 +479,8 @@ void MKLDNNPSROIPoolingNode::executeSpecified() {
const auto *bottomRoisBeginning = reinterpret_cast<const float *>(getParentEdgeAt(1)->getMemoryPtr()->GetPtr());
auto *dstData = reinterpret_cast<outputType *>(getChildEdgeAt(0)->getMemoryPtr()->GetPtr());
auto srcDesc = getParentEdgeAt(0)->getDesc();
auto dstDesc = getChildEdgeAt(0)->getDesc();
auto srcDesc = getParentEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
auto dstDesc = getChildEdgeAt(0)->getMemory().GetDescWithType<BlockedMemoryDesc>();
int realRois = 0;
for (; realRois < nn; realRois++) {
@@ -497,7 +496,7 @@ void MKLDNNPSROIPoolingNode::executeSpecified() {
int channelsEachClass = outputDim;
if (!noTrans) {
bottomTrans = reinterpret_cast<const float *>(getParentEdgeAt(2)->getMemoryPtr()->GetPtr());
numClasses = static_cast<int>(getParentEdgeAt(2)->getDesc().getDims()[1]) / 2;
numClasses = static_cast<int>(getParentEdgeAt(2)->getShape().getStaticDims()[1]) / 2;
channelsEachClass /= numClasses;
}
@@ -534,8 +533,8 @@ struct MKLDNNPSROIPoolingNode::PSROIPoolingExecute {
};
void MKLDNNPSROIPoolingNode::execute(mkldnn::stream strm) {
auto inputPrec = getParentEdgesAtPort(0)[0]->getDesc().getPrecision();
auto outputPrec = getChildEdgesAtPort(0)[0]->getDesc().getPrecision();
auto inputPrec = getParentEdgesAtPort(0)[0]->getMemory().GetDesc().getPrecision();
auto outputPrec = getChildEdgesAtPort(0)[0]->getMemory().GetDesc().getPrecision();
if (!((inputPrec == Precision::BF16 && outputPrec == Precision::BF16) ||
(inputPrec == Precision::FP32 && outputPrec == Precision::FP32))) {
@@ -50,10 +50,9 @@ private:
std::string errorPrefix;
void unpackParams(const InferenceEngine::TensorDesc& srcDesc, const InferenceEngine::TensorDesc& dstDesc,
void unpackParams(const BlockedMemoryDesc& srcDesc, const BlockedMemoryDesc& dstDesc,
int& hInputStride, int& wInputStride,
int& hOutputStride, int& wOutputStride,
InferenceEngine::Layout& inFmt, InferenceEngine::Layout& outFmt,
int& inBlockSize, int& outBlockSize,
int& outBlockCount,
unsigned long& inputChannelsPadding, unsigned long& outputChannelsPadding);
@@ -61,12 +60,12 @@ private:
template <typename inputType, typename outputType>
void executeAverage(const inputType *srcData, outputType *dstData, const float *bottomRois,
const int n, const int roiBatchInd,
const InferenceEngine::TensorDesc& srcDesc, const InferenceEngine::TensorDesc& dstDesc);
const BlockedMemoryDesc& srcDesc, const BlockedMemoryDesc& dstDesc);
template <typename inputType, typename outputType>
void executeBilinear(const inputType *srcData, outputType *dstData, const float *bottomRois,
const int currentRoi, const int roiBatchInd,
const InferenceEngine::TensorDesc& srcDesc, const InferenceEngine::TensorDesc& dstDesc);
const BlockedMemoryDesc& srcDesc, const BlockedMemoryDesc& dstDesc);
template <typename inputType, typename outputType>
void executeBilinearDeformable(const inputType *srcData, outputType *dstData, const float *bottomRois,
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <ngraph/opsets/opset1.hpp>
@@ -65,8 +63,8 @@ void MKLDNNRangeNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
std::vector<DataConfigurator> inDataConf;
std::vector<DataConfigurator> outDataConf;
std::vector<PortConfigurator> inDataConf;
std::vector<PortConfigurator> outDataConf;
if (!(getOriginalInputPrecisionAtPort(RANGE_START) == Precision::I32 &&
getOriginalInputPrecisionAtPort(RANGE_LIMIT) == Precision::I32 &&
@@ -78,23 +76,23 @@ void MKLDNNRangeNode::initSupportedPrimitiveDescriptors() {
getOriginalOutputPrecisionAtPort(0) == Precision::FP32)) {
inDataConf.reserve(getOriginalInputsNumber());
for (int i = 0; i < getOriginalInputsNumber(); ++i)
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp, Precision::FP32);
inDataConf.emplace_back(LayoutType::ncsp, Precision::FP32);
outDataConf.reserve(1);
outDataConf.emplace_back(TensorDescCreatorTypes::ncsp, Precision::FP32);
outDataConf.emplace_back(LayoutType::ncsp, Precision::FP32);
addSupportedPrimDesc(inDataConf, outDataConf, impl_desc_type::ref_any);
} else {
inDataConf.reserve(getOriginalInputsNumber());
for (int i = 0; i < getOriginalInputsNumber(); ++i)
inDataConf.emplace_back(TensorDescCreatorTypes::ncsp);
inDataConf.emplace_back(LayoutType::ncsp);
outDataConf.reserve(1);
outDataConf.emplace_back(TensorDescCreatorTypes::ncsp);
outDataConf.emplace_back(LayoutType::ncsp);
addSupportedPrimDesc(inDataConf, outDataConf, impl_desc_type::ref_any);
}
}
void MKLDNNRangeNode::execute(mkldnn::stream strm) {
StatusCode retcode = OK;
switch (getParentEdgeAt(0)->getDesc().getPrecision()) {
switch (getParentEdgeAt(0)->getMemory().GetDesc().getPrecision()) {
case Precision::FP32:
retcode = rangeKernel<float>();
break;
@@ -112,7 +110,7 @@ void MKLDNNRangeNode::execute(mkldnn::stream strm) {
template <typename data_t>
InferenceEngine::StatusCode MKLDNNRangeNode::rangeKernel() noexcept {
size_t dst_size = (getChildEdgesAtPort(0)[0]->getDims())[0];
size_t dst_size = (getChildEdgesAtPort(0)[0]->getShape().getStaticDims())[0];
data_t* dst_data = reinterpret_cast<data_t *>(getChildEdgesAtPort(0)[0]->getMemoryPtr()->GetPtr());
data_t start = reinterpret_cast<const data_t *>(getParentEdgeAt(RANGE_START)->getMemoryPtr()->GetPtr())[0];
data_t limit = reinterpret_cast<const data_t *>(getParentEdgeAt(RANGE_LIMIT)->getMemoryPtr()->GetPtr())[0];
@@ -1405,18 +1405,18 @@ void MKLDNNReduceNode::getSupportedDescriptors() {
if (getChildEdges().empty())
IE_THROW() << errorPrefix << " gets incorrect number of output edges!";
if (getParentEdgeAt(REDUCE_INDEXES)->getDims().ndims() != 1) {
if (getParentEdgeAt(REDUCE_INDEXES)->getShape().getRank() != 1) {
IE_THROW() << errorPrefix << " gets incorrect index vector dimension! Index vector should be 1 dimension.";
}
if (keep_dims) {
if (getParentEdgeAt(REDUCE_DATA)->getDims().ndims() != getChildEdgeAt(0)->getDims().ndims())
if (getParentEdgeAt(REDUCE_DATA)->getShape().getRank() != getChildEdgeAt(0)->getShape().getRank())
IE_THROW() << errorPrefix << " gets incorrect number of input/output dimensions!";
} else {
// In fact, after the Reduce operation, the shape must be a scalar if the previous one was 1d.
// But for now, 0d tensor (scalar) is emulated as 1d tensor. Skip checking in such cases.
bool is_emulated_0d_as_1d = getParentEdgeAt(REDUCE_DATA)->getDims().ndims() == 1 && getChildEdgeAt(0)->getDims().ndims() == 1;
if (getParentEdgeAt(REDUCE_DATA)->getDims().ndims() <= getChildEdgeAt(0)->getDims().ndims() && !is_emulated_0d_as_1d)
bool is_emulated_0d_as_1d = getParentEdgeAt(REDUCE_DATA)->getShape().getRank() == 1 && getChildEdgeAt(0)->getShape().getRank() == 1;
if (getParentEdgeAt(REDUCE_DATA)->getShape().getRank() <= getChildEdgeAt(0)->getShape().getRank() && !is_emulated_0d_as_1d)
IE_THROW() << errorPrefix << "gets incorrect number of input/output dimensions!";
}
}
@@ -1436,7 +1436,7 @@ void MKLDNNReduceNode::initSupportedPrimitiveDescriptors() {
Precision inputPrecision = getOriginalInputPrecisionAtPort(REDUCE_DATA);
Precision outputPrecision = getOriginalOutputPrecisionAtPort(0);
jit_mode = (mayiuse(cpu::x64::sse41)) && getParentEdgeAt(REDUCE_DATA)->getDims().ndims() <= 5 &&
jit_mode = (mayiuse(cpu::x64::sse41)) && getParentEdgeAt(REDUCE_DATA)->getShape().getRank() <= 5 &&
std::find(std::begin(supportedPrecisions), std::end(supportedPrecisions), inputPrecision) != std::end(supportedPrecisions) &&
std::find(std::begin(supportedPrecisions), std::end(supportedPrecisions), outputPrecision) != std::end(supportedPrecisions);
@@ -1461,7 +1461,7 @@ void MKLDNNReduceNode::initSupportedPrimitiveDescriptors() {
src_data_size = MKLDNNExtensionUtils::sizeOfDataType(inputDataType);
dst_data_size = MKLDNNExtensionUtils::sizeOfDataType(outputDataType);
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = false;
config.inConfs.resize(2);
config.outConfs.resize(1);
@@ -1474,10 +1474,12 @@ void MKLDNNReduceNode::initSupportedPrimitiveDescriptors() {
auto pushDesc = [&](memory::format_tag inFormat, memory::format_tag outFormat, memory::data_type inDataType,
memory::data_type outDataType, impl_desc_type impl_type) {
config.inConfs[REDUCE_DATA].desc = MKLDNNMemoryDesc(getParentEdgeAt(REDUCE_DATA)->getDims(), inDataType, inFormat);
config.inConfs[REDUCE_INDEXES].desc = MKLDNNMemoryDesc(getParentEdgeAt(REDUCE_INDEXES)->getDims(), memory::data_type::s32, memory::format_tag::x);
config.outConfs[0].desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outDataType, outFormat);
supportedPrimitiveDescriptors.push_back({config, impl_type, outFormat});
config.inConfs[REDUCE_DATA].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(REDUCE_DATA)->getShape().getStaticDims(),
inDataType, inFormat);
config.inConfs[REDUCE_INDEXES].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(REDUCE_INDEXES)->getShape().getStaticDims(),
memory::data_type::s32, memory::format_tag::x);
config.outConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getChildEdgeAt(0)->getShape().getStaticDims(), outDataType, outFormat);
supportedPrimitiveDescriptors.push_back({config, impl_type});
};
if (jit_mode) {
@@ -1488,16 +1490,16 @@ void MKLDNNReduceNode::initSupportedPrimitiveDescriptors() {
impl_type = impl_desc_type::jit_avx2;
}
pushDesc(MKLDNNMemory::GetPlainFormat(memory::dims(getParentEdgeAt(REDUCE_DATA)->getDims().ndims())),
MKLDNNMemory::GetPlainFormat(memory::dims(getChildEdgeAt(0)->getDims().ndims())), inputDataType, outputDataType, impl_type);
pushDesc(MKLDNNMemory::GetPlainFormatByRank(getParentEdgeAt(REDUCE_DATA)->getShape().getRank()),
MKLDNNMemory::GetPlainFormatByRank(getChildEdgeAt(0)->getShape().getRank()), inputDataType, outputDataType, impl_type);
if (keep_dims) {
if (getParentEdgeAt(REDUCE_DATA)->getDims().ndims() == 4 && getParentEdgeAt(REDUCE_DATA)->getDims().ToSizeVector()[1] > 1) {
if (getParentEdgeAt(REDUCE_DATA)->getShape().getRank() == 4 && getParentEdgeAt(REDUCE_DATA)->getShape().getStaticDims()[1] > 1) {
if (mayiuse(cpu::x64::avx512_common)) {
pushDesc(memory::format_tag::nChw16c, memory::format_tag::nChw16c, inputDataType, outputDataType, impl_type);
} else if (mayiuse(cpu::x64::avx2) || mayiuse(cpu::x64::sse41)) {
pushDesc(memory::format_tag::nChw8c, memory::format_tag::nChw8c, inputDataType, outputDataType, impl_type);
}
} else if (getParentEdgeAt(REDUCE_DATA)->getDims().ndims() == 5 && getParentEdgeAt(REDUCE_DATA)->getDims().ToSizeVector()[1] > 1) {
} else if (getParentEdgeAt(REDUCE_DATA)->getShape().getRank() == 5 && getParentEdgeAt(REDUCE_DATA)->getShape().getStaticDims()[1] > 1) {
if (mayiuse(cpu::x64::avx512_common)) {
pushDesc(memory::format_tag::nCdhw16c, memory::format_tag::nCdhw16c, inputDataType, outputDataType, impl_type);
} else if (mayiuse(cpu::x64::avx2) || mayiuse(cpu::x64::sse41)) {
@@ -1506,8 +1508,8 @@ void MKLDNNReduceNode::initSupportedPrimitiveDescriptors() {
}
}
} else {
pushDesc(MKLDNNMemory::GetPlainFormat(memory::dims(getParentEdgeAt(REDUCE_DATA)->getDims().ndims())),
MKLDNNMemory::GetPlainFormat(memory::dims(getChildEdgeAt(0)->getDims().ndims())),
pushDesc(MKLDNNMemory::GetPlainFormatByRank(getParentEdgeAt(REDUCE_DATA)->getShape().getRank()),
MKLDNNMemory::GetPlainFormatByRank(getChildEdgeAt(0)->getShape().getRank()),
memory::data_type::f32, memory::data_type::f32, impl_desc_type::ref);
}
}
@@ -1524,11 +1526,11 @@ void MKLDNNReduceNode::createPrimitive() {
IE_THROW() << errorPrefix << " has nullable preferable primitive descriptor";
auto selectedPD = getSelectedPrimitiveDescriptor();
planar_layout = getParentEdgeAt(REDUCE_DATA)->getMemory().GetDesc().isPlainFormat();
planar_layout = getParentEdgeAt(REDUCE_DATA)->getMemory().GetDesc().hasLayoutType(LayoutType::ncsp);
auto jcp = jit_reduce_config_params();
jcp.src_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(selectedPD->getConfig().inConfs[REDUCE_DATA].desc.getPrecision());
jcp.dst_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(selectedPD->getConfig().outConfs[0].desc.getPrecision());
jcp.src_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(selectedPD->getConfig().inConfs[REDUCE_DATA].desc->getPrecision());
jcp.dst_dt = MKLDNNExtensionUtils::IEPrecisionToDataType(selectedPD->getConfig().outConfs[0].desc->getPrecision());
jcp.src_data_size = MKLDNNExtensionUtils::sizeOfDataType(jcp.src_dt);
jcp.dst_data_size = MKLDNNExtensionUtils::sizeOfDataType(jcp.dst_dt);
jcp.planar_layout = planar_layout;
@@ -1564,8 +1566,8 @@ void MKLDNNReduceNode::execute(mkldnn::stream strm) {
const auto idx_data = reinterpret_cast<const int32_t *>(srcIndexesMemPtr->GetData());
size_t dst_size = dstMemPtr->GetSize();
src_dims = getParentEdgeAt(REDUCE_DATA)->getDesc().getDims();
src_strides = getParentEdgeAt(REDUCE_DATA)->getDesc().getBlockingDesc().getStrides();
src_dims = getParentEdgeAt(REDUCE_DATA)->getShape().getStaticDims();
src_strides = getParentEdgeAt(REDUCE_DATA)->getMemory().GetDescWithType<BlockedMemoryDesc>().getStrides();
dims_size = src_dims.size();
calc_process_dst_dims(idx_data);
@@ -1930,9 +1932,9 @@ inline void MKLDNNReduceNode::init_dst_data(uint8_t *out_ptr, size_t dst_size) {
inline void MKLDNNReduceNode::calc_process_dst_dims(const int32_t *idx_data) {
SizeVector out_dims;
SizeVector dst_dims = getChildEdgeAt(0)->getDesc().getDims();
SizeVector dst_dims = getChildEdgeAt(0)->getShape().getStaticDims();
std::set<size_t> axes;
for (size_t i = 0; i < getParentEdgeAt(REDUCE_INDEXES)->getDims()[0]; i++) {
for (size_t i = 0; i < getParentEdgeAt(REDUCE_INDEXES)->getShape().getStaticDims()[0]; i++) {
int32_t axis = idx_data[i];
if (axis < 0)
axis += src_dims.size();
@@ -6,6 +6,7 @@
#include <ie_ngraph_utils.hpp>
#include <mkldnn_extension_utils.h>
#include <ngraph/runtime/host_tensor.hpp>
#include "common/blocked_desc_creator.h"
using namespace mkldnn;
using namespace MKLDNNPlugin;
@@ -28,45 +29,32 @@ void MKLDNNReferenceNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
InferenceEngine::LayerConfig config;
for (size_t i = 0; i < inDims.size(); i++) {
InferenceEngine::DataConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = MKLDNNMemoryDesc(inDims[i],
MKLDNNExtensionUtils::IEPrecisionToDataType(convertPrecision(ngraphOp->get_input_element_type(i))),
MKLDNNMemory::GetPlainFormat(inDims[i]));
config.inConfs.push_back(dataConfig);
std::vector<PortConfigurator> inputConfigurators;
inputConfigurators.reserve(inputShapes.size());
for (size_t i = 0; i < inputShapes.size(); i++) {
inputConfigurators.emplace_back(LayoutType::ncsp, convertPrecision(ngraphOp->get_input_element_type(i)), inputShapes[i]);
}
for (size_t i = 0; i < outDims.size(); i++) {
InferenceEngine::DataConfig dataConfig;
dataConfig.inPlace = -1;
dataConfig.constant = false;
dataConfig.desc = MKLDNNMemoryDesc(outDims[i],
MKLDNNExtensionUtils::IEPrecisionToDataType(convertPrecision(ngraphOp->get_output_element_type(i))),
MKLDNNMemory::GetPlainFormat(outDims[i]));
config.outConfs.push_back(dataConfig);
std::vector<PortConfigurator> outputConfigurators;
outputConfigurators.reserve(inputShapes.size());
for (size_t i = 0; i < outputShapes.size(); i++) {
outputConfigurators.emplace_back(LayoutType::ncsp, convertPrecision(ngraphOp->get_output_element_type(i)), outputShapes[i]);
}
supportedPrimitiveDescriptors.push_back({config, impl_desc_type::ref, memory::format_tag::undef});
addSupportedPrimDesc(inputConfigurators, outputConfigurators, impl_desc_type::ref);
}
void MKLDNNReferenceNode::createPrimitive() {}
void MKLDNNReferenceNode::execute(mkldnn::stream strm) {
ngraph::HostTensorVector inputs;
for (size_t i = 0; i < inDims.size(); i++) {
for (size_t i = 0; i < inputShapes.size(); i++) {
void *srcDataPtr = getParentEdgesAtPort(i)[0]->getMemory().GetPtr();
inputs.push_back(std::make_shared<ngraph::HostTensor>(ngraphOp->get_input_element_type(i), ngraphOp->get_input_shape(i), srcDataPtr));
}
ngraph::HostTensorVector outputs;
for (size_t i = 0; i < outDims.size(); i++) {
for (size_t i = 0; i < outputShapes.size(); i++) {
void *dstDataPtr = getChildEdgesAtPort(i)[0]->getMemory().GetPtr();
outputs.push_back(std::make_shared<ngraph::HostTensor>(ngraphOp->get_output_element_type(i), ngraphOp->get_output_shape(i), dstDataPtr));
}
@@ -8,7 +8,7 @@
#include <mkldnn_types.h>
#include "ie_parallel.hpp"
#include "mkldnn_region_yolo_node.h"
#include <nodes/common/tensor_desc_creator.h>
#include <nodes/common/blocked_desc_creator.h>
#include <ngraph/opsets/opset1.hpp>
#include "common/cpu_convert.h"
#include <cpu/x64/jit_generator.hpp>
@@ -291,8 +291,8 @@ void MKLDNNRegionYoloNode::initSupportedPrimitiveDescriptors() {
impl_type = impl_desc_type::ref;
}
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, input_prec}},
{{TensorDescCreatorTypes::ncsp, output_prec}},
addSupportedPrimDesc({{LayoutType::ncsp, input_prec}},
{{LayoutType::ncsp, output_prec}},
impl_type);
}
@@ -367,13 +367,10 @@ inline void MKLDNNRegionYoloNode::calculate_logistic(size_t start_index, int cou
}
void MKLDNNRegionYoloNode::execute(mkldnn::stream strm) {
auto inputDesc = getParentEdgeAt(0)->getDesc();
auto outputDesc = getChildEdgeAt(0)->getDesc();
size_t B = (inputDesc.getDims().size() > 0) ? inputDesc.getDims()[0] : 1;
size_t IC = (inputDesc.getDims().size() > 1) ? inputDesc.getDims()[1] : 1;
size_t IH = (inputDesc.getDims().size() > 2) ? inputDesc.getDims()[2] : 1;
size_t IW = (inputDesc.getDims().size() > 3) ? inputDesc.getDims()[3] : 1;
size_t B = (getParentEdgeAt(0)->getShape().getRank() > 0) ? getParentEdgeAt(0)->getShape().getStaticDims()[0] : 1;
size_t IC = (getParentEdgeAt(0)->getShape().getRank() > 1) ? getParentEdgeAt(0)->getShape().getStaticDims()[1] : 1;
size_t IH = (getParentEdgeAt(0)->getShape().getRank() > 2) ? getParentEdgeAt(0)->getShape().getStaticDims()[2] : 1;
size_t IW = (getParentEdgeAt(0)->getShape().getRank() > 3) ? getParentEdgeAt(0)->getShape().getStaticDims()[3] : 1;
size_t mask_size = mask.size();
int end_index = 0;
@@ -400,7 +397,8 @@ void MKLDNNRegionYoloNode::execute(mkldnn::stream strm) {
const auto *src_data = reinterpret_cast<const uint8_t *>(getParentEdgeAt(0)->getMemoryPtr()->GetPtr());
auto *dst_data = reinterpret_cast<uint8_t *>(getChildEdgeAt(0)->getMemoryPtr()->GetPtr());
cpu_convert(src_data, dst_data, inputDesc.getPrecision(), outputDesc.getPrecision(), output_size);
cpu_convert(src_data, dst_data, getParentEdgeAt(0)->getMemory().GetDesc().getPrecision(),
getChildEdgeAt(0)->getMemory().GetDesc().getPrecision(), output_size);
for (int b = 0; b < B; b++) {
for (int n = 0; n < num_; n++) {
@@ -25,10 +25,6 @@ MKLDNNReorderNode::MKLDNNReorderNode(const std::string& name, const mkldnn::engi
MKLDNNNode("Reorder", name, eng, w_cache) {
}
void MKLDNNReorderNode::getSupportedDescriptors() {
if (outDims.empty() && output.getLayout() != InferenceEngine::Layout::ANY)
outDims.push_back(MKLDNNDims(output.getDims()));
if (inDims.empty() && input.getLayout() != InferenceEngine::Layout::ANY)
inDims.push_back(MKLDNNDims(input.getDims()));
if (getParentEdges().size() != 1)
IE_THROW() << "Incorrect number of input edges for layer " << getName();
if (getChildEdges().empty())
@@ -39,13 +35,10 @@ void MKLDNNReorderNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
auto inputDataType = MKLDNNMemoryDesc(input).getDataType();
auto outputDataType = MKLDNNMemoryDesc(output).getDataType();
auto parent = getParentEdgeAt(0)->getParent();
auto child = getChildEdgeAt(0)->getChild();
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = true;
config.inConfs.resize(1);
config.outConfs.resize(1);
@@ -57,19 +50,18 @@ void MKLDNNReorderNode::initSupportedPrimitiveDescriptors() {
config.inConfs[0].inPlace = 0;
config.outConfs[0].inPlace = 0;
}
if (input.getLayout() != InferenceEngine::Layout::ANY && output.getLayout() != InferenceEngine::Layout::ANY) {
config.inConfs[0].desc = input;
config.outConfs[0].desc = output;
if (input && output) {
config.inConfs[0].desc = input->clone();
config.outConfs[0].desc = output->clone();
} else if (parent->getSelectedPrimitiveDescriptor() != nullptr &&
child->getSelectedPrimitiveDescriptor() != nullptr) {
config.inConfs[0].desc = parent->getSelectedPrimitiveDescriptor()->getConfig().outConfs[0].desc;
config.outConfs[0].desc = child->getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc;
config.inConfs[0].desc = parent->getSelectedPrimitiveDescriptor()->getConfig().outConfs[0].desc->clone();
config.outConfs[0].desc = child->getSelectedPrimitiveDescriptor()->getConfig().inConfs[0].desc->clone();
} else {
config.inConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, memory::format_tag::any);
config.outConfs[0].desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, memory::format_tag::any);
IE_THROW() << "Cannot initialize supported PDs for Reorder node with name `" << getName() << "`";
}
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::reorder, MKLDNNMemory::Convert(config.outConfs[0].desc.getLayout()));
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::reorder);
}
void MKLDNNReorderNode::createPrimitive() {
@@ -82,21 +74,23 @@ void MKLDNNReorderNode::createPrimitive() {
if (getSelectedPrimitiveDescriptor() == nullptr)
IE_THROW() << "Preferable primitive descriptor is not set.";
auto inDims = getParentEdgeAt(0)->getShape().getStaticDims();
if (!isOptimized) {
if (MKLDNNPlugin::one_of(getParentEdgeAt(0)->getDims().ndims(), 4, 5) &&
getParentEdgeAt(0)->getDims()[1] <= 64 &&
getParentEdgeAt(0)->getDims()[1] >= 16 &&
(getParentEdgeAt(0)->getMemory().GetElementsCount() / getParentEdgeAt(0)->getDims()[1]) >= 128 &&
getParentEdgeAt(0)->getMemory().GetDesc().isTailCFormat() &&
getChildEdgeAt(0)->getMemory().GetDesc().isPlainFormat() &&
getParentEdgeAt(0)->getMemory().GetDesc().getDataType() == memory::data_type::f32 &&
getChildEdgeAt(0)->getMemory().GetDesc().getDataType() == memory::data_type::f32) {
if (MKLDNNPlugin::one_of(inDims.size(), 4, 5) &&
inDims[1] <= 64 &&
inDims[1] >= 16 &&
(getParentEdgeAt(0)->getMemory().GetElementsCount() / inDims[1]) >= 128 &&
getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nspc) &&
getChildEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::ncsp) &&
getParentEdgeAt(0)->getMemory().GetDesc().getPrecision() == Precision::FP32 &&
getChildEdgeAt(0)->getMemory().GetDesc().getPrecision() == Precision::FP32) {
// oneDNN JIT reorder shows bad perf for nspc to ncsp reorder case so we fallback on simple c++ implementation
canUseOptimizedNspc2Ncsp = true;
} else if (!impl::cpu::x64::mayiuse(impl::cpu::x64::avx2) &&
MKLDNNPlugin::one_of(getParentEdgeAt(0)->getDims().ndims(), 4, 5) &&
getParentEdgeAt(0)->getMemory().GetDesc().isPlainFormat() &&
getChildEdgeAt(0)->getMemory().GetDesc().isTailCFormat() &&
MKLDNNPlugin::one_of(inDims.size(), 4, 5) &&
getParentEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::ncsp) &&
getChildEdgeAt(0)->getMemory().GetDesc().hasLayoutType(LayoutType::nspc) &&
getParentEdgeAt(0)->getMemory().GetDataType() == getChildEdgeAt(0)->getMemory().GetDataType() &&
MKLDNNExtensionUtils::sizeOfDataType(getParentEdgeAt(0)->getMemory().GetDataType()) == 1) {
// oneDNN doesn't provide JIT reorder impl for non-avx2 targets so we fallback on simple c++ implementation which shows better perf
@@ -110,29 +104,12 @@ void MKLDNNReorderNode::createPrimitive() {
void MKLDNNReorderNode::createReorderPrimitive(const mkldnn::memory::desc &srcDesc, void* srcPtr, const mkldnn::memory::desc &dstDesc, void* dstPtr) {
src_blocked = std::make_shared<MKLDNNMemory>(getEngine());
src_blocked->Create(srcDesc, srcPtr, false);
src_blocked->Create(MKLDNNMemoryDesc(srcDesc), srcPtr, false);
dst_blocked = std::make_shared<MKLDNNMemory>(getEngine());
dst_blocked->Create(dstDesc, dstPtr, false);
dst_blocked->Create(MKLDNNMemoryDesc(dstDesc), dstPtr, false);
mkldnn::primitive_attr attr;
if (_scales) {
std::vector<float> scales;
float* scaleData = static_cast<float*>(_scales->buffer());
for (size_t i = 0; i < _scales->size(); i++) {
scales.push_back(scaleData[i]);
}
int mask = 0;
int oc_dim_id = 1;
mask = 1 << oc_dim_id;
attr.set_output_scales(mask, scales);
}
auto createReorder = [&]() -> bool {
// No autoblocking. Reorder can be applied as is
reorder::primitive_desc pd = mkldnn::reorder::primitive_desc(src_blocked->GetPrimitive(), dst_blocked->GetPrimitive(), attr, true);
@@ -159,13 +136,13 @@ void MKLDNNReorderNode::createReorderPrimitive(const mkldnn::memory::desc &srcDe
// MKLDNN doesn't support direct reorders from planar data formats to grouped weights formats.
// Code block below tries to detect such cases and reinterpret data planar formats (e.g. nchw)
// as grouped weights planar formats (e.g. goihw) since they have same physical memory layout.
if (src_blocked->GetDesc().isPlainFormat() &&
if (src_blocked->GetDesc().hasLayoutType(LayoutType::ncsp) &&
src_blocked->GetDims().size() + 1 == dst_blocked->GetDims().size()) {
const auto newDims = dst_blocked->GetDims();
const auto newFormat = MKLDNNMemory::GetPlainFormat(newDims);
const auto newFormat = MKLDNNMemory::GetPlainFormatByRank(newDims.size());
auto newDesc = mkldnn::memory::desc(newDims, src_blocked->GetDataType(), newFormat);
src_blocked->Create(newDesc, srcPtr, false);
src_blocked->Create(MKLDNNMemoryDesc(newDesc), srcPtr, false);
success = createReorder();
}
@@ -192,12 +169,14 @@ bool MKLDNNReorderNode::created() const {
void MKLDNNReorderNode::optimizedNcsp2Nspc() {
auto parentEdge = getParentEdgeAt(0);
auto childEdge = getChildEdgeAt(0);
const int ndims = parentEdge->getDims().ndims();
const size_t DIM0 = parentEdge->getDims()[0];
const size_t DIM1 = parentEdge->getDims()[1];
const size_t DIM2 = ndims == 5 ? parentEdge->getDims()[ndims - 3] : 1;
const size_t DIM3 = parentEdge->getDims()[ndims - 2];
const size_t DIM4 = parentEdge->getDims()[ndims - 1];
auto inDims = parentEdge->getShape().getStaticDims();
const size_t ndims = inDims.size();
const size_t DIM0 = inDims[0];
const size_t DIM1 = inDims[1];
const size_t DIM2 = ndims == 5 ? inDims[ndims - 3] : 1;
const size_t DIM3 = inDims[ndims - 2];
const size_t DIM4 = inDims[ndims - 1];
auto src_data = reinterpret_cast<const uint8_t *>(parentEdge->getMemoryPtr()->GetPtr());
auto dst_data = reinterpret_cast<uint8_t *>(childEdge->getMemoryPtr()->GetPtr());
@@ -221,12 +200,14 @@ void MKLDNNReorderNode::optimizedNcsp2Nspc() {
void MKLDNNReorderNode::optimizedNspc2Ncsp() {
auto parentEdge = getParentEdgeAt(0);
auto childEdge = getChildEdgeAt(0);
const int ndims = parentEdge->getDims().ndims();
const size_t DIM0 = parentEdge->getDims()[0];
const size_t DIM1 = parentEdge->getDims()[1];
const size_t DIM2 = ndims == 5 ? parentEdge->getDims()[ndims - 3] : 1;
const size_t DIM3 = parentEdge->getDims()[ndims - 2];
const size_t DIM4 = parentEdge->getDims()[ndims - 1];
auto inDims = parentEdge->getShape().getStaticDims();
const size_t ndims = inDims.size();
const size_t DIM0 = inDims[0];
const size_t DIM1 = inDims[1];
const size_t DIM2 = ndims == 5 ? inDims[ndims - 3] : 1;
const size_t DIM3 = inDims[ndims - 2];
const size_t DIM4 = inDims[ndims - 1];
auto src_data = reinterpret_cast<const float *>(parentEdge->getMemoryPtr()->GetPtr());
auto dst_data = reinterpret_cast<float *>(childEdge->getMemoryPtr()->GetPtr());
@@ -279,4 +260,20 @@ void MKLDNNReorderNode::setDynamicBatchLim(int lim) {
createReorderPrimitive(src_d, src_data_hdl, dst_d, dst_data_hdl);
}
}
std::string MKLDNNReorderNode::getReorderArgs(const MemoryDesc &parentDesc, const MemoryDesc &childDesc) {
std::string inArgs, outArgs;
if (parentDesc.getPrecision() != childDesc.getPrecision()) {
inArgs += (inArgs.empty() ? "" : "_") + std::string(parentDesc.getPrecision().name());
outArgs += (outArgs.empty() ? "" : "_") + std::string(childDesc.getPrecision().name());
}
auto formatSrc = parentDesc.serializeFormat();
auto formatDst = childDesc.serializeFormat();
if (formatSrc != formatDst || one_of(std::string("undef"), formatSrc, formatDst)) {
inArgs += (inArgs.empty() ? "" : "_") + formatSrc;
outArgs += (outArgs.empty() ? "" : "_") + formatDst;
}
return inArgs + "_" + outArgs;
}
REG_MKLDNN_PRIM_FOR(MKLDNNReorderNode, Reorder);
@@ -9,6 +9,7 @@
#include <string>
#include <memory>
#include <vector>
#include <utils/general_utils.h>
namespace MKLDNNPlugin {
@@ -24,9 +25,14 @@ public:
bool created() const override;
const std::vector<impl_desc_type>& getPrimitivesPriority() override;
void setDescs(const InferenceEngine::TensorDesc& input, const InferenceEngine::TensorDesc& output) {
this->input = input;
this->output = output;
void setDescs(const MemoryDesc& input, const MemoryDesc& output) {
this->input = input.clone();
inputShapes.clear();
inputShapes.push_back(this->input->getShape());
this->output = output.clone();
outputShapes.clear();
outputShapes.push_back(this->output->getShape());
}
void setOptimized(bool isOptimized) {
@@ -39,17 +45,14 @@ public:
return false;
}
const InferenceEngine::TensorDesc& getInput() { return input; }
const InferenceEngine::TensorDesc& getOutput() { return output; }
const MemoryDesc& getInput() { return *input; }
const MemoryDesc& getOutput() { return *output; }
/**
* @brief A pointer to a scales blob
*/
InferenceEngine::Blob::Ptr _scales;
static std::string getReorderArgs(const MemoryDesc &parentDesc, const MemoryDesc &childDesc);
private:
InferenceEngine::TensorDesc input;
InferenceEngine::TensorDesc output;
std::unique_ptr<MemoryDesc> input;
std::unique_ptr<MemoryDesc> output;
MKLDNNMemoryPtr dst_blocked;
MKLDNNMemoryPtr src_blocked;
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <ngraph/opsets/opset2.hpp>
@@ -48,8 +46,8 @@ void MKLDNNReorgYoloNode::initSupportedPrimitiveDescriptors() {
if (!supportedPrimitiveDescriptors.empty())
return;
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32}},
{{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
@@ -57,10 +55,10 @@ void MKLDNNReorgYoloNode::execute(mkldnn::stream strm) {
const auto *src_data = reinterpret_cast<const float *>(getParentEdgeAt(0)->getMemoryPtr()->GetPtr());
auto *dst_data = reinterpret_cast<float *>(getChildEdgesAtPort(0)[0]->getMemoryPtr()->GetPtr());
int IW = (getParentEdgeAt(0)->getDesc().getDims().size() > 3) ? getParentEdgeAt(0)->getDims()[3] : 1;
int IH = (getParentEdgeAt(0)->getDesc().getDims().size() > 2) ? getParentEdgeAt(0)->getDims()[2] : 1;
int IC = (getParentEdgeAt(0)->getDesc().getDims().size() > 1) ? getParentEdgeAt(0)->getDims()[1] : 1;
int B = (getParentEdgeAt(0)->getDesc().getDims().size() > 0) ? getParentEdgeAt(0)->getDims()[0] : 1;
int IW = (getParentEdgeAt(0)->getShape().getRank() > 3) ? getParentEdgeAt(0)->getShape().getStaticDims()[3] : 1;
int IH = (getParentEdgeAt(0)->getShape().getRank() > 2) ? getParentEdgeAt(0)->getShape().getStaticDims()[2] : 1;
int IC = (getParentEdgeAt(0)->getShape().getRank() > 1) ? getParentEdgeAt(0)->getShape().getStaticDims()[1] : 1;
int B = (getParentEdgeAt(0)->getShape().getRank() > 0) ? getParentEdgeAt(0)->getShape().getStaticDims()[0] : 1;
int ic_off = IC / (stride * stride);
int ih_off = IH * stride;
@@ -35,18 +35,18 @@ void MKLDNNReshapeNode::initSupportedPrimitiveDescriptors() {
if (inputDataType != outputDataType)
inputDataType = outputDataType;
InferenceEngine::LayerConfig config;
NodeConfig config;
config.dynBatchSupport = true;
config.inConfs.resize(getParentEdges().size());
for (size_t i = 0; i <getParentEdges().size(); i++) {
config.inConfs[i].inPlace = -1;
config.inConfs[i].constant = false;
config.inConfs[i].desc = MKLDNNMemoryDesc(getParentEdgeAt(i)->getDims(), inputDataType);
config.inConfs[i].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getParentEdgeAt(i)->getShape().getStaticDims(), inputDataType);
}
config.outConfs.resize(1);
config.outConfs[0].inPlace = 0;
config.outConfs[0].constant = false;
config.outConfs[0].desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType);
config.outConfs[0].desc = MKLDNNPlugin::make_unique<MKLDNNMemoryDesc>(getChildEdgeAt(0)->getShape().getStaticDims(), outputDataType);
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown);
}
@@ -2,8 +2,6 @@
// SPDX-License-Identifier: Apache-2.0
//
#include "base.hpp"
#include <string>
#include <vector>
@@ -85,9 +83,9 @@ void MKLDNNReverseSequenceNode::initSupportedPrimitiveDescriptors() {
if (lengthsPrecision != Precision::I32 && lengthsPrecision != Precision::FP32)
lengthsPrecision = Precision::I32;
addSupportedPrimDesc({{TensorDescCreatorTypes::ncsp, Precision::FP32},
{TensorDescCreatorTypes::ncsp, lengthsPrecision}},
{{TensorDescCreatorTypes::ncsp, Precision::FP32}},
addSupportedPrimDesc({{LayoutType::ncsp, Precision::FP32},
{LayoutType::ncsp, lengthsPrecision}},
{{LayoutType::ncsp, Precision::FP32}},
impl_desc_type::ref_any);
}
@@ -96,7 +94,7 @@ void MKLDNNReverseSequenceNode::execute(mkldnn::stream strm) {
const float *src_data = reinterpret_cast<const float *>(getParentEdgeAt(REVERSESEQUENCE_DATA)->getMemoryPtr()->GetPtr());
float* dst_data = reinterpret_cast<float *>(getChildEdgesAtPort(0)[0]->getMemoryPtr()->GetPtr());
switch (getParentEdgeAt(REVERSESEQUENCE_LENGTHS)->getDesc().getPrecision()) {
switch (getParentEdgeAt(REVERSESEQUENCE_LENGTHS)->getMemory().GetDesc().getPrecision()) {
case Precision::FP32: {
float *seq_lengths_data = reinterpret_cast<float *>(getParentEdgeAt(REVERSESEQUENCE_LENGTHS)->getMemoryPtr()->GetPtr());
for (i = 0; i < src_dims[batch_axis]; i++) {
@@ -171,7 +169,7 @@ void MKLDNNReverseSequenceNode::execute(mkldnn::stream strm) {
break;
default:
IE_THROW() << "ReverseSequence layer does not support "
<< getParentEdgeAt(REVERSESEQUENCE_LENGTHS)->getDesc().getPrecision() << " precision";
<< getParentEdgeAt(REVERSESEQUENCE_LENGTHS)->getMemory().GetDesc().getPrecision() << " precision";
}
}
Loaded 100 of 129 files, more files were not shown because too many files have changed in this diff. Show more