1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
5 #include "mkldnn_depthwise_node.h"
6 #include "desc_iterator.hpp"
10 #include <mkldnn_types.h>
11 #include <mkldnn_extension_utils.h>
12 #include "details/caseless.hpp"
14 using namespace mkldnn;
15 using namespace MKLDNNPlugin;
16 using namespace InferenceEngine;
17 using namespace InferenceEngine::details;
19 MKLDNNDepthwiseNode::MKLDNNDepthwiseNode(InferenceEngine::CNNLayerPtr layer, const mkldnn::engine& eng) : MKLDNNNode(layer, eng) {
20 internalBlobDesc.emplace_back([&](primitive_desc_iterator &primitive_desc_it, size_t idx) -> MKLDNNMemoryDesc {
21 return MKLDNNMemoryDesc(primitive_desc_it.weights_primitive_desc(0).desc());
23 internalBlobDesc.emplace_back([&](primitive_desc_iterator &primitive_desc_it, size_t idx) -> MKLDNNMemoryDesc {
25 return MKLDNNMemoryDesc();
26 return MKLDNNMemoryDesc(primitive_desc_it.weights_primitive_desc(1).desc());
30 void MKLDNNDepthwiseNode::getSupportedDescriptors() {
31 InferenceEngine::Precision precision = getCnnLayer()->insData[0].lock()->getPrecision();
32 if (precision != InferenceEngine::Precision::FP32)
33 precision = InferenceEngine::Precision::FP32;
34 auto inputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(precision);
36 auto parentOutDims = getParentEdgeAt(0)->getDims();
38 if (getParentEdges().size() != 1)
39 THROW_IE_EXCEPTION << "Cannot create layer " << getName() << ": Incorrect number of inputs!";
40 if (parentOutDims != getChildEdgeAt(0)->getDims())
41 THROW_IE_EXCEPTION << "Cannot create layer " << getName() << ": Incorrect dimensions!";
43 SizeVector weightDims = { (long unsigned int)parentOutDims[1] };
44 MKLDNNDims blocked_weightDims(weightDims);
46 auto * wLayer = dynamic_cast<InferenceEngine::WeightableLayer*>(getCnnLayer().get());
47 if (wLayer == nullptr)
48 THROW_IE_EXCEPTION << "Cannot get weightable layer for node " << getName() << ".";
50 InferenceEngine::Blob::Ptr blb = wLayer->_weights;
52 realWeightSize = blb->size();
53 internalBlobs.push_back(createInternalBlob(weightDims, true));
55 InferenceEngine::Blob::Ptr blb = wLayer->_biases;
57 realBiasSize = blb->size();
58 internalBlobs.push_back(createInternalBlob(weightDims, false));
61 for (auto format : getAvailableFormatsForDims(parentOutDims)) {
62 MKLDNNMemoryDesc in_candidate{parentOutDims, inputDataType, format};
63 createDescriptor({in_candidate}, {});
67 void MKLDNNDepthwiseNode::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.";
80 auto prim_desc = createPrimitiveDescriptor<depthwise_forward::primitive_desc, depthwise_forward::desc>();
83 float broadcastValue = static_cast<float*>(internalBlobMemory[0]->GetData())[0];
84 size_t blbSize = internalBlobMemory[0]->GetPrimitiveDescriptor().desc().data.dims[0];
85 for (int i = 1; i < blbSize && realWeightSize != blbSize; i++) {
86 static_cast<float*>(internalBlobMemory[0]->GetData())[i] = broadcastValue;
90 blbSize = internalBlobMemory[1]->GetPrimitiveDescriptor().desc().data.dims[0];
91 broadcastValue = static_cast<float*>(internalBlobMemory[1]->GetData())[0];
92 for (int i = 1; i < blbSize && realBiasSize != blbSize; i++) {
93 static_cast<float*>(internalBlobMemory[1]->GetData())[i] = broadcastValue;
97 size_t blbSize = internalBlobMemory[0]->GetPrimitiveDescriptor().desc().data.dims[0];
98 if (realWeightSize != blbSize)
99 THROW_IE_EXCEPTION << "Cannot create layer " << getName() << ": Incorrect weights!";
100 if (isWithBiases()) {
101 blbSize = internalBlobMemory[1]->GetPrimitiveDescriptor().desc().data.dims[0];
102 if (realBiasSize != blbSize)
103 THROW_IE_EXCEPTION << "Cannot create layer " << getName() << ": Incorrect biases!";
107 if (isWithBiases()) {
108 prim.reset(new depthwise_forward(prim_desc, getParentEdgeAt(0)->getMemory().GetPrimitive(),
109 internalBlobMemory[0]->GetPrimitive(),
110 internalBlobMemory[1]->GetPrimitive(),
111 getChildEdgeAt(0)->getMemory().GetPrimitive()));
113 prim.reset(new depthwise_forward(prim_desc, getParentEdgeAt(0)->getMemory().GetPrimitive(),
114 internalBlobMemory[0]->GetPrimitive(),
115 getChildEdgeAt(0)->getMemory().GetPrimitive()));
119 bool MKLDNNDepthwiseNode::created() const {
120 return getType() == Depthwise;
123 void MKLDNNDepthwiseNode::initValues() {
124 GenericLayer* depthwiseLayer = getCnnLayer().get();
125 if (depthwiseLayer == nullptr)
126 THROW_IE_EXCEPTION << "Cannot get CNNLayer.";
128 CaselessEq<std::string> comparator;
129 if (comparator(depthwiseLayer->type, "ScaleShift")) {
130 auto *scshLayer = dynamic_cast<ScaleShiftLayer*>(getCnnLayer().get());
131 if (scshLayer->_weights == nullptr)
132 THROW_IE_EXCEPTION << "ScaleShift without weights is not supported";
134 algorithm = depthwise_scale_shift;
135 withBiases = scshLayer->_biases != nullptr;
136 broadcast = static_cast<bool>(scshLayer->_broadcast);
137 } else if (comparator(depthwiseLayer->type, "PReLU")) {
138 auto *preluLayer = dynamic_cast<PReLULayer*>(getCnnLayer().get());
139 if (preluLayer->_weights == nullptr)
140 THROW_IE_EXCEPTION << "PReLU without weights is not supported";
142 algorithm = depthwise_prelu;
144 broadcast = preluLayer->_channel_shared;
146 THROW_IE_EXCEPTION << "Unsupported depthwise operation";
152 void MKLDNNDepthwiseNode::createDescriptor(const std::vector<InferenceEngine::TensorDesc> &inputDesc,
153 const std::vector<InferenceEngine::TensorDesc> &outputDesc) {
154 MKLDNNMemoryDesc in_candidate(inputDesc[0]);
155 MKLDNNMemoryDesc out_candidate(inputDesc[0]);
156 MKLDNNDims weightDims({in_candidate.getDims()[1]});
158 MKLDNNMemoryDesc wgh_candidate{weightDims, in_candidate.getDataType(), memory::x};
160 if (isWithBiases()) {
161 MKLDNNMemoryDesc bias_candidate{weightDims, in_candidate.getDataType(), memory::x};
162 MKLDNNDescriptor desc(std::shared_ptr<depthwise_forward::desc>(
163 new depthwise_forward::desc(prop_kind::forward_scoring, getAlgorithm(), in_candidate, out_candidate, wgh_candidate, bias_candidate)));
164 descs.push_back(desc);
166 MKLDNNDescriptor desc(std::shared_ptr<depthwise_forward::desc>(
167 new depthwise_forward::desc(prop_kind::forward_scoring, getAlgorithm(), in_candidate, out_candidate, wgh_candidate)));
168 descs.push_back(desc);
172 void MKLDNNDepthwiseNode::initOptimalPrimitiveDescriptor() {
173 auto config = getSelectedPrimitiveDescriptor()->getConfig();
174 if (isInitConfig(config))
177 if (config.inConfs.size() != 1 || config.outConfs.size() != 1 || (!isUninitTensorDesc(config.inConfs[0].desc) &&
178 !isUninitTensorDesc(config.outConfs[0].desc) && config.inConfs[0].desc != config.outConfs[0].desc))
179 THROW_IE_EXCEPTION << "Layer " << getName() << " has incorrect selected config!";
181 if (!isUninitTensorDesc(config.inConfs[0].desc)) {
182 config.outConfs[0].desc = config.inConfs[0].desc;
183 } else if (!isUninitTensorDesc(config.outConfs[0].desc)) {
184 config.inConfs[0].desc = config.outConfs[0].desc;
186 config.outConfs[0].desc = config.inConfs[0].desc = getConfiguredInputDesc(config, 0);
189 initDescriptor(config);