1 // Copyright (C) 2018 Intel Corporation
3 // SPDX-License-Identifier: Apache-2.0
6 #include "mkldnn_tile_node.h"
9 #include <mkldnn_types.h>
10 #include <mkldnn_extension_utils.h>
12 using namespace mkldnn;
13 using namespace MKLDNNPlugin;
14 using namespace InferenceEngine;
16 MKLDNNTileNode::MKLDNNTileNode(const InferenceEngine::CNNLayerPtr& layer, const mkldnn::engine& eng) : MKLDNNNode(layer, eng) {}
18 void MKLDNNTileNode::getSupportedDescriptors() {
19 auto * tileLayer = dynamic_cast<TileLayer*>(getCnnLayer().get());
21 if (tileLayer == nullptr)
22 THROW_IE_EXCEPTION << "Cannot convert tile layer.";
24 if (getParentEdges().size() != 1)
25 THROW_IE_EXCEPTION << "Incorrect number of input edges.";
26 if (!getChildEdges().size())
27 THROW_IE_EXCEPTION << "Incorrect number of output edges.";
29 axis = tileLayer->axis;
30 tiles = tileLayer->tiles;
33 void MKLDNNTileNode::initSupportedPrimitiveDescriptors() {
34 if (!supportedPrimitiveDescriptors.empty())
37 InferenceEngine::Precision precision = getCnnLayer()->insData[0].lock()->getPrecision();
38 if (precision != InferenceEngine::Precision::FP32)
39 precision = InferenceEngine::Precision::FP32;
40 auto inputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(precision);
41 precision = getCnnLayer()->outData[0]->getPrecision();
42 if (precision != InferenceEngine::Precision::FP32)
43 precision = InferenceEngine::Precision::FP32;
44 auto outputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(precision);
46 auto& inDims = getParentEdgeAt(0)->getDims();
47 memory::format fmt = memory::format::any;
48 if (inDims.ndims() == 2) {
49 fmt = memory::format::nc;
50 } else if (inDims.ndims() == 4) {
51 fmt = memory::format::nchw;
53 if (fmt == memory::format::any) {
54 THROW_IE_EXCEPTION << "Tile " << getName() << " supports only 2d and 4d dimensions!";
57 InferenceEngine::LayerConfig config;
58 config.dynBatchSupport = true;
59 config.inConfs.resize(1);
60 config.outConfs.resize(1);
61 config.inConfs[0].inPlace = -1;
62 config.inConfs[0].constant = false;
63 config.inConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, fmt);
64 config.outConfs[0].inPlace = -1;
65 config.outConfs[0].constant = false;
66 config.outConfs[0].desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, fmt);
67 supportedPrimitiveDescriptors.push_back({config, impl_desc_type::unknown});
70 void MKLDNNTileNode::createPrimitive() {
71 auto& dstMemPtr = getChildEdgeAt(0)->getMemoryPtr();
72 auto& srcMemPtr = getParentEdgeAt(0)->getMemoryPtr();
73 if (!dstMemPtr || !dstMemPtr->GetPrimitivePtr())
74 THROW_IE_EXCEPTION << "Destination memory didn't allocate.";
75 if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr())
76 THROW_IE_EXCEPTION << "Input memory didn't allocate.";
77 if (getSelectedPrimitiveDescriptor() == nullptr)
78 THROW_IE_EXCEPTION << "Preferable primitive descriptor does not set.";
79 if (getParentEdges().size() != 1)
80 THROW_IE_EXCEPTION << "Incorrect number of input edges.";
83 void MKLDNNTileNode::execute(mkldnn::stream strm) {
84 auto& srcMemory = getParentEdgeAt(0)->getMemory();
86 const float *src_ptr = reinterpret_cast<const float*>(srcMemory.GetData()) +
87 srcMemory.GetDescriptor().data.layout_desc.blocking.offset_padding;
88 float *dst_ptr = reinterpret_cast<float*>(getChildEdgeAt(0)->getMemory().GetData()) +
89 getChildEdgeAt(0)->getMemory().GetDescriptor().data.layout_desc.blocking.offset_padding;
93 memory::dims inDims = srcMemory.GetDims();
94 for (int i=0; i < axis; i++ ) m_outer_dim *= inDims[i];
95 for (int i=axis; i < inDims.size(); i++ ) m_inner_dim *= inDims[i];
97 m_outer_dim /= inDims[0];
98 m_outer_dim *= batchToProcess();
100 m_inner_dim /= inDims[0];
101 m_inner_dim *= batchToProcess();
104 if (m_inner_dim == 1 && inDims.size() == 4 && m_outer_dim%8 == 0 && srcMemory.GetFormat() == memory::nChw8c) {
106 * We may enable tile processing directly to appropriate output format (nChw8c)
110 } else if (m_inner_dim == 1 && inDims.size() == 4 && m_outer_dim%16 == 0
111 && srcMemory.GetFormat() == memory::nChw16c) {
113 * We may enable tile processing directly to appropriate output format (nChw16c)
119 for (int i = 0; i < m_outer_dim; ++i) {
120 for (int t = 0; t < tiles; ++t) {
121 memcpy(dst_ptr, src_ptr, m_inner_dim* sizeof(float));
122 dst_ptr += m_inner_dim;
124 src_ptr += m_inner_dim;
128 bool MKLDNNTileNode::created() const {
129 return getType() == Tile;