OpenFPM_pdata  4.1.0
Project that contain the implementation of distributed structures
map_grid_cuda_ker.cuh
1 /*
2  * map_grid_cuda_ker.hpp
3  *
4  * Created on: Jun 28, 2018
5  * Author: i-bird
6  */
7 
8 #ifndef MAP_GRID_CUDA_KER_HPP_
9 #define MAP_GRID_CUDA_KER_HPP_
10 
11 #include "config.h"
12 #include "Grid/grid_base_impl_layout.hpp"
13 #include "util/tokernel_transformation.hpp"
14 #ifdef CUDA_GPU
15 #include "memory/CudaMemory.cuh"
16 #endif
17 #ifdef HAVE_OPENMP
18 #include <omp.h>
19 #endif
20 
32 template<typename T_type_src,typename T_type_dst>
34 {
36  const T_type_src & src;
38  T_type_dst & dst;
39 
40 
47  inline copy_switch_memory_c_no_cpy(const T_type_src & src,
48  T_type_dst & dst)
49  :src(src),dst(dst)
50  {
51  };
52 
53 
55  template<typename T>
56  inline void operator()(T& t)
57  {
58  boost::fusion::at_c<T::value>(dst).disable_manage_memory();
59 
60  boost::fusion::at_c<T::value>(dst).mem = boost::fusion::at_c<T::value>(src).mem;
61 
62  boost::fusion::at_c<T::value>(dst).mem_r.bind_ref(boost::fusion::at_c<T::value>(src).mem_r);
63  boost::fusion::at_c<T::value>(dst).switchToDevicePtr();
64  }
65 };
66 
67 template<bool inte_or_lin,typename T>
69 {
70  template<typename ggk_type> static inline void construct(const ggk_type & cpy,ggk_type & this_)
71  {
72  copy_switch_memory_c_no_cpy<decltype(cpy.get_data_()),decltype(this_.get_data_())> bp_mc(cpy.get_data_(),this_.get_data_());
73 
74  boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(bp_mc);
75  }
76 };
77 
78 template<typename T>
80 {
81  template<typename ggk_type> static inline void construct(const ggk_type & cpy,ggk_type & this_)
82  {
83  this_.get_data_().disable_manage_memory();
84  this_.get_data_().mem = cpy.get_data_().mem;
85 
86  this_.get_data_().mem_r.bind_ref(cpy.get_data_().mem_r);
87  this_.get_data_().switchToDevicePtr();
88  }
89 };
90 
91 template<unsigned int dim, int prp, typename ids_type>
92 __device__ void fill_grid_error_array_overflow(const void * sptr,grid_key_dx<dim,ids_type> key)
93 {
94 #ifdef CUDA_GPU
95 
96  int * ptr = (int *)&global_cuda_error_array[0];
97 
98  ptr[0] = 1;
99  ptr[1] = ((size_t)sptr) & 0xFFFFFFFF;
100  ptr[2] = (((size_t)sptr) & 0xFFFFFFFF00000000) >> 32;
101  ptr[3] = prp;
102  ptr[4] = dim;
103 
104  for (int i = 0 ; i < dim ; i++)
105  {ptr[i+5] = key.get(i);}
106 
107 #ifdef __NVCC__
108 
109  ptr[5+dim] = blockIdx.x;
110  ptr[6+dim] = blockIdx.y;
111  ptr[7+dim] = blockIdx.z;
112 
113  ptr[8+dim] = blockDim.x;
114  ptr[9+dim] = blockDim.y;
115  ptr[10+dim] = blockDim.z;
116 
117  ptr[11+dim] = threadIdx.x;
118  ptr[12+dim] = threadIdx.y;
119  ptr[13+dim] = threadIdx.z;
120 
121 #endif
122 
123 #endif
124 }
125 
126 template<unsigned int dim>
127 __device__ void fill_grid_error_array(size_t lin_id)
128 {
129 #ifdef CUDA_GPU
130 
131  int * ptr = (int *)&global_cuda_error_array[0];
132 
133  ptr[0] = 1;
134  ptr[1] = 1;
135  ptr[2] = lin_id;
136 
137 #endif
138 }
139 
140 template<unsigned int dim, typename T, template <typename> class layout_base, typename linearizer>
142 
148 template<unsigned int dim, typename T, template <typename> class layout_base, typename linearizer>
150 {
152  typedef typename apply_transform<layout_base,T>::type T_;
153 
155  linearizer g1;
156 
158  typedef typename layout_base<T_>::type layout;
159 
161  mutable layout data_;
162 
163 
164 
172  template<typename ids_type> __device__ __host__ inline bool check_bound(const grid_key_dx<dim,ids_type> & v1) const
173  {
174  for (long int i = 0 ; i < dim ; i++)
175  {
176  if (v1.get(i) >= (long int)getGrid().size(i))
177  {return false;}
178  else if (v1.get(i) < 0)
179  {return false;}
180  }
181  return true;
182  }
183 
191  __device__ __host__ inline bool check_bound(size_t v1) const
192  {
193  return v1 < getGrid().size();
194  }
195 
196 public:
197 
199  typedef int yes_i_am_grid;
200 
202  typedef T value_type;
203 
204  __device__ __host__ grid_gpu_ker()
205  {}
206 
207  __device__ __host__ grid_gpu_ker(const linearizer & g1)
208  :g1(g1)
209  {
210  }
211 
212  __device__ __host__ grid_gpu_ker(const grid_gpu_ker & cpy)
213  :g1(cpy.g1)
214  {
216  }
217 
218  __device__ __host__ void constructor_impl(const grid_gpu_ker & cpy)
219  {
220  g1 = cpy.g1;
222  }
223 
224  __device__ __host__ void constructor_impl(const grid_gpu_ker_ref<dim,T,layout_base,linearizer> & cpy)
225  {
226  g1 = cpy.ggk.g1;
227  grid_gpu_ker_constructor_impl<is_layout_inte<layout_base<T_>>::value,T_>::construct(cpy.ggk,*this);
228  }
229 
237  __device__ __host__ const grid_sm<dim,void> & getGrid() const
238  {
239  return g1;
240  }
241 
249  template <unsigned int p, typename ids_type,typename r_type=decltype(layout_base<T_>::template get<p>(data_,g1,grid_key_dx<dim>()))>
250  __device__ __host__ inline r_type get(const grid_key_dx<dim,ids_type> & v1)
251  {
252 #ifdef SE_CLASS1
253  if (check_bound(v1) == false)
254  {fill_grid_error_array_overflow<dim,p>(this->template getPointer<p>(),v1);}
255 #endif
256 
257  return layout_base<T_>::template get<p>(data_,g1,v1);
258  }
259 
267  template <unsigned int p, typename ids_type, typename r_type=decltype(layout_base<T_>::template get<p>(data_,g1,grid_key_dx<dim>()))>
268  __device__ __host__ inline r_type get_debug(const grid_key_dx<dim,ids_type> & v1) const
269  {
270 #ifdef SE_CLASS1
271  if (check_bound(v1) == false)
272  {fill_grid_error_array_overflow<dim,p>(this->template getPointer<p>(),v1);}
273 #endif
274 
275  return layout_base<T_>::template get<p>(data_,g1,v1);
276  }
277 
285  template <unsigned int p, typename ids_type, typename r_type=decltype(layout_base<T_>::template get<p>(data_,g1,grid_key_dx<dim>()))>
286  __device__ __host__ inline r_type get(const grid_key_dx<dim,ids_type> & v1) const
287  {
288 #ifdef SE_CLASS1
289  if (check_bound(v1) == false)
290  {fill_grid_error_array_overflow<dim,p>(this->template getPointer<p>(),v1);}
291 #endif
292  return layout_base<T_>::template get<p>(data_,g1,v1);
293  }
294 
302  template <unsigned int p, typename r_type=decltype(layout_base<T_>::template get_lin<p>(data_,g1,0))>
303  __device__ __host__ inline r_type get(const size_t lin_id)
304  {
305 #ifdef SE_CLASS1
306  if (check_bound(lin_id) == false)
307  {fill_grid_error_array_overflow<p>(this->getPointer(),lin_id);}
308 #endif
309  return layout_base<T_>::template get_lin<p>(data_,g1,lin_id);
310  }
311 
319  template <unsigned int p, typename r_type=decltype(layout_base<T_>::template get_lin<p>(data_,g1,0))>
320  __device__ __host__ inline const r_type get(size_t lin_id) const
321  {
322 #ifdef SE_CLASS1
323  if (check_bound(lin_id) == false)
324  {fill_grid_error_array_overflow<p>(this->getPointer(),lin_id);}
325 #endif
326  return layout_base<T_>::template get_lin<p>(data_,g1,lin_id);
327  }
328 
340  template<typename Tk>
341  __device__ inline encapc<dim,T_,layout> get_o(const grid_key_dx<dim,Tk> & v1)
342  {
343 #ifdef SE_CLASS1
344  if (check_bound(v1) == false)
345  {fill_grid_error_array_overflow<dim,-1>(this->template getPointer<0>(),v1);}
346 #endif
347  return mem_geto<dim,T_,layout_base<T_>,decltype(this->data_),decltype(this->g1),decltype(v1)>::get(data_,g1,v1);
348  }
349 
361  template<typename Tk>
362  __device__ inline const encapc<dim,T_,layout> get_o(const grid_key_dx<dim,Tk> & v1) const
363  {
364 #ifdef SE_CLASS1
365  if (check_bound(v1) == false)
366  {fill_grid_error_array_overflow<dim,-1>(this->template getPointer<0>(),v1);}
367 #endif
368  return mem_geto<dim,T,layout_base<T_>,decltype(this->data_),decltype(this->g1),decltype(v1)>::get(const_cast<decltype(this->data_) &>(data_),g1,v1);
369  }
370 
371 
372  __device__ inline void set(const grid_key_dx<dim> & key1,const grid_gpu_ker<dim,T_,layout_base, linearizer> & g, const grid_key_dx<dim> & key2)
373  {
374 #ifdef SE_CLASS1
375  if (check_bound(key1) == false)
376  {fill_grid_error_array_overflow<dim,-1>(this->template getPointer<0>(),key1);}
377 
378  if (g.check_bound(key2) == false)
379  {fill_grid_error_array_overflow<dim,-1>(g.template getPointer<0>(),key2);}
380 
381 #endif
382 
383  this->get_o(key1) = g.get_o(key2);
384  }
385 
386  template<unsigned int ... prp> __device__ inline void set(const grid_key_dx<dim> & key1,const grid_gpu_ker<dim,T_,layout_base, linearizer> & g, const grid_key_dx<dim> & key2)
387  {
388 #ifdef SE_CLASS1
389  if (check_bound(key1) == false)
390  {fill_grid_error_array_overflow<dim,-1>(this->template getPointer<0>(),key1);}
391 
392  if (g.check_bound(key2) == false)
393  {fill_grid_error_array_overflow<dim,-1>(g.template getPointer<0>(),key2);}
394 
395 #endif
396 
397  auto edest = this->get_o(key1);
398  auto esrc = g.get_o(key2);
399 
400  copy_cpu_encap_encap_prp<decltype(g.get_o(key2)),decltype(this->get_o(key1)),prp...> ec(esrc,edest);
401 
402  boost::mpl::for_each_ref<boost::mpl::range_c<int,0,sizeof...(prp)>>(ec);
403  }
404 
413  template<typename Memory> __device__ inline void set(grid_key_dx<dim> key1, const encapc<1,T,Memory> & obj)
414  {
415 #ifdef SE_CLASS1
416  if (check_bound(key1) == false)
417  {fill_grid_error_array_overflow<dim,-1>(this->template getPointer<0>(),key1);}
418 #endif
419 
420  this->get_o(key1) = obj;
421  }
422 
428  template<unsigned int p> __device__ __host__ void * getPointer()
429  {
430  return mem_getpointer<decltype(data_),layout_base<T>>::template getPointer<p>(data_);
431  }
432 
438  template<unsigned int p> __device__ __host__ const void * getPointer() const
439  {
440  return mem_getpointer<decltype(data_),layout_base<T>>::template getPointer<p>(data_);
441  }
442 
449  {
450  g1 = g.g1;
451 
453 
454  return *this;
455  }
456 
463  struct ite_gpu<dim> getGPUIterator(grid_key_dx<dim> & key1, grid_key_dx<dim> & key2, size_t n_thr = default_kernel_wg_threads_) const
464  {
465  return getGPUIterator_impl<dim>(g1,key1,key2,n_thr);
466  }
467 
473  __device__ __host__ inline layout & get_data_()
474  {
475  return data_;
476  }
477 
483  __device__ __host__ inline const layout & get_data_() const
484  {
485  return data_;
486  }
487 };
488 
489 // This is an abstraction for reference type. It exist because the compiler by C++ starndard even if we return a reference deduce
490 // as value. To force as reference we have to create an object grid_gpu_ker_ref that emulate the reference concept
491 
492 template<unsigned int dim, typename T, template <typename> class layout_base, typename linearizer>
493 class grid_gpu_ker_ref
494 {
496 
497  typedef typename apply_transform<layout_base,T>::type T_;
498 
499  typedef typename layout_base<T_>::type layout;
500 
501 public:
502 
504  typedef int yes_i_am_grid;
505 
507  typedef T value_type;
508 
510  static constexpr unsigned int dims = dim;
511 
512  __device__ __host__ grid_gpu_ker_ref()
513  {}
514 
516  :ggk(ggk)
517  {}
518 
519 
520  __device__ __host__ const grid_sm<dim,void> & getGrid() const
521  {
522  return ggk.getGrid();
523  }
524 
525  __device__ __host__ size_t size() const
526  {
527  return ggk.getGrid().size();
528  }
529 
530  template <unsigned int p, typename ids_type>
531  __device__ __host__ inline auto get(const grid_key_dx<dim,ids_type> & v1) -> decltype(ggk.template get<p>(v1))
532  {
533  return ggk.template get<p>(v1);
534  }
535 
536  template <unsigned int p, typename ids_type>
537  __device__ __host__ inline auto get(const grid_key_dx<dim,ids_type> & v1) const -> decltype(ggk.template get<p>(v1))
538  {
539  return ggk.template get<p>(v1);
540  }
541 
542  template <unsigned int p>
543  __device__ __host__ inline auto get(const size_t lin_id) -> decltype(ggk.template get<p>(lin_id))
544  {
545  return ggk.template get<p>(lin_id);
546  }
547 
548  template <unsigned int p>
549  __device__ __host__ inline auto get(size_t lin_id) const -> decltype(ggk.template get<p>(lin_id))
550  {
551  return ggk.template get<p>(lin_id);
552  }
553 
554  template<typename Tk>
555  __device__ inline auto get_o(const grid_key_dx<dim,Tk> & v1) -> decltype(ggk.get_o(v1))
556  {
557  return ggk.get_o(v1);
558  }
559 
560  template<typename Tk>
561  __device__ inline auto get_o(const grid_key_dx<dim,Tk> & v1) const -> decltype(ggk.get_o(v1))
562  {
563  return ggk.get_o(v1);
564  }
565 
566 
567  __device__ inline void set(const grid_key_dx<dim> & key1,const grid_gpu_ker<dim,T_,layout_base, linearizer> & g, const grid_key_dx<dim> & key2)
568  {
569  ggk.set(key1,g,key2);
570  }
571 
572  template<unsigned int ... prp> __device__ inline void set(const grid_key_dx<dim> & key1,const grid_gpu_ker<dim,T_,layout_base, linearizer> & g, const grid_key_dx<dim> & key2)
573  {
574  ggk.template set<prp ...>(key1,g,key2);
575  }
576 
577  template<typename Memory> __device__ inline void set(grid_key_dx<dim> key1, const encapc<1,T,Memory> & obj)
578  {
579  ggk.set(key1,obj);
580  }
581 
582  template<unsigned int p> __device__ __host__ void * getPointer()
583  {
584  return ggk.template getPointer<p>();
585  }
586 
587  template<unsigned int p> __device__ __host__ const void * getPointer() const
588  {
589  return ggk.template getPointer<p>();
590  }
591 
593  {
594  ggk.operator=(g);
595 
596  return *this;
597  }
598 
599  struct ite_gpu<dim> getGPUIterator(grid_key_dx<dim> & key1, grid_key_dx<dim> & key2, size_t n_thr = default_kernel_wg_threads_) const
600  {
601  return ggk.getGPUIterator(key1,key2,n_thr);
602  }
603 
604  __device__ __host__ inline layout & get_data_()
605  {
606  return ggk.get_data_();
607  }
608 
609  __device__ __host__ inline const layout & get_data_() const
610  {
611  return ggk.get_data_();
612  }
613 
614  const grid_gpu_ker_ref & toKernel() const
615  {
616  return *this;
617  }
618 
619  friend class grid_gpu_ker<dim,T,layout_base,linearizer>;
620 };
621 
622 #endif /* MAP_GRID_CUDA_KER_HPP_ */
T value_type
Type of the value the vector is storing.
__device__ const encapc< dim, T_, layout > get_o(const grid_key_dx< dim, Tk > &v1) const
Get the of the selected element as a boost::fusion::vector.
void operator()(T &t)
It call the copy function for each property.
this class is a functor for "for_each" algorithm
__device__ __host__ const layout & get_data_() const
Get the internal data_ structure.
const T_type_src & src
encapsulated source object
__device__ __host__ size_t size() const
Return the size of the grid.
Definition: grid_sm.hpp:637
static constexpr unsigned int dims
expose the dimansionality as a static const
__device__ __host__ index_type get(index_type i) const
Get the i index.
Definition: grid_key.hpp:503
__device__ void set(grid_key_dx< dim > key1, const encapc< 1, T, Memory > &obj)
set an element of the grid
grid interface available when on gpu
__device__ __host__ bool check_bound(size_t v1) const
Check that the key is inside the grid.
T_type_dst & dst
encapsulated destination object
__device__ __host__ const grid_sm< dim, void > & getGrid() const
Return the internal grid information.
Case memory_traits_lin.
Definition: Encap.hpp:925
layout_base< T_ >::type layout
type of layout of the structure
__device__ encapc< dim, T_, layout > get_o(const grid_key_dx< dim, Tk > &v1)
Get the of the selected element as a boost::fusion::vector.
copy_switch_memory_c_no_cpy(const T_type_src &src, T_type_dst &dst)
constructor
this class is a functor for "for_each" algorithm
Definition: Encap.hpp:32
linearizer g1
grid information
__device__ __host__ const r_type get(size_t lin_id) const
Get the const reference of the selected element.
KeyT const ValueT ValueT OffsetIteratorT OffsetIteratorT int
[in] The number of segments that comprise the sorting data
__device__ __host__ r_type get_debug(const grid_key_dx< dim, ids_type > &v1) const
Get the const reference of the selected element.
struct ite_gpu< dim > getGPUIterator(grid_key_dx< dim > &key1, grid_key_dx< dim > &key2, size_t n_thr=default_kernel_wg_threads_) const
Get an iterator for the GPU.
__device__ __host__ const void * getPointer() const
Get the pointer for the property p.
__device__ __host__ r_type get(const grid_key_dx< dim, ids_type > &v1)
Get the reference of the selected element.
grid_gpu_ker< dim, T_, layout_base, linearizer > & operator=(const grid_gpu_ker< dim, T_, layout_base, linearizer > &g)
operator= this operator absorb the pointers, consider that this object wrap device pointers
int yes_i_am_grid
it define that it is a grid
int yes_i_am_grid
it define that it is a grid
T value_type
Type of the value the vector is storing.
__device__ __host__ layout & get_data_()
Get the internal data_ structure.
__device__ __host__ r_type get(const size_t lin_id)
Get the reference of the selected element.
layout data_
layout data
__device__ __host__ bool check_bound(const grid_key_dx< dim, ids_type > &v1) const
Check that the key is inside the grid.
__device__ __host__ void * getPointer()
Get the pointer for the property p.
apply_transform< layout_base, T >::type T_
Type T.
__device__ __host__ r_type get(const grid_key_dx< dim, ids_type > &v1) const
Get the const reference of the selected element.