Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / src / gna_plugin / gna_layer_info.hpp
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 #pragma once
6
7 #include <string>
8 #include <memory>
9 #include "inference_engine.hpp"
10 #include "details/caseless.hpp"
11 #include "ie_algorithm.hpp"
12
13
14 namespace GNAPluginNS {
15
16 /**
17  * @brief detecting of const pointer for dynamic cast operations
18  * @tparam T
19  */
20 template <class T>
21 struct is_const_pointer : public std::false_type{
22 };
23
24 template <class T>
25 struct is_const_pointer<const T *> : public std::true_type{
26 };
27
28
29 /**
30  * similar to type traits determined in standard library this trait provides details per layer type, with some attributes specific for GNA
31  * we don't need to have compile time performance for this yet
32  */
33 class LayerInfo {
34     InferenceEngine::CNNLayer * layer;
35
36 #define IS_VALID() if (nullptr == layer) return false
37
38  public:
39     explicit LayerInfo(InferenceEngine::CNNLayer & layer)
40         : LayerInfo(&layer) {
41     }
42     explicit LayerInfo(const InferenceEngine::CNNLayerPtr & layer)
43         : LayerInfo(layer.get()) {
44     }
45     explicit LayerInfo(InferenceEngine::CNNLayer * layer)
46         : layer(layer) {
47     }
48     bool has16BOutput() const noexcept {
49         IS_VALID();
50         static InferenceEngine::details::caseless_set<std::string> layersWith16BOutputs = {"memory", "input", "split", "slice", "concat", "copy"};
51         return layersWith16BOutputs.find(layer->type) != layersWith16BOutputs.end() ||
52                                                                         isActivation() ||
53                                                             (isCrop() && !isCropAffined());
54     }
55     bool has32BOutput() const noexcept {
56         IS_VALID();
57         static  InferenceEngine::details::caseless_set<std::string> layersWith32BOutputs =
58                 {"FullyConnected", "InnerProduct", "AffineFilter", "Eltwise", "ScaleShift", "Convolution", "Pooling"};
59         return (layersWith32BOutputs.find(layer->type) != layersWith32BOutputs.end()) ||
60                                                             (isCrop() && isCropAffined());
61     }
62     static bool isBatchSizeConstrained(const std::string name) {
63         static InferenceEngine::details::caseless_set<std::string> layersWithConstrains = {"memory", "convolution"};
64         return layersWithConstrains.find(name) != layersWithConstrains.end();
65     }
66     bool isActivation() const noexcept {
67         IS_VALID();
68         static InferenceEngine::details::caseless_set<std::string> activations = {"clamp", "sigmoid", "identity", "relu", "leakyrelu", "tanh", "prelu"};
69         return activations.find(layer->type) != activations.end();
70     }
71     bool isRelu() const noexcept {
72         IS_VALID();
73         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "relu");
74     }
75     bool isConvolution() const noexcept {
76         IS_VALID();
77         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "convolution");
78     }
79     bool isPower() const noexcept {
80         IS_VALID();
81         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "power");
82     }
83     bool has32BInput() const noexcept {
84         IS_VALID();
85         return isActivation() || isPooling();
86     }
87     bool isInput() const noexcept {
88         IS_VALID();
89         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "input");
90     }
91     bool isScaleShift() const noexcept {
92         IS_VALID();
93         return nullptr != as<const InferenceEngine::ScaleShiftLayer*>();
94     }
95
96     bool isEltwise() const noexcept {
97         IS_VALID();
98         return nullptr != as<const InferenceEngine::EltwiseLayer*>();
99     }
100     bool isEltwiseSum() const noexcept {
101         IS_VALID();
102         if (!isEltwise()) return false;
103         return dynamic_cast<const InferenceEngine::EltwiseLayer*>(layer)->_operation ==
104             InferenceEngine::EltwiseLayer::Sum;
105     }
106     bool isEltwiseMul() const noexcept {
107         IS_VALID();
108         if (!isEltwise()) return false;
109         return dynamic_cast<const InferenceEngine::EltwiseLayer*>(layer)->_operation ==
110             InferenceEngine::EltwiseLayer::Prod;
111     }
112     bool isIdentity() const noexcept {
113         IS_VALID();
114         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "identity");
115     }
116     bool isFullyConnected() const noexcept {
117         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "FullyConnected") ||
118                 InferenceEngine::details::CaselessEq<std::string>()(layer->type, "InnerProduct");
119     }
120     bool isSplit() const noexcept {
121         IS_VALID();
122         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "split");
123     }
124     bool isSlice() const noexcept {
125         IS_VALID();
126         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "slice");
127     }
128     bool isConcat() const noexcept {
129         IS_VALID();
130         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "concat");
131     }
132     bool isReshape() const noexcept {
133         IS_VALID();
134         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "reshape");
135     }
136     bool isPermute() const noexcept {
137         IS_VALID();
138         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "permute");
139     }
140     bool isPooling() const noexcept {
141         IS_VALID();
142         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "Pooling");
143     }
144     bool isMaxPooling() const noexcept {
145         IS_VALID();
146         if (!isPooling()) return false;
147         return as<const InferenceEngine::PoolingLayer*>()->_type == InferenceEngine::PoolingLayer::MAX;
148     }
149     bool isMemory() const noexcept {
150         IS_VALID();
151         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "memory");
152     }
153     bool isCrop() const noexcept {
154         IS_VALID();
155         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "crop");
156     }
157     bool isCropAffined() const noexcept {
158         auto cropLayer = dynamic_cast<InferenceEngine::CropLayer *> (layer);
159         size_t cropOffset = cropLayer->offset.back() * cropLayer->precision.size();
160         return (ALIGN64(cropOffset) != cropOffset);
161     }
162     bool isCopy() const noexcept {
163         IS_VALID();
164         return InferenceEngine::details::CaselessEq<std::string>()(layer->type, "copy");
165     }
166     size_t paddingSize() const noexcept {
167         static InferenceEngine::details::caseless_set<std::string> layersWithPossiblePadding = {"FullyConnected",
168                                                                         "InnerProduct",
169                                                                              "Pooling",
170                                                                          "Convolution"};
171         if (layersWithPossiblePadding.find(layer->type) != layersWithPossiblePadding.end()) {
172             size_t size_without_padding = 0;
173             auto inputs = layer->insData.begin()->lock();
174             if (inputs) {
175                 size_without_padding = InferenceEngine::details::product(begin(inputs->dims),
176                                                                    end(inputs->dims));
177             }
178             return ALIGN(size_without_padding, 8) - size_without_padding;
179         }
180         return 0;
181     }
182     template <class T>
183     typename std::enable_if<!is_const_pointer<T>::value, T>::type as() noexcept {
184         return dynamic_cast<T>(layer);
185     }
186     template <class T>
187     typename std::enable_if<is_const_pointer<T>::value, T>::type as() const noexcept {
188         return dynamic_cast<T>(layer);
189     }
190     operator InferenceEngine::CNNLayer *() noexcept {
191         return layer;
192     }
193     operator const InferenceEngine::CNNLayer *() const noexcept {
194         return layer;
195     }
196     operator InferenceEngine::CNNLayerPtr () const noexcept {
197         return std::shared_ptr<InferenceEngine::CNNLayer>(layer, [] (InferenceEngine::CNNLayer * p) {});
198     }
199
200     #undef IS_VALID
201 };
202
203 inline std::ostream & operator <<(std::ostream &os, const LayerInfo & info) {
204     os << static_cast<const InferenceEngine::CNNLayer*>(info)->name;
205     return os;
206 }
207
208 }  // namespace GNAPluginNS