OpenFPM  5.2.0
Project that contain the implementation of distributed structures
vector_dist_operators_functions.hpp
1 /*
2  * vector_dist_operators_functions.hpp
3  *
4  * Created on: Jul 17, 2016
5  * Author: i-bird
6  */
7 
8 #ifndef OPENFPM_NUMERICS_SRC_OPERATORS_VECTOR_VECTOR_DIST_OPERATORS_FUNCTIONS_HPP_
9 #define OPENFPM_NUMERICS_SRC_OPERATORS_VECTOR_VECTOR_DIST_OPERATORS_FUNCTIONS_HPP_
10 
11 #ifdef __NVCC__
12 #include "cuda/vector_dist_operators_cuda.cuh"
13 #endif
14 
15 
22 #define CREATE_VDIST_ARG_FUNC(fun_base,fun_name,OP_ID) \
23 \
24 \
25 template <typename exp1>\
26 class vector_dist_expression_op<exp1,void,OP_ID>\
27 {\
28  const exp1 o1;\
29 \
30 public:\
31 \
32  typedef typename exp1::is_ker is_ker;\
33 \
34  typedef typename vector_result<typename exp1::vtype,void>::type vtype;\
35 \
36  typedef typename nn_type_result<typename exp1::NN_type,void>::type NN_type;\
37 \
38  vector_dist_expression_op(const exp1 & o1)\
39  :o1(o1)\
40  {}\
41 \
42  inline NN_type * getNN()\
43  {\
44  return nn_type_result<typename exp1::NN_type,void>::getNN(o1);\
45  }\
46 \
47  const vtype & getVector()\
48  {\
49  return vector_result<typename exp1::vtype,void>::getVector(o1);\
50  }\
51 \
52  inline const exp1 & getExpr() const\
53  {\
54  return o1;\
55  }\
56  \
57  inline void init() const\
58  {\
59  o1.init();\
60  }\
61 \
62  template<typename r_type=typename std::remove_reference<decltype(fun_base(o1.value(vect_dist_key_dx(0))))>::type > \
63  __device__ __host__ inline r_type value(const vect_dist_key_dx & key) const\
64  {\
65  return fun_base(o1.value(key));\
66  }\
67 \
68  template<typename r_type=typename std::remove_reference<decltype(fun_base(o1.value(vect_dist_key_dx(0))))>::type > \
69  __device__ __host__ inline r_type value(const unsigned int & key) const\
70  {\
71  return fun_base(o1.value(key));\
72  }\
73  \
74  const vtype & getVector() const\
75  {\
76  return o1.getVector();\
77  }\
78  \
79 };\
80 \
81 \
82 template<typename exp1, typename exp2_, unsigned int op1>\
83 inline vector_dist_expression_op<vector_dist_expression_op<exp1,exp2_,op1>,void,OP_ID>\
84 fun_name(const vector_dist_expression_op<exp1,exp2_,op1> & va)\
85 {\
86  vector_dist_expression_op<vector_dist_expression_op<exp1,exp2_,op1>,void,OP_ID> exp_sum(va);\
87 \
88  return exp_sum;\
89 }\
90 \
91 \
92 template<unsigned int prp1, typename v1>\
93 inline vector_dist_expression_op<vector_dist_expression<prp1,v1>,void,OP_ID>\
94 fun_name(const vector_dist_expression<prp1,v1> & va)\
95 {\
96  vector_dist_expression_op<vector_dist_expression<prp1,v1>,void,OP_ID> exp_sum(va);\
97 \
98  return exp_sum;\
99 }
100 
101 CREATE_VDIST_ARG_FUNC(norm,norm,VECT_NORM)
102 CREATE_VDIST_ARG_FUNC(norm2,norm2,VECT_NORM2)
103 CREATE_VDIST_ARG_FUNC(abs,abs,POINT_ABS)
104 CREATE_VDIST_ARG_FUNC(exp,exp,POINT_EXP)
105 CREATE_VDIST_ARG_FUNC(exp2,exp2,POINT_EXP2)
106 CREATE_VDIST_ARG_FUNC(expm1,expm1,POINT_EXPM1)
107 CREATE_VDIST_ARG_FUNC(log,log,POINT_LOG)
108 CREATE_VDIST_ARG_FUNC(log10,log10,POINT_LOG10)
109 CREATE_VDIST_ARG_FUNC(log2,log2,POINT_LOG2)
110 CREATE_VDIST_ARG_FUNC(log1p,log1p,POINT_LOG1P)
111 CREATE_VDIST_ARG_FUNC(sqrt,sqrt,POINT_SQRT)
112 CREATE_VDIST_ARG_FUNC(cbrt,cbrt,POINT_CBRT)
113 CREATE_VDIST_ARG_FUNC(sin,sin,POINT_SIN)
114 CREATE_VDIST_ARG_FUNC(cos,cos,POINT_COS)
115 CREATE_VDIST_ARG_FUNC(tan,tan,POINT_TAN)
116 CREATE_VDIST_ARG_FUNC(asin,asin,POINT_ASIN)
117 CREATE_VDIST_ARG_FUNC(acos,acos,POINT_ACOS)
118 CREATE_VDIST_ARG_FUNC(atan,atan,POINT_ATAN)
119 CREATE_VDIST_ARG_FUNC(sinh,sinh,POINT_SINH)
120 CREATE_VDIST_ARG_FUNC(cosh,cosh,POINT_COSH)
121 CREATE_VDIST_ARG_FUNC(tanh,tanh,POINT_TANH)
122 CREATE_VDIST_ARG_FUNC(asinh,asinh,POINT_ASINH)
123 CREATE_VDIST_ARG_FUNC(acosh,acosh,POINT_ACOSH)
124 CREATE_VDIST_ARG_FUNC(atanh,atanh,POINT_ATANH)
125 CREATE_VDIST_ARG_FUNC(erf,erf,POINT_ERF)
126 CREATE_VDIST_ARG_FUNC(erfc,erfc,POINT_ERFC)
127 CREATE_VDIST_ARG_FUNC(tgamma,tgamma,POINT_TGAMMA)
128 CREATE_VDIST_ARG_FUNC(lgamma,lgamma,POINT_LGAMMA)
129 CREATE_VDIST_ARG_FUNC(ceil,ceil,POINT_CEIL)
130 CREATE_VDIST_ARG_FUNC(floor,floor,POINT_FLOOR)
131 CREATE_VDIST_ARG_FUNC(trunc,trunc,POINT_TRUNC)
132 CREATE_VDIST_ARG_FUNC(round,round,POINT_ROUND)
133 CREATE_VDIST_ARG_FUNC(nearbyint,nearbyint,POINT_NEARBYINT)
134 CREATE_VDIST_ARG_FUNC(rint,rint,POINT_RINT)
135 
136 
137 
143 #define CREATE_VDIST_ARG2_FUNC(fun_base,fun_name,OP_ID) \
144 \
145 \
146 template <typename exp1,typename exp2>\
147 class vector_dist_expression_op<exp1,exp2,OP_ID>\
148 {\
149  const exp1 o1;\
150  const exp2 o2;\
151 \
152 public:\
153 \
154  typedef std::integral_constant<bool,exp1::is_ker::value || exp1::is_ker::value> is_ker;\
155 \
156  typedef typename vector_result<typename exp1::vtype,typename exp2::vtype>::type vtype;\
157 \
158  typedef typename nn_type_result<typename exp1::NN_type,typename exp2::NN_type>::type NN_type;\
159 \
160  inline NN_type * getNN()\
161  {\
162  return nn_type_result<typename exp1::NN_type,typename exp2::NN_type>::getNN(o1,o2);\
163  }\
164 \
165  vtype & getVector()\
166  {\
167  return vector_result<typename exp1::vtype,typename exp2::vtype>::getVector(o1,o2);\
168  }\
169  const vtype & getVector() const\
170  {\
171  return vector_result<typename exp1::vtype,typename exp2::vtype>::getVector(o1,o2);\
172  }\
173 \
174 \
175  vector_dist_expression_op(const exp1 & o1, const exp2 & o2)\
176  :o1(o1),o2(o2)\
177  {}\
178 \
179  inline void init() const\
180  {\
181  o1.init();\
182  o2.init();\
183  }\
184 \
185  template<typename r_type=typename std::remove_reference<decltype(fun_base(o1.value(vect_dist_key_dx(0)),o2.value(vect_dist_key_dx(0)) ))>::type > inline r_type value(const vect_dist_key_dx & key) const\
186  {\
187  return fun_base(o1.value(key),o2.value(key));\
188  }\
189 };\
190 \
191 \
192 template<unsigned int p1, unsigned int p2, typename v1, typename v2>\
193 inline vector_dist_expression_op<vector_dist_expression<p1,v1>,vector_dist_expression<p2,v2>,OP_ID>\
194 fun_name(const vector_dist_expression<p1,v1> & va, const vector_dist_expression<p2,v2> & vb)\
195 {\
196  vector_dist_expression_op<vector_dist_expression<p1,v1>,vector_dist_expression<p2,v2>,OP_ID> exp_sum(va,vb);\
197 \
198  return exp_sum;\
199 }\
200 \
201 template<typename exp1 , typename exp2, unsigned int op1, unsigned int prp1, typename v1>\
202 inline vector_dist_expression_op<vector_dist_expression_op<exp1,exp2,op1>,vector_dist_expression<prp1,v1>,OP_ID>\
203 fun_name(const vector_dist_expression_op<exp1,exp2,op1> & va, const vector_dist_expression<prp1,v1> & vb)\
204 {\
205  vector_dist_expression_op<vector_dist_expression_op<exp1,exp2,op1>,vector_dist_expression<prp1,v1>,OP_ID> exp_sum(va,vb);\
206 \
207  return exp_sum;\
208 }\
209 \
210 template<typename exp1 , typename exp2, unsigned int op1, unsigned int prp1, typename v1>\
211 inline vector_dist_expression_op<vector_dist_expression<prp1,v1>,vector_dist_expression_op<exp1,exp2,op1>,OP_ID>\
212 fun_name(const vector_dist_expression<prp1,v1> & va, const vector_dist_expression_op<exp1,exp2,op1> & vb)\
213 {\
214  vector_dist_expression_op<vector_dist_expression<prp1,v1>,vector_dist_expression_op<exp1,exp2,op1>,OP_ID> exp_sum(va,vb);\
215 \
216  return exp_sum;\
217 }\
218 \
219 template<typename exp1 , typename exp2, unsigned int op1, typename exp3 , typename exp4, unsigned int op2>\
220 inline vector_dist_expression_op<vector_dist_expression_op<exp1,exp2,op1>,vector_dist_expression_op<exp3,exp4,op2>,OP_ID>\
221 fun_name(const vector_dist_expression_op<exp1,exp2,op1> & va, const vector_dist_expression_op<exp3,exp4,op2> & vb)\
222 {\
223  vector_dist_expression_op<vector_dist_expression_op<exp1,exp2,op1>,vector_dist_expression_op<exp3,exp4,op2>,OP_ID> exp_sum(va,vb);\
224 \
225  return exp_sum;\
226 }\
227 \
228 template<unsigned int prp1 , typename v1>\
229 inline vector_dist_expression_op<vector_dist_expression<prp1,v1>,vector_dist_expression<0,double>,OP_ID>\
230 fun_name(const vector_dist_expression<prp1,v1> & va, double d)\
231 {\
232  vector_dist_expression_op<vector_dist_expression<prp1,v1>,vector_dist_expression<0,double>,OP_ID> exp_sum(va,vector_dist_expression<0,double>(d));\
233 \
234  return exp_sum;\
235 }\
236 \
237 template<unsigned int prp1 , typename v1>\
238 inline vector_dist_expression_op<vector_dist_expression<0,double>,vector_dist_expression<prp1,v1>,OP_ID>\
239 fun_name(double d, const vector_dist_expression<prp1,v1> & vb)\
240 {\
241  vector_dist_expression_op<vector_dist_expression<0,double>,vector_dist_expression<prp1,v1>,OP_ID> exp_sum(vector_dist_expression<0,double>(d),vb);\
242 \
243  return exp_sum;\
244 }\
245 \
246 template<typename exp1 , typename exp2, unsigned int op1>\
247 inline vector_dist_expression_op<vector_dist_expression_op<exp1,exp2,op1>,vector_dist_expression<0,double>,OP_ID>\
248 fun_name(const vector_dist_expression_op<exp1,exp2,op1> & va, double d)\
249 {\
250  vector_dist_expression_op<vector_dist_expression_op<exp1,exp2,op1>,vector_dist_expression<0,double>,OP_ID> exp_sum(va,vector_dist_expression<0,double>(d));\
251 \
252  return exp_sum;\
253 }\
254 \
255 template<typename exp1 , typename exp2, unsigned int op1>\
256 inline vector_dist_expression_op<vector_dist_expression<0,double>,vector_dist_expression_op<exp1,exp2,op1>,OP_ID>\
257 fun_name(double d, const vector_dist_expression_op<exp1,exp2,op1> & va)\
258 {\
259  vector_dist_expression_op<vector_dist_expression_op<exp1,exp2,op1>,vector_dist_expression<0,double>,OP_ID> exp_sum(vector_dist_expression<0,double>(d),va);\
260 \
261  return exp_sum;\
262 }
263 
264 CREATE_VDIST_ARG2_FUNC(pmul,pmul,VECT_PMUL)
265 
266 
268 template<typename val_type, bool is_scalar = is_Point<val_type>::type::value>
270 {
271  typedef aggregate<val_type> type;
272 
273  template<typename vector_type, typename expression>
274  static void process(val_type & val, vector_type & ve, expression & o1)
275  {
276 #ifdef __NVCC__
277 
278  auto vek = ve.toKernel();
280 
281  exp_tmp2[0].resize(sizeof(val_type));
282 
283  auto & v_cl = create_vcluster<CudaMemory>();
284 
285  openfpm::reduce((val_type *)ve.template getDeviceBuffer<0>(), ve.size(), (val_type *)(exp_tmp2[0].getDevicePointer()), gpu::plus_t<val_type>(), v_cl.getGpuContext());
286 
287  exp_tmp2[0].deviceToHost();
288 
289  val = *(val_type *)(exp_tmp2[0].getPointer());
290 #else
291  std::cout << __FILE__ << ":" << __LINE__ << " error: to make expression work on GPU the file must be compiled on GPU" << std::endl;
292 #endif
293  }
294 };
295 
296 template<typename val_type>
297 struct point_scalar_process<val_type,true>
298 {
299  typedef val_type type;
300 
301  template<typename vector_type, typename expression>
302  static void process(val_type & val, vector_type & ve, expression & o1)
303  {
304 #ifdef __NVCC__
305 
306 // auto ite = ve.getGPUIterator(256);
307 
308 // compute_expr_ker_vv<0,val_type::dims><<<ite.wthr,ite.thr>>>(ve.toKernel(),o1);
309 
310  auto vek = ve.toKernel();
311  vector_dist_op_compute_op<0,comp_dev>::template compute_expr_vv<val_type::dims>(vek,o1);
312 
313  exp_tmp2[0].resize(sizeof(val_type));
314 
315  size_t offset = 0;
316 
317  auto & v_cl = create_vcluster<CudaMemory>();
318 
319  for (size_t i = 0 ; i < val_type::dims ; i++)
320  {
321  openfpm::reduce(&((typename val_type::coord_type *)ve.template getDeviceBuffer<0>())[offset],
322  ve.size(),
323  (typename val_type::coord_type *)(exp_tmp2[0].getDevicePointer()),
325  v_cl.getGpuContext());
326 
327  exp_tmp2[0].deviceToHost();
328 
329  val.get(i) = *(typename val_type::coord_type *)exp_tmp2[0].getPointer();
330 
331  offset += ve.capacity();
332  }
333 
334 #else
335  std::cout << __FILE__ << ":" << __LINE__ << " error: to make expression work on GPU the file must be compiled on GPU" << std::endl;
336 #endif
337  }
338 };
339 
340 
341 template<bool is_device>
343 {
344  template<typename o1_type, typename val_type>
345  static void red(o1_type & o1, val_type & val)
346  {
347 
348 #ifdef __NVCC__
349 
350  // we have to do it on GPU
351 
353  CudaMemory,
356 
357  auto & orig_v = o1.getVector();
358 
359  if (exp_tmp.ref() == 0)
360  {exp_tmp.incRef();}
361 
362  ve.setMemory(exp_tmp);
363  ve.resize(orig_v.size_local());
364 
366 #else
367  std::cout << __FILE__ << ":" << __LINE__ << " error, to use expression on GPU you must compile with nvcc compiler " << std::endl;
368 #endif
369  }
370 };
371 
372 template<>
374 {
375  template<typename o1_type, typename val_type>
376  static void red(o1_type & o1, val_type & val)
377  {
378  const auto & orig_v = o1.getVector();
379 
380  o1.init();
381 
382  val = 0.0;
383 
384  auto it = orig_v.getDomainIterator();
385 
386  while (it.isNext())
387  {
388  auto key = it.get();
389 
390  val += o1.value(key);
391 
392  ++it;
393  }
394  }
395 };
396 
403 template <typename exp1>
404 class vector_dist_expression_op<exp1,void,VECT_SUM_REDUCE>
405 {
406 
408  const exp1 o1;
409 
411  typedef typename apply_kernel_rtype<decltype(o1.value(vect_dist_key_dx()))>::rtype rtype;
412 
414  mutable typename std::remove_reference<rtype>::type val;
415 
416 public:
417 
419  typedef typename exp1::is_ker is_ker;
420 
422  typedef typename vector_result<typename exp1::vtype,void>::type vtype;
423 
425  typedef typename nn_type_result<typename exp1::NN_type,void>::type NN_type;
426 
428  vector_dist_expression_op(const exp1 & o1)
429  :o1(o1),val(0)
430  {}
431 
433  // this produce a cache for the calculated value
434  inline void init() const
435  {
437  }
438 
444  inline NN_type * getNN() const
445  {
447  }
448 
450  inline typename std::remove_reference<rtype>::type get()
451  {
452  init();
453  return value(vect_dist_key_dx());
454  }
455 
457  template<typename r_type= typename std::remove_reference<rtype>::type >
458  __device__ __host__ inline r_type value(const vect_dist_key_dx & key) const
459  {
460  return val;
461  }
462 
471  {
472  return o1.getVector();
473  }
474 
482  const vtype & getVector() const
483  {
484  return o1.getVector();
485  }
486 };
487 
489 template<typename exp1, typename exp2_, unsigned int op1>
492 {
494 
495  return exp_sum;
496 }
497 
499 template<unsigned int prp1, typename v1>
501 rsum(const vector_dist_expression<prp1,v1> & va)
502 {
503  vector_dist_expression_op<vector_dist_expression<prp1,v1>,void,VECT_SUM_REDUCE> exp_sum(va);
504 
505  return exp_sum;
506 }
507 
508 namespace openfpm
509 {
514  template <typename T, typename P> auto distance(T exp1, P exp2) -> decltype(norm(exp1 - exp2))
515  {
516  return norm(exp1 - exp2);
517  }
518 }
519 
520 
527 template <typename exp1>
528 class vector_dist_expression_op<exp1,void,VECT_NORM_INF>
529 {
530 
532  const exp1 o1;
533 
535  typedef typename apply_kernel_rtype<decltype(o1.value(vect_dist_key_dx()))>::rtype rtype;
536 
538  mutable typename std::remove_reference<rtype>::type val;
539 
540 public:
541 
543  typedef typename exp1::is_ker is_ker;
544 
546  typedef typename vector_result<typename exp1::vtype,void>::type vtype;
547 
549  typedef typename nn_type_result<typename exp1::NN_type,void>::type NN_type;
550 
552  vector_dist_expression_op(const exp1 & o1)
553  :o1(o1),val(0)
554  {}
555 
557  // this produce a cache for the calculated value
558  inline void init() const
559  {
560  if (exp1::is_ker::value == true)
561  {
562 
563 #ifdef __NVCC__
564  typedef decltype(val) val_type;
565 
566  // we have to do it on GPU
567 
569  CudaMemory,
572 
573  auto & orig_v = o1.getVector();
574 
575  if (exp_tmp.ref() == 0)
576  {exp_tmp.incRef();}
577 
578  ve.setMemory(exp_tmp);
579  ve.resize(orig_v.size_local());
580 
582 #else
583  std::cout << __FILE__ << ":" << __LINE__ << " error, to use expression on GPU you must compile with nvcc compiler " << std::endl;
584 #endif
585  }
586  else
587  {
588  const auto & orig_v = o1.getVector();
589 
590  o1.init();
591 
592  val = 0.0;
593 
594  auto it = orig_v.getDomainIterator();
595 
596  while (it.isNext())
597  {
598  auto key = it.get();
599  if(fabs(o1.value(key))>val) {
600  val = fabs(o1.value(key));
601  }
602  ++it;
603  }
604  }
605  }
606 
612  inline NN_type * getNN() const
613  {
615  }
616 
618  inline typename std::remove_reference<rtype>::type get()
619  {
620  init();
621  return value(vect_dist_key_dx());
622  }
623 
625  template<typename r_type= typename std::remove_reference<rtype>::type > inline r_type value(const vect_dist_key_dx & key) const
626  {
627  return val;
628  }
629 
631  template<typename r_type= typename std::remove_reference<rtype>::type > inline r_type getReduction() const
632  {
633  return val;
634  }
635 
644  {
645  return o1.getVector();
646  }
647 
655  const vtype & getVector() const
656  {
657  return o1.getVector();
658  }
659 };
660 
662 template<typename exp1, typename exp2_, unsigned int op1>
665 {
667 
668  return exp_sum;
669 }
670 
672 template<unsigned int prp1, typename v1>
674 norm_inf(const vector_dist_expression<prp1,v1> & va)
675 {
676  vector_dist_expression_op<vector_dist_expression<prp1,v1>,void,VECT_NORM_INF> exp_sum(va);
677 
678  return exp_sum;
679 }
680 
681 #endif /* OPENFPM_NUMERICS_SRC_OPERATORS_VECTOR_VECTOR_DIST_OPERATORS_FUNCTIONS_HPP_ */
Test structure used for several test.
Definition: Point_test.hpp:106
Grow policy define how the vector should grow every time we exceed the size.
Implementation of 1-D std::vector like structure.
Definition: map_vector.hpp:204
Grid key for a distributed grid.
nn_type_result< typename exp1::NN_type, void >::type NN_type
NN_type.
void init() const
sum reduction require initialization where we calculate the reduction
r_type getReduction() const
it return the result of the expression for ODEINT
std::remove_reference< rtype >::type val
return type of the calculated value (without reference)
vector_dist_expression_op(const exp1 &o1)
constructor from an epxression exp1 and a vector vd
vector_result< typename exp1::vtype, void >::type vtype
return the vector type on which this expression operate
const vtype & getVector() const
Return the vector on which is acting.
exp1::is_ker is_ker
Indicate if it is an in kernel expression.
r_type value(const vect_dist_key_dx &key) const
it return the result of the expression (precalculated before)
std::remove_reference< rtype >::type get()
it return the result of the expression
apply_kernel_rtype< decltype(o1.value(vect_dist_key_dx()))>::rtype rtype
return type of this expression
nn_type_result< typename exp1::NN_type, void >::type NN_type
NN_type.
apply_kernel_rtype< decltype(o1.value(vect_dist_key_dx()))>::rtype rtype
return type of this expression
std::remove_reference< rtype >::type get()
it return the result of the expression
vector_result< typename exp1::vtype, void >::type vtype
return the vector type on which this expression operate
const vtype & getVector() const
Return the vector on which is acting.
void init() const
sum reduction require initialization where we calculate the reduction
vector_dist_expression_op(const exp1 &o1)
constructor from an epxression exp1 and a vector vd
__device__ __host__ r_type value(const vect_dist_key_dx &key) const
it return the result of the expression (precalculated before)
std::remove_reference< rtype >::type val
return type of the calculated value (without reference)
exp1::is_ker is_ker
Indicate if it is an in kernel expression.
Unknown operation specialization.
Main class that encapsulate a vector properties operand to be used for expressions construction.
Distributed vector.
OutputIteratorT OffsetT ReductionOpT OuputT init
< [in] The initial value of the reduction
convert a type into constant type
Definition: aggregate.hpp:302
auto distance(T exp1, P exp2) -> decltype(norm(exp1 - exp2))
General distance formula.
aggregate of properties, from a list of object if create a struct that follow the OPENFPM native stru...
Definition: aggregate.hpp:221
It give the return type of the expression if applicable.
Transform the boost::fusion::vector into memory specification (memory_traits)
Definition: memory_conf.hpp:84
temporal buffer for reductions