Skip to content

Commit

Permalink
The convert layer was fixed after review.
Browse files Browse the repository at this point in the history
  • Loading branch information
maxnick committed Dec 21, 2020
1 parent 8e28cc0 commit e1639f3
Show file tree
Hide file tree
Showing 4 changed files with 157 additions and 35 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (C) 2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#include "tensor_desc_creator.h"
#include <numeric>

using namespace InferenceEngine;
using namespace MKLDNNPlugin;

namespace {
constexpr size_t channelsPos = 1lu;
}

InferenceEngine::TensorDesc PlainFormatCreator::createDesc(const InferenceEngine::Precision &precision, const InferenceEngine::SizeVector &srcDims) const {
SizeVector order(srcDims.size());
std::iota(order.begin(), order.end(), 0);
return TensorDesc(precision, srcDims, {srcDims, order});
}

InferenceEngine::TensorDesc PerChannelCreator::createDesc(const InferenceEngine::Precision &precision, const InferenceEngine::SizeVector &srcDims) const {
SizeVector order(srcDims.size());
std::iota(order.begin(), order.end(), 0);
SizeVector blkDims = srcDims;
if (srcDims.size() > 2) {
auto moveElementBack = [](SizeVector& vector, size_t indx) {
auto itr = vector.begin() + indx;
std::rotate(itr, itr + 1, vector.end());
};

moveElementBack(order, channelsPos);
moveElementBack(blkDims, channelsPos);
}

return TensorDesc(precision, srcDims, {blkDims, order});
}

InferenceEngine::TensorDesc ChannelBlockedCreator::createDesc(const InferenceEngine::Precision &precision, const InferenceEngine::SizeVector &srcDims) const {
if (srcDims.size() < 2) {
THROW_IE_EXCEPTION << "Can't create blocked tensor descriptor!";
}

SizeVector order(srcDims.size());
std::iota(order.begin(), order.end(), 0);
order.push_back(channelsPos);

SizeVector blkDims = srcDims;
blkDims[channelsPos] = blkDims[channelsPos] / _blockSize + (blkDims[channelsPos] % _blockSize ? 1 : 0);
blkDims.push_back(_blockSize);

return TensorDesc(precision, srcDims, {blkDims, order});
}

