OpenFPM_pdata  4.1.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 
126  {
127  if (mem != 0)
128  {mem_r.set_pointer(mem->getDevicePointer());}
129  }
130 
137  const memory& getMemory() const
138  {
139  return *this->mem;
140  }
141 
145  bool allocate(const size_t sz, bool skip_initialization = false)
146  {
147  memory * mem = this->mem;
148 
150  mem->resize( sz*sizeof(T) );
151 
153  mem_r.initialize(mem->getPointer(),sz,mem->isInitialized() | skip_initialization);
154 
155  return true;
156  }
157 
159  memory_c(bool manage_memory = true)
160  :manage_memory(manage_memory),mem(NULL){}
161 
164  {
165  // deinitialixe mem_r
166  if (manage_memory)
167  {
168  mem_r.deinit();
169  if (mem != NULL)
170  {
171  mem->decRef();
172 
173  if (mem->ref() == 0)
174  delete(mem);
175  }
176  }
177  }
178 
183  {
184  manage_memory = false;
185  }
186 
192  void swap(memory_c & mem_obj)
193  {
194  // Save on temporal
195 
196  void * mem_tmp = static_cast<void*>(mem);
197  mem = mem_obj.mem;
198  mem_obj.mem = static_cast<memory*>(mem_tmp);
199 
200  mem_obj.mem_r.swap(mem_r);
201  }
202 
208  template<typename Mem_type>
209  __host__ void swap_nomode(memory_c & mem_obj)
210  {
211  // It would be better a dynamic_cast, unfortunately nvcc
212  // does not accept it. It seems that for some reason nvcc want to
213  // produce device code out of this method. While it is true
214  // that this method is called inside a generic __device__ __host__
215  // function, tagging this method only __host__ does not stop
216  // nvcc from the intention to produce device code.
217  // The workaround is to use static_cast. Another workaround (to test)
218  // could be create a duplicate for_each function tagged only __host__ ,
219  // but I have to intention to duplicate code
220 
221  Mem_type * mem_tmp = static_cast<Mem_type*>(mem);
222  mem_tmp->swap(*static_cast<Mem_type*>(mem_obj.mem));
223 
224  mem_obj.mem_r.swap(mem_r);
225  }
226 
227 };
228 
238 template<typename T>
240 {
241  typedef T type;
242 };
243 
244 
250 template<typename T, unsigned int N>
251 struct mult
252 {
253  enum { value = mult<T,N-1>::value * boost::mpl::at<T,boost::mpl::int_<N>>::type::value };
254 };
255 
256 template <typename T>
257 struct mult<T,1>
258 {
259  enum { value = boost::mpl::at<T,boost::mpl::int_<1>>::type::value };
260 };
261 
262 template<typename size_type, unsigned int dim>
263 static inline std::array<size_type ,dim> zero_dims()
264 {
265  std::array<size_type ,dim> dimensions;
266 
267  // fill runtime, and the other dimensions
268  for (size_t i = 0 ; i < dim ; i++)
269  {dimensions[i] = 0;}
270 
271  return dimensions;
272 }
273 
274 template<unsigned int dim, typename size_type>
275 struct array_ord
276 {
277 };
278 
279 template<typename size_type>
280 struct array_ord<4,size_type>
281 {
282  static constexpr size_type data[4] = {0,3,2,1};
283 };
284 
285 template<typename size_type>
286 struct array_ord<3,size_type>
287 {
288  static constexpr size_type data[3] = {0,2,1};
289 };
290 
291 template<typename size_type>
292 struct array_ord<2,size_type>
293 {
294  static constexpr size_type data[2] = {0,1};
295 };
296 
297 template<unsigned int dim>
298 struct array_asc
299 {
300 };
301 
302 template<>
303 struct array_asc<4>
304 {
305  static constexpr bool data[4] = {true,true,true,true};
306 };
307 
308 template<>
309 struct array_asc<3>
310 {
311  static constexpr bool data[3] = {true,true,true};
312 };
313 
314 template<>
315 struct array_asc<2>
316 {
317  static constexpr bool data[2] = {true,true};
318 };
319 
320 
335 template<typename T, typename D>
336 class memory_c<multi_array<T>, MEMORY_C_STANDARD, D>
337 {
343  bool manage_memory = true;
344 
352  template<size_t index,size_t N> struct ascending
353  {
354  enum { value = true };
355  };
356 
358  typedef typename boost::mpl::push_front<typename boost::mpl::pop_front<T>::type,boost::mpl::int_<-1>>::type Tv;
359 
361  template<int S> using int_ = boost::mpl::int_<S>;
362 
364  typedef typename boost::mpl::size<T> size_p;
365 
367  template< typename S, unsigned int n> using at = boost::mpl::at<S,boost::mpl::int_<n> >;
368 
369  typedef typename at<T,0>::type base;
370 
372  typedef typename openfpm::multi_array_ref_openfpm<base,size_p::value,Tv>::size_type size_type;
373 
374  public:
375 
382  void setMemory(memory & mem)
383  {
384  if (manage_memory)
385  {
386  if (this->mem != NULL)
387  {
388  this->mem->decRef();
389 
390  if (this->mem->ref() == 0 && &mem != this->mem)
391  delete(this->mem);
392  }
393  mem.incRef();
394  }
395  this->mem = &mem;
396  }
397 
405  {
406  return *this->mem;
407  }
408 
413  {
414  if (mem != NULL)
415  {mem_r.set_pointer(mem->getDevicePointer());}
416  }
417 
418 
425  bool bind_ref(const memory_c<multi_array<T>, MEMORY_C_STANDARD, D> & ref)
426  {
427  mem = ref.mem;
428  if (manage_memory)
429  {mem->incRef();}
430 
432  mem_r = ref.mem_r;
433 
434  return true;
435  }
436 
443  bool allocate(const size_t sz, bool skip_initialization = false)
444  {
445  memory * mem = this->mem;
446 
448  mem->resize( sz*mult<T,size_p::value-1>::value*sizeof(base) );
449 
451  sz,
453 
455  mem_r.swap(tmp);
456 
457  return true;
458  }
459 
462  typedef boost::multi_array<base,size_p::value> type;
463 
465  D * mem;
466 
469 
471  memory_c(bool manage_memory = true)
472  :manage_memory(manage_memory),mem(NULL),
473  mem_r(static_cast<base *>(NULL),0,openfpm::ofp_storage_order())
474  {}
475 
478  {
479  // Indicate that this memory_c does not manage the memory
480  if (manage_memory)
481  {
482  if (mem != NULL)
483  {
484  mem->decRef();
485  if (mem->ref() == 0)
486  delete(mem);
487  }
488  }
489  }
490 
495  {
496  manage_memory = false;
497  }
498 
500  void set_mem(memory & mem)
501  {
502  this->mem = &mem;
503  }
504 
510  void swap(memory_c & mem_obj)
511  {
512  // Save on temporal
513 
514  void * mem_tmp = static_cast<void*>(mem);
515  mem = mem_obj.mem;
516  mem_obj.mem = static_cast<D*>(mem_tmp);
517 
518  mem_r.swap(mem_obj.mem_r);
519  }
520 
521 
531  template<typename Mem_type>
532  __host__ void swap_nomode(memory_c & mem_obj)
533  {
534  // It would be better a dynamic_cast, unfortunately nvcc
535  // does not accept it. It seems that for some reason nvcc want to
536  // produce device code out of this method. While it is true
537  // that this function is called inside a generic __device__ __host__
538  // function, tagging this method only __host__ does not stop
539  // nvcc from the intention to produce device code.
540  // The workaround is to use static_cast. Another workaround (to test)
541  // could be create a duplicate for_each function tagged only __host__ ,
542  // but I have to intention to duplicate code
543 
544  Mem_type * mem_tmp = static_cast<Mem_type*>(mem);
545  mem_tmp->swap(*static_cast<Mem_type*>(mem_obj.mem));
546 
547  mem_obj.mem_r.swap(mem_r);
548  }
549 };
550 
552 template<typename T>
554 {
555 };
556 
557 
559 template<typename T,size_t N1>
560 struct array_to_vmpl<T[N1]>
561 {
563  typedef boost::mpl::vector<T,boost::mpl::int_<N1>> prim_vmpl;
564 };
565 
566 
568 template<typename T,size_t N1,size_t N2>
569 struct array_to_vmpl<T[N1][N2]>
570 {
572  typedef boost::mpl::vector<T,boost::mpl::int_<N1>,
573  boost::mpl::int_<N2>> prim_vmpl;
574 };
575 
587 template<typename T>
589 {
590  // first we convert the type into a boost vector containing the primitive, followed by array dimension
591  typedef typename array_to_vmpl<T>::prim_vmpl prim_vmpl;
592 
593  // Than we operate at compile-time the same operation memory_c<multi_array does
595  typedef typename boost::mpl::push_front<typename boost::mpl::pop_front<prim_vmpl>::type,boost::mpl::int_<-1>>::type vmpl;
596 
597 
598 };
599 
600 #endif
601 
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:573
boost::multi_array< base, size_p::value > type
Definition: memory_c.hpp:462
convert a type into constant type
Definition: aggregate.hpp:292
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:563
Derivative second order on h (spacing)
Definition: Derivative.hpp:28
virtual bool resize(size_t sz)=0
resize on device a buffer
memory_c< T > type
define T
Definition: memory_c.hpp:57
memory_c(bool manage_memory=true)
constructor
Definition: memory_c.hpp:471
OpenFPM use memory_c<multi_array<T> ..... > to implement the structure of array layout.
Definition: memory_c.hpp:588
virtual long int ref()=0
Return the actual reference counter.
void set_pointer(void *ptr_)
Set the internal pointer to the indicated chunk of memory.
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:425
void disable_manage_memory()
Disable the management of memory (it is used for toKernel views)
Definition: memory_c.hpp:494
memory_array< T > mem_r
object that represent the memory as an array of objects T
Definition: memory_c.hpp:69
virtual void * getDevicePointer()=0
Return the device pointer of the memory.
This class is a container for the memory interface like HeapMemory CudaMemory.
Definition: memory_c.hpp:45
__host__ void swap_nomode(memory_c &mem_obj)
swap the memory
Definition: memory_c.hpp:209
void deinit()
Deinitialize the memory.
T & reference
define a reference to T
Definition: memory_c.hpp:60
void swap(memory_c &mem_obj)
swap the memory
Definition: memory_c.hpp:510
memory & getMemory()
This function get the object that allocate memory.
Definition: memory_c.hpp:404
openfpm::multi_array_ref_openfpm< base, boost::mpl::size< T >::value, Tv > mem_r
object that represent the memory as a multi-dimensional array of objects T
Definition: memory_c.hpp:468
this class multiply all the elements in a boost::mpl::vector excluding the first element
Definition: memory_c.hpp:251
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:595
boost::mpl::size< T > size_p
define the template vector size it give a number at compile time
Definition: memory_c.hpp:364
void disable_manage_memory()
Disable the management of memory (it is used for toKernel views)
Definition: memory_c.hpp:182
Partial specialization for scalar N=0.
Definition: memory_c.hpp:553
D * mem
Reference to an object to allocate memory.
Definition: memory_c.hpp:465
void setMemory(memory &mem)
This function set the object that allocate memory.
Definition: memory_c.hpp:76
bool allocate(const size_t sz, bool skip_initialization=false)
This function allocate memory.
Definition: memory_c.hpp:145
openfpm::multi_array_ref_openfpm< base, size_p::value, Tv >::size_type size_type
define size_type
Definition: memory_c.hpp:372
memory_c(bool manage_memory=true)
constructor
Definition: memory_c.hpp:159
void initialize(void *ptr, size_t sz, bool init)
Initialize the memory array.
void switchToDevicePtr()
Switch the pointer to device pointer (if the memory has been already set)
Definition: memory_c.hpp:125
void setMemory(memory &mem)
This function set the object that allocate memory.
Definition: memory_c.hpp:382
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
memory & getMemory()
This function get the object that allocate memory.
Definition: memory_c.hpp:117
void set_mem(memory &mem)
set the device memory interface, the object that allocate memory
Definition: memory_c.hpp:500
virtual void decRef()=0
Decrement the internal reference counter.
const memory & getMemory() const
This function get the object that allocate memory.
Definition: memory_c.hpp:137
virtual bool isInitialized()=0
Return if the actual memory that is going to be allocated is already initialized.
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:443
void swap(memory_c &mem_obj)
swap the memory
Definition: memory_c.hpp:192
void switchToDevicePtr()
Switch the pointer to device pointer.
Definition: memory_c.hpp:412
This class give a representation to a chunk or memory.
boost::mpl::at< S, boost::mpl::int_< n > > at
Define "at" meta function without boost::mpl.
Definition: memory_c.hpp:367
virtual void * getPointer()=0
return a data pointer
boost::mpl::int_< S > int_
define boost::mpl::int_ without boost::mpl
Definition: memory_c.hpp:361
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:358
virtual void incRef()=0
Increment the internal reference counter.
memory * mem
object that allocate memory like HeapMemory or CudaMemory
Definition: memory_c.hpp:66
This class is a trick to indicate the compiler a specific specialization pattern.
Definition: memory_c.hpp:239
__host__ void swap_nomode(memory_c &mem_obj)
swap the memory
Definition: memory_c.hpp:532