Publishing 2019 R1 content
[platform/upstream/dldt.git] / inference-engine / include / ie_layouts.h
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 /**
6  * @brief A header file for data layouts and conversion between them
7  * @file ie_layouts.h
8  */
9 #pragma once
10
11 #include <algorithm>
12
13 #include "ie_api.h"
14 #include "ie_common.h"
15 #include "ie_precision.hpp"
16
17 namespace InferenceEngine {
18
19 /**
20  * @brief This class describes blocking layouts
21  */
22 class INFERENCE_ENGINE_API_CLASS(BlockingDesc) {
23 public:
24     /**
25      * @brief The default constructor which creates empty blocking descriptor
26      */
27     BlockingDesc();
28     /**
29      * @brief The constructor which allows to create blocking descriptors for standard layouts
30      * @param dims real dimensions
31      * @param layout memory layout
32      */
33     BlockingDesc(const SizeVector& dims, Layout layout);
34     /**
35      * @brief The constructor allows to create blocking descriptors for blocked memory
36      * @param blocked_dims blocked dimensions
37      * @param order the order of dimensions
38      */
39     BlockingDesc(const SizeVector& blocked_dims, const SizeVector& order);
40     /**
41      * @brief The constructor allows to create blocking descriptors for blocked memory
42      * @param blocked_dims blocked dimensions
43      * @param order the order of dimensions
44      * @param offset offset to the current memory block
45      */
46     BlockingDesc(const SizeVector& blocked_dims, const SizeVector& order, size_t offset);
47     /**
48      * @brief The constructor allows to create blocking descriptors for blocked memory
49      * @param blocked_dims blocked dimensions
50      * @param order the order of dimensions
51      * @param offset offset to the current memory block
52      * @param dimOffsets per-dimension offset from the padding to actual data,
53      */
54     BlockingDesc(const SizeVector& blocked_dims, const SizeVector& order, size_t offset, SizeVector dimOffsets);
55     /**
56      * @brief The constructor allows to create blocking descriptors for blocked memory
57      * @param blocked_dims blocked dimensions
58      * @param order the order of dimensions
59      * @param offset offset to the current memory block
60      * @param dimOffsets per-dimension offset from the padding to actual data,
61      * @param strides strides for each dimension
62      */
63     BlockingDesc(const SizeVector& blocked_dims, const SizeVector& order, size_t offset, SizeVector dimOffsets, SizeVector strides);
64     /**
65      * @brief Destructor
66      */
67     virtual ~BlockingDesc() = default;
68
69     /**
70      * @brief Returns the blocked dimensions vector
71      * @return blocked dimensions
72      */
73     const SizeVector& getBlockDims() const {
74         return blockedDims;
75     }
76
77     /**
78      * @brief Returns the vector of order
79      * @return order
80      */
81     const SizeVector& getOrder() const {
82         return order;
83     }
84
85     /**
86      * @brief Returns the per-dimension offset vector
87      * @return offsets
88      */
89     const SizeVector& getOffsetPaddingToData() const {
90         return offsetPaddingToData;
91     }
92
93     /**
94      * @brief Returns the offset to the current memory block
95      * @return offset
96      */
97     size_t getOffsetPadding() const {
98         return offsetPadding;
99     }
100
101     /**
102      * @brief Returns strides for each dimension
103      * @return strides
104      */
105     const SizeVector& getStrides() const {
106         return strides;
107     }
108
109     /**
110      * @brief The comparison operator for the BlockingDesc
111      * @param rhs object to compare
112      * @return true if objects are equal
113      */
114     bool operator == (const BlockingDesc& rhs) const;
115     /**
116      * @brief The comparison operator for the BlockingDesc
117      * @param rhs object to compare
118      * @return true if objects aren't equal
119      */
120     bool operator != (const BlockingDesc& rhs) const;
121
122 protected:
123     void fillDesc(const SizeVector& blocked_dims, const SizeVector& order);
124
125 private:
126     /** Blocked dimensions. */
127     SizeVector blockedDims;
128     /** Strides for blocked dimensions */
129     SizeVector strides;
130     /** The order of blocked dimensions **/
131     SizeVector order;
132     /** Per-dimension offset from the padding to actual data, the top-level
133      * tensor with offsets applied must lie within the padding area. */
134     SizeVector offsetPaddingToData;
135     /** Offset from memory origin to the current block, non-zero only in
136      * a description of a memory sub-block. */
137     size_t offsetPadding;
138 };
139
140 /**
141  * @brief This class defines Tensor description
142  */
143 class INFERENCE_ENGINE_API_CLASS(TensorDesc) {
144 public:
145     /**
146      * @brief The constructor creates the tensor descriptor using blocking descriptor
147      * @param precision memory precision
148      * @param dims memory dimensions
149      * @param blockDesc blocking descriptor
150      */
151     TensorDesc(const Precision& precision, SizeVector dims, const BlockingDesc& blockDesc);
152     /**
153      * @brief The constructor creates the tensor descriptor using standard layout
154      * @param precision memory precision
155      * @param dims memory dimensions
156      * @param layout memory layout
157      */
158     TensorDesc(const Precision& precision, SizeVector dims, Layout layout);
159     /**
160      * @brief The constructor creates the empty tensor descriptor with precision and layout
161      * @param precision memory precision
162      * @param layout memory layout
163      */
164     TensorDesc(const Precision& precision, Layout layout);
165     /**
166      * @brief The default constructor which creates empty tensor descriptor
167      */
168     TensorDesc();
169     /**
170      * @brief Destructor
171      */
172     virtual ~TensorDesc() = default;
173
174     /**
175      * @brief Reshapes the tensor descriptor
176      * @param dims new dimensions
177      * @param layout new layout if it is necessary
178      */
179     void reshape(const SizeVector &dims, Layout layout = Layout::ANY);
180     /**
181      * @brief Reshapes the tensor descriptor
182      * @param dims new dimensions
183      * @param blockDesc new blocking descriptor
184      */
185     void reshape(const SizeVector &dims, const BlockingDesc &blockDesc);
186
187     /**
188      * @brief Returns the vector of dimensions
189      * @return dimensions
190      */
191     SizeVector& getDims() {
192         return dims;
193     }
194     /**
195      * @brief Returns the constant vector of dimensions
196      * @return dimensions
197      */
198     const SizeVector& getDims() const {
199         return dims;
200     }
201     /**
202      * @brief Sets dimensions
203      * @param dims new dimensions
204      */
205     void setDims(const SizeVector& dims);
206
207     /**
208      * @brief Returns the memory layout
209      * @return layout
210      */
211     Layout getLayout() const {
212         return layout;
213     }
214
215     /**
216      * @brief Sets the layout
217      * @param l memory layout
218      */
219     void setLayout(Layout l) {
220         bool inconsistentLayout = true;
221         switch (l) {
222             case Layout::SCALAR:
223                 inconsistentLayout = !dims.empty();
224                 break;
225             case Layout::C:
226                 inconsistentLayout = dims.size() != 1;
227                 break;
228             case Layout::BLOCKED:
229                 inconsistentLayout = false;
230                 break;
231             case Layout::NCDHW:
232             case Layout::NDHWC:
233                 inconsistentLayout = dims.size() != 5;
234                 break;
235             case Layout::OIHW:
236             case Layout::NCHW:
237             case Layout::NHWC:
238                 inconsistentLayout = dims.size() != 4;
239                 break;
240             case Layout::CHW:
241                 inconsistentLayout = dims.size() != 3;
242                 break;
243             case Layout::CN:
244             case Layout::NC:
245             case Layout::HW:
246                 inconsistentLayout = dims.size() != 2;
247                 break;
248             default:
249                 break;
250         }
251         if (inconsistentLayout)
252             THROW_IE_EXCEPTION << "Size of dims(" << std::to_string(dims.size()) << ") and format(" << l << ") are inconsistent.";
253         layout = l;
254     }
255
256     /**
257      * @brief Returns the memory precision
258      * @return precision
259      */
260     const Precision& getPrecision() const {
261         return precision;
262     }
263
264     /**
265      * @brief Sets the memory precision
266      * @param p precision
267      */
268     void setPrecision(const Precision& p) {
269         precision = p;
270     }
271
272     /**
273      * @brief Returns the blocking descriptor
274      * @return blocking descriptor
275      */
276     const BlockingDesc& getBlockingDesc() const {
277         return blockingDesc;
278     }
279
280     /**
281      * @brief The comparison operator for the TensorDesc
282      * @param rhs object to compare
283      * @return true if objects are equal
284      */
285     bool operator == (const TensorDesc& rhs) const;
286     /**
287      * @brief The comparison operator for the TensorDesc
288      * @param rhs object to compare
289      * @return true if objects aren't equal
290      */
291     bool operator != (const TensorDesc& rhs) const;
292
293     /**
294      * @brief Calculates offset for the vector of dimensions
295      * @param v vector of dimensions
296      * @return offset
297      */
298     size_t offset(const SizeVector& v) const;
299     /**
300      * @brief Calculates offset for the local offset
301      * @param l local offset
302      * @return offset
303      */
304     size_t offset(size_t l) const;
305
306     /**
307      * @brief Returns the standard layout for dimensions
308      * @param dims the vector of dimensions
309      * @return the standard memory layout
310      */
311     static Layout getLayoutByDims(SizeVector dims);
312 private:
313     /**
314      * Memory layout
315      */
316     Layout layout;
317     /**
318      * @brief blob's dimensions
319      */
320     SizeVector dims;
321     /**
322      * @brief memory precision
323      */
324     Precision precision;
325     /**
326      * Detailed information about layout construction
327      */
328     BlockingDesc blockingDesc;
329 };
330
331 /**
332  * @deprecated
333  */
334 static const size_t I_N = 3;
335 static const size_t I_C = 2;
336 static const size_t I_H = 1;
337 static const size_t I_W = 0;
338
339 /**
340  * @deprecated Uses TensorDesc working with layouts
341  * @brief This class helps calculating offset in different layouts
342  */
343 class INFERENCE_ENGINE_API_CLASS(LayoutOffsetCounter) {
344 private:
345     Layout _layout;
346     SizeVector _dims;
347
348     size_t _dims_count;
349
350     /**
351      * @brief Stores multipliers that are calculated during the LayoutOffsetCounter construction.
352      * The multipliers are used for conversion.
353      */
354     SizeVector _muls;
355 public:
356     /**
357      * @brief A default constructor
358      * @param dims Tensor dimension array (reverse NCHW order as in the IR: w,h,c,n)
359      */
360     LayoutOffsetCounter(Layout layout, SizeVector dims);
361
362     /**
363      * @brief Calculates an offset for the specified layout
364      * @param pos Tensor position array (reverse NCHW order as in the IR: w,h,c,n)
365      */
366     size_t Offset(SizeVector pos);
367 };
368
369 /**
370  * @deprecated Please use TensorDescriptors for conversion
371  */
372 template<typename T> void ConvertLayout(Layout sourceLayout, Layout destLayout, const T* sourceBuffer, T* destBuffer, SizeVector dims) {
373     if (dims.size() == 0) return;
374
375     SizeVector pos(dims.size(), 0);
376     LayoutOffsetCounter srcOffsetCounter(sourceLayout, dims);
377     LayoutOffsetCounter destOffsetCounter(destLayout, dims);
378
379     while (true) {
380         // Setting the current item
381         size_t ps = srcOffsetCounter.Offset(pos);
382         size_t pd = destOffsetCounter.Offset(pos);
383
384         destBuffer[pd] = sourceBuffer[ps];
385
386         // Advancing pos
387         size_t caret = 0;
388         pos[caret]++;
389         while (pos[caret] >= dims[caret]) {
390             pos[caret] = 0;
391             caret++;
392             if (caret == pos.size()) {
393                 // We have finished converting
394                 return;
395             }
396             pos[caret]++;
397         }
398     }
399 }
400
401 }  // namespace InferenceEngine