Publishing 2020.1 content
[platform/upstream/dldt.git] / inference-engine / include / ie_blob.h
1 // Copyright (C) 2018-2020 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 /**
6  * @brief A header file for Blob and generic TBlob<>
7  *
8  * @file ie_blob.h
9  */
10 #pragma once
11
12 #include <cstring>
13 #include <functional>
14 #include <map>
15 #include <memory>
16 #include <numeric>
17 #include <string>
18 #include <type_traits>
19 #include <utility>
20 #include <vector>
21
22 #include "details/ie_blob_iterator.hpp"
23 #include "details/ie_exception.hpp"
24 #include "details/ie_pre_allocator.hpp"
25 #include "ie_allocator.hpp"
26 #include "ie_common.h"
27 #include "ie_layouts.h"
28 #include "ie_locked_memory.hpp"
29 #include "ie_precision.hpp"
30
31 namespace InferenceEngine {
32 /**
33  * @brief This class represents a universal container in the Inference Engine
34  *
35  * @note Each Blob implementation must be derived from this Blob class directly or indirectly
36  */
37 class INFERENCE_ENGINE_API_CLASS(Blob) {
38 public:
39     /**
40      * @brief A smart pointer containing Blob object
41      */
42     using Ptr = std::shared_ptr<Blob>;
43
44     /**
45      * @brief A smart pointer to the const Blob object
46      */
47     using CPtr = std::shared_ptr<const Blob>;
48
49     /**
50      * @brief Creates a TBlob<> object from a Data node
51      *
52      * @param Data reference to a smart pointer of the Data node
53      * @return Smart pointer to TBlob<> with the relevant C type to the precision of the data node
54      */
55     static Ptr CreateFromData(const DataPtr& data);
56
57     /**
58      * @brief Blob virtual destructor
59      */
60     virtual ~Blob();
61
62     /**
63      * @brief Checks if the Blob object can be cast to the type T*
64      *
65      * @tparam T Type to be checked. Must represent a class derived from the Blob
66      * @return true if this object can be dynamically cast to the type T*. Otherwise, false
67      */
68     template <typename T,
69               typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
70               typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
71     bool is() noexcept {
72         return dynamic_cast<T*>(this) != nullptr;
73     }
74
75     /**
76      * @brief Checks if the Blob object can be cast to the type const T*
77      *
78      * @tparam T Type to be checked. Must represent a class derived from the Blob
79      * @return true if this object can be dynamically cast to the type const T*. Otherwise, false
80      */
81     template <typename T,
82               typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
83               typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
84     bool is() const noexcept {
85         return dynamic_cast<const T*>(this) != nullptr;
86     }
87
88     /**
89      * @brief Casts this Blob object to the type T*.
90      *
91      * Use InferenceEngine::as() to operate with shared Blob objects instead of raw pointers
92      *
93      * @tparam T Type to cast to. Must represent a class derived from the Blob
94      * @return Raw pointer to the object of the type T or nullptr on error
95      */
96     template <typename T,
97               typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
98               typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
99     T* as() noexcept {
100         return dynamic_cast<T*>(this);
101     }
102
103     /**
104      * @brief Casts this Blob object to the type const T*.
105      *
106      * Use InferenceEngine::as() to operate with shared Blob objects instead of raw pointers
107      *
108      * @tparam T Type to cast to. Must represent a class derived from the Blob
109      * @return Raw pointer to the object of the type const T or nullptr on error
110      */
111     template <typename T,
112               typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
113               typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
114     const T* as() const noexcept {
115         return dynamic_cast<const T*>(this);
116     }
117
118     /**
119      * @brief Constructor. Creates an empty Blob object with the specified precision.
120      *
121      * @param tensorDesc Defines the layout and dims of the blob
122      */
123     explicit Blob(const TensorDesc& tensorDesc): tensorDesc(tensorDesc) {}
124
125     /**
126      * @brief Returns the tensor description
127      */
128     virtual const TensorDesc& getTensorDesc() const noexcept {
129         return tensorDesc;
130     }
131
132     /**
133      * @brief Returns the tensor description
134      */
135     virtual TensorDesc& getTensorDesc() noexcept {
136         return tensorDesc;
137     }
138
139     /**
140      * @brief By default, returns the total number of elements (a product of all the dims or 1 for scalar)
141      *
142      * Return value and its interpretation heavily depend on the blob type
143      */
144     virtual size_t size() const noexcept {
145         if (tensorDesc.getLayout() == Layout::SCALAR) return 1;
146         return product(tensorDesc.getDims());
147     }
148
149     /**
150      * @brief Returns the size of the current Blob in bytes.
151      */
152     virtual size_t byteSize() const noexcept {
153         return size() * element_size();
154     }
155
156     /**
157      * @deprecated Cast to MemoryBlob and use its API instead.
158      * Blob class can represent compound blob, which do not refer to the only solid memory.
159      *
160      * @brief Returns the number of bytes per element.
161      *
162      * The overall Blob capacity is size() * element_size(). Abstract method.
163      */
164     virtual size_t element_size() const noexcept = 0;
165
166     /**
167      * @brief Allocates memory to store the data.
168      *
169      * Abstract method.
170      */
171     virtual void allocate() noexcept = 0;
172
173     /**
174      * @brief Releases previously allocated data.
175      *
176      * Abstract method.
177      */
178     virtual bool deallocate() noexcept = 0;
179
180     /**
181      * @deprecated Cast to MemoryBlob and use new wlock/rwlock API instead.
182      * Blob class can represent compound blob, which do not refer to the only solid memory.
183      * @brief Gets access to the allocated memory.
184      *
185      * Abstract method.
186      *
187      * @return A LockedMemory object
188      */
189     virtual LockedMemory<void> buffer() noexcept = 0;
190
191     /**
192      * @deprecated Cast to MemoryBlob and use new MemoryBlob::rmap() function instead.
193      * Blob class can represent compound blob, which do not refer to the only solid memory.
194      * @brief Gets read-only access to the allocated memory.
195      *
196      * Abstract method.
197      *
198      * @return A LockedMemory object
199      */
200     virtual LockedMemory<const void> cbuffer() const noexcept = 0;
201
202 protected:
203     /**
204      * @brief The tensor descriptor of the given blob.
205      */
206     TensorDesc tensorDesc;
207
208     /**
209      * @deprecated Cast to MemoryBlob and use its API instead.
210      * @brief Multiplies the dimension vector values.
211      *
212      * @param dims Reference to a vector with dimension values of type size_t
213      * @return Result of multiplication
214      */
215     static size_t product(const SizeVector& dims) noexcept {
216         if (dims.empty()) return 0;
217         return std::accumulate(std::begin(dims), std::end(dims), (size_t)1, std::multiplies<size_t>());
218     }
219
220     /**
221      * @brief Gets an allocator for allocator-based blobs
222      *
223      * @return The allocator for allocator-based blobs or nullptr if there is none
224      */
225     virtual const std::shared_ptr<IAllocator>& getAllocator() const noexcept = 0;
226
227     /**
228      * @brief Gets a handle to allocated memory
229      *
230      * @return The handle to allocated memory for allocator-based blobs or nullptr if there is none
231      */
232     virtual void* getHandle() const noexcept = 0;
233
234     template <typename>
235     friend class TBlobProxy;
236 };
237
238 /**
239  * @brief Helper cast function to work with shared Blob objects
240  *
241  * @return shared_ptr to the type T. Returned shared_ptr shares ownership of the object with the
242  *         input Blob::Ptr
243  */
244 template <typename T,
245           typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
246           typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
247 std::shared_ptr<T> as(const Blob::Ptr& blob) noexcept {
248     return std::dynamic_pointer_cast<T>(blob);
249 }
250
251 /**
252  * @brief Helper cast function to work with shared Blob objects
253  *
254  * @return shared_ptr to the type const T. Returned shared_ptr shares ownership of the object with
255  *         the input Blob::Ptr
256  */
257 template <typename T,
258           typename std::enable_if<!std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
259           typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
260 std::shared_ptr<const T> as(const Blob::CPtr& blob) noexcept {
261     return std::dynamic_pointer_cast<const T>(blob);
262 }
263
264 /**
265  * @brief This class implements a container object that represents a tensor in memory (host and
266  * remote/accelerated)
267  *
268  * @note Any Blob implementation that represents a concept of a tensor in memory (for example,
269  * TBlob) must be a subclass of MemoryBlob instead of Blob
270  */
271 class INFERENCE_ENGINE_API_CLASS(MemoryBlob): public Blob {
272 public:
273     /**
274      * @brief A smart pointer to the MemoryBlob object
275      */
276     using Ptr = std::shared_ptr<MemoryBlob>;
277
278     /**
279      * @brief A smart pointer to the const MemoryBlob object
280      */
281     using CPtr = std::shared_ptr<const MemoryBlob>;
282
283     /**
284      * @brief MemoryBlob virtual destructor
285      */
286     virtual ~MemoryBlob();
287
288     /**
289      * @brief Constructor. Creates an empty MemoryBlob object with the specified precision.
290      *
291      * @param tensorDesc Defines the layout and dims of the blob
292      */
293     explicit MemoryBlob(const TensorDesc& tensorDesc): Blob(tensorDesc) {}
294
295     /**
296      * @brief Returns the tensor description
297      */
298     const TensorDesc& getTensorDesc() const noexcept override {
299         return tensorDesc;
300     }
301
302     /**
303      * @brief Returns the tensor description
304      */
305     TensorDesc& getTensorDesc() noexcept override {
306         return tensorDesc;
307     }
308
309     /**
310      * @brief Returns the total number of elements, which is a product of all the dimensions
311      */
312     size_t size() const noexcept override {
313         if (tensorDesc.getLayout() == Layout::SCALAR) return 1;
314         return product(tensorDesc.getDims());
315     }
316
317     /**
318      * @brief Returns the size of the current Blob in bytes
319      */
320     size_t byteSize() const noexcept override {
321         return size() * element_size();
322     }
323
324     /**
325      * @brief Returns the number of bytes per element.
326      *
327      * The overall MemoryBlob capacity is size() * element_size().
328      * Abstract method.
329      */
330     size_t element_size() const noexcept override = 0;
331
332     /**
333      * @brief Allocates memory to store the data.
334      *
335      * Abstract method.
336      */
337     void allocate() noexcept override = 0;
338
339     /**
340      * @brief Releases previously allocated data.
341      *
342      * Abstract method.
343      */
344     bool deallocate() noexcept override = 0;
345
346     /**
347      * @deprecated Use wmap() or rwmap() API instead.
348      * @brief Gets access to the allocated memory.
349      *
350      * Abstract method.
351      *
352      * @return A LockedMemory object
353      */
354     LockedMemory<void> buffer() noexcept override = 0;
355
356     /**
357      * @deprecated Use rmap() function instead.
358      * @brief Gets read-only access to the allocated memory.
359      *
360      * Abstract method.
361      *
362      * @return A LockedMemory object
363      */
364     LockedMemory<const void> cbuffer() const noexcept override = 0;
365
366     /**
367      * @brief Gets read/write access to the memory in virtual space of the process.
368      * The function returns object which retains mapped memory.
369      * The memory been addressed in the MemoryBlob in general case can be allocated on remote device.
370      * This function maps remote memory to the memory in the virtual process space and after destruction
371      * of the LockedMemory will upload changed content to the accelerator.
372      *
373      * To avoid extra copy of data, you can use rmap() and wmap() functions.
374      *
375      * In case of memory originally allocated on the host, this function returns LockedMemory which will
376      * transparently refer to original memory address. No extra copy will happen
377      *
378      * In general case, pointer received from that LockedMemory becomes invalid just after
379      * destruction of LockedMemory instance. Keep Locked memory alive while you need to address memory
380      * in the process on the host.
381      *
382      * Abstract method.
383      *
384      * @return A LockedMemory object
385      */
386     virtual LockedMemory<void> rwmap()noexcept = 0;
387
388     /**
389      * @brief Gets read only access to the memory in virtual space of the process.
390      * The function returns object which retains mapped memory.
391      *
392      * The memory been addressed in the MemoryBlob in general case can be allocated on remote device.
393      * This function copies remote memory to the memory in the virtual process space and after
394      * destruction of the LockedMemory it will not upload host memory back, bacause it is expected that
395      * content is not changed.
396      *
397      * To have an ability change content, you can use rwmap() and wmap() functions.
398      *
399      * In case of memory originally allocated on the host, this function returns LockedMemory which will
400      * transparently refer to original memory address. No extra copy will happen
401      *
402      * In general case, pointer received from that LockedMemory becomes invalid just after destruction
403      * of LockedMemory instance. Keep Locked memory alive while you need to address memory in the
404      * process on the host.
405      *
406      * Abstract method.
407      *
408      * @return A LockedMemory object
409      */
410     virtual LockedMemory<const void> rmap()const noexcept = 0;
411
412     /**
413      * @brief Gets "write only direction" access to the memory in virtual space of the process.
414      * The function returns object which retains memory to be uploaded on device.
415      *
416      * The memory been addressed in the MemoryBlob in general case can be allocated on remote device.
417      * This function does not copy of the content from the device to the memory in the virtual process
418      * space, the content of the memory just after calling of this functin is not specified. After
419      * destruction of the LockedMemory, content will be upload host memory.
420      * In the same time there is no abilities to restrict reading from the memory, you need to care of
421      * reading from memory got by wmap(), it might have sence in some cases like filling of content and
422      * before uploading to device
423      *
424      * To access data stored in the blob, you can use rwmap() and rmap() functions.
425      *
426      * In case of memory originally allocated on the host, this function returns LockedMemory which will
427      * transparently refer to original memory address. No extra copy will happen
428      *
429      * In general case, pointer received from that LockedMemory becomes invalid just after destruction
430      * of LockedMemory instance. Keep Locked memory alive while you need to address memory in the
431      * process on the host.
432      *
433      * Abstract method.
434      *
435      * @return A LockedMemory object
436      */
437     virtual LockedMemory<void> wmap()noexcept = 0;
438
439
440
441 protected:
442     /**
443      * @brief Gets the allocator for allocator-based blobs.
444      *
445      * @return The allocator for allocator-based blobs or if there is none then a nullptr.
446      */
447     const std::shared_ptr<IAllocator>& getAllocator() const noexcept override = 0;
448
449     /**
450      * @brief Gets the handle to allocated memory.
451      *
452      * @return The handle to allocated memory for allocator-based blobs or if there is none then a nullptr.
453      */
454     void* getHandle() const noexcept override = 0;
455
456     template <typename>
457     friend class TBlobProxy;
458 };
459
460 /**
461  * @brief This is a convenient type for working with a map containing pairs(string, pointer to a Blob instance).
462  */
463 using BlobMap = std::map<std::string, Blob::Ptr>;
464
465 /**
466  * @brief Represents real host memory allocated for a Tensor/Blob per C type.
467  */
468 template <typename T, typename = std::enable_if<std::is_pod<T>::value>>
469 class TBlob : public MemoryBlob {
470     template <typename, typename>
471     friend class TBlob;
472
473 public:
474     /**
475      * @brief Smart Pointer to this TBlob object.
476      */
477     using Ptr = std::shared_ptr<TBlob<T>>;
478
479     /**
480      * @brief Creates a TBlob object with the specified dimensions and layout but does not allocate the memory.
481      *
482      * Use the allocate() method to allocate memory.
483      *
484      * @param tensorDesc Tensor description
485      */
486     explicit TBlob(const TensorDesc& tensorDesc): MemoryBlob(tensorDesc) {}
487
488     /**
489      * @brief The constructor creates a TBlob object with the specified dimensions and layout
490      * on the pre-allocated memory.
491      *
492      * The allocate() call is not required.
493      *
494      * @param tensorDesc Tensor description
495      * @param ptr Pointer to the pre-allocated memory
496      * @param data_size Length of the pre-allocated array. If not set, size is assumed equal
497      * to the dot product of dims.
498      */
499     TBlob(const TensorDesc& tensorDesc, T* ptr, size_t data_size = 0): MemoryBlob(tensorDesc) {
500         if (data_size == 0) {
501             data_size = size();
502         }
503
504         if (data_size != 0 && ptr == nullptr) {
505             THROW_IE_EXCEPTION << "Using Blob on external nullptr memory";
506         }
507
508         _allocator = details::make_pre_allocator(ptr, data_size);
509         // blob on attached memory is always allocated, so we are not forcing the user to call allocate()
510         allocate();
511     }
512
513     /**
514      * @brief Creates a TBlob object with the specified dimensions, layout and custom memory allocator but does not
515      * allocate the memory.
516      *
517      * @param p Precision
518      * @param l Layout
519      * @param dims Tensor dimensions
520      * @param alloc Allocator to be used
521      */
522     TBlob(const TensorDesc& tensorDesc, const std::shared_ptr<IAllocator>& alloc)
523         : MemoryBlob(tensorDesc), _allocator(alloc) {}
524
525     /**
526      * @brief The copy constructor data is reallocated and copied from the source to the target blob.
527      *
528      * @param blob Source blob
529      */
530     TBlob(const TBlob<T>& blob): MemoryBlob(blob.getTensorDesc()) {
531         copyFrom(blob);
532     }
533
534     /**
535      * @brief A move constructor.
536      *
537      * @param blob rvalue to make a move from
538      */
539     TBlob(TBlob<T>&& blob): MemoryBlob(blob.getTensorDesc()) {
540         moveFrom(blob);
541     }
542
543     /**
544      * @brief Copy operator for the TBlob object.
545      *
546      * @param blob object reference to copy from
547      * @return Newly copied object
548      */
549     TBlob& operator=(const TBlob& blob) {
550         copyFrom(blob);
551         return *this;
552     }
553
554     /**
555      *@brief Virtual destructor.
556      */
557 #ifdef __clang__
558     virtual ~TBlob();
559 #else
560     virtual ~TBlob() {
561         free();
562     }
563 #endif  // __clang__
564
565     /**
566      * @brief Gets the size of the given type.
567      *
568      * @return Size of the type
569      */
570     size_t element_size() const noexcept override {
571         return sizeof(T);
572     }
573
574     /**
575      * @brief Creates an new empty rvalue LockedMemory object.
576      *
577      * @return rvalue for the empty locked object of type T
578      */
579     virtual LockedMemory<T> data() noexcept {
580         return std::move(lockme<T>());
581     }
582
583     /**
584      * @brief Creates a new empty rvalue read-only LockedMemory object.
585      *
586      * @return rvalue for the empty locked const object of type T.
587      */
588     virtual LockedMemory<const T> readOnly() const noexcept {
589         return std::move(lockme<const T>());
590     }
591
592     /**
593      * @brief Allocates or reallocates memory
594      */
595     void allocate() noexcept override {
596         if (_handle != nullptr) {
597             getAllocator()->free(_handle);
598         }
599         _handle = getAllocator()->alloc(size() * sizeof(T));
600     }
601
602     /**
603      * @brief Frees all allocated data
604      */
605     bool deallocate() noexcept override {
606         return free();
607     }
608
609     /**
610      * @brief Creates a new LockedMemory instance holding void pointer.
611      *
612      * @return LockedMemory instance holding void pointer
613      */
614     LockedMemory<void> buffer() noexcept override {
615         return std::move(lockme<void>());
616     }
617
618     /**
619      * @brief Creates a new LockedMemory instance holding constant void pointer.
620      *
621      * @return LockedMemory instance holding constant void pointer
622      */
623     LockedMemory<const void> cbuffer() const noexcept override {
624         return std::move(lockme<const void>());
625     }
626
627     LockedMemory<void> rwmap()noexcept override {
628         return std::move(lockme<void>());
629     }
630
631     LockedMemory<const void> rmap() const noexcept override {
632         return std::move(lockme<const void>());
633     }
634     LockedMemory<void> wmap()noexcept override {
635         return std::move(lockme<void>());
636     }
637
638     /**
639      * @brief Gets BlobIterator for the data.
640      *
641      * Enables a ranged loop support for the TBlob object.
642      *
643      * @return BlobIterator object of type T
644      */
645     details::BlobIterator<T> begin() {
646         return details::BlobIterator<T>(data());
647     }
648
649     /**
650      * @brief Gets BlobIterator for the end of data.
651      *
652      * Enables a ranged loop support for the TBlob object.
653      *
654      * @return BlobIterator object of type T representing end of the data
655      */
656     details::BlobIterator<T> end() {
657         return details::BlobIterator<T>(data(), size());
658     }
659
660     /**
661      * @brief Gets a const BlobIterator for the read-only data.
662      *
663      * Enables a ranged loop support for the TBlob object.
664      *
665      * @return BlobIterator object of type const T
666      */
667     details::BlobIterator<const T> begin() const {
668         return details::BlobIterator<const T>(readOnly());
669     }
670
671     /**
672      * @brief Gets a const BlobIterator for the end of read-only data.
673      *
674      * Enables a ranged loop support for the TBlob object.
675      *
676      * @return BlobIterator object of type const T representing end of data
677      */
678     details::BlobIterator<const T> end() const {
679         return details::BlobIterator<const T>(readOnly(), size());
680     }
681
682 protected:
683     /**
684      * @brief Local instance of IAllocator to manipulate memory.
685      */
686     mutable std::shared_ptr<IAllocator> _allocator;
687
688     /**
689      * @brief A handle for the stored memory returned from _allocator.alloc().
690      */
691     void* _handle = nullptr;
692
693     /**
694      * @brief Copies dimensions and data from the TBlob object.
695      *
696      * @param blob object reference to copy from
697      */
698     void copyFrom(const TBlob<T>& blob) {
699         tensorDesc = blob.tensorDesc;
700         this->allocate();
701         auto memptr = data();
702         memcpy(memptr, blob.readOnly(), byteSize());
703     }
704
705     /**
706      * @brief Swaps memory handlers between the current blob and the given one.
707      *
708      * @tparam U Type of the blob to move from
709      * @param blob TBlob instance to move from
710      */
711     template <class U>
712     void moveFrom(TBlob<U>& blob) {
713         tensorDesc = blob.tensorDesc;
714         this->_allocator = std::move(blob._allocator);
715         std::swap(this->_handle, blob._handle);
716     }
717
718     /**
719      * @brief Frees handler and cleans up the stored data.
720      */
721     virtual bool free() {
722         bool bCanRelease = getAllocator()->free(_handle);
723         _handle = nullptr;
724         return bCanRelease;
725     }
726
727     /**
728      * @brief Creates a LockedMemory instance.
729      *
730      * @tparam S Type of the LockedMemory to be created
731      * @return A created instance of LockedMemory
732      */
733     template <class S>
734     LockedMemory<S> lockme() const {
735         return LockedMemory<S>(_allocator.get(), _handle, 0);
736     }
737
738     /**
739      * @brief Gets an allocator or creates a default one.
740      *
741      * @return IAllocator instance
742      */
743     const std::shared_ptr<IAllocator>& getAllocator() const noexcept override {
744         // in case when constructor without allocator was used
745         if (!_allocator) {
746             _allocator = shared_from_irelease(CreateDefaultAllocator());
747         }
748
749         return _allocator;
750     }
751
752     /**
753      * @brief Returns handle to the stored data.
754      */
755     void* getHandle() const noexcept override {
756         return _handle;
757     }
758 };
759
760 #ifdef __clang__
761 extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<float>);
762 extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<double>);
763 extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<int16_t>);
764 extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<uint16_t>);
765 extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<int8_t>);
766 extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<uint8_t>);
767 extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<int>);
768 extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<long>);
769 extern template class INFERENCE_ENGINE_API_CLASS(InferenceEngine::TBlob<long long>);
770 #endif  // __clang__
771
772 /**
773  * @brief Creates a blob with the given tensor descriptor.
774  *
775  * @tparam Type Type of the shared pointer to be created
776  * @param tensorDesc Tensor descriptor for Blob creation
777  * @return A shared pointer to the newly created blob of the given type
778  */
779 template <typename Type>
780 inline typename InferenceEngine::TBlob<Type>::Ptr make_shared_blob(const TensorDesc& tensorDesc) {
781     if (!tensorDesc.getPrecision().hasStorageType<Type>())
782         THROW_IE_EXCEPTION << "Cannot make shared blob! "
783                            << "The blob type cannot be used to store objects of current precision";
784     return std::make_shared<InferenceEngine::TBlob<Type>>(tensorDesc);
785 }
786
787 /**
788  * @brief Creates a blob with the given tensor descriptor from the pointer to the pre-allocated memory.
789  *
790  * @tparam Type Type of the shared pointer to be created
791  * @param tensorDesc TensorDesc for Blob creation
792  * @param ptr Pointer to the pre-allocated memory
793  * @param size Length of the pre-allocated array
794  * @return A shared pointer to the newly created blob of the given type
795  */
796 template <typename Type>
797 inline typename InferenceEngine::TBlob<Type>::Ptr make_shared_blob(const TensorDesc& tensorDesc, Type* ptr,
798                                                                    size_t size = 0) {
799     if (!tensorDesc.getPrecision().hasStorageType<Type>())
800         THROW_IE_EXCEPTION << "Cannot make shared blob! "
801                            << "The blob type cannot be used to store objects of current precision";
802     return std::make_shared<InferenceEngine::TBlob<Type>>(tensorDesc, ptr, size);
803 }
804
805 /**
806  * @brief Creates a blob with the given tensor descriptor and allocator.
807  *
808  * @tparam Type Type of the shared pointer to be created
809  * @param tensorDesc Tensor descriptor for Blob creation
810  * @param alloc Shared pointer to IAllocator to use in the blob
811  * @return A shared pointer to the newly created blob of the given type
812  */
813 template <typename Type>
814 inline typename InferenceEngine::TBlob<Type>::Ptr make_shared_blob(
815     const TensorDesc& tensorDesc, const std::shared_ptr<InferenceEngine::IAllocator>& alloc) {
816     if (!tensorDesc.getPrecision().hasStorageType<Type>())
817         THROW_IE_EXCEPTION << "Cannot make shared blob! "
818                            << "The blob type cannot be used to store objects of current precision";
819     return std::make_shared<InferenceEngine::TBlob<Type>>(tensorDesc, alloc);
820 }
821
822 /**
823  * @brief Creates a copy of given TBlob instance.
824  *
825  * @tparam TypeTo Type of the shared pointer to be created
826  * @param arg given pointer to blob
827  * @return A shared pointer to the newly created blob of the given type
828  */
829 template <typename TypeTo>
830 inline typename InferenceEngine::TBlob<TypeTo>::Ptr make_shared_blob(const TBlob<TypeTo>& arg) {
831     return std::make_shared<InferenceEngine::TBlob<TypeTo>>(arg);
832 }
833
834 /**
835  * @brief Creates a Blob object of the specified type
836  *
837  * @param args Constructor arguments for the Blob object
838  * @return A shared pointer to the newly created Blob object
839  */
840 template <typename T, typename... Args, typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
841 std::shared_ptr<T> make_shared_blob(Args&&... args) {
842     return std::make_shared<T>(std::forward<Args>(args)...);
843 }
844
845 /**
846  * @brief This structure describes ROI data.
847  */
848 struct ROI {
849     size_t id;     // ID of a ROI
850     size_t posX;   // W upper left coordinate of ROI
851     size_t posY;   // H upper left coordinate of ROI
852     size_t sizeX;  // W size of ROI
853     size_t sizeY;  // H size of ROI
854 };
855
856 /**
857  * @brief Creates a blob describing given ROI object based on the given blob with pre-allocated memory.
858  *
859  * @param inputBlob original blob with pre-allocated memory.
860  * @param roi A ROI object inside of the original blob.
861  * @return A shared pointer to the newly created blob.
862  */
863 INFERENCE_ENGINE_API_CPP(Blob::Ptr) make_shared_blob(const Blob::Ptr& inputBlob, const ROI& roi);
864
865 }  // namespace InferenceEngine