OpenFPM  5.2.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  auto &grid_layout = boost::fusion::at_c<T::value>(dst);
59 
60  grid_layout.disable_manage_memory();
61  grid_layout.mem = boost::fusion::at_c<T::value>(src).mem;
62  grid_layout.mem_r.bind_ref(boost::fusion::at_c<T::value>(src).mem_r);
63 #ifdef CUDA_GPU
64  if (grid_layout.mem)
65  {grid_layout.mem_r.set_pointer(((CudaMemory*)grid_layout.mem)->getDevicePointer());}
66 #endif
67  }
68 };
69 
70 template<bool inte_or_lin,typename T>
72 {
73  template<typename ggk_type> static inline void construct(const ggk_type & cpy,ggk_type & this_)
74  {
75  copy_switch_memory_c_no_cpy<decltype(cpy.get_data_()),decltype(this_.get_data_())> bp_mc(cpy.get_data_(),this_.get_data_());
76 
77  boost::mpl::for_each_ref< boost::mpl::range_c<int,0,T::max_prop> >(bp_mc);
78  }
79 };
80 
81 template<typename T>
83 {
84  template<typename ggk_type> static inline void construct(const ggk_type & cpy,ggk_type & this_)
85  {
86  auto &grid_layout = this_.get_data_();
87 
88  grid_layout.disable_manage_memory();
89  grid_layout.mem = cpy.get_data_().mem;
90  grid_layout.mem_r.bind_ref(cpy.get_data_().mem_r);
91 
92 #ifdef CUDA_GPU
93  if (grid_layout.mem)
94  {grid_layout.mem_r.set_pointer(((CudaMemory*)grid_layout.mem)->getDevicePointer());}
95 #endif
96  }
97 };
98 
99 template<unsigned int dim, int prp, typename ids_type>
100 __device__ void fill_grid_error_array_overflow(const void * sptr,grid_key_dx<dim,ids_type> key)
101 {
102 #ifdef CUDA_GPU
103 
104  int * ptr = (int *)&global_cuda_error_array[0];
105 
106  ptr[0] = 1;
107  ptr[1] = ((size_t)sptr) & 0xFFFFFFFF;
108  ptr[2] = (((size_t)sptr) & 0xFFFFFFFF00000000) >> 32;
109  ptr[3] = prp;
110  ptr[4] = dim;
111 
112  for (int i = 0 ; i < dim ; i++)
113  {ptr[i+5] = key.get(i);}
114 
115 #ifdef __NVCC__
116 
117  ptr[5+dim] = blockIdx.x;
118  ptr[6+dim] = blockIdx.y;
119  ptr[7+dim] = blockIdx.z;
120 
121  ptr[8+dim] = blockDim.x;
122  ptr[9+dim] = blockDim.y;
123  ptr[10+dim] = blockDim.z;
124 
125  ptr[11+dim] = threadIdx.x;
126  ptr[12+dim] = threadIdx.y;
127  ptr[13+dim] = threadIdx.z;
128 
129 #endif
130 
131 #endif
132 }
133 
134 template<unsigned int dim>
135 __device__ void fill_grid_error_array(size_t lin_id)
136 {
137 #ifdef CUDA_GPU
138 
139  int * ptr = (int *)&global_cuda_error_array[0];
140 
141  ptr[0] = 1;
142  ptr[1] = 1;
143  ptr[2] = lin_id;
144 
145 #endif
146 }
147 
148 template<unsigned int dim, typename T, template <typename> class layout_base, typename linearizer>
149 class grid_gpu_ker_ref;
150 
156 template<unsigned int dim, typename T, template <typename> class layout_base, typename linearizer>
158 {
160  typedef typename apply_transform<layout_base,T>::type T_;
161 
163  linearizer g1;
164 
166  typedef typename layout_base<T_>::type layout;
167 
169  mutable layout data_;
170 
171 
172 
180  template<typename ids_type> __device__ __host__ inline bool check_bound(const grid_key_dx<dim,ids_type> & v1) const
181  {
182  for (long int i = 0 ; i < dim ; i++)
183  {
184  if (v1.get(i) >= (long int)getGrid().size(i))
185  {return false;}
186  else if (v1.get(i) < 0)
187  {return false;}
188  }
189  return true;
190  }
191 
199  __device__ __host__ inline bool check_bound(size_t v1) const
200  {
201  return v1 < getGrid().size();
202  }
203 
204 public:
205 
207  typedef int yes_i_am_grid;
208 
210  typedef T value_type;
211 
212  __device__ __host__ grid_gpu_ker()
213  {}
214 
215  __device__ __host__ grid_gpu_ker(const linearizer & g1)
216  :g1(g1)
217  {
218  }
219 
220  __device__ __host__ grid_gpu_ker(const grid_gpu_ker & cpy)
221  :g1(cpy.g1)
222  {
224  }
225 
226  __device__ __host__ void constructor_impl(const grid_gpu_ker & cpy)
227  {
228  g1 = cpy.g1;
230  }
231 
232  __device__ __host__ void constructor_impl(const grid_gpu_ker_ref<dim,T,layout_base,linearizer> & cpy)
233  {
234  g1 = cpy.ggk.g1;
235  grid_gpu_ker_constructor_impl<is_layout_inte<layout_base<T_>>::value,T_>::construct(cpy.ggk,*this);
236  }
237 
245  __device__ __host__ const grid_sm<dim,void> & getGrid() const
246  {
247  return g1;
248  }
249 
257  template <unsigned int p, typename ids_type,typename r_type=decltype(layout_base<T_>::template get<p>(data_,g1,grid_key_dx<dim>()))>
258  __device__ __host__ inline r_type get(const grid_key_dx<dim,ids_type> & v1)
259  {
260 #ifdef SE_CLASS1
261  if (check_bound(v1) == false)
262  {fill_grid_error_array_overflow<dim,p>(this->template getPointer<p>(),v1);}
263 #endif
264 
265  return layout_base<T_>::template get<p>(data_,g1,v1);
266  }
267 
275  template <unsigned int p, typename ids_type, typename r_type=decltype(layout_base<T_>::template get<p>(data_,g1,grid_key_dx<dim>()))>
276  __device__ __host__ inline r_type get_debug(const grid_key_dx<dim,ids_type> & v1) const
277  {
278 #ifdef SE_CLASS1
279  if (check_bound(v1) == false)
280  {fill_grid_error_array_overflow<dim,p>(this->template getPointer<p>(),v1);}
281 #endif
282 
283  return layout_base<T_>::template get<p>(data_,g1,v1);
284  }
285 
293  template <unsigned int p, typename ids_type, typename r_type=decltype(layout_base<T_>::template get<p>(data_,g1,grid_key_dx<dim>()))>
294  __device__ __host__ inline r_type get(const grid_key_dx<dim,ids_type> & v1) const
295  {
296 #ifdef SE_CLASS1
297  if (check_bound(v1) == false)
298  {fill_grid_error_array_overflow<dim,p>(this->template getPointer<p>(),v1);}
299 #endif
300  return layout_base<T_>::template get<p>(data_,g1,v1);
301  }
302 
310  template <unsigned int p, typename r_type=decltype(layout_base<T_>::template get_lin<p>(data_,g1,0))>
311  __device__ __host__ inline r_type get(const size_t lin_id)
312  {
313 #ifdef SE_CLASS1
314  if (check_bound(lin_id) == false)
315  {fill_grid_error_array_overflow<p>(this->getPointer(),lin_id);}
316 #endif
317  return layout_base<T_>::template get_lin<p>(data_,g1,lin_id);
318  }
319 
327  template <unsigned int p, typename r_type=decltype(layout_base<T_>::template get_lin<p>(data_,g1,0))>
328  __device__ __host__ inline const r_type get(size_t lin_id) const
329  {
330 #ifdef SE_CLASS1
331  if (check_bound(lin_id) == false)
332  {fill_grid_error_array_overflow<p>(this->getPointer(),lin_id);}
333 #endif
334  return layout_base<T_>::template get_lin<p>(data_,g1,lin_id);
335  }
336 
348  template<typename Tk>
349  __device__ inline encapc<dim,T_,layout> get_o(const grid_key_dx<dim,Tk> & v1)
350  {
351 #ifdef SE_CLASS1
352  if (check_bound(v1) == false)
353  {fill_grid_error_array_overflow<dim,-1>(this->template getPointer<0>(),v1);}
354 #endif
355  return mem_geto<dim,T_,layout_base<T_>,decltype(this->data_),decltype(this->g1),decltype(v1)>::get(data_,g1,v1);
356  }
357 
369  template<typename Tk>
370  __device__ inline const encapc<dim,T_,layout> get_o(const grid_key_dx<dim,Tk> & v1) const
371  {
372 #ifdef SE_CLASS1
373  if (check_bound(v1) == false)
374  {fill_grid_error_array_overflow<dim,-1>(this->template getPointer<0>(),v1);}
375 #endif
376  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);
377  }
378 
379 
380  __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)
381  {
382 #ifdef SE_CLASS1
383  if (check_bound(key1) == false)
384  {fill_grid_error_array_overflow<dim,-1>(this->template getPointer<0>(),key1);}
385 
386  if (g.check_bound(key2) == false)
387  {fill_grid_error_array_overflow<dim,-1>(g.template getPointer<0>(),key2);}
388 
389 #endif
390 
391  this->get_o(key1) = g.get_o(key2);
392  }
393 
394  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)
395  {
396 #ifdef SE_CLASS1
397  if (check_bound(key1) == false)
398  {fill_grid_error_array_overflow<dim,-1>(this->template getPointer<0>(),key1);}
399 
400  if (g.check_bound(key2) == false)
401  {fill_grid_error_array_overflow<dim,-1>(g.template getPointer<0>(),key2);}
402 
403 #endif
404 
405  auto edest = this->get_o(key1);
406  auto esrc = g.get_o(key2);
407 
408  copy_cpu_encap_encap_prp<decltype(g.get_o(key2)),decltype(this->get_o(key1)),prp...> ec(esrc,edest);
409 
410  boost::mpl::for_each_ref<boost::mpl::range_c<int,0,sizeof...(prp)>>(ec);
411  }
412 
421  template<typename Memory> __device__ inline void set(grid_key_dx<dim> key1, const encapc<1,T,Memory> & obj)
422  {
423 #ifdef SE_CLASS1
424  if (check_bound(key1) == false)
425  {fill_grid_error_array_overflow<dim,-1>(this->template getPointer<0>(),key1);}
426 #endif
427 
428  this->get_o(key1) = obj;
429  }
430 
436  template<unsigned int p> __device__ __host__ void * getPointer()
437  {
438  return mem_getpointer<decltype(data_),layout_base<T>>::template getPointer<p>(data_);
439  }
440 
446  template<unsigned int p> __device__ __host__ const void * getPointer() const
447  {
448  return mem_getpointer<decltype(data_),layout_base<T>>::template getPointer<p>(data_);
449  }
450 
457  {
458  g1 = g.g1;
459 
461 
462  return *this;
463  }
464 
471  struct ite_gpu<dim> getGPUIterator(grid_key_dx<dim> & key1, grid_key_dx<dim> & key2, size_t n_thr = default_kernel_wg_threads_) const
472  {
473  return getGPUIterator_impl<dim>(g1,key1,key2,n_thr);
474  }
475 
481  __device__ __host__ inline layout & get_data_()
482  {
483  return data_;
484  }
485 
491  __device__ __host__ inline const layout & get_data_() const
492  {
493  return data_;
494  }
495 };
496 
497 // This is an abstraction for reference type. It exist because the compiler by C++ starndard even if we return a reference deduce
498 // as value. To force as reference we have to create an object grid_gpu_ker_ref that emulate the reference concept
499 
500 template<unsigned int dim, typename T, template <typename> class layout_base, typename linearizer>
502 {
504 
505  typedef typename apply_transform<layout_base,T>::type T_;
506 
507  typedef typename layout_base<T_>::type layout;
508 
509 public:
510 
512  typedef int yes_i_am_grid;
513 
515  typedef T value_type;
516 
518  static constexpr unsigned int dims = dim;
519 
520  __device__ __host__ grid_gpu_ker_ref()
521  {}
522 
524  :ggk(ggk)
525  {}
526 
527 
528  __device__ __host__ const grid_sm<dim,void> & getGrid() const
529  {
530  return ggk.getGrid();
531  }
532 
533  __device__ __host__ size_t size() const
534  {
535  return ggk.getGrid().size();
536  }
537 
538  template <unsigned int p, typename ids_type>
539  __device__ __host__ inline auto get(const grid_key_dx<dim,ids_type> & v1) -> decltype(ggk.template get<p>(v1))
540  {
541  return ggk.template get<p>(v1);
542  }
543 
544  template <unsigned int p, typename ids_type>
545  __device__ __host__ inline auto get(const grid_key_dx<dim,ids_type> & v1) const -> decltype(ggk.template get<p>(v1))
546  {
547  return ggk.template get<p>(v1);
548  }
549 
550  template <unsigned int p>
551  __device__ __host__ inline auto get(const size_t lin_id) -> decltype(ggk.template get<p>(lin_id))
552  {
553  return ggk.template get<p>(lin_id);
554  }
555 
556  template <unsigned int p>
557  __device__ __host__ inline auto get(size_t lin_id) const -> decltype(ggk.template get<p>(lin_id))
558  {
559  return ggk.template get<p>(lin_id);
560  }
561 
562  template<typename Tk>
563  __device__ inline auto get_o(const grid_key_dx<dim,Tk> & v1) -> decltype(ggk.get_o(v1))
564  {
565  return ggk.get_o(v1);
566  }
567 
568  template<typename Tk>
569  __device__ inline auto get_o(const grid_key_dx<dim,Tk> & v1) const -> decltype(ggk.get_o(v1))
570  {
571  return ggk.get_o(v1);
572  }
573 
574 
575  __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)
576  {
577  ggk.set(key1,g,key2);
578  }
579 
580  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)
581  {
582  ggk.template set<prp ...>(key1,g,key2);
583  }
584 
585  template<typename Memory> __device__ inline void set(grid_key_dx<dim> key1, const encapc<1,T,Memory> & obj)
586  {
587  ggk.set(key1,obj);
588  }
589 
590  template<unsigned int p> __device__ __host__ void * getPointer()
591  {
592  return ggk.template getPointer<p>();
593  }
594 
595  template<unsigned int p> __device__ __host__ const void * getPointer() const
596  {
597  return ggk.template getPointer<p>();
598  }
599 
601  {
602  ggk.operator=(g);
603 
604  return *this;
605  }
606 
607  struct ite_gpu<dim> getGPUIterator(grid_key_dx<dim> & key1, grid_key_dx<dim> & key2, size_t n_thr = default_kernel_wg_threads_) const
608  {
609  return ggk.getGPUIterator(key1,key2,n_thr);
610  }
611 
612  __device__ __host__ inline layout & get_data_()
613  {
614  return ggk.get_data_();
615  }
616 
617  __device__ __host__ inline const layout & get_data_() const
618  {
619  return ggk.get_data_();
620  }
621 
622  const grid_gpu_ker_ref & toKernel() const
623  {
624  return *this;
625  }
626 
627  friend class grid_gpu_ker<dim,T,layout_base,linearizer>;
628 };
629 
630 #endif /* MAP_GRID_CUDA_KER_HPP_ */
T value_type
Type of the value the vector is storing.
int yes_i_am_grid
it define that it is a grid
static constexpr unsigned int dims
expose the dimansionality as a static const
grid interface available when on gpu
__device__ __host__ bool check_bound(size_t v1) const
Check that the key is inside the grid.
__device__ __host__ r_type get(const size_t lin_id)
Get the reference of the selected element.
__device__ __host__ const layout & get_data_() const
Get the internal data_ structure.
__device__ __host__ bool check_bound(const grid_key_dx< dim, ids_type > &v1) const
Check that the key is inside the grid.
__device__ __host__ layout & get_data_()
Get the internal data_ structure.
__device__ __host__ r_type get(const grid_key_dx< dim, ids_type > &v1)
Get the reference of the selected element.
apply_transform< layout_base, T >::type T_
Type T.
__device__ __host__ void * getPointer()
Get the pointer for the property p.
int yes_i_am_grid
it define that it is a grid
__device__ __host__ const void * getPointer() const
Get the pointer for the property p.
__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.
layout data_
layout data
__device__ __host__ const r_type get(size_t lin_id) const
Get the const reference of the selected element.
__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.
__device__ void set(grid_key_dx< dim > key1, const encapc< 1, T, Memory > &obj)
set an element of the grid
__device__ __host__ r_type get_debug(const grid_key_dx< dim, ids_type > &v1) const
Get the const 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
__device__ __host__ r_type get(const grid_key_dx< dim, ids_type > &v1) const
Get the const reference of the selected element.
__device__ __host__ const grid_sm< dim, void > & getGrid() const
Return the internal grid information.
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.
layout_base< T_ >::type layout
type of layout of the structure
T value_type
Type of the value the vector is storing.
linearizer g1
grid information
grid_key_dx is the key to access any element in the grid
Definition: grid_key.hpp:19
__device__ __host__ index_type get(index_type i) const
Get the i index.
Definition: grid_key.hpp:503
__device__ __host__ size_t size() const
Return the size of the grid.
Definition: grid_sm.hpp:657
KeyT const ValueT ValueT OffsetIteratorT OffsetIteratorT int
[in] The number of segments that comprise the sorting data
this class is a functor for "for_each" algorithm
Definition: Encap.hpp:33
this class is a functor for "for_each" algorithm
copy_switch_memory_c_no_cpy(const T_type_src &src, T_type_dst &dst)
constructor
const T_type_src & src
encapsulated source object
void operator()(T &t)
It call the copy function for each property.
T_type_dst & dst
encapsulated destination object
Case memory_traits_lin.
Definition: Encap.hpp:926