std::map<TensorDescCreatorTypes, TensorDescCreator::CreatorConstPtr> TensorDescCreator::getCommonCreators() {
return { { TensorDescCreatorTypes::plain, CreatorConstPtr(new PlainFormatCreator) },
{ TensorDescCreatorTypes::perChannel, CreatorConstPtr(new PerChannelCreator) },
{ TensorDescCreatorTypes::channelBlocked8, CreatorConstPtr(new ChannelBlockedCreator(8)) },
{ TensorDescCreatorTypes::channelBlocked16, CreatorConstPtr(new ChannelBlockedCreator(16)) } };
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright (C) 2020 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
//

#pragma once

#include <ie_layouts.h>

namespace MKLDNNPlugin {

enum class TensorDescCreatorTypes {
plain,
perChannel,
channelBlocked8,
channelBlocked16
};

class TensorDescCreator {
public:
typedef std::shared_ptr<TensorDescCreator> CreatorPtr;
typedef std::shared_ptr<const TensorDescCreator> CreatorConstPtr;

public:
static std::map<TensorDescCreatorTypes, CreatorConstPtr> getCommonCreators();
virtual InferenceEngine::TensorDesc createDesc(const InferenceEngine::Precision& precision, const InferenceEngine::SizeVector& srcDims) const = 0;
virtual ~TensorDescCreator() {}
};

class PlainFormatCreator : public TensorDescCreator {
public:
virtual InferenceEngine::TensorDesc createDesc(const InferenceEngine::Precision& precision, const InferenceEngine::SizeVector& srcDims) const;
};

class PerChannelCreator : public TensorDescCreator {
public:
virtual InferenceEngine::TensorDesc createDesc(const InferenceEngine::Precision& precision, const InferenceEngine::SizeVector& srcDims) const;
};

class ChannelBlockedCreator : public TensorDescCreator {
public:
ChannelBlockedCreator(size_t blockSize) : _blockSize(blockSize) {}
virtual InferenceEngine::TensorDesc createDesc(const InferenceEngine::Precision& precision, const InferenceEngine::SizeVector& srcDims) const;

private:
size_t _blockSize;
};
} // namespace MKLDNNPlugin
74 changes: 45 additions & 29 deletions inference-engine/src/mkldnn_plugin/nodes/mkldnn_convert_node.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
//

#include <mkldnn_extension_utils.h>
#include "mkldnn_convert_node.h"
#include "common/cpu_convert.h"
#include "common/tensor_desc_creator.h"

#define THROW_ERROR THROW_IE_EXCEPTION << getTypeStr() << " layer with name '" << getName() <<"' ERROR: "

using namespace mkldnn;
using namespace MKLDNNPlugin;
Expand All @@ -13,14 +17,14 @@ MKLDNNConvertNode::MKLDNNConvertNode(const InferenceEngine::CNNLayerPtr& layer,
MKLDNNNode(layer, eng, cache) {}

void MKLDNNConvertNode::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 (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 (getParentEdges().size() != 1)
THROW_IE_EXCEPTION << "Incorrect number of input edges for layer " << getName();
THROW_ERROR << "Incorrect number of input edges";
if (getChildEdges().empty())
THROW_IE_EXCEPTION << "Incorrect number of output edges for layer " << getName();
THROW_ERROR << "Incorrect number of output edges";
}

void MKLDNNConvertNode::initSupportedPrimitiveDescriptors() {
Expand All @@ -29,60 +33,72 @@ void MKLDNNConvertNode::initSupportedPrimitiveDescriptors() {

auto layer = getCnnLayer();
if (layer == nullptr) {
THROW_IE_EXCEPTION << "Cannot get CNN layer for layer name " << getName();
THROW_ERROR << "Cannot get CNN layer";
}

LayerConfig config;
DataConfig dataIn;
DataConfig dataConfigOut;

memory::format fmt;
config.dynBatchSupport = false;

if (input.getLayout() != InferenceEngine::Layout::ANY && output.getLayout() != InferenceEngine::Layout::ANY) {
dataIn.desc = input;
if (input && input->getLayout() != InferenceEngine::Layout::ANY && output && output->getLayout() != InferenceEngine::Layout::ANY) {
dataIn.desc = *input;
config.inConfs.push_back(dataIn);

const auto layout = config.inConfs[0].desc.getLayout(); // inp/out layouts must be the same
dataConfigOut.desc = TensorDesc(output.getPrecision(), input.getDims(), layout);
const auto& BlockingDesc = config.inConfs[0].desc.getBlockingDesc(); // inp/out layouts must be the same
dataConfigOut.desc = TensorDesc(output->getPrecision(), input->getDims(), BlockingDesc);
config.outConfs.push_back(dataConfigOut);
fmt = MKLDNNMemory::Convert(layout);
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown, MKLDNNMemoryDesc(config.outConfs.front().desc).getFormat());
} else if (layer->insData.size() == 1 && layer->outData.size() == 1) {
const SizeVector& ins_dims = layer->insData[0].lock()->getTensorDesc().getDims();
const auto layout = layer->insData[0].lock()->getTensorDesc().getLayout(); // inp/out layouts must be the same
dataIn.desc = TensorDesc(layer->insData[0].lock()->getTensorDesc().getPrecision(), ins_dims, layout);
config.inConfs.push_back(dataIn);
auto insData = layer->insData[0].lock();
if (nullptr == insData) {
THROW_ERROR << "Input data is empty";
}

const SizeVector& ins_dims = insData->getTensorDesc().getDims();
auto insPrecision = insData->getTensorDesc().getPrecision();
const SizeVector& out_dims = layer->outData[0]->getTensorDesc().getDims();
dataConfigOut.desc = TensorDesc(layer->outData[0]->getTensorDesc().getPrecision(), out_dims, layout);
auto outPrecision = layer->outData[0]->getTensorDesc().getPrecision();

config.inConfs.push_back(dataIn);
config.outConfs.push_back(dataConfigOut);
fmt = MKLDNNMemory::Convert(layout);

for (auto item : TensorDescCreator::getCommonCreators()) {
config.inConfs[0].desc = item.second->createDesc(insPrecision, ins_dims);
config.outConfs[0].desc = item.second->createDesc(outPrecision, out_dims);

supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown, MKLDNNMemoryDesc(config.outConfs.front().desc).getFormat());
}
} else {
THROW_IE_EXCEPTION << "Convert layer with name '" << getName() << "' has incorrect number of input/output edges";
THROW_ERROR << "Incorrect number of input/output edges";
}

config.dynBatchSupport = false;
supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown, fmt);
}

void MKLDNNConvertNode::createPrimitive() {
auto& dstMemPtr = getChildEdgeAt(0)->getMemoryPtr();
auto& srcMemPtr = getParentEdgeAt(0)->getMemoryPtr();
if (!dstMemPtr || !dstMemPtr->GetPrimitivePtr())
THROW_IE_EXCEPTION << "Destination memory didn't allocate.";
THROW_ERROR << "Destination memory didn't allocate.";
if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr())
THROW_IE_EXCEPTION << "Input memory didn't allocate.";
THROW_ERROR << "Input memory didn't allocate.";
if (getSelectedPrimitiveDescriptor() == nullptr)
THROW_IE_EXCEPTION << "Preferable primitive descriptor is not set.";
THROW_ERROR << "Preferable primitive descriptor is not set.";
}

static inline uint8_t* getDataPtr(const MKLDNNMemory& memoryPtr) {
return reinterpret_cast<uint8_t*>(memoryPtr.GetData()) + memoryPtr.GetDescriptor().data.layout_desc.blocking.offset_padding *
MKLDNNExtensionUtils::sizeOfDataType(mkldnn::memory::data_type(memoryPtr.GetDescriptor().data.data_type));
}

void MKLDNNConvertNode::execute(mkldnn::stream strm) {
auto& parentMem = getParentEdgeAt(0)->getMemory();
auto& childMem = getChildEdgeAt(0)->getMemory();
if (parentMem.GetElementsCount() != childMem.GetElementsCount())
THROW_IE_EXCEPTION << "Convert layer with name '" << getName() << "' has input and output buffers with different elements count";
THROW_ERROR << "Input and output buffers have different elements count";

void *srcPtr = getParentEdgeAt(0)->getMemory().GetData();
void *dstPtr = getChildEdgeAt(0)->getMemory().GetData();
void* srcPtr = getDataPtr(parentMem);
void* dstPtr = getDataPtr(childMem);
cpu_convert(srcPtr, dstPtr, getParentEdgeAt(0)->getDesc().getPrecision(), getChildEdgeAt(0)->getDesc().getPrecision(), parentMem.GetElementsCount());
}

Expand Down
12 changes: 6 additions & 6 deletions inference-engine/src/mkldnn_plugin/nodes/mkldnn_convert_node.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ class MKLDNNConvertNode : public MKLDNNNode {
}

void setDescs(const InferenceEngine::TensorDesc& input, const InferenceEngine::TensorDesc& output) {
this->input = input;
this->output = output;
this->input.reset(new InferenceEngine::TensorDesc(input));
this->output.reset(new InferenceEngine::TensorDesc(output));
}

const InferenceEngine::TensorDesc& getInput() { return input; }
const InferenceEngine::TensorDesc& getOutput() { return output; }
std::shared_ptr<const InferenceEngine::TensorDesc> getInput() const { return input; }
std::shared_ptr<const InferenceEngine::TensorDesc> getOutput() const { return output; }
private:
InferenceEngine::TensorDesc input;
InferenceEngine::TensorDesc output;
std::shared_ptr<InferenceEngine::TensorDesc> input;
std::shared_ptr<InferenceEngine::TensorDesc> output;
};
} // namespace MKLDNNPlugin

0 comments on commit e1639f3

Please sign in to comment.