OpenFPM  5.2.0
Project that contain the implementation of distributed structures
memory_c.hpp
1 /*
2  * memory_c.hpp
3  *
4  * Created on: Aug 17, 2014
5  * Author: Pietro Incardona
6  */
7 
8 #include <boost/multi_array.hpp>
9 #include <boost/fusion/mpl.hpp>
10 #include <boost/fusion/include/mpl.hpp>
11 #include <boost/mpl/vector.hpp>
12 #include <array>
13 #include <boost/mpl/pop_front.hpp>
14 #include <boost/mpl/push_front.hpp>
15 
16 //#include "util/boost/boost_multi_array_openfpm.hpp"
17 #include "util/multi_array_openfpm/multi_array_ref_openfpm.hpp"
18 #include "util/ct_array.hpp"
19 #include "memory_array.hpp"
20 #include "memory/memory.hpp"
21 
22 #ifndef MEMORY_C_HPP_
23 #define MEMORY_C_HPP_
24 
25 #define MEMORY_C_STANDARD 1
26 #define MEMORY_C_REDUCED 2
27 
28 template<typename T, unsigned int impl = MEMORY_C_STANDARD, typename D = memory>
29 class memory_c
30 {
31 
32 };
33 
44 template<typename T, typename D>
45 class memory_c<T,MEMORY_C_STANDARD,D>
46 {
52  bool manage_memory = true;
53 
54  public:
55 
57  typedef memory_c<T> type;
58 
60  typedef T& reference;
61 
63  typedef T vtype;
64 
67 
70 
76  void setMemory(memory & mem)
77  {
78  if (manage_memory)
79  {
80  if (this->mem != NULL)
81  {
82  this->mem->decRef();
83 
84  if (this->mem->ref() == 0 && &mem != this->mem)
85  delete(this->mem);
86  }
87  mem.incRef();
88  }
89  this->mem = &mem;
90  }
91 
99  {
100  mem = ref.mem;
101 
102  if (manage_memory)
103  {mem->incRef();}
104 
106  mem_r = ref.mem_r;
107 
108  return true;
109  }
110 
118  {
119  return *this->mem;
120  }
121 
128  const memory& getMemory() const
129  {
130  return *this->mem;
131  }
132 
136  bool allocate(const size_t sz, bool skip_initialization = false)
137  {
138  memory * mem = this->mem;
139 
141  mem->resize( sz*sizeof(T) );
142 
144  mem_r.initialize(mem->getPointer(),sz,mem->isInitialized() | skip_initialization);
145 
146  return true;
147  }
148 
150  memory_c(bool manage_memory = true)
151  :manage_memory(manage_memory),mem(NULL){}
152 
155  {
156  // deinitialixe mem_r
157  if (manage_memory)
158  {
159  mem_r.deinit();
160  if (mem != NULL)
161  {
162  mem->decRef();
163 
164  if (mem->ref() == 0)
165  delete(mem);
166  }
167  }
168  }
169 
174  {
175  manage_memory = false;
176  }
177 
183  void swap(memory_c & mem_obj)
184  {
185  // Save on temporal
186 
187  void * mem_tmp = static_cast<void*>(mem);
188  mem = mem_obj.mem;
189  mem_obj.mem = static_cast<memory*>(mem_tmp);
190 
191  mem_obj.mem_r.swap(mem_r);
192  }
193 
199  template<typename Mem_type>
200  __host__ void swap_nomode(memory_c & mem_obj)
201  {
202  // It would be better a dynamic_cast, unfortunately nvcc
203  // does not accept it. It seems that for some reason nvcc want to
204  // produce device code out of this method. While it is true
205  // that this method is called inside a generic __device__ __host__
206  // function, tagging this method only __host__ does not stop
207  // nvcc from the intention to produce device code.
208  // The workaround is to use static_cast. Another workaround (to test)
209  // could be create a duplicate for_each function tagged only __host__ ,
210  // but I have to intention to duplicate code
211 
212  Mem_type * mem_tmp = static_cast<Mem_type*>(mem);
213  mem_tmp->swap(*static_cast<Mem_type*>(mem_obj.mem));
214 
215  mem_obj.mem_r.swap(mem_r);
216  }
217 
218 };
219 
229 template<typename T>
231 {
232  typedef T type;
233 };
234 
235 
241 template<typename T, unsigned int N>
242 struct mult
243 {
244  enum { value = mult<T,N-1>::value * boost::mpl::at<T,boost::mpl::int_<N>>::type::value };
245 };
246 
247 template <typename T>
248 struct mult<T,1>
249 {
250  enum { value = boost::mpl::at<T,boost::mpl::int_<1>>::type::value };
251 };
252 
253 
268 template<typename T, typename D>
269 class memory_c<multi_array<T>, MEMORY_C_STANDARD, D>
270 {
276  bool manage_memory = true;
277 
285  template<size_t index,size_t N> struct ascending
286  {
287  enum { value = true };
288  };
289 
291  typedef typename boost::mpl::push_front<typename boost::mpl::pop_front<T>::type,boost::mpl::int_<-1>>::type Tv;
292 
294  template<int S> using int_ = boost::mpl::int_<S>;
295 
297  typedef typename boost::mpl::size<T> size_p;
298 
300  template< typename S, unsigned int n> using at = boost::mpl::at<S,boost::mpl::int_<n> >;
301 
302  typedef typename at<T,0>::type base;
303 
305  typedef typename openfpm::multi_array_ref_openfpm<base,size_p::value,Tv>::size_type size_type;
306 
307  public:
308 
315  void setMemory(memory & mem)
316  {
317  if (manage_memory)
318  {
319  if (this->mem != NULL)
320  {
321  this->mem->decRef();
322 
323  if (this->mem->ref() == 0 && &mem != this->mem)
324  delete(this->mem);
325  }
326  mem.incRef();
327  }
328  this->mem = &mem;
329  }
330 
338  {
339  return *this->mem;
340  }
341 
342 
349  bool bind_ref(const memory_c<multi_array<T>, MEMORY_C_STANDARD, D> & ref)
350  {
351  mem = ref.mem;
352  if (manage_memory)
353  {mem->incRef();}
354 
356  mem_r = ref.mem_r;
357 
358  return true;
359  }
360 
367  bool allocate(const size_t sz, bool skip_initialization = false)
368  {
369  memory * mem = this->mem;
370 
372  mem->resize( sz*mult<T,size_p::value-1>::value*sizeof(base) );
373 
375 
377  mem_r.swap(tmp);
378 
379  return true;
380  }
381 
384  typedef boost::multi_array<base,size_p::value> type;
385 
387  typedef typename openfpm::ofp_storage_order<size_p::value>::value storage_order;
388 
390  D * mem;
391 
394 
396  memory_c(bool manage_memory = true)
397  :manage_memory(manage_memory),mem(NULL),
398  mem_r(static_cast<base *>(NULL),0)
399  {}
400 
403  {
404  // Indicate that this memory_c does not manage the memory
405  if (manage_memory)
406  {
407  if (mem != NULL)
408  {
409  mem->decRef();
410  if (mem->ref() == 0)
411  delete(mem);
412  }
413  }
414  }
415 
420  {
421  manage_memory = false;
422  }
423 
425  void set_mem(memory & mem)
426  {
427  this->mem = &mem;
428  }
429 
435  void swap(memory_c & mem_obj)
436  {
437  // Save on temporal
438 
439  void * mem_tmp = static_cast<void*>(mem);
440  mem = mem_obj.mem;
441  mem_obj.mem = static_cast<D*>(mem_tmp);
442 
443  mem_r.swap(mem_obj.mem_r);
444  }
445 
446 
456  template<typename Mem_type>
457  __host__ void swap_nomode(memory_c & mem_obj)
458  {
459  // It would be better a dynamic_cast, unfortunately nvcc
460  // does not accept it. It seems that for some reason nvcc want to
461  // produce device code out of this method. While it is true
462  // that this function is called inside a generic __device__ __host__
463  // function, tagging this method only __host__ does not stop
464  // nvcc from the intention to produce device code.
465  // The workaround is to use static_cast. Another workaround (to test)
466  // could be create a duplicate for_each function tagged only __host__ ,
467  // but I have to intention to duplicate code
468 
469  Mem_type * mem_tmp = static_cast<Mem_type*>(mem);
470  mem_tmp->swap(*static_cast<Mem_type*>(mem_obj.mem));
471 
472  mem_obj.mem_r.swap(mem_r);
473  }
474 };
475 
477 template<typename T>
479 {
480 };
481 
482 
484 template<typename T,size_t N1>
485 struct array_to_vmpl<T[N1]>
486 {
488  typedef boost::mpl::vector<T,boost::mpl::int_<N1>> prim_vmpl;
489 };
490 
491 
493 template<typename T,size_t N1,size_t N2>
494 struct array_to_vmpl<T[N1][N2]>
495 {
497  typedef boost::mpl::vector<T,boost::mpl::int_<N1>,
498  boost::mpl::int_<N2>> prim_vmpl;
499 };
500 
512 template<typename T>
514 {
515  // first we convert the type into a boost vector containing the primitive, followed by array dimension
516  typedef typename array_to_vmpl<T>::prim_vmpl prim_vmpl;
517 
518  // Than we operate at compile-time the same operation memory_c<multi_array does
520  typedef typename boost::mpl::push_front<typename boost::mpl::pop_front<prim_vmpl>::type,boost::mpl::int_<-1>>::type vmpl;
521 
522 
523 };
524 
525 #endif
526 
Derivative second order on h (spacing)
Definition: Derivative.hpp:29
This class give a representation to a chunk or memory.
void initialize(void *ptr, size_t sz, bool init)
Initialize the memory array.
void deinit()
Deinitialize the memory.
This class is a container for the memory interface like HeapMemory CudaMemory.
Definition: memory_c.hpp:46
memory_array< T > mem_r
object that represent the memory as an array of objects T
Definition: memory_c.hpp:69
bool bind_ref(const memory_c< T, MEMORY_C_STANDARD, D > &ref)
This function bind the memory_c to this memory_c as reference.
Definition: memory_c.hpp:98
bool allocate(const size_t sz, bool skip_initialization=false)
This function allocate memory.
Definition: memory_c.hpp:136
__host__ void swap_nomode(memory_c &mem_obj)
swap the memory
Definition: memory_c.hpp:200
const memory & getMemory() const
This function get the object that allocate memory.
Definition: memory_c.hpp:128
memory_c(bool manage_memory=true)
constructor
Definition: memory_c.hpp:150
memory_c< T > type
define T
Definition: memory_c.hpp:57
memory * mem
object that allocate memory like HeapMemory or CudaMemory
Definition: memory_c.hpp:66
void setMemory(memory &mem)
This function set the object that allocate memory.
Definition: memory_c.hpp:76
T & reference
define a reference to T
Definition: memory_c.hpp:60
void disable_manage_memory()
Disable the management of memory (it is used for toKernel views)
Definition: memory_c.hpp:173
memory & getMemory()
This function get the object that allocate memory.
Definition: memory_c.hpp:117
void swap(memory_c &mem_obj)
swap the memory
Definition: memory_c.hpp:183
openfpm::multi_array_ref_openfpm< base, size_p::value, Tv >::size_type size_type
define size_type
Definition: memory_c.hpp:305
void swap(memory_c &mem_obj)
swap the memory
Definition: memory_c.hpp:435
openfpm::ofp_storage_order< size_p::value >::value storage_order
define the storage order used to reference multidimensional arrays
Definition: memory_c.hpp:387
__host__ void swap_nomode(memory_c &mem_obj)
swap the memory
Definition: memory_c.hpp:457
bool allocate(const size_t sz, bool skip_initialization=false)
This function allocate memory and associate the representation to mem_r.
Definition: memory_c.hpp:367
boost::multi_array< base, size_p::value > type
Definition: memory_c.hpp:384
void disable_manage_memory()
Disable the management of memory (it is used for toKernel views)
Definition: memory_c.hpp:419
openfpm::multi_array_ref_openfpm< base, boost::mpl::size< T >::value, Tv, storage_order > mem_r
object that represent the memory as a multi-dimensional array of objects T
Definition: memory_c.hpp:393
D * mem
Reference to an object to allocate memory.
Definition: memory_c.hpp:390
boost::mpl::at< S, boost::mpl::int_< n > > at
Define "at" meta function without boost::mpl.
Definition: memory_c.hpp:300
void set_mem(memory &mem)
set the device memory interface, the object that allocate memory
Definition: memory_c.hpp:425
boost::mpl::int_< S > int_
define boost::mpl::int_ without boost::mpl
Definition: memory_c.hpp:294
memory_c(bool manage_memory=true)
constructor
Definition: memory_c.hpp:396
void setMemory(memory &mem)
This function set the object that allocate memory.
Definition: memory_c.hpp:315
bool bind_ref(const memory_c< multi_array< T >, MEMORY_C_STANDARD, D > &ref)
This function bind the memory_c to this memory_c as reference.
Definition: memory_c.hpp:349
boost::mpl::push_front< typename boost::mpl::pop_front< T >::type, boost::mpl::int_<-1 > >::type Tv
Remove the first element.
Definition: memory_c.hpp:291
memory & getMemory()
This function get the object that allocate memory.
Definition: memory_c.hpp:337
boost::mpl::size< T > size_p
define the template vector size it give a number at compile time
Definition: memory_c.hpp:297
virtual long int ref()=0
Return the actual reference counter.
virtual bool resize(size_t sz)=0
resize on device a buffer
virtual bool isInitialized()=0
Return if the actual memory that is going to be allocated is already initialized.
virtual void * getPointer()=0
return a data pointer
virtual void incRef()=0
Increment the internal reference counter.
virtual void decRef()=0
Decrement the internal reference counter.
This class is a trick to indicate the compiler a specific specialization pattern.
Definition: memory_c.hpp:231
boost::mpl::vector< T, boost::mpl::int_< N1 >, boost::mpl::int_< N2 > > prim_vmpl
the internal array primitive information represented into a boost mpl vector
Definition: memory_c.hpp:498
boost::mpl::vector< T, boost::mpl::int_< N1 > > prim_vmpl
the internal array primitive information represented into a boost mpl vector
Definition: memory_c.hpp:488
Partial specialization for scalar N=0.
Definition: memory_c.hpp:479
this class multiply all the elements in a boost::mpl::vector excluding the first element
Definition: memory_c.hpp:243
OpenFPM use memory_c<multi_array<T> ..... > to implement the structure of array layout.
Definition: memory_c.hpp:514
boost::mpl::push_front< typename boost::mpl::pop_front< prim_vmpl >::type, boost::mpl::int_<-1 > >::type vmpl
Remove the first element (this is the Tv parameter of )
Definition: memory_c.hpp:520