Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / src / mkldnn_plugin / nodes / mkldnn_power_node.cpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #include "mkldnn_power_node.h"
6 #include "ie_layers.h"
7 #include <string>
8 #include <cmath>
9 #include <mkldnn_types.h>
10 #include <mkldnn_extension_utils.h>
11 #include <limits>
12 #include "ie_parallel.hpp"
13
14 using namespace mkldnn;
15 using namespace MKLDNNPlugin;
16 using namespace InferenceEngine;
17
18 MKLDNNPowerNode::MKLDNNPowerNode(const InferenceEngine::CNNLayerPtr& layer, const mkldnn::engine& eng)
19         : MKLDNNNode(layer, eng), scale(1.0f), shift(1.0f), power(1.0f) {}
20
21 void MKLDNNPowerNode::getSupportedDescriptors() {
22     auto * powerLayer = dynamic_cast<PowerLayer*>(getCnnLayer().get());
23
24     if (powerLayer == nullptr)
25         THROW_IE_EXCEPTION << "Cannot convert power layer.";
26     scale = powerLayer->scale;
27     power = powerLayer->power;
28     shift = powerLayer->offset;
29
30     if (getParentEdges().size() != 1)
31         THROW_IE_EXCEPTION << "Incorrect number of input edges for layer " << getName();
32     if (getChildEdges().empty())
33         THROW_IE_EXCEPTION << "Incorrect number of output edges for layer " << getName();
34 }
35
36 void MKLDNNPowerNode::initSupportedPrimitiveDescriptors() {
37     if (!supportedPrimitiveDescriptors.empty())
38         return;
39
40     InferenceEngine::Precision precision = getCnnLayer()->insData[0].lock()->getPrecision();
41     if (precision != InferenceEngine::Precision::FP32)
42         precision = InferenceEngine::Precision::FP32;
43     auto inputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(precision);
44     precision = getCnnLayer()->outData[0]->getPrecision();
45     if (precision != InferenceEngine::Precision::FP32)
46         precision = InferenceEngine::Precision::FP32;
47     auto outputDataType = MKLDNNExtensionUtils::IEPrecisionToDataType(precision);
48
49     InferenceEngine::LayerConfig config;
50     config.dynBatchSupport = true;
51     config.inConfs.resize(1);
52     config.outConfs.resize(1);
53     config.inConfs[0].inPlace = -1;
54     config.inConfs[0].constant = false;
55     config.outConfs[0].inPlace = -1;
56     config.outConfs[0].constant = false;
57     for (auto format : getAvailableFormatsForDims(getParentEdgeAt(0)->getDims())) {
58         config.inConfs[0].desc = MKLDNNMemoryDesc(getParentEdgeAt(0)->getDims(), inputDataType, format);
59         config.outConfs[0].desc = MKLDNNMemoryDesc(getChildEdgeAt(0)->getDims(), outputDataType, format);
60         if (format != memory::any) {
61             config.inConfs[0].desc = InferenceEngine::TensorDesc(config.inConfs[0].desc.getPrecision(),
62                                                                  config.inConfs[0].desc.getDims(), {
63                                                                          config.inConfs[0].desc.getBlockingDesc().getBlockDims(),
64                                                                          config.inConfs[0].desc.getBlockingDesc().getOrder(),
65                                                                          std::numeric_limits<size_t>::max()
66                                                                  });
67             config.outConfs[0].desc = InferenceEngine::TensorDesc(config.outConfs[0].desc.getPrecision(),
68                                                                   config.outConfs[0].desc.getDims(), {
69                                                                           config.outConfs[0].desc.getBlockingDesc().getBlockDims(),
70                                                                           config.outConfs[0].desc.getBlockingDesc().getOrder(),
71                                                                           std::numeric_limits<size_t>::max()
72                                                                   });
73         }
74         supportedPrimitiveDescriptors.emplace_back(config, impl_desc_type::unknown);
75     }
76 }
77
78 void MKLDNNPowerNode::createPrimitive() {
79     auto& dstMemPtr = getChildEdgeAt(0)->getMemoryPtr();
80     auto& srcMemPtr = getParentEdgeAt(0)->getMemoryPtr();
81     if (!dstMemPtr || !dstMemPtr->GetPrimitivePtr())
82         THROW_IE_EXCEPTION << "Destination memory didn't allocate.";
83     if (!srcMemPtr || !srcMemPtr->GetPrimitivePtr())
84         THROW_IE_EXCEPTION << "Input memory didn't allocate.";
85     if (getSelectedPrimitiveDescriptor() == nullptr)
86         THROW_IE_EXCEPTION << "Preferable primitive descriptor does not set.";
87 }
88
89 void MKLDNNPowerNode::execute(mkldnn::stream strm) {
90     auto& srcMemory = getParentEdgeAt(0)->getMemory();
91     auto& dstMemory = getChildEdgeAt(0)->getMemory();
92     const size_t data_size = srcMemory.GetSize() / sizeof(float) / srcMemory.GetDims()[0] * batchToProcess();
93
94     const auto *src_ptr = reinterpret_cast<const float*>(srcMemory.GetData()) +
95             srcMemory.GetDescriptor().data.layout_desc.blocking.offset_padding;
96     float *dst_ptr = reinterpret_cast<float*>(dstMemory.GetData()) +
97             dstMemory.GetDescriptor().data.layout_desc.blocking.offset_padding;
98
99     if (power == 1.0f) {
100         parallel_for(data_size, [&](size_t i) {
101             dst_ptr[i] = src_ptr[i] * scale + shift;
102         });
103     } else {
104         parallel_for(data_size, [&](size_t i) {
105             dst_ptr[i] = pow(src_ptr[i] * scale + shift, power);
106         });
107     }
108 }
109
110 bool MKLDNNPowerNode::created() const {
111     return getType() == Power;
112 }