Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_Parallel_Reduce.hpp
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 2.0
6 // Copyright (2014) Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
39 //
40 // ************************************************************************
41 //@HEADER
42 */
43 
44 #ifndef KOKKOS_PARALLEL_REDUCE_HPP
45 #define KOKKOS_PARALLEL_REDUCE_HPP
46 
47 #include <Kokkos_NumericTraits.hpp>
48 
49 namespace Kokkos {
50 
51 template<class T, class Enable = void>
52 struct is_reducer_type {
53  enum { value = 0 };
54 };
55 
56 
57 template<class T>
58 struct is_reducer_type<T,typename std::enable_if<
59  std::is_same<typename std::remove_cv<T>::type,
60  typename std::remove_cv<typename T::reducer>::type>::value
61  >::type> {
62  enum { value = 1 };
63 };
64 
65 template<class Scalar, class Space>
66 struct Sum {
67 public:
68  //Required
69  typedef Sum reducer;
70  typedef typename std::remove_cv<Scalar>::type value_type;
71 
72  typedef Kokkos::View<value_type, Space> result_view_type;
73 
74 private:
75  result_view_type value;
76  bool references_scalar_v;
77 
78 public:
79 
80  KOKKOS_INLINE_FUNCTION
81  Sum(value_type& value_): value(&value_),references_scalar_v(true) {}
82 
83  KOKKOS_INLINE_FUNCTION
84  Sum(const result_view_type& value_): value(value_),references_scalar_v(false) {}
85 
86  //Required
87  KOKKOS_INLINE_FUNCTION
88  void join(value_type& dest, const value_type& src) const {
89  dest += src;
90  }
91 
92  KOKKOS_INLINE_FUNCTION
93  void join(volatile value_type& dest, const volatile value_type& src) const {
94  dest += src;
95  }
96 
97  KOKKOS_INLINE_FUNCTION
98  void init( value_type& val) const {
99  val = reduction_identity<value_type>::sum();
100  }
101 
102  KOKKOS_INLINE_FUNCTION
103  value_type& reference() const {
104  return *value.data();
105  }
106 
107  KOKKOS_INLINE_FUNCTION
108  result_view_type view() const {
109  return value;
110  }
111 
112  KOKKOS_INLINE_FUNCTION
113  bool references_scalar() const {
114  return references_scalar_v;
115  }
116 };
117 
118 template<class Scalar, class Space>
119 struct Prod {
120 public:
121  //Required
122  typedef Prod reducer;
123  typedef typename std::remove_cv<Scalar>::type value_type;
124 
125  typedef Kokkos::View<value_type, Space> result_view_type;
126 
127 private:
128  result_view_type value;
129  bool references_scalar_v;
130 
131 public:
132 
133  KOKKOS_INLINE_FUNCTION
134  Prod(value_type& value_): value(&value_),references_scalar_v(true) {}
135 
136  KOKKOS_INLINE_FUNCTION
137  Prod(const result_view_type& value_): value(value_),references_scalar_v(false) {}
138 
139  //Required
140  KOKKOS_INLINE_FUNCTION
141  void join(value_type& dest, const value_type& src) const {
142  dest *= src;
143  }
144 
145  KOKKOS_INLINE_FUNCTION
146  void join(volatile value_type& dest, const volatile value_type& src) const {
147  dest *= src;
148  }
149 
150  KOKKOS_INLINE_FUNCTION
151  void init( value_type& val) const {
152  val = reduction_identity<value_type>::prod();
153  }
154 
155  KOKKOS_INLINE_FUNCTION
156  value_type& reference() const {
157  return *value.data();
158  }
159 
160  KOKKOS_INLINE_FUNCTION
161  result_view_type view() const {
162  return value;
163  }
164 
165  KOKKOS_INLINE_FUNCTION
166  bool references_scalar() const {
167  return references_scalar_v;
168  }
169 };
170 
171 template<class Scalar, class Space>
172 struct Min {
173 public:
174  //Required
175  typedef Min reducer;
176  typedef typename std::remove_cv<Scalar>::type value_type;
177 
178  typedef Kokkos::View<value_type, Space> result_view_type;
179 
180 private:
181  result_view_type value;
182  bool references_scalar_v;
183 
184 public:
185 
186  KOKKOS_INLINE_FUNCTION
187  Min(value_type& value_): value(&value_),references_scalar_v(true) {}
188 
189  KOKKOS_INLINE_FUNCTION
190  Min(const result_view_type& value_): value(value_),references_scalar_v(false) {}
191 
192  //Required
193  KOKKOS_INLINE_FUNCTION
194  void join(value_type& dest, const value_type& src) const {
195  if ( src < dest )
196  dest = src;
197  }
198 
199  KOKKOS_INLINE_FUNCTION
200  void join(volatile value_type& dest, const volatile value_type& src) const {
201  if ( src < dest )
202  dest = src;
203  }
204 
205  KOKKOS_INLINE_FUNCTION
206  void init( value_type& val) const {
207  val = reduction_identity<value_type>::min();
208  }
209 
210  KOKKOS_INLINE_FUNCTION
211  value_type& reference() const {
212  return *value.data();
213  }
214 
215  KOKKOS_INLINE_FUNCTION
216  result_view_type view() const {
217  return value;
218  }
219 
220  KOKKOS_INLINE_FUNCTION
221  bool references_scalar() const {
222  return references_scalar_v;
223  }
224 };
225 
226 template<class Scalar, class Space>
227 struct Max {
228 public:
229  //Required
230  typedef Max reducer;
231  typedef typename std::remove_cv<Scalar>::type value_type;
232 
233  typedef Kokkos::View<value_type, Space> result_view_type;
234 
235 private:
236  result_view_type value;
237  bool references_scalar_v;
238 
239 public:
240 
241  KOKKOS_INLINE_FUNCTION
242  Max(value_type& value_): value(&value_),references_scalar_v(true) {}
243 
244  KOKKOS_INLINE_FUNCTION
245  Max(const result_view_type& value_): value(value_),references_scalar_v(false) {}
246 
247  //Required
248  KOKKOS_INLINE_FUNCTION
249  void join(value_type& dest, const value_type& src) const {
250  if ( src > dest )
251  dest = src;
252  }
253 
254  KOKKOS_INLINE_FUNCTION
255  void join(volatile value_type& dest, const volatile value_type& src) const {
256  if ( src > dest )
257  dest = src;
258  }
259 
260  //Required
261  KOKKOS_INLINE_FUNCTION
262  void init( value_type& val) const {
263  val = reduction_identity<value_type>::max();
264  }
265 
266  KOKKOS_INLINE_FUNCTION
267  value_type& reference() const {
268  return *value.data();
269  }
270 
271  KOKKOS_INLINE_FUNCTION
272  result_view_type view() const {
273  return value;
274  }
275 
276  KOKKOS_INLINE_FUNCTION
277  bool references_scalar() const {
278  return references_scalar_v;
279  }
280 };
281 
282 template<class Scalar, class Space>
283 struct LAnd {
284 public:
285  //Required
286  typedef LAnd reducer;
287  typedef typename std::remove_cv<Scalar>::type value_type;
288 
289  typedef Kokkos::View<value_type, Space> result_view_type;
290 
291 private:
292  result_view_type value;
293  bool references_scalar_v;
294 
295 public:
296 
297  KOKKOS_INLINE_FUNCTION
298  LAnd(value_type& value_): value(&value_),references_scalar_v(true) {}
299 
300  KOKKOS_INLINE_FUNCTION
301  LAnd(const result_view_type& value_): value(value_),references_scalar_v(false) {}
302 
303  KOKKOS_INLINE_FUNCTION
304  void join(value_type& dest, const value_type& src) const {
305  dest = dest && src;
306  }
307 
308  KOKKOS_INLINE_FUNCTION
309  void join(volatile value_type& dest, const volatile value_type& src) const {
310  dest = dest && src;
311  }
312 
313  KOKKOS_INLINE_FUNCTION
314  void init( value_type& val) const {
315  val = reduction_identity<value_type>::land();
316  }
317 
318  KOKKOS_INLINE_FUNCTION
319  value_type& reference() const {
320  return *value.data();
321  }
322 
323  KOKKOS_INLINE_FUNCTION
324  result_view_type view() const {
325  return value;
326  }
327 
328  KOKKOS_INLINE_FUNCTION
329  bool references_scalar() const {
330  return references_scalar_v;
331  }
332 };
333 
334 template<class Scalar, class Space>
335 struct LOr {
336 public:
337  //Required
338  typedef LOr reducer;
339  typedef typename std::remove_cv<Scalar>::type value_type;
340 
341  typedef Kokkos::View<value_type, Space> result_view_type;
342 
343 private:
344  result_view_type value;
345  bool references_scalar_v;
346 
347 public:
348 
349  KOKKOS_INLINE_FUNCTION
350  LOr(value_type& value_): value(&value_),references_scalar_v(true) {}
351 
352  KOKKOS_INLINE_FUNCTION
353  LOr(const result_view_type& value_): value(value_),references_scalar_v(false) {}
354 
355  //Required
356  KOKKOS_INLINE_FUNCTION
357  void join(value_type& dest, const value_type& src) const {
358  dest = dest || src;
359  }
360 
361  KOKKOS_INLINE_FUNCTION
362  void join(volatile value_type& dest, const volatile value_type& src) const {
363  dest = dest || src;
364  }
365 
366  KOKKOS_INLINE_FUNCTION
367  void init( value_type& val) const {
368  val = reduction_identity<value_type>::lor();
369  }
370 
371  KOKKOS_INLINE_FUNCTION
372  value_type& reference() const {
373  return *value.data();
374  }
375 
376  KOKKOS_INLINE_FUNCTION
377  result_view_type view() const {
378  return value;
379  }
380 
381  KOKKOS_INLINE_FUNCTION
382  bool references_scalar() const {
383  return references_scalar_v;
384  }
385 };
386 
387 template<class Scalar, class Space>
388 struct BAnd {
389 public:
390  //Required
391  typedef BAnd reducer;
392  typedef typename std::remove_cv<Scalar>::type value_type;
393 
394  typedef Kokkos::View<value_type, Space> result_view_type;
395 
396 private:
397  result_view_type value;
398  bool references_scalar_v;
399 
400 public:
401 
402  KOKKOS_INLINE_FUNCTION
403  BAnd(value_type& value_): value(&value_),references_scalar_v(true) {}
404 
405  KOKKOS_INLINE_FUNCTION
406  BAnd(const result_view_type& value_): value(value_),references_scalar_v(false) {}
407 
408  //Required
409  KOKKOS_INLINE_FUNCTION
410  void join(value_type& dest, const value_type& src) const {
411  dest = dest & src;
412  }
413 
414  KOKKOS_INLINE_FUNCTION
415  void join(volatile value_type& dest, const volatile value_type& src) const {
416  dest = dest & src;
417  }
418 
419  KOKKOS_INLINE_FUNCTION
420  void init( value_type& val) const {
421  val = reduction_identity<value_type>::band();
422  }
423 
424  KOKKOS_INLINE_FUNCTION
425  value_type& reference() const {
426  return *value.data();
427  }
428 
429  KOKKOS_INLINE_FUNCTION
430  result_view_type view() const {
431  return value;
432  }
433 
434  KOKKOS_INLINE_FUNCTION
435  bool references_scalar() const {
436  return references_scalar_v;
437  }
438 };
439 
440 template<class Scalar, class Space>
441 struct BOr {
442 public:
443  //Required
444  typedef BOr reducer;
445  typedef typename std::remove_cv<Scalar>::type value_type;
446 
447  typedef Kokkos::View<value_type, Space> result_view_type;
448 
449 private:
450  result_view_type value;
451  bool references_scalar_v;
452 
453 public:
454 
455  KOKKOS_INLINE_FUNCTION
456  BOr(value_type& value_): value(&value_),references_scalar_v(true) {}
457 
458  KOKKOS_INLINE_FUNCTION
459  BOr(const result_view_type& value_): value(value_),references_scalar_v(false) {}
460 
461  //Required
462  KOKKOS_INLINE_FUNCTION
463  void join(value_type& dest, const value_type& src) const {
464  dest = dest | src;
465  }
466 
467  KOKKOS_INLINE_FUNCTION
468  void join(volatile value_type& dest, const volatile value_type& src) const {
469  dest = dest | src;
470  }
471 
472  KOKKOS_INLINE_FUNCTION
473  void init( value_type& val) const {
474  val = reduction_identity<value_type>::bor();
475  }
476 
477  KOKKOS_INLINE_FUNCTION
478  value_type& reference() const {
479  return *value.data();
480  }
481 
482  KOKKOS_INLINE_FUNCTION
483  result_view_type view() const {
484  return value;
485  }
486 
487  KOKKOS_INLINE_FUNCTION
488  bool references_scalar() const {
489  return references_scalar_v;
490  }
491 };
492 
493 template<class Scalar, class Index>
494 struct ValLocScalar {
495  Scalar val;
496  Index loc;
497 
498  KOKKOS_INLINE_FUNCTION
499  void operator = (const ValLocScalar& rhs) {
500  val = rhs.val;
501  loc = rhs.loc;
502  }
503 
504  KOKKOS_INLINE_FUNCTION
505  void operator = (const volatile ValLocScalar& rhs) volatile {
506  val = rhs.val;
507  loc = rhs.loc;
508  }
509 };
510 
511 template<class Scalar, class Index, class Space>
512 struct MinLoc {
513 private:
514  typedef typename std::remove_cv<Scalar>::type scalar_type;
515  typedef typename std::remove_cv<Index>::type index_type;
516 
517 public:
518  //Required
519  typedef MinLoc reducer;
520  typedef ValLocScalar<scalar_type,index_type> value_type;
521 
522  typedef Kokkos::View<value_type, Space> result_view_type;
523 
524 private:
525  result_view_type value;
526  bool references_scalar_v;
527 
528 public:
529 
530  KOKKOS_INLINE_FUNCTION
531  MinLoc(value_type& value_): value(&value_),references_scalar_v(true) {}
532 
533  KOKKOS_INLINE_FUNCTION
534  MinLoc(const result_view_type& value_): value(value_),references_scalar_v(false) {}
535 
536 
537  //Required
538  KOKKOS_INLINE_FUNCTION
539  void join(value_type& dest, const value_type& src) const {
540  if ( src.val < dest.val )
541  dest = src;
542  }
543 
544  KOKKOS_INLINE_FUNCTION
545  void join(volatile value_type& dest, const volatile value_type& src) const {
546  if ( src.val < dest.val )
547  dest = src;
548  }
549 
550  KOKKOS_INLINE_FUNCTION
551  void init( value_type& val) const {
552  val.val = reduction_identity<scalar_type>::min();
553  val.loc = reduction_identity<index_type>::min();
554  }
555 
556  KOKKOS_INLINE_FUNCTION
557  value_type& reference() const {
558  return *value.data();
559  }
560 
561  KOKKOS_INLINE_FUNCTION
562  result_view_type view() const {
563  return value;
564  }
565 
566  KOKKOS_INLINE_FUNCTION
567  bool references_scalar() const {
568  return references_scalar_v;
569  }
570 };
571 
572 template<class Scalar, class Index, class Space>
573 struct MaxLoc {
574 private:
575  typedef typename std::remove_cv<Scalar>::type scalar_type;
576  typedef typename std::remove_cv<Index>::type index_type;
577 
578 public:
579  //Required
580  typedef MaxLoc reducer;
581  typedef ValLocScalar<scalar_type,index_type> value_type;
582 
583  typedef Kokkos::View<value_type, Space> result_view_type;
584 
585 private:
586  result_view_type value;
587  bool references_scalar_v;
588 
589 public:
590 
591  KOKKOS_INLINE_FUNCTION
592  MaxLoc(value_type& value_): value(&value_),references_scalar_v(true) {}
593 
594  KOKKOS_INLINE_FUNCTION
595  MaxLoc(const result_view_type& value_): value(value_),references_scalar_v(false) {}
596 
597  //Required
598  KOKKOS_INLINE_FUNCTION
599  void join(value_type& dest, const value_type& src) const {
600  if ( src.val > dest.val )
601  dest = src;
602  }
603 
604  KOKKOS_INLINE_FUNCTION
605  void join(volatile value_type& dest, const volatile value_type& src) const {
606  if ( src.val > dest.val )
607  dest = src;
608  }
609 
610  KOKKOS_INLINE_FUNCTION
611  void init( value_type& val) const {
612  val.val = reduction_identity<scalar_type>::max();;
613  val.loc = reduction_identity<index_type>::min();
614  }
615 
616  KOKKOS_INLINE_FUNCTION
617  value_type& reference() const {
618  return *value.data();
619  }
620 
621  KOKKOS_INLINE_FUNCTION
622  result_view_type view() const {
623  return value;
624  }
625 
626  KOKKOS_INLINE_FUNCTION
627  bool references_scalar() const {
628  return references_scalar_v;
629  }
630 };
631 
632 template<class Scalar>
633 struct MinMaxScalar {
634  Scalar min_val,max_val;
635 
636  KOKKOS_INLINE_FUNCTION
637  void operator = (const MinMaxScalar& rhs) {
638  min_val = rhs.min_val;
639  max_val = rhs.max_val;
640  }
641 
642  KOKKOS_INLINE_FUNCTION
643  void operator = (const volatile MinMaxScalar& rhs) volatile {
644  min_val = rhs.min_val;
645  max_val = rhs.max_val;
646  }
647 };
648 
649 template<class Scalar, class Space>
650 struct MinMax {
651 private:
652  typedef typename std::remove_cv<Scalar>::type scalar_type;
653 
654 public:
655  //Required
656  typedef MinMax reducer;
657  typedef MinMaxScalar<scalar_type> value_type;
658 
659  typedef Kokkos::View<value_type, Space> result_view_type;
660 
661 private:
662  result_view_type value;
663  bool references_scalar_v;
664 
665 public:
666 
667  KOKKOS_INLINE_FUNCTION
668  MinMax(value_type& value_): value(&value_),references_scalar_v(true) {}
669 
670  KOKKOS_INLINE_FUNCTION
671  MinMax(const result_view_type& value_): value(value_),references_scalar_v(false) {}
672 
673  //Required
674  KOKKOS_INLINE_FUNCTION
675  void join(value_type& dest, const value_type& src) const {
676  if ( src.min_val < dest.min_val ) {
677  dest.min_val = src.min_val;
678  }
679  if ( src.max_val > dest.max_val ) {
680  dest.max_val = src.max_val;
681  }
682  }
683 
684  KOKKOS_INLINE_FUNCTION
685  void join(volatile value_type& dest, const volatile value_type& src) const {
686  if ( src.min_val < dest.min_val ) {
687  dest.min_val = src.min_val;
688  }
689  if ( src.max_val > dest.max_val ) {
690  dest.max_val = src.max_val;
691  }
692  }
693 
694  KOKKOS_INLINE_FUNCTION
695  void init( value_type& val) const {
696  val.max_val = reduction_identity<scalar_type>::max();;
697  val.min_val = reduction_identity<scalar_type>::min();
698  }
699 
700  KOKKOS_INLINE_FUNCTION
701  value_type& reference() const {
702  return *value.data();
703  }
704 
705  KOKKOS_INLINE_FUNCTION
706  result_view_type view() const {
707  return value;
708  }
709 
710  KOKKOS_INLINE_FUNCTION
711  bool references_scalar() const {
712  return references_scalar_v;
713  }
714 };
715 
716 template<class Scalar, class Index>
717 struct MinMaxLocScalar {
718  Scalar min_val,max_val;
719  Index min_loc,max_loc;
720 
721  KOKKOS_INLINE_FUNCTION
722  void operator = (const MinMaxLocScalar& rhs) {
723  min_val = rhs.min_val;
724  min_loc = rhs.min_loc;
725  max_val = rhs.max_val;
726  max_loc = rhs.max_loc;
727  }
728 
729  KOKKOS_INLINE_FUNCTION
730  void operator = (const volatile MinMaxLocScalar& rhs) volatile {
731  min_val = rhs.min_val;
732  min_loc = rhs.min_loc;
733  max_val = rhs.max_val;
734  max_loc = rhs.max_loc;
735  }
736 };
737 
738 template<class Scalar, class Index, class Space>
739 struct MinMaxLoc {
740 private:
741  typedef typename std::remove_cv<Scalar>::type scalar_type;
742  typedef typename std::remove_cv<Index>::type index_type;
743 
744 public:
745  //Required
746  typedef MinMaxLoc reducer;
747  typedef MinMaxLocScalar<scalar_type,index_type> value_type;
748 
749  typedef Kokkos::View<value_type, Space> result_view_type;
750 
751 private:
752  result_view_type value;
753  bool references_scalar_v;
754 
755 public:
756 
757  KOKKOS_INLINE_FUNCTION
758  MinMaxLoc(value_type& value_): value(&value_),references_scalar_v(true) {}
759 
760  KOKKOS_INLINE_FUNCTION
761  MinMaxLoc(const result_view_type& value_): value(value_),references_scalar_v(false) {}
762 
763  //Required
764  KOKKOS_INLINE_FUNCTION
765  void join(value_type& dest, const value_type& src) const {
766  if ( src.min_val < dest.min_val ) {
767  dest.min_val = src.min_val;
768  dest.min_loc = src.min_loc;
769  }
770  if ( src.max_val > dest.max_val ) {
771  dest.max_val = src.max_val;
772  dest.max_loc = src.max_loc;
773  }
774  }
775 
776  KOKKOS_INLINE_FUNCTION
777  void join(volatile value_type& dest, const volatile value_type& src) const {
778  if ( src.min_val < dest.min_val ) {
779  dest.min_val = src.min_val;
780  dest.min_loc = src.min_loc;
781  }
782  if ( src.max_val > dest.max_val ) {
783  dest.max_val = src.max_val;
784  dest.max_loc = src.max_loc;
785  }
786  }
787 
788  KOKKOS_INLINE_FUNCTION
789  void init( value_type& val) const {
790  val.max_val = reduction_identity<scalar_type>::max();;
791  val.min_val = reduction_identity<scalar_type>::min();
792  val.max_loc = reduction_identity<index_type>::min();
793  val.min_loc = reduction_identity<index_type>::min();
794  }
795 
796  KOKKOS_INLINE_FUNCTION
797  value_type& reference() const {
798  return *value.data();
799  }
800 
801  KOKKOS_INLINE_FUNCTION
802  result_view_type view() const {
803  return value;
804  }
805 
806  KOKKOS_INLINE_FUNCTION
807  bool references_scalar() const {
808  return references_scalar_v;
809  }
810 };
811 }
812 namespace Kokkos{
813 namespace Impl {
814 
815 template< class T, class ReturnType , class ValueTraits>
816 struct ParallelReduceReturnValue;
817 
818 template< class ReturnType , class FunctorType >
819 struct ParallelReduceReturnValue<typename std::enable_if<Kokkos::is_view<ReturnType>::value>::type, ReturnType, FunctorType> {
820  typedef ReturnType return_type;
821  typedef InvalidType reducer_type;
822 
823  typedef typename return_type::value_type value_type_scalar;
824  typedef typename return_type::value_type* const value_type_array;
825 
826  typedef typename if_c<return_type::rank==0,value_type_scalar,value_type_array>::type value_type;
827 
828  static return_type& return_value(ReturnType& return_val, const FunctorType&) {
829  return return_val;
830  }
831 };
832 
833 template< class ReturnType , class FunctorType>
834 struct ParallelReduceReturnValue<typename std::enable_if<
835  !Kokkos::is_view<ReturnType>::value &&
836  (!std::is_array<ReturnType>::value && !std::is_pointer<ReturnType>::value) &&
837  !Kokkos::is_reducer_type<ReturnType>::value
838  >::type, ReturnType, FunctorType> {
839  typedef Kokkos::View< ReturnType
841  , Kokkos::MemoryUnmanaged
842  > return_type;
843 
844  typedef InvalidType reducer_type;
845 
846  typedef typename return_type::value_type value_type;
847 
848  static return_type return_value(ReturnType& return_val, const FunctorType&) {
849  return return_type(&return_val);
850  }
851 };
852 
853 template< class ReturnType , class FunctorType>
854 struct ParallelReduceReturnValue<typename std::enable_if<
855  (is_array<ReturnType>::value || std::is_pointer<ReturnType>::value)
856  >::type, ReturnType, FunctorType> {
859  , Kokkos::MemoryUnmanaged
860  > return_type;
861 
862  typedef InvalidType reducer_type;
863 
864  typedef typename return_type::value_type value_type[];
865 
866  static return_type return_value(ReturnType& return_val,
867  const FunctorType& functor) {
868 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
869  return return_type(return_val,functor.value_count);
870 #else
871  if ( is_array<ReturnType>::value )
872  return return_type(return_val);
873  else
874  return return_type(return_val,functor.value_count);
875 #endif
876  }
877 };
878 
879 template< class ReturnType , class FunctorType>
880 struct ParallelReduceReturnValue<typename std::enable_if<
881  Kokkos::is_reducer_type<ReturnType>::value
882  >::type, ReturnType, FunctorType> {
883  typedef ReturnType return_type;
884  typedef ReturnType reducer_type;
885  typedef typename return_type::value_type value_type;
886 
887  static return_type return_value(ReturnType& return_val,
888  const FunctorType&) {
889  return return_val;
890  }
891 };
892 
893 template< class T, class ReturnType , class FunctorType>
894 struct ParallelReducePolicyType;
895 
896 template< class PolicyType , class FunctorType >
897 struct ParallelReducePolicyType<typename std::enable_if<Kokkos::Impl::is_execution_policy<PolicyType>::value>::type, PolicyType,FunctorType> {
898 
899  typedef PolicyType policy_type;
900  static PolicyType policy(const PolicyType& policy_) {
901  return policy_;
902  }
903 };
904 
905 template< class PolicyType , class FunctorType >
906 struct ParallelReducePolicyType<typename std::enable_if<std::is_integral<PolicyType>::value>::type, PolicyType,FunctorType> {
907  typedef typename
908  Impl::FunctorPolicyExecutionSpace< FunctorType , void >::execution_space
909  execution_space ;
910 
911  typedef Kokkos::RangePolicy<execution_space> policy_type;
912 
913  static policy_type policy(const PolicyType& policy_) {
914  return policy_type(0,policy_);
915  }
916 };
917 
918 
919  template< class FunctorType, class ExecPolicy, class ValueType, class ExecutionSpace>
920  struct ParallelReduceFunctorType {
921  typedef FunctorType functor_type;
922  static const functor_type& functor(const functor_type& functor) {
923  return functor;
924  }
925  };
926 
927  template< class PolicyType, class FunctorType, class ReturnType >
928  struct ParallelReduceAdaptor {
929  typedef Impl::ParallelReduceReturnValue<void,ReturnType,FunctorType> return_value_adapter;
930  #ifdef KOKKOS_IMPL_NEED_FUNCTOR_WRAPPER
931  typedef Impl::ParallelReduceFunctorType<FunctorType,PolicyType,
932  typename return_value_adapter::value_type,
933  typename PolicyType::execution_space> functor_adaptor;
934  #endif
935  static inline
936  void execute(const std::string& label,
937  const PolicyType& policy,
938  const FunctorType& functor,
939  ReturnType& return_value) {
940  #if defined(KOKKOS_ENABLE_PROFILING)
941  uint64_t kpID = 0;
942  if(Kokkos::Profiling::profileLibraryLoaded()) {
943  Kokkos::Impl::ParallelConstructName<FunctorType, typename PolicyType::work_tag> name(label);
944  Kokkos::Profiling::beginParallelReduce(name.get(), 0, &kpID);
945  }
946  #endif
947 
948  Kokkos::Impl::shared_allocation_tracking_disable();
949  #ifdef KOKKOS_IMPL_NEED_FUNCTOR_WRAPPER
950  Impl::ParallelReduce<typename functor_adaptor::functor_type, PolicyType, typename return_value_adapter::reducer_type >
951  closure(functor_adaptor::functor(functor),
952  policy,
953  return_value_adapter::return_value(return_value,functor));
954  #else
955  Impl::ParallelReduce<FunctorType, PolicyType, typename return_value_adapter::reducer_type >
956  closure(functor,
957  policy,
958  return_value_adapter::return_value(return_value,functor));
959  #endif
960  Kokkos::Impl::shared_allocation_tracking_enable();
961  closure.execute();
962 
963  #if defined(KOKKOS_ENABLE_PROFILING)
964  if(Kokkos::Profiling::profileLibraryLoaded()) {
965  Kokkos::Profiling::endParallelReduce(kpID);
966  }
967  #endif
968  }
969 
970  };
971 }
972 
973 //----------------------------------------------------------------------------
974 
983 // Parallel Reduce Blocking behavior
984 
985 namespace Impl {
986 template <typename T>
987  struct ReducerHasTestReferenceFunction
988  {
989  template <typename E> static std::true_type test_func( decltype(&E::references_scalar) ) ;
990  template <typename E> static std::false_type test_func(...);
991 
992  enum { value = std::is_same<std::true_type,decltype(test_func<T>(0))>::value };
993  };
994 
995  template<class T, bool is_reducer = ReducerHasTestReferenceFunction<T>::value>
996  struct ParallelReduceFence {
997  static void fence(const T&) {
998  Kokkos::fence();
999  }
1000  };
1001  template<class ... Args>
1002  struct ParallelReduceFence<View<Args...>, false> {
1003  static void fence(const View<Args...>) {};
1004  };
1005  template<class T>
1006  struct ParallelReduceFence<T,true> {
1007  static void fence(const T& reducer) {
1008  if(reducer.references_scalar())
1009  Kokkos::fence();
1010  }
1011  };
1012 }
1013 
1053 // ReturnValue is scalar or array: take by reference
1054 
1055 template< class PolicyType, class FunctorType, class ReturnType >
1056 inline
1057 void parallel_reduce(const std::string& label,
1058  const PolicyType& policy,
1059  const FunctorType& functor,
1060  ReturnType& return_value,
1061  typename Impl::enable_if<
1062  Kokkos::Impl::is_execution_policy<PolicyType>::value
1063  >::type * = 0) {
1064  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,ReturnType>::execute(label,policy,functor,return_value);
1065  Impl::ParallelReduceFence<ReturnType>::fence(return_value);
1066 }
1067 
1068 template< class PolicyType, class FunctorType, class ReturnType >
1069 inline
1070 void parallel_reduce(const PolicyType& policy,
1071  const FunctorType& functor,
1072  ReturnType& return_value,
1073  typename Impl::enable_if<
1074  Kokkos::Impl::is_execution_policy<PolicyType>::value
1075  >::type * = 0) {
1076  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,ReturnType>::execute("",policy,functor,return_value);
1077  Impl::ParallelReduceFence<ReturnType>::fence(return_value);
1078 }
1079 
1080 template< class FunctorType, class ReturnType >
1081 inline
1082 void parallel_reduce(const size_t& policy,
1083  const FunctorType& functor,
1084  ReturnType& return_value) {
1085  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1086  Impl::ParallelReduceAdaptor<policy_type,FunctorType,ReturnType>::execute("",policy_type(0,policy),functor,return_value);
1087  Impl::ParallelReduceFence<ReturnType>::fence(return_value);
1088 }
1089 
1090 template< class FunctorType, class ReturnType >
1091 inline
1092 void parallel_reduce(const std::string& label,
1093  const size_t& policy,
1094  const FunctorType& functor,
1095  ReturnType& return_value) {
1096  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1097  Impl::ParallelReduceAdaptor<policy_type,FunctorType,ReturnType>::execute(label,policy_type(0,policy),functor,return_value);
1098  Impl::ParallelReduceFence<ReturnType>::fence(return_value);
1099 }
1100 
1101 // ReturnValue as View or Reducer: take by copy to allow for inline construction
1102 
1103 template< class PolicyType, class FunctorType, class ReturnType >
1104 inline
1105 void parallel_reduce(const std::string& label,
1106  const PolicyType& policy,
1107  const FunctorType& functor,
1108  const ReturnType& return_value,
1109  typename Impl::enable_if<
1110  Kokkos::Impl::is_execution_policy<PolicyType>::value
1111  >::type * = 0) {
1112  ReturnType return_value_impl = return_value;
1113  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,ReturnType>::execute(label,policy,functor,return_value_impl);
1114  Impl::ParallelReduceFence<ReturnType>::fence(return_value);
1115 }
1116 
1117 template< class PolicyType, class FunctorType, class ReturnType >
1118 inline
1119 void parallel_reduce(const PolicyType& policy,
1120  const FunctorType& functor,
1121  const ReturnType& return_value,
1122  typename Impl::enable_if<
1123  Kokkos::Impl::is_execution_policy<PolicyType>::value
1124  >::type * = 0) {
1125  ReturnType return_value_impl = return_value;
1126  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,ReturnType>::execute("",policy,functor,return_value_impl);
1127  Impl::ParallelReduceFence<ReturnType>::fence(return_value);
1128 }
1129 
1130 template< class FunctorType, class ReturnType >
1131 inline
1132 void parallel_reduce(const size_t& policy,
1133  const FunctorType& functor,
1134  const ReturnType& return_value) {
1135  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1136  ReturnType return_value_impl = return_value;
1137  Impl::ParallelReduceAdaptor<policy_type,FunctorType,ReturnType>::execute("",policy_type(0,policy),functor,return_value_impl);
1138  Impl::ParallelReduceFence<ReturnType>::fence(return_value);
1139 }
1140 
1141 template< class FunctorType, class ReturnType >
1142 inline
1143 void parallel_reduce(const std::string& label,
1144  const size_t& policy,
1145  const FunctorType& functor,
1146  const ReturnType& return_value) {
1147  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1148  ReturnType return_value_impl = return_value;
1149  Impl::ParallelReduceAdaptor<policy_type,FunctorType,ReturnType>::execute(label,policy_type(0,policy),functor,return_value_impl);
1150  Impl::ParallelReduceFence<ReturnType>::fence(return_value);
1151 }
1152 
1153 // No Return Argument
1154 
1155 template< class PolicyType, class FunctorType>
1156 inline
1157 void parallel_reduce(const std::string& label,
1158  const PolicyType& policy,
1159  const FunctorType& functor,
1160  typename Impl::enable_if<
1161  Kokkos::Impl::is_execution_policy<PolicyType>::value
1162  >::type * = 0) {
1163  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
1164  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
1165  , typename ValueTraits::value_type
1166  , typename ValueTraits::pointer_type
1167  >::type value_type ;
1168 
1169  static_assert(Impl::FunctorAnalysis<Impl::FunctorPatternInterface::REDUCE,PolicyType,FunctorType>::
1170  has_final_member_function,"Calling parallel_reduce without either return value or final function.");
1171 
1172  typedef Kokkos::View< value_type
1174  , Kokkos::MemoryUnmanaged
1175  > result_view_type;
1176  result_view_type result_view ;
1177 
1178  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,result_view_type>::execute(label,policy,functor,result_view);
1179 }
1180 
1181 template< class PolicyType, class FunctorType >
1182 inline
1183 void parallel_reduce(const PolicyType& policy,
1184  const FunctorType& functor,
1185  typename Impl::enable_if<
1186  Kokkos::Impl::is_execution_policy<PolicyType>::value
1187  >::type * = 0) {
1188  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
1189  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
1190  , typename ValueTraits::value_type
1191  , typename ValueTraits::pointer_type
1192  >::type value_type ;
1193 
1194  static_assert(Impl::FunctorAnalysis<Impl::FunctorPatternInterface::REDUCE,PolicyType,FunctorType>::
1195  has_final_member_function,"Calling parallel_reduce without either return value or final function.");
1196 
1197  typedef Kokkos::View< value_type
1199  , Kokkos::MemoryUnmanaged
1200  > result_view_type;
1201  result_view_type result_view ;
1202 
1203  Impl::ParallelReduceAdaptor<PolicyType,FunctorType,result_view_type>::execute("",policy,functor,result_view);
1204 }
1205 
1206 template< class FunctorType >
1207 inline
1208 void parallel_reduce(const size_t& policy,
1209  const FunctorType& functor) {
1210  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1211  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
1212  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
1213  , typename ValueTraits::value_type
1214  , typename ValueTraits::pointer_type
1215  >::type value_type ;
1216 
1217  static_assert(Impl::FunctorAnalysis<Impl::FunctorPatternInterface::REDUCE,RangePolicy<>,FunctorType>::
1218  has_final_member_function,"Calling parallel_reduce without either return value or final function.");
1219 
1220  typedef Kokkos::View< value_type
1222  , Kokkos::MemoryUnmanaged
1223  > result_view_type;
1224  result_view_type result_view ;
1225 
1226  Impl::ParallelReduceAdaptor<policy_type,FunctorType,result_view_type>::execute("",policy_type(0,policy),functor,result_view);
1227 }
1228 
1229 template< class FunctorType>
1230 inline
1231 void parallel_reduce(const std::string& label,
1232  const size_t& policy,
1233  const FunctorType& functor) {
1234  typedef typename Impl::ParallelReducePolicyType<void,size_t,FunctorType>::policy_type policy_type;
1235  typedef Kokkos::Impl::FunctorValueTraits< FunctorType , void > ValueTraits ;
1236  typedef typename Kokkos::Impl::if_c< (ValueTraits::StaticValueSize != 0)
1237  , typename ValueTraits::value_type
1238  , typename ValueTraits::pointer_type
1239  >::type value_type ;
1240 
1241  static_assert(Impl::FunctorAnalysis<Impl::FunctorPatternInterface::REDUCE,RangePolicy<>,FunctorType>::
1242  has_final_member_function,"Calling parallel_reduce without either return value or final function.");
1243 
1244  typedef Kokkos::View< value_type
1245  , Kokkos::HostSpace
1246  , Kokkos::MemoryUnmanaged
1247  > result_view_type;
1248  result_view_type result_view ;
1249 
1250  Impl::ParallelReduceAdaptor<policy_type,FunctorType,result_view_type>::execute(label,policy_type(0,policy),functor,result_view);
1251 }
1252 
1253 } //namespace Kokkos
1254 
1255 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
1256 //backwards compatiblity for Kokkos::Experimental reducers
1257 namespace Kokkos { namespace Experimental {
1258 using Kokkos::Sum;
1259 using Kokkos::Prod;
1260 using Kokkos::Min;
1261 using Kokkos::Max;
1262 using Kokkos::LAnd;
1263 using Kokkos::LOr;
1264 using Kokkos::BAnd;
1265 using Kokkos::BOr;
1266 using Kokkos::ValLocScalar;
1267 using Kokkos::MinLoc;
1268 using Kokkos::MaxLoc;
1269 using Kokkos::MinMaxScalar;
1270 using Kokkos::MinMax;
1271 using Kokkos::MinMaxLocScalar;
1272 using Kokkos::MinMaxLoc;
1273 }} //namespace Kokkos::Experimental
1274 #endif
1275 
1276 #endif // KOKKOS_PARALLEL_REDUCE_HPP
1277 
void parallel_reduce(const std::string &label, const PolicyType &policy, const FunctorType &functor, ReturnType &return_value, typename Impl::enable_if< Kokkos::Impl::is_execution_policy< PolicyType >::value >::type *=0)
Parallel reduction.
Memory management for host memory.
ReturnType
Execution policy for work over a range of an integral type.