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