clDNN
memory.hpp
1 /*
2 // Copyright (c) 2016 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 */
16 
18 #pragma once
19 #include <cstdint>
20 #include "cldnn_defs.h"
21 #include "compounds.h"
22 #include "layout.hpp"
23 #include "engine.hpp"
24 #include <memory>
25 #include <iterator>
26 
27 namespace cldnn
28 {
29 
32 
35 
36 template<typename T> struct pointer;
37 
38 namespace details { struct memory_c_to_cpp_converter; }
39 
42 struct memory
43 {
44  friend struct data;
45  friend struct network;
46  friend struct network_output;
48 
50  static memory allocate(const engine& engine, const layout& layout)
51  {
52  size_t size = layout.bytes_count();
53  if (size == 0) throw std::invalid_argument("size should be more than 0");
54  return check_status<cldnn_memory>("memory allocation failed", [&](status_t* status)
55  {
56  return cldnn_allocate_memory(engine.get(), layout, status);
57  });
58  }
59 
64  template<typename T>
65  static memory attach(const cldnn::layout& layout, T* ptr, size_t size)
66  {
67  if (!ptr) throw std::invalid_argument("pointer should not be null");
68  size_t data_size = size * sizeof(T);
69  if (data_size != layout.bytes_count()) {
70  std::string err_str("buffer size mismatch - input size " + std::to_string(data_size) + " layout size " + std::to_string(layout.bytes_count()));
71  throw std::invalid_argument(err_str);
72  }
73 
74  return check_status<cldnn_memory>("memory attach failed", [&](status_t* status)
75  {
76  return cldnn_attach_memory(layout, ptr, data_size, status);
77  });
78  }
79 
80  memory(const memory& other)
81  :_impl(other._impl), _layout(other._layout)
82  ,_size(other._size), _count(other._count)
83  {
84  retain();
85  }
86 
87  memory& operator=(const memory& other)
88  {
89  if (_impl == other._impl) return *this;
90  release();
91  _impl = other._impl;
92  _layout = other._layout;
93  _size = other._size;
94  _count = other._count;
95  retain();
96  return *this;
97  }
98 
99  ~memory()
100  {
101  release();
102  }
103 
104  friend bool operator==(const memory& lhs, const memory& rhs) { return lhs._impl == rhs._impl; }
105  friend bool operator!=(const memory& lhs, const memory& rhs) { return !(lhs == rhs); }
106 
108  size_t count() const { return _count; }
109 
111  size_t size() const { return _size; }
112 
114  const layout& get_layout() const { return _layout; }
115 
117  bool is_allocated_by(const engine& engine) const
118  {
119  auto my_engine = check_status<cldnn_engine>("get memory engine failed", [&](status_t* status)
120  {
121  return cldnn_get_memory_engine(_impl, status);
122  });
123  return my_engine == engine.get();
124  }
125 
126  bool is_the_same_buffer(const memory& other) const
127  {
128  return check_status<bool>("checking if two memories refers to the same buffer failed", [&](status_t* status)
129  {
130  return cldnn_is_the_same_buffer(_impl, other._impl, status) != 0;
131  });
132  }
133 
135  template<typename T> friend struct cldnn::pointer;
136  template<typename T> cldnn::pointer<T> pointer() const;
137 
139  cldnn_memory get() const { return _impl; }
140 
141 private:
142  friend struct engine;
143  cldnn_memory _impl;
144  layout _layout;
145  size_t _size;
146  size_t _count;
147 
148  static layout get_layout_impl(cldnn_memory mem)
149  {
150  if (!mem) throw std::invalid_argument("mem");
151 
152  return check_status<layout>("get memory layout failed", [=](status_t* status)
153  {
154  return cldnn_get_memory_layout(mem, status);
155  });
156  }
157 
158  memory(cldnn_memory data)
159  :_impl(data), _layout(get_layout_impl(data))
160  , _size(_layout.bytes_count()), _count(_layout.count())
161  {
162  if (_impl == nullptr)
163  throw std::invalid_argument("implementation pointer should not be null");
164  }
165 
166  void retain()
167  {
168  check_status<void>("retain memory failed", [=](status_t* status) { cldnn_retain_memory(_impl, status); });
169  }
170  void release()
171  {
172  check_status<void>("release memory failed", [=](status_t* status) { cldnn_release_memory(_impl, status); });
173  }
174 
175  template<typename T>
176  T* lock() const
177  {
178  if (data_type_traits::align_of(_layout.data_type) % alignof(T) != 0)
179  {
180  throw std::logic_error("memory data type alignment do not match");
181  }
182  return check_status<T*>("memory lock failed", [=](status_t* status) { return static_cast<T*>(cldnn_lock_memory(_impl, status)); });
183  }
184 
185  void unlock() const
186  {
187  check_status<void>("memory unlock failed", [=](status_t* status) { return cldnn_unlock_memory(_impl, status); });
188  }
189 };
190 
191 namespace details
192 {
193 //we need this hackish structure as long as primitives (which are used internally) use c++ api 'memory' (see: cldnn::data)
195 {
196  //does not retain @p c_mem
197  static memory convert(cldnn_memory c_mem)
198  {
199  return memory{ c_mem };
200  }
201 };
202 }
203 
210 template<typename T>
211 struct pointer
212 {
214  pointer(const memory& mem)
215  : _mem(mem)
216  , _size(_mem.size()/sizeof(T))
217  , _ptr(_mem.lock<T>())
218  {}
219 
221  ~pointer() { _mem.unlock(); }
222 
224  pointer(const pointer& other) : pointer(other._mem){}
225 
227  pointer& operator=(const pointer& other)
228  {
229  if (this->_mem != other._mem)
230  do_copy(other._mem);
231  return *this;
232  }
233 
235  size_t size() const { return _size; }
236 
237 #if defined(_SECURE_SCL) && (_SECURE_SCL > 0)
238  typedef stdext::checked_array_iterator<T*> iterator;
239  typedef stdext::checked_array_iterator<const T*> const_iterator;
240 
241  iterator begin() & { return stdext::make_checked_array_iterator(_ptr, size()); }
242  iterator end() & { return stdext::make_checked_array_iterator(_ptr, size(), size()); }
243 
244  const_iterator begin() const& { return stdext::make_checked_array_iterator(_ptr, size()); }
245  const_iterator end() const& { return stdext::make_checked_array_iterator(_ptr, size(), size()); }
246 #else
247  typedef T* iterator;
248  typedef const T* const_iterator;
249  iterator begin() & { return _ptr; }
250  iterator end() & { return _ptr + size(); }
251  const_iterator begin() const& { return _ptr; }
252  const_iterator end() const& { return _ptr + size(); }
253 #endif
254 
256  T& operator[](size_t idx) const&
257  {
258  assert(idx < _size);
259  return _ptr[idx];
260  }
261 
263  T* data() & { return _ptr; }
265  const T* data() const& { return _ptr; }
266 
267  friend bool operator==(const pointer& lhs, const pointer& rhs) { return lhs._mem == rhs._mem; }
268  friend bool operator!=(const pointer& lhs, const pointer& rhs) { return !(lhs == rhs); }
269 
270  // do not use this class as temporary object
271  // ReSharper disable CppMemberFunctionMayBeStatic, CppMemberFunctionMayBeConst
273  void data() && {}
275  void begin() && {}
277  void end() && {}
279  void operator[](size_t idx) && {}
280  // ReSharper restore CppMemberFunctionMayBeConst, CppMemberFunctionMayBeStatic
281 
282 private:
283  memory _mem;
284  size_t _size;
285  T* _ptr;
286 
287  //TODO implement exception safe code.
288  void do_copy(const memory& mem)
289  {
290  auto ptr = mem.lock<T>();
291  _mem.unlock();
292  _mem = mem;
293  _size = _mem.size() / sizeof(T);
294  _ptr = ptr;
295  }
296 };
297 
298 #ifndef DOXYGEN_SHOULD_SKIP_THIS
299 template <typename T>
300 pointer<T> memory::pointer() const { return cldnn::pointer<T>(*this); }
301 #endif
302 
304 
306 
307 }
CLDNN_API void cldnn_unlock_memory(cldnn_memory memory, cldnn_status *status)
Unlocks memory locked by cldnn_lock_memory(cldnn_memory memory, cldnn_status* status).
T & operator[](size_t idx) const &
Provides indexed access to pointed memory.
Definition: memory.hpp:256
::cldnn_engine get() const
get C API engine handler.
Definition: engine.hpp:180
size_t size() const
Returns the number of elements (of type T) stored in memory.
Definition: memory.hpp:235
void operator[](size_t idx) &&
Prevents to use pointer as temporary object.
Definition: memory.hpp:279
pointer(const memory &mem)
Constructs pointer from memory and locks (pin) ref@ memory object.
Definition: memory.hpp:214
CLDNN_API int32_t cldnn_is_the_same_buffer(cldnn_memory mem1, cldnn_memory mem2, cldnn_status *status)
Checks if two memory objects refer to the same underlaying buffer.
Represents network output returned by network::get_output().
Definition: network.hpp:39
CLDNN_API cldnn_layout cldnn_get_memory_layout(cldnn_memory memory, cldnn_status *status)
Returns memory layout.
~pointer()
Unlocks memory.
Definition: memory.hpp:221
data_types data_type
Data type stored in memory (see. data_types)
Definition: layout.hpp:373
CLDNN_API cldnn_engine cldnn_get_memory_engine(cldnn_memory memory, cldnn_status *status)
Returns reference to the engine associated with memory object.
Provides input data to topology.
Definition: data.hpp:36
struct cldnn_memory_impl * cldnn_memory
Memory object.
Definition: cldnn.h:119
static memory attach(const cldnn::layout &layout, T *ptr, size_t size)
Definition: memory.hpp:65
CLDNN_API cldnn_memory cldnn_allocate_memory(cldnn_engine engine, cldnn_layout layout, cldnn_status *status)
Allocate memory on engine using specified layout.
void data() &&
Prevents to use pointer as temporary object.
Definition: memory.hpp:273
bool is_allocated_by(const engine &engine) const
Test if memory is allocated by engine.
Definition: memory.hpp:117
T * data() &
Returns the raw pointer to pointed memory.
Definition: memory.hpp:263
CLDNN_API void cldnn_release_memory(cldnn_memory memory, cldnn_status *status)
Decrement reference counter for the memory object. Deletes object when counter becomes zero...
static memory allocate(const engine &engine, const layout &layout)
Allocate memory on engine using specified layout.
Definition: memory.hpp:50
CLDNN_API cldnn_memory cldnn_attach_memory(cldnn_layout layout, void *pointer, size_t size, cldnn_status *status)
Create memory object attached to the buffer allocated by user.
const T * data() const &
Returns the constant raw pointer to pointed memory.
Definition: memory.hpp:265
CLDNN_API void * cldnn_lock_memory(cldnn_memory memory, cldnn_status *status)
Locks memory buffer. Provides direct access to memory data.
size_t bytes_count() const
Number of bytes needed to store this layout.
Definition: layout.hpp:385
CLDNN_API void cldnn_retain_memory(cldnn_memory memory, cldnn_status *status)
Increment reference counter for the memory object.
Executable network allocated from program.
Definition: network.hpp:59
const layout & get_layout() const
Associated layout.
Definition: memory.hpp:114
pointer(const pointer &other)
Copy construction.
Definition: memory.hpp:224
Represents clDNN engine object.
Definition: engine.hpp:110
Helper class to get an access memory data.
Definition: memory.hpp:36
Represents buffer with particular layout.
Definition: memory.hpp:42
pointer & operator=(const pointer &other)
Copy assignment.
Definition: memory.hpp:227
size_t size() const
number of bytes used by memory
Definition: memory.hpp:111
void begin() &&
Prevents to use pointer as temporary object.
Definition: memory.hpp:275
Describes memory layout.
Definition: layout.hpp:223
void end() &&
Prevents to use pointer as temporary object.
Definition: memory.hpp:277
size_t count() const
number of elements of _layout.data_type stored in memory
Definition: memory.hpp:108