Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_ScatterView.hpp
Go to the documentation of this file.
1 //@HEADER
2 // ************************************************************************
3 //
4 // Kokkos v. 4.0
5 // Copyright (2022) National Technology & Engineering
6 // Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://kokkos.org/LICENSE for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //@HEADER
16 
22 
23 #ifndef KOKKOS_SCATTER_VIEW_HPP
24 #define KOKKOS_SCATTER_VIEW_HPP
25 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
26 #define KOKKOS_IMPL_PUBLIC_INCLUDE
27 #define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_SCATTERVIEW
28 #endif
29 
30 #include <Kokkos_Core.hpp>
31 #include <utility>
32 
33 namespace Kokkos {
34 namespace Experimental {
35 
36 /*
37  * Reduction Type list
38  * - These corresponds to subset of the reducers in parallel_reduce
39  * - See Implementations of ScatterValue for details.
40  */
41 struct ScatterSum {};
42 struct ScatterProd {};
43 struct ScatterMax {};
44 struct ScatterMin {};
45 
46 struct ScatterNonDuplicated {};
47 struct ScatterDuplicated {};
48 
49 struct ScatterNonAtomic {};
50 struct ScatterAtomic {};
51 
52 } // namespace Experimental
53 } // namespace Kokkos
54 
55 namespace Kokkos {
56 namespace Impl {
57 namespace Experimental {
58 
59 template <typename ExecSpace>
60 struct DefaultDuplication;
61 
62 template <typename ExecSpace, typename Duplication>
63 struct DefaultContribution;
64 
65 #ifdef KOKKOS_ENABLE_SERIAL
66 template <>
67 struct DefaultDuplication<Kokkos::Serial> {
68  using type = Kokkos::Experimental::ScatterNonDuplicated;
69 };
70 
71 template <>
72 struct DefaultContribution<Kokkos::Serial,
73  Kokkos::Experimental::ScatterNonDuplicated> {
74  using type = Kokkos::Experimental::ScatterNonAtomic;
75 };
76 template <>
77 struct DefaultContribution<Kokkos::Serial,
78  Kokkos::Experimental::ScatterDuplicated> {
79  using type = Kokkos::Experimental::ScatterNonAtomic;
80 };
81 #endif
82 
83 #ifdef KOKKOS_ENABLE_OPENMP
84 template <>
85 struct DefaultDuplication<Kokkos::OpenMP> {
86  using type = Kokkos::Experimental::ScatterDuplicated;
87 };
88 template <>
89 struct DefaultContribution<Kokkos::OpenMP,
90  Kokkos::Experimental::ScatterNonDuplicated> {
91  using type = Kokkos::Experimental::ScatterAtomic;
92 };
93 template <>
94 struct DefaultContribution<Kokkos::OpenMP,
95  Kokkos::Experimental::ScatterDuplicated> {
96  using type = Kokkos::Experimental::ScatterNonAtomic;
97 };
98 #endif
99 
100 #ifdef KOKKOS_ENABLE_OPENMPTARGET
101 template <>
102 struct DefaultDuplication<Kokkos::Experimental::OpenMPTarget> {
103  using type = Kokkos::Experimental::ScatterNonDuplicated;
104 };
105 template <>
106 struct DefaultContribution<Kokkos::Experimental::OpenMPTarget,
107  Kokkos::Experimental::ScatterNonDuplicated> {
108  using type = Kokkos::Experimental::ScatterAtomic;
109 };
110 template <>
111 struct DefaultContribution<Kokkos::Experimental::OpenMPTarget,
112  Kokkos::Experimental::ScatterDuplicated> {
113  using type = Kokkos::Experimental::ScatterNonAtomic;
114 };
115 #endif
116 
117 #ifdef KOKKOS_ENABLE_HPX
118 template <>
119 struct DefaultDuplication<Kokkos::Experimental::HPX> {
120  using type = Kokkos::Experimental::ScatterDuplicated;
121 };
122 template <>
123 struct DefaultContribution<Kokkos::Experimental::HPX,
124  Kokkos::Experimental::ScatterNonDuplicated> {
125  using type = Kokkos::Experimental::ScatterAtomic;
126 };
127 template <>
128 struct DefaultContribution<Kokkos::Experimental::HPX,
129  Kokkos::Experimental::ScatterDuplicated> {
130  using type = Kokkos::Experimental::ScatterNonAtomic;
131 };
132 #endif
133 
134 #ifdef KOKKOS_ENABLE_THREADS
135 template <>
136 struct DefaultDuplication<Kokkos::Threads> {
137  using type = Kokkos::Experimental::ScatterDuplicated;
138 };
139 template <>
140 struct DefaultContribution<Kokkos::Threads,
141  Kokkos::Experimental::ScatterNonDuplicated> {
142  using type = Kokkos::Experimental::ScatterAtomic;
143 };
144 template <>
145 struct DefaultContribution<Kokkos::Threads,
146  Kokkos::Experimental::ScatterDuplicated> {
147  using type = Kokkos::Experimental::ScatterNonAtomic;
148 };
149 #endif
150 
151 #ifdef KOKKOS_ENABLE_CUDA
152 template <>
153 struct DefaultDuplication<Kokkos::Cuda> {
154  using type = Kokkos::Experimental::ScatterNonDuplicated;
155 };
156 template <>
157 struct DefaultContribution<Kokkos::Cuda,
158  Kokkos::Experimental::ScatterNonDuplicated> {
159  using type = Kokkos::Experimental::ScatterAtomic;
160 };
161 template <>
162 struct DefaultContribution<Kokkos::Cuda,
163  Kokkos::Experimental::ScatterDuplicated> {
164  using type = Kokkos::Experimental::ScatterAtomic;
165 };
166 #endif
167 
168 #ifdef KOKKOS_ENABLE_HIP
169 template <>
170 struct DefaultDuplication<Kokkos::HIP> {
171  using type = Kokkos::Experimental::ScatterNonDuplicated;
172 };
173 template <>
174 struct DefaultContribution<Kokkos::HIP,
175  Kokkos::Experimental::ScatterNonDuplicated> {
176  using type = Kokkos::Experimental::ScatterAtomic;
177 };
178 template <>
179 struct DefaultContribution<Kokkos::HIP,
180  Kokkos::Experimental::ScatterDuplicated> {
181  using type = Kokkos::Experimental::ScatterAtomic;
182 };
183 #endif
184 
185 #ifdef KOKKOS_ENABLE_SYCL
186 template <>
187 struct DefaultDuplication<Kokkos::SYCL> {
188  using type = Kokkos::Experimental::ScatterNonDuplicated;
189 };
190 template <>
191 struct DefaultContribution<Kokkos::SYCL,
192  Kokkos::Experimental::ScatterNonDuplicated> {
193  using type = Kokkos::Experimental::ScatterAtomic;
194 };
195 template <>
196 struct DefaultContribution<Kokkos::SYCL,
197  Kokkos::Experimental::ScatterDuplicated> {
198  using type = Kokkos::Experimental::ScatterAtomic;
199 };
200 #endif
201 
202 // FIXME All these scatter values need overhaul:
203 // - like should they be copyable at all?
204 // - what is the internal handle type
205 // - remove join
206 // - consistently use the update function in operators
207 template <typename ValueType, typename Op, typename DeviceType,
208  typename Contribution>
209 struct ScatterValue;
210 
211 /* ScatterValue <Op=ScatterSum, Contribution=ScatterNonAtomic> is
212  the object returned by the access operator() of ScatterAccess. This class
213  inherits from the Sum<> reducer and it wraps join(dest, src) with convenient
214  operator+=, etc. Note the addition of update(ValueType const& rhs) and
215  reset() so that all reducers can have common functions See ReduceDuplicates
216  and ResetDuplicates ) */
217 template <typename ValueType, typename DeviceType>
218 struct ScatterValue<ValueType, Kokkos::Experimental::ScatterSum, DeviceType,
219  Kokkos::Experimental::ScatterNonAtomic> {
220  ValueType& value;
221 
222  public:
223  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ValueType& value_in)
224  : value(value_in) {}
225  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ScatterValue&& other)
226  : value(other.value) {}
227  KOKKOS_FORCEINLINE_FUNCTION void operator+=(ValueType const& rhs) {
228  update(rhs);
229  }
230  KOKKOS_FORCEINLINE_FUNCTION void operator++() { update(1); }
231  KOKKOS_FORCEINLINE_FUNCTION void operator++(int) { update(1); }
232  KOKKOS_FORCEINLINE_FUNCTION void operator-=(ValueType const& rhs) {
233  update(ValueType(-rhs));
234  }
235  KOKKOS_FORCEINLINE_FUNCTION void operator--() { update(ValueType(-1)); }
236  KOKKOS_FORCEINLINE_FUNCTION void operator--(int) { update(ValueType(-1)); }
237  KOKKOS_FORCEINLINE_FUNCTION void update(ValueType const& rhs) {
238  value += rhs;
239  }
240  KOKKOS_FORCEINLINE_FUNCTION void reset() {
241  value = reduction_identity<ValueType>::sum();
242  }
243 };
244 
245 /* ScatterValue <Op=ScatterSum, Contribution=ScatterAtomic> is the
246  object returned by the access operator() of ScatterAccess. This class inherits
247  from the Sum<> reducer, and similar to that returned by an Atomic View, it
248  wraps Kokkos::atomic_add with convenient operator+=, etc. This version also has
249  the update(rhs) and reset() functions. */
250 template <typename ValueType, typename DeviceType>
251 struct ScatterValue<ValueType, Kokkos::Experimental::ScatterSum, DeviceType,
252  Kokkos::Experimental::ScatterAtomic> {
253  ValueType& value;
254 
255  public:
256  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ValueType& value_in)
257  : value(value_in) {}
258 
259  KOKKOS_FORCEINLINE_FUNCTION void operator+=(ValueType const& rhs) {
260  this->join(value, rhs);
261  }
262  KOKKOS_FORCEINLINE_FUNCTION void operator++() { this->join(value, 1); }
263  KOKKOS_FORCEINLINE_FUNCTION void operator++(int) { this->join(value, 1); }
264  KOKKOS_FORCEINLINE_FUNCTION void operator-=(ValueType const& rhs) {
265  this->join(value, ValueType(-rhs));
266  }
267  KOKKOS_FORCEINLINE_FUNCTION void operator--() {
268  this->join(value, ValueType(-1));
269  }
270  KOKKOS_FORCEINLINE_FUNCTION void operator--(int) {
271  this->join(value, ValueType(-1));
272  }
273 
274  KOKKOS_INLINE_FUNCTION
275  void join(ValueType& dest, const ValueType& src) const {
276  Kokkos::atomic_add(&dest, src);
277  }
278 
279  KOKKOS_FORCEINLINE_FUNCTION void update(ValueType const& rhs) {
280  this->join(value, rhs);
281  }
282 
283  KOKKOS_FORCEINLINE_FUNCTION void reset() {
284  value = reduction_identity<ValueType>::sum();
285  }
286 };
287 
288 /* ScatterValue <Op=ScatterProd, Contribution=ScatterNonAtomic> is
289  the object returned by the access operator() of ScatterAccess. This class
290  inherits from the Prod<> reducer, and it wraps join(dest, src) with
291  convenient operator*=, etc. Note the addition of update(ValueType const& rhs)
292  and reset() so that all reducers can have common functions See
293  ReduceDuplicates and ResetDuplicates ) */
294 template <typename ValueType, typename DeviceType>
295 struct ScatterValue<ValueType, Kokkos::Experimental::ScatterProd, DeviceType,
296  Kokkos::Experimental::ScatterNonAtomic> {
297  ValueType& value;
298 
299  public:
300  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ValueType& value_in)
301  : value(value_in) {}
302  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ScatterValue&& other)
303  : value(other.value) {}
304  KOKKOS_FORCEINLINE_FUNCTION void operator*=(ValueType const& rhs) {
305  value *= rhs;
306  }
307  KOKKOS_FORCEINLINE_FUNCTION void operator/=(ValueType const& rhs) {
308  value /= rhs;
309  }
310 
311  KOKKOS_FORCEINLINE_FUNCTION void update(ValueType const& rhs) {
312  value *= rhs;
313  }
314  KOKKOS_FORCEINLINE_FUNCTION void reset() {
315  value = reduction_identity<ValueType>::prod();
316  }
317 };
318 
319 /* ScatterValue <Op=ScatterProd, Contribution=ScatterAtomic> is the
320  object returned by the access operator() of ScatterAccess. This class
321  inherits from the Prod<> reducer, and similar to that returned by an Atomic
322  View, it wraps and atomic_prod with convenient operator*=, etc. atomic_prod
323  uses the atomic_compare_exchange. This version also has the update(rhs)
324  and reset() functions. */
325 template <typename ValueType, typename DeviceType>
326 struct ScatterValue<ValueType, Kokkos::Experimental::ScatterProd, DeviceType,
327  Kokkos::Experimental::ScatterAtomic> {
328  ValueType& value;
329 
330  public:
331  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ValueType& value_in)
332  : value(value_in) {}
333  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ScatterValue&& other)
334  : value(other.value) {}
335 
336  KOKKOS_FORCEINLINE_FUNCTION void operator*=(ValueType const& rhs) {
337  Kokkos::atomic_mul(&value, rhs);
338  }
339  KOKKOS_FORCEINLINE_FUNCTION void operator/=(ValueType const& rhs) {
340  Kokkos::atomic_div(&value, rhs);
341  }
342 
343  KOKKOS_INLINE_FUNCTION
344  void join(ValueType& dest, const ValueType& src) const {
345  atomic_prod(&dest, src);
346  }
347 
348  KOKKOS_FORCEINLINE_FUNCTION void update(ValueType const& rhs) {
349  atomic_prod(&value, rhs);
350  }
351  KOKKOS_FORCEINLINE_FUNCTION void reset() {
352  value = reduction_identity<ValueType>::prod();
353  }
354 };
355 
356 /* ScatterValue <Op=ScatterMin, Contribution=ScatterNonAtomic> is
357  the object returned by the access operator() of ScatterAccess. This class
358  inherits from the Min<> reducer and it wraps join(dest, src) with convenient
359  update(rhs). Note the addition of update(ValueType const& rhs) and reset()
360  are so that all reducers can have a common update function See
361  ReduceDuplicates and ResetDuplicates ) */
362 template <typename ValueType, typename DeviceType>
363 struct ScatterValue<ValueType, Kokkos::Experimental::ScatterMin, DeviceType,
364  Kokkos::Experimental::ScatterNonAtomic> {
365  ValueType& value;
366  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ValueType& value_in)
367  : value(value_in) {}
368  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ScatterValue&& other)
369  : value(other.value) {}
370 
371  public:
372  KOKKOS_FORCEINLINE_FUNCTION void update(ValueType const& rhs) {
373  value = rhs < value ? rhs : value;
374  }
375  KOKKOS_FORCEINLINE_FUNCTION void reset() {
376  value = reduction_identity<ValueType>::min();
377  }
378 };
379 
380 /* ScatterValue <Op=ScatterMin, Contribution=ScatterAtomic> is the
381  object returned by the access operator() of ScatterAccess. This class
382  inherits from the Min<> reducer, and similar to that returned by an Atomic
383  View, it wraps atomic_min with join(), etc. atomic_min uses the
384  atomic_compare_exchange. This version also has the update(rhs) and reset()
385  functions. */
386 template <typename ValueType, typename DeviceType>
387 struct ScatterValue<ValueType, Kokkos::Experimental::ScatterMin, DeviceType,
388  Kokkos::Experimental::ScatterAtomic> {
389  ValueType& value;
390 
391  public:
392  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ValueType& value_in)
393  : value(value_in) {}
394  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ScatterValue&& other)
395  : value(other.value) {}
396 
397  KOKKOS_INLINE_FUNCTION
398  void join(ValueType& dest, const ValueType& src) const {
399  atomic_min(&dest, src);
400  }
401 
402  KOKKOS_FORCEINLINE_FUNCTION void update(ValueType const& rhs) {
403  this->join(value, rhs);
404  }
405  KOKKOS_FORCEINLINE_FUNCTION void reset() {
406  value = reduction_identity<ValueType>::min();
407  }
408 };
409 
410 /* ScatterValue <Op=ScatterMax, Contribution=ScatterNonAtomic> is
411  the object returned by the access operator() of ScatterAccess. This class
412  inherits from the Max<> reducer and it wraps join(dest, src) with convenient
413  update(rhs). Note the addition of update(ValueType const& rhs) and reset()
414  are so that all reducers can have a common update function See
415  ReduceDuplicates and ResetDuplicates ) */
416 template <typename ValueType, typename DeviceType>
417 struct ScatterValue<ValueType, Kokkos::Experimental::ScatterMax, DeviceType,
418  Kokkos::Experimental::ScatterNonAtomic> {
419  ValueType& value;
420 
421  public:
422  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ValueType& value_in)
423  : value(value_in) {}
424  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ScatterValue&& other)
425  : value(other.value) {}
426  KOKKOS_FORCEINLINE_FUNCTION void update(ValueType const& rhs) {
427  value = rhs > value ? rhs : value;
428  }
429  KOKKOS_FORCEINLINE_FUNCTION void reset() {
430  value = reduction_identity<ValueType>::max();
431  }
432 };
433 
434 /* ScatterValue <Op=ScatterMax, Contribution=ScatterAtomic> is the
435  object returned by the access operator() of ScatterAccess. This class
436  inherits from the Max<> reducer, and similar to that returned by an Atomic
437  View, it wraps atomic_max with join(), etc. atomic_max uses the
438  atomic_compare_exchange. This version also has the update(rhs) and reset()
439  functions. */
440 template <typename ValueType, typename DeviceType>
441 struct ScatterValue<ValueType, Kokkos::Experimental::ScatterMax, DeviceType,
442  Kokkos::Experimental::ScatterAtomic> {
443  ValueType& value;
444 
445  public:
446  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ValueType& value_in)
447  : value(value_in) {}
448  KOKKOS_FORCEINLINE_FUNCTION ScatterValue(ScatterValue&& other)
449  : value(other.value) {}
450 
451  KOKKOS_INLINE_FUNCTION
452  void join(ValueType& dest, const ValueType& src) const {
453  atomic_max(&dest, src);
454  }
455 
456  KOKKOS_FORCEINLINE_FUNCTION void update(ValueType const& rhs) {
457  this->join(value, rhs);
458  }
459  KOKKOS_FORCEINLINE_FUNCTION void reset() {
460  value = reduction_identity<ValueType>::max();
461  }
462 };
463 
464 /* DuplicatedDataType, given a View DataType, will create a new DataType
465  that has a new runtime dimension which becomes the largest-stride dimension.
466  In the case of LayoutLeft, due to the limitation induced by the design of
467  DataType itself, it must convert any existing compile-time dimensions into
468  runtime dimensions. */
469 template <typename T, typename Layout>
470 struct DuplicatedDataType;
471 
472 template <typename T>
473 struct DuplicatedDataType<T, Kokkos::LayoutRight> {
474  using value_type = T*; // For LayoutRight, add a star all the way on the left
475 };
476 
477 template <typename T, size_t N>
478 struct DuplicatedDataType<T[N], Kokkos::LayoutRight> {
479  using value_type =
480  typename DuplicatedDataType<T, Kokkos::LayoutRight>::value_type[N];
481 };
482 
483 template <typename T>
484 struct DuplicatedDataType<T[], Kokkos::LayoutRight> {
485  using value_type =
486  typename DuplicatedDataType<T, Kokkos::LayoutRight>::value_type[];
487 };
488 
489 template <typename T>
490 struct DuplicatedDataType<T*, Kokkos::LayoutRight> {
491  using value_type =
492  typename DuplicatedDataType<T, Kokkos::LayoutRight>::value_type*;
493 };
494 
495 template <typename T>
496 struct DuplicatedDataType<T, Kokkos::LayoutLeft> {
497  using value_type = T*;
498 };
499 
500 template <typename T, size_t N>
501 struct DuplicatedDataType<T[N], Kokkos::LayoutLeft> {
502  using value_type =
503  typename DuplicatedDataType<T, Kokkos::LayoutLeft>::value_type*;
504 };
505 
506 template <typename T>
507 struct DuplicatedDataType<T[], Kokkos::LayoutLeft> {
508  using value_type =
509  typename DuplicatedDataType<T, Kokkos::LayoutLeft>::value_type*;
510 };
511 
512 template <typename T>
513 struct DuplicatedDataType<T*, Kokkos::LayoutLeft> {
514  using value_type =
515  typename DuplicatedDataType<T, Kokkos::LayoutLeft>::value_type*;
516 };
517 
518 /* Insert integer argument pack into array */
519 
520 template <class T>
521 void args_to_array(size_t* array, int pos, T dim0) {
522  array[pos] = dim0;
523 }
524 template <class T, class... Dims>
525 void args_to_array(size_t* array, int pos, T dim0, Dims... dims) {
526  array[pos] = dim0;
527  args_to_array(array, pos + 1, dims...);
528 }
529 
530 /* Slice is just responsible for stuffing the correct number of Kokkos::ALL
531  arguments on the correct side of the index in a call to subview() to get a
532  subview where the index specified is the largest-stride one. */
533 template <typename Layout, int rank, typename V, typename... Args>
534 struct Slice {
535  using next = Slice<Layout, rank - 1, V, Kokkos::ALL_t, Args...>;
536  static auto get(V const& src, const size_t i, Args... args) {
537  return next::get(src, i, Kokkos::ALL, args...);
538  }
539 };
540 
541 template <typename V, typename... Args>
542 struct Slice<Kokkos::LayoutRight, 1, V, Args...> {
543  static auto get(V const& src, const size_t i, Args... args) {
544  return Kokkos::subview(src, i, args...);
545  }
546 };
547 
548 template <typename V, typename... Args>
549 struct Slice<Kokkos::LayoutLeft, 1, V, Args...> {
550  static auto get(V const& src, const size_t i, Args... args) {
551  return Kokkos::subview(src, args..., i);
552  }
553 };
554 
555 #ifdef KOKKOS_ENABLE_IMPL_MDSPAN
556 template <typename V, typename... Args>
557 struct Slice<Kokkos::layout_right, 1, V, Args...> {
558  static auto get(V const& src, const size_t i, Args... args) {
559  return Kokkos::subview(src, i, args...);
560  }
561 };
562 
563 template <typename V, typename... Args>
564 struct Slice<Kokkos::layout_left, 1, V, Args...> {
565  static auto get(V const& src, const size_t i, Args... args) {
566  return Kokkos::subview(src, args..., i);
567  }
568 };
569 
570 template <size_t Pad, typename V, typename... Args>
571 struct Slice<Kokkos::Experimental::layout_right_padded<Pad>, 1, V, Args...> {
572  static auto get(V const& src, const size_t i, Args... args) {
573  return Kokkos::subview(src, i, args...);
574  }
575 };
576 
577 template <size_t Pad, typename V, typename... Args>
578 struct Slice<Kokkos::Experimental::layout_left_padded<Pad>, 1, V, Args...> {
579  static auto get(V const& src, const size_t i, Args... args) {
580  return Kokkos::subview(src, args..., i);
581  }
582 };
583 #endif
584 
585 template <typename ExecSpace, typename ValueType, typename Op>
586 struct ReduceDuplicates;
587 
588 template <typename ExecSpace, typename ValueType, typename Op>
589 struct ReduceDuplicatesBase {
590  using Derived = ReduceDuplicates<ExecSpace, ValueType, Op>;
591  ValueType const* src;
592  ValueType* dst;
593  size_t stride;
594  size_t start;
595  size_t n;
596  ReduceDuplicatesBase(ExecSpace const& exec_space, ValueType const* src_in,
597  ValueType* dest_in, size_t stride_in, size_t start_in,
598  size_t n_in, std::string const& name)
599  : src(src_in), dst(dest_in), stride(stride_in), start(start_in), n(n_in) {
600  parallel_for(
601  std::string("Kokkos::ScatterView::ReduceDuplicates [") + name + "]",
602  RangePolicy<ExecSpace, size_t>(exec_space, 0, stride),
603  static_cast<Derived const&>(*this));
604  }
605 };
606 
607 /* ReduceDuplicates -- Perform reduction on destination array using strided
608  * source Use ScatterValue<> specific to operation to wrap destination array so
609  * that the reduction operation can be accessed via the update(rhs) function */
610 template <typename ExecSpace, typename ValueType, typename Op>
611 struct ReduceDuplicates
612  : public ReduceDuplicatesBase<ExecSpace, ValueType, Op> {
613  using Base = ReduceDuplicatesBase<ExecSpace, ValueType, Op>;
614  ReduceDuplicates(ExecSpace const& exec_space, ValueType const* src_in,
615  ValueType* dst_in, size_t stride_in, size_t start_in,
616  size_t n_in, std::string const& name)
617  : Base(exec_space, src_in, dst_in, stride_in, start_in, n_in, name) {}
618  KOKKOS_FORCEINLINE_FUNCTION void operator()(size_t i) const {
619  for (size_t j = Base::start; j < Base::n; ++j) {
620  ScatterValue<ValueType, Op, ExecSpace,
621  Kokkos::Experimental::ScatterNonAtomic>
622  sv(Base::dst[i]);
623  sv.update(Base::src[i + Base::stride * j]);
624  }
625  }
626 };
627 
628 template <typename ExecSpace, typename ValueType, typename Op>
629 struct ResetDuplicates;
630 
631 template <typename ExecSpace, typename ValueType, typename Op>
632 struct ResetDuplicatesBase {
633  using Derived = ResetDuplicates<ExecSpace, ValueType, Op>;
634  ValueType* data;
635  ResetDuplicatesBase(ExecSpace const& exec_space, ValueType* data_in,
636  size_t size_in, std::string const& name)
637  : data(data_in) {
638  parallel_for(
639  std::string("Kokkos::ScatterView::ResetDuplicates [") + name + "]",
640  RangePolicy<ExecSpace, size_t>(exec_space, 0, size_in),
641  static_cast<Derived const&>(*this));
642  }
643 };
644 
645 /* ResetDuplicates -- Perform reset on destination array
646  * Use ScatterValue<> specific to operation to wrap destination array so that
647  * the reset operation can be accessed via the reset() function */
648 template <typename ExecSpace, typename ValueType, typename Op>
649 struct ResetDuplicates : public ResetDuplicatesBase<ExecSpace, ValueType, Op> {
650  using Base = ResetDuplicatesBase<ExecSpace, ValueType, Op>;
651  ResetDuplicates(ExecSpace const& exec_space, ValueType* data_in,
652  size_t size_in, std::string const& name)
653  : Base(exec_space, data_in, size_in, name) {}
654  KOKKOS_FORCEINLINE_FUNCTION void operator()(size_t i) const {
655  ScatterValue<ValueType, Op, ExecSpace,
656  Kokkos::Experimental::ScatterNonAtomic>
657  sv(Base::data[i]);
658  sv.reset();
659  }
660 };
661 
662 template <typename... P>
663 void check_scatter_view_allocation_properties_argument(
664  ViewCtorProp<P...> const&) {
665  static_assert(ViewCtorProp<P...>::has_execution_space &&
666  ViewCtorProp<P...>::has_label &&
667  ViewCtorProp<P...>::initialize,
668  "Allocation property must have an execution name as well as a "
669  "label, and must perform the view initialization");
670 }
671 
672 } // namespace Experimental
673 } // namespace Impl
674 } // namespace Kokkos
675 
676 namespace Kokkos {
677 namespace Experimental {
678 
679 template <typename DataType,
680  typename Layout = Kokkos::DefaultExecutionSpace::array_layout,
681  typename DeviceType = Kokkos::DefaultExecutionSpace,
682  typename Op = Kokkos::Experimental::ScatterSum,
683  typename Duplication = typename Kokkos::Impl::Experimental::
684  DefaultDuplication<typename DeviceType::execution_space>::type,
685  typename Contribution =
686  typename Kokkos::Impl::Experimental::DefaultContribution<
687  typename DeviceType::execution_space, Duplication>::type>
688 class ScatterView;
689 
690 template <class>
691 struct is_scatter_view : public std::false_type {};
692 
693 template <class D, class... P>
694 struct is_scatter_view<ScatterView<D, P...>> : public std::true_type {};
695 
696 template <class D, class... P>
697 struct is_scatter_view<const ScatterView<D, P...>> : public std::true_type {};
698 
699 template <class T>
700 inline constexpr bool is_scatter_view_v = is_scatter_view<T>::value;
701 
702 template <typename DataType, typename Op, typename DeviceType, typename Layout,
703  typename Duplication, typename Contribution,
704  typename OverrideContribution>
705 class ScatterAccess;
706 
707 // non-duplicated implementation
708 template <typename DataType, typename Op, typename DeviceType, typename Layout,
709  typename Contribution>
710 class ScatterView<DataType, Layout, DeviceType, Op, ScatterNonDuplicated,
711  Contribution> {
712  public:
713  using execution_space = typename DeviceType::execution_space;
714  using memory_space = typename DeviceType::memory_space;
715  using device_type = Kokkos::Device<execution_space, memory_space>;
716  using original_view_type = Kokkos::View<DataType, Layout, device_type>;
717  using original_value_type = typename original_view_type::value_type;
718  using original_reference_type = typename original_view_type::reference_type;
719  friend class ScatterAccess<DataType, Op, DeviceType, Layout,
720  ScatterNonDuplicated, Contribution,
721  ScatterNonAtomic>;
722  friend class ScatterAccess<DataType, Op, DeviceType, Layout,
723  ScatterNonDuplicated, Contribution, ScatterAtomic>;
724  template <class, class, class, class, class, class>
725  friend class ScatterView;
726 
727  ScatterView() = default;
728 
729  template <typename RT, typename... RP>
730  ScatterView(View<RT, RP...> const& original_view)
731  : internal_view(original_view) {}
732 
733  template <typename RT, typename... P, typename... RP>
734  ScatterView(execution_space const& /* exec_space */,
735  View<RT, RP...> const& original_view)
736  : internal_view(original_view) {}
737 
738  template <typename... Dims>
739  ScatterView(std::string const& name, Dims... dims)
740  : internal_view(name, dims...) {}
741 
742  // This overload allows specifying an execution space instance to be
743  // used by passing, e.g., Kokkos::view_alloc(exec_space, "label") as
744  // first argument.
745  template <typename... P, typename... Dims>
746  ScatterView(::Kokkos::Impl::ViewCtorProp<P...> const& arg_prop, Dims... dims)
747  : internal_view(arg_prop, dims...) {
748  using ::Kokkos::Impl::Experimental::
749  check_scatter_view_allocation_properties_argument;
750  check_scatter_view_allocation_properties_argument(arg_prop);
751  }
752 
753  template <typename OtherDataType, typename OtherDeviceType>
754  KOKKOS_FUNCTION ScatterView(
755  const ScatterView<OtherDataType, Layout, OtherDeviceType, Op,
756  ScatterNonDuplicated, Contribution>& other_view)
757  : internal_view(other_view.internal_view) {}
758 
759  template <typename OtherDataType, typename OtherDeviceType>
760  KOKKOS_FUNCTION ScatterView& operator=(
761  const ScatterView<OtherDataType, Layout, OtherDeviceType, Op,
762  ScatterNonDuplicated, Contribution>& other_view) {
763  internal_view = other_view.internal_view;
764  return *this;
765  }
766 
767  template <typename OverrideContribution = Contribution>
768  KOKKOS_FORCEINLINE_FUNCTION
769  ScatterAccess<DataType, Op, DeviceType, Layout, ScatterNonDuplicated,
770  Contribution, OverrideContribution>
771  access() const {
772  return ScatterAccess<DataType, Op, DeviceType, Layout, ScatterNonDuplicated,
773  Contribution, OverrideContribution>(*this);
774  }
775 
776  original_view_type subview() const { return internal_view; }
777 
778  KOKKOS_INLINE_FUNCTION constexpr bool is_allocated() const {
779  return internal_view.is_allocated();
780  }
781 
782  template <typename DT, typename... RP>
783  void contribute_into(View<DT, RP...> const& dest) const {
784  contribute_into(execution_space(), dest);
785  }
786 
787  template <typename DT, typename... RP>
788  void contribute_into(execution_space const& exec_space,
789  View<DT, RP...> const& dest) const {
790  using dest_type = View<DT, RP...>;
791  static_assert(std::is_same<typename dest_type::array_layout, Layout>::value,
792  "ScatterView contribute destination has different layout");
793  static_assert(
795  execution_space, typename dest_type::memory_space>::accessible,
796  "ScatterView contribute destination memory space not accessible");
797  if (dest.data() == internal_view.data()) return;
798  Kokkos::Impl::Experimental::ReduceDuplicates<execution_space,
799  original_value_type, Op>(
800  exec_space, internal_view.data(), dest.data(), 0, 0, 1,
801  internal_view.label());
802  }
803 
804  void reset(execution_space const& exec_space = execution_space()) {
805  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
806  original_value_type, Op>(
807  exec_space, internal_view.data(), internal_view.size(),
808  internal_view.label());
809  }
810  template <typename DT, typename... RP>
811  void reset_except(View<DT, RP...> const& view) {
812  reset_except(execution_space(), view);
813  }
814 
815  template <typename DT, typename... RP>
816  void reset_except(const execution_space& exec_space,
817  View<DT, RP...> const& view) {
818  if (view.data() != internal_view.data()) reset(exec_space);
819  }
820 
821  void resize(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
822  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
823  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
824  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
825  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
826  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
827  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
828  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
829  ::Kokkos::resize(internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
830  }
831 
832  template <class... ViewCtorArgs>
833  void resize(const ::Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
834  const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
835  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
836  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
837  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
838  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
839  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
840  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
841  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
842  ::Kokkos::resize(arg_prop, internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
843  }
844 
845  template <class I>
846  std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> resize(
847  const I& arg_prop, const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
848  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
849  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
850  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
851  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
852  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
853  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
854  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
855  ::Kokkos::resize(arg_prop, internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
856  }
857 
858  template <class... ViewCtorArgs>
859  void realloc(const Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
860  const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
861  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
862  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
863  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
864  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
865  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
866  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
867  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
868  ::Kokkos::realloc(arg_prop, internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
869  }
870 
871  void realloc(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
872  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
873  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
874  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
875  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
876  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
877  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
878  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
879  ::Kokkos::realloc(internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
880  }
881 
882  template <class I>
883  std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> realloc(
884  const I& arg_prop, const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
885  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
886  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
887  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
888  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
889  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
890  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
891  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
892  ::Kokkos::realloc(arg_prop, internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
893  }
894 
895  protected:
896  template <typename... Args>
897  KOKKOS_FORCEINLINE_FUNCTION original_reference_type at(Args... args) const {
898  return internal_view(args...);
899  }
900 
901  private:
902  using internal_view_type = original_view_type;
903  internal_view_type internal_view;
904 };
905 
906 template <typename DataType, typename Op, typename DeviceType, typename Layout,
907  typename Contribution, typename OverrideContribution>
908 class ScatterAccess<DataType, Op, DeviceType, Layout, ScatterNonDuplicated,
909  Contribution, OverrideContribution> {
910  public:
911  using view_type = ScatterView<DataType, Layout, DeviceType, Op,
912  ScatterNonDuplicated, Contribution>;
913  using original_value_type = typename view_type::original_value_type;
914  using value_type = Kokkos::Impl::Experimental::ScatterValue<
915  original_value_type, Op, DeviceType, OverrideContribution>;
916 
917  KOKKOS_INLINE_FUNCTION
918  ScatterAccess() : view(view_type()) {}
919 
920  KOKKOS_INLINE_FUNCTION
921  ScatterAccess(view_type const& view_in) : view(view_in) {}
922  KOKKOS_DEFAULTED_FUNCTION
923  ~ScatterAccess() = default;
924 
925  template <typename... Args>
926  KOKKOS_FORCEINLINE_FUNCTION value_type operator()(Args... args) const {
927  return view.at(args...);
928  }
929 
930  template <typename Arg>
931  KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
932  std::is_integral_v<Arg> && view_type::original_view_type::rank == 1,
933  value_type>
934  operator[](Arg arg) const {
935  return view.at(arg);
936  }
937 
938  private:
939  view_type const& view;
940 };
941 
942 // duplicated implementation
943 // LayoutLeft and LayoutRight are different enough that we'll just specialize
944 // each
945 
946 template <typename DataType, typename Op, typename DeviceType,
947  typename Contribution>
948 class ScatterView<DataType, Kokkos::LayoutRight, DeviceType, Op,
949  ScatterDuplicated, Contribution> {
950  public:
951  using execution_space = typename DeviceType::execution_space;
952  using memory_space = typename DeviceType::memory_space;
953  using device_type = Kokkos::Device<execution_space, memory_space>;
954  using original_view_type =
955  Kokkos::View<DataType, Kokkos::LayoutRight, device_type>;
956  using original_value_type = typename original_view_type::value_type;
957  using original_reference_type = typename original_view_type::reference_type;
958  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
959  ScatterDuplicated, Contribution, ScatterNonAtomic>;
960  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
961  ScatterDuplicated, Contribution, ScatterAtomic>;
962  template <class, class, class, class, class, class>
963  friend class ScatterView;
964 
965  using data_type_info =
966  typename Kokkos::Impl::Experimental::DuplicatedDataType<
967  DataType, Kokkos::LayoutRight>;
968  using internal_data_type = typename data_type_info::value_type;
969  using internal_view_type =
970  Kokkos::View<internal_data_type, Kokkos::LayoutRight, device_type>;
971 
972  ScatterView() = default;
973 
974  template <typename OtherDataType, typename OtherDeviceType>
975  KOKKOS_FUNCTION ScatterView(
976  const ScatterView<OtherDataType, Kokkos::LayoutRight, OtherDeviceType, Op,
977  ScatterDuplicated, Contribution>& other_view)
978  : unique_token(other_view.unique_token),
979  internal_view(other_view.internal_view) {}
980 
981  template <typename OtherDataType, typename OtherDeviceType>
982  KOKKOS_FUNCTION ScatterView& operator=(
983  const ScatterView<OtherDataType, Kokkos::LayoutRight, OtherDeviceType, Op,
984  ScatterDuplicated, Contribution>& other_view) {
985  unique_token = other_view.unique_token;
986  internal_view = other_view.internal_view;
987  return *this;
988  }
989 
990  template <typename RT, typename... RP>
991  ScatterView(View<RT, RP...> const& original_view)
992  : ScatterView(execution_space(), original_view) {}
993 
994  template <typename RT, typename... P, typename... RP>
995  ScatterView(execution_space const& exec_space,
996  View<RT, RP...> const& original_view)
997  : unique_token(),
998  internal_view(
999  view_alloc(WithoutInitializing,
1000  std::string("duplicated_") + original_view.label(),
1001  exec_space),
1002  unique_token.size(),
1003  original_view.rank_dynamic > 0 ? original_view.extent(0)
1004  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1005  original_view.rank_dynamic > 1 ? original_view.extent(1)
1006  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1007  original_view.rank_dynamic > 2 ? original_view.extent(2)
1008  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1009  original_view.rank_dynamic > 3 ? original_view.extent(3)
1010  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1011  original_view.rank_dynamic > 4 ? original_view.extent(4)
1012  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1013  original_view.rank_dynamic > 5 ? original_view.extent(5)
1014  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1015  original_view.rank_dynamic > 6 ? original_view.extent(6)
1016  : KOKKOS_IMPL_CTOR_DEFAULT_ARG)
1017 
1018  {
1019  reset(exec_space);
1020  }
1021 
1022  template <typename... Dims>
1023  ScatterView(std::string const& name, Dims... dims)
1024  : ScatterView(view_alloc(execution_space(), name), dims...) {}
1025 
1026  // This overload allows specifying an execution space instance to be
1027  // used by passing, e.g., Kokkos::view_alloc(exec_space, "label") as
1028  // first argument.
1029  template <typename... P, typename... Dims>
1030  ScatterView(::Kokkos::Impl::ViewCtorProp<P...> const& arg_prop, Dims... dims)
1031  : internal_view(view_alloc(WithoutInitializing,
1032  static_cast<::Kokkos::Impl::ViewCtorProp<
1033  void, std::string> const&>(arg_prop)
1034  .value),
1035  unique_token.size(), dims...) {
1036  using ::Kokkos::Impl::Experimental::
1037  check_scatter_view_allocation_properties_argument;
1038  check_scatter_view_allocation_properties_argument(arg_prop);
1039 
1040  auto const& exec_space =
1041  Kokkos::Impl::get_property<Kokkos::Impl::ExecutionSpaceTag>(arg_prop);
1042  reset(exec_space);
1043  }
1044 
1045  template <typename OverrideContribution = Contribution>
1046  KOKKOS_FORCEINLINE_FUNCTION
1047  ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
1048  ScatterDuplicated, Contribution, OverrideContribution>
1049  access() const {
1050  return ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
1051  ScatterDuplicated, Contribution, OverrideContribution>(
1052  *this);
1053  }
1054 
1055  auto subview() const {
1056  return Kokkos::Impl::Experimental::Slice<
1057  Kokkos::LayoutRight, internal_view_type::rank,
1058  internal_view_type>::get(internal_view, 0);
1059  }
1060 
1061  KOKKOS_INLINE_FUNCTION constexpr bool is_allocated() const {
1062  return internal_view.is_allocated();
1063  }
1064 
1065  template <typename DT, typename... RP>
1066  void contribute_into(View<DT, RP...> const& dest) const {
1067  contribute_into(execution_space(), dest);
1068  }
1069 
1070  template <typename DT, typename... RP>
1071  void contribute_into(execution_space const& exec_space,
1072  View<DT, RP...> const& dest) const {
1073  using dest_type = View<DT, RP...>;
1074  static_assert(std::is_same<typename dest_type::array_layout,
1075  Kokkos::LayoutRight>::value,
1076  "ScatterView deep_copy destination has different layout");
1077  static_assert(
1079  execution_space, typename dest_type::memory_space>::accessible,
1080  "ScatterView deep_copy destination memory space not accessible");
1081  bool is_equal = (dest.data() == internal_view.data());
1082  size_t start = is_equal ? 1 : 0;
1083  Kokkos::Impl::Experimental::ReduceDuplicates<execution_space,
1084  original_value_type, Op>(
1085  exec_space, internal_view.data(), dest.data(), internal_view.stride(0),
1086  start, internal_view.extent(0), internal_view.label());
1087  }
1088 
1089  void reset(execution_space const& exec_space = execution_space()) {
1090  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1091  original_value_type, Op>(
1092  exec_space, internal_view.data(), internal_view.size(),
1093  internal_view.label());
1094  }
1095 
1096  template <typename DT, typename... RP>
1097  void reset_except(View<DT, RP...> const& view) {
1098  reset_except(execution_space(), view);
1099  }
1100 
1101  template <typename DT, typename... RP>
1102  void reset_except(execution_space const& exec_space,
1103  View<DT, RP...> const& view) {
1104  if (view.data() != internal_view.data()) {
1105  reset(exec_space);
1106  return;
1107  }
1108  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1109  original_value_type, Op>(
1110  exec_space, internal_view.data() + view.size(),
1111  internal_view.size() - view.size(), internal_view.label());
1112  }
1113 
1114  void resize(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1115  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1116  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1117  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1118  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1119  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1120  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1121  ::Kokkos::resize(internal_view, unique_token.size(), n0, n1, n2, n3, n4, n5,
1122  n6);
1123  }
1124 
1125  template <class... ViewCtorArgs>
1126  void resize(const ::Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1127  const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1128  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1129  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1130  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1131  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1132  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1133  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1134  ::Kokkos::resize(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1135  n3, n4, n5, n6);
1136  }
1137 
1138  template <class I>
1139  std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> resize(
1140  const I& arg_prop, const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1141  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1142  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1143  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1144  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1145  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1146  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1147  ::Kokkos::resize(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1148  n3, n4, n5, n6);
1149  }
1150 
1151  template <class... ViewCtorArgs>
1152  void realloc(const ::Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1153  const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1154  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1155  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1156  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1157  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1158  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1159  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1160  ::Kokkos::realloc(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1161  n3, n4, n5, n6);
1162  }
1163 
1164  void realloc(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1165  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1166  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1167  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1168  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1169  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1170  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1171  ::Kokkos::realloc(internal_view, unique_token.size(), n0, n1, n2, n3, n4,
1172  n5, n6);
1173  }
1174 
1175  template <class I>
1176  std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> realloc(
1177  const I& arg_prop, const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1178  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1179  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1180  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1181  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1182  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1183  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1184  ::Kokkos::realloc(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1185  n3, n4, n5, n6);
1186  }
1187 
1188  protected:
1189  template <typename... Args>
1190  KOKKOS_FORCEINLINE_FUNCTION original_reference_type at(int rank,
1191  Args... args) const {
1192  return internal_view(rank, args...);
1193  }
1194 
1195  protected:
1196  using unique_token_type = Kokkos::Experimental::UniqueToken<
1197  execution_space, Kokkos::Experimental::UniqueTokenScope::Global>;
1198 
1199  unique_token_type unique_token;
1200  internal_view_type internal_view;
1201 };
1202 
1203 template <typename DataType, typename Op, typename DeviceType,
1204  typename Contribution>
1205 class ScatterView<DataType, Kokkos::LayoutLeft, DeviceType, Op,
1206  ScatterDuplicated, Contribution> {
1207  public:
1208  using execution_space = typename DeviceType::execution_space;
1209  using memory_space = typename DeviceType::memory_space;
1210  using device_type = Kokkos::Device<execution_space, memory_space>;
1211  using original_view_type =
1212  Kokkos::View<DataType, Kokkos::LayoutLeft, device_type>;
1213  using original_value_type = typename original_view_type::value_type;
1214  using original_reference_type = typename original_view_type::reference_type;
1215  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1216  ScatterDuplicated, Contribution, ScatterNonAtomic>;
1217  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1218  ScatterDuplicated, Contribution, ScatterAtomic>;
1219  template <class, class, class, class, class, class>
1220  friend class ScatterView;
1221 
1222  using data_type_info =
1223  typename Kokkos::Impl::Experimental::DuplicatedDataType<
1224  DataType, Kokkos::LayoutLeft>;
1225  using internal_data_type = typename data_type_info::value_type;
1226  using internal_view_type =
1227  Kokkos::View<internal_data_type, Kokkos::LayoutLeft, device_type>;
1228 
1229  ScatterView() = default;
1230 
1231  template <typename RT, typename... RP>
1232  ScatterView(View<RT, RP...> const& original_view)
1233  : ScatterView(execution_space(), original_view) {}
1234 
1235  template <typename RT, typename... P, typename... RP>
1236  ScatterView(execution_space const& exec_space,
1237  View<RT, RP...> const& original_view)
1238  : unique_token() {
1239  size_t arg_N[8] = {original_view.rank > 0 ? original_view.extent(0)
1240  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1241  original_view.rank > 1 ? original_view.extent(1)
1242  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1243  original_view.rank > 2 ? original_view.extent(2)
1244  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1245  original_view.rank > 3 ? original_view.extent(3)
1246  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1247  original_view.rank > 4 ? original_view.extent(4)
1248  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1249  original_view.rank > 5 ? original_view.extent(5)
1250  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1251  original_view.rank > 6 ? original_view.extent(6)
1252  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1253  KOKKOS_IMPL_CTOR_DEFAULT_ARG};
1254  arg_N[internal_view_type::rank - 1] = unique_token.size();
1255  internal_view = internal_view_type(
1256  view_alloc(WithoutInitializing,
1257  std::string("duplicated_") + original_view.label(),
1258  exec_space),
1259  arg_N[0], arg_N[1], arg_N[2], arg_N[3], arg_N[4], arg_N[5], arg_N[6],
1260  arg_N[7]);
1261  reset(exec_space);
1262  }
1263 
1264  template <typename... Dims>
1265  ScatterView(std::string const& name, Dims... dims)
1266  : ScatterView(view_alloc(execution_space(), name), dims...) {}
1267 
1268  // This overload allows specifying an execution space instance to be
1269  // used by passing, e.g., Kokkos::view_alloc(exec_space, "label") as
1270  // first argument.
1271  template <typename... P, typename... Dims>
1272  ScatterView(::Kokkos::Impl::ViewCtorProp<P...> const& arg_prop,
1273  Dims... dims) {
1274  using ::Kokkos::Impl::Experimental::
1275  check_scatter_view_allocation_properties_argument;
1276  check_scatter_view_allocation_properties_argument(arg_prop);
1277 
1278  original_view_type original_view;
1279  size_t arg_N[8] = {original_view.rank > 0 ? original_view.static_extent(0)
1280  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1281  original_view.rank > 1 ? original_view.static_extent(1)
1282  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1283  original_view.rank > 2 ? original_view.static_extent(2)
1284  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1285  original_view.rank > 3 ? original_view.static_extent(3)
1286  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1287  original_view.rank > 4 ? original_view.static_extent(4)
1288  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1289  original_view.rank > 5 ? original_view.static_extent(5)
1290  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1291  original_view.rank > 6 ? original_view.static_extent(6)
1292  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1293  KOKKOS_IMPL_CTOR_DEFAULT_ARG};
1294  Kokkos::Impl::Experimental::args_to_array(arg_N, 0, dims...);
1295  arg_N[internal_view_type::rank - 1] = unique_token.size();
1296 
1297  auto const& name =
1298  Kokkos::Impl::get_property<Kokkos::Impl::LabelTag>(arg_prop);
1299  internal_view = internal_view_type(view_alloc(WithoutInitializing, name),
1300  arg_N[0], arg_N[1], arg_N[2], arg_N[3],
1301  arg_N[4], arg_N[5], arg_N[6], arg_N[7]);
1302 
1303  auto const& exec_space =
1304  Kokkos::Impl::get_property<Kokkos::Impl::ExecutionSpaceTag>(arg_prop);
1305  reset(exec_space);
1306  }
1307 
1308  template <typename OtherDataType, typename OtherDeviceType>
1309  KOKKOS_FUNCTION ScatterView(
1310  const ScatterView<OtherDataType, Kokkos::LayoutLeft, OtherDeviceType, Op,
1311  ScatterDuplicated, Contribution>& other_view)
1312  : unique_token(other_view.unique_token),
1313  internal_view(other_view.internal_view) {}
1314 
1315  template <typename OtherDataType, typename OtherDeviceType>
1316  KOKKOS_FUNCTION ScatterView& operator=(
1317  const ScatterView<OtherDataType, Kokkos::LayoutLeft, OtherDeviceType, Op,
1318  ScatterDuplicated, Contribution>& other_view) {
1319  unique_token = other_view.unique_token;
1320  internal_view = other_view.internal_view;
1321  return *this;
1322  }
1323 
1324  template <typename OverrideContribution = Contribution>
1325  KOKKOS_FORCEINLINE_FUNCTION
1326  ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1327  ScatterDuplicated, Contribution, OverrideContribution>
1328  access() const {
1329  return ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1330  ScatterDuplicated, Contribution, OverrideContribution>(
1331  *this);
1332  }
1333 
1334  auto subview() const {
1335  return Kokkos::Impl::Experimental::Slice<
1336  Kokkos::LayoutLeft, internal_view_type::rank,
1337  internal_view_type>::get(internal_view, 0);
1338  }
1339 
1340  KOKKOS_INLINE_FUNCTION constexpr bool is_allocated() const {
1341  return internal_view.is_allocated();
1342  }
1343 
1344  template <typename... RP>
1345  void contribute_into(View<RP...> const& dest) const {
1346  contribute_into(execution_space(), dest);
1347  }
1348 
1349  template <typename... RP>
1350  void contribute_into(execution_space const& exec_space,
1351  View<RP...> const& dest) const {
1352  using dest_type = View<RP...>;
1353  static_assert(
1354  std::is_same<typename dest_type::value_type,
1355  typename original_view_type::non_const_value_type>::value,
1356  "ScatterView deep_copy destination has wrong value_type");
1357  static_assert(std::is_same<typename dest_type::array_layout,
1358  Kokkos::LayoutLeft>::value,
1359  "ScatterView deep_copy destination has different layout");
1360  static_assert(
1362  execution_space, typename dest_type::memory_space>::accessible,
1363  "ScatterView deep_copy destination memory space not accessible");
1364  auto extent = internal_view.extent(internal_view_type::rank - 1);
1365  bool is_equal = (dest.data() == internal_view.data());
1366  size_t start = is_equal ? 1 : 0;
1367  Kokkos::Impl::Experimental::ReduceDuplicates<execution_space,
1368  original_value_type, Op>(
1369  exec_space, internal_view.data(), dest.data(),
1370  internal_view.stride(internal_view_type::rank - 1), start, extent,
1371  internal_view.label());
1372  }
1373 
1374  void reset(execution_space const& exec_space = execution_space()) {
1375  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1376  original_value_type, Op>(
1377  exec_space, internal_view.data(), internal_view.size(),
1378  internal_view.label());
1379  }
1380 
1381  template <typename DT, typename... RP>
1382  void reset_except(View<DT, RP...> const& view) {
1383  reset_except(execution_space(), view);
1384  }
1385 
1386  template <typename DT, typename... RP>
1387  void reset_except(execution_space const& exec_space,
1388  View<DT, RP...> const& view) {
1389  if (view.data() != internal_view.data()) {
1390  reset(exec_space);
1391  return;
1392  }
1393  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1394  original_value_type, Op>(
1395  exec_space, internal_view.data() + view.size(),
1396  internal_view.size() - view.size(), internal_view.label());
1397  }
1398 
1399  void resize(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1400  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1401  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1402  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1403  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1404  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1405  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1406  size_t arg_N[8] = {n0, n1, n2, n3, n4, n5, n6, 0};
1407  const int i = internal_view.rank - 1;
1408  arg_N[i] = unique_token.size();
1409 
1410  ::Kokkos::resize(internal_view, arg_N[0], arg_N[1], arg_N[2], arg_N[3],
1411  arg_N[4], arg_N[5], arg_N[6], arg_N[7]);
1412  }
1413 
1414  void realloc(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1415  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1416  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1417  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1418  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1419  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1420  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1421  size_t arg_N[8] = {n0, n1, n2, n3, n4, n5, n6, 0};
1422  const int i = internal_view.rank - 1;
1423  arg_N[i] = unique_token.size();
1424 
1425  ::Kokkos::realloc(internal_view, arg_N[0], arg_N[1], arg_N[2], arg_N[3],
1426  arg_N[4], arg_N[5], arg_N[6], arg_N[7]);
1427  }
1428 
1429  protected:
1430  template <typename... Args>
1431  KOKKOS_FORCEINLINE_FUNCTION original_reference_type at(int thread_id,
1432  Args... args) const {
1433  return internal_view(args..., thread_id);
1434  }
1435 
1436  protected:
1437  using unique_token_type = Kokkos::Experimental::UniqueToken<
1438  execution_space, Kokkos::Experimental::UniqueTokenScope::Global>;
1439 
1440  unique_token_type unique_token;
1441  internal_view_type internal_view;
1442 };
1443 
1444 /* This object has to be separate in order to store the thread ID, which cannot
1445  be obtained until one is inside a parallel construct, and may be relatively
1446  expensive to obtain at every contribution
1447  (calls a non-inlined function, looks up a thread-local variable).
1448  Due to the expense, it is sensible to query it at most once per parallel
1449  iterate (ideally once per thread, but parallel_for doesn't expose that) and
1450  then store it in a stack variable.
1451  ScatterAccess serves as a non-const object on the stack which can store the
1452  thread ID */
1453 
1454 template <typename DataType, typename Op, typename DeviceType, typename Layout,
1455  typename Contribution, typename OverrideContribution>
1456 class ScatterAccess<DataType, Op, DeviceType, Layout, ScatterDuplicated,
1457  Contribution, OverrideContribution> {
1458  public:
1459  using view_type = ScatterView<DataType, Layout, DeviceType, Op,
1460  ScatterDuplicated, Contribution>;
1461  using original_value_type = typename view_type::original_value_type;
1462  using value_type = Kokkos::Impl::Experimental::ScatterValue<
1463  original_value_type, Op, DeviceType, OverrideContribution>;
1464 
1465  KOKKOS_FORCEINLINE_FUNCTION
1466  ScatterAccess(view_type const& view_in)
1467  : view(view_in), thread_id(view_in.unique_token.acquire()) {}
1468 
1469  KOKKOS_FORCEINLINE_FUNCTION
1470  ~ScatterAccess() {
1471  if (thread_id != ~thread_id_type(0)) view.unique_token.release(thread_id);
1472  }
1473 
1474  template <typename... Args>
1475  KOKKOS_FORCEINLINE_FUNCTION value_type operator()(Args... args) const {
1476  return view.at(thread_id, args...);
1477  }
1478 
1479  template <typename Arg>
1480  KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
1481  std::is_integral_v<Arg> && view_type::original_view_type::rank == 1,
1482  value_type>
1483  operator[](Arg arg) const {
1484  return view.at(thread_id, arg);
1485  }
1486 
1487  private:
1488  view_type const& view;
1489 
1490  // simplify RAII by disallowing copies
1491  ScatterAccess(ScatterAccess const& other) = delete;
1492  ScatterAccess& operator=(ScatterAccess const& other) = delete;
1493  ScatterAccess& operator=(ScatterAccess&& other) = delete;
1494 
1495  public:
1496  // do need to allow moves though, for the common
1497  // auto b = a.access();
1498  // that assignments turns into a move constructor call
1499  KOKKOS_FORCEINLINE_FUNCTION
1500  ScatterAccess(ScatterAccess&& other)
1501  : view(other.view), thread_id(other.thread_id) {
1502  other.thread_id = ~thread_id_type(0);
1503  }
1504 
1505  private:
1506  using unique_token_type = typename view_type::unique_token_type;
1507  using thread_id_type = typename unique_token_type::size_type;
1508  thread_id_type thread_id;
1509 };
1510 
1511 template <typename Op = Kokkos::Experimental::ScatterSum,
1512  typename Duplication = void, typename Contribution = void,
1513  typename RT, typename... RP>
1514 ScatterView<
1515  RT, typename ViewTraits<RT, RP...>::array_layout,
1516  typename ViewTraits<RT, RP...>::device_type, Op,
1517  std::conditional_t<
1518  std::is_void_v<Duplication>,
1519  typename Kokkos::Impl::Experimental::DefaultDuplication<
1520  typename ViewTraits<RT, RP...>::execution_space>::type,
1521  Duplication>,
1522  std::conditional_t<
1523  std::is_void_v<Contribution>,
1524  typename Kokkos::Impl::Experimental::DefaultContribution<
1525  typename ViewTraits<RT, RP...>::execution_space,
1526  typename std::conditional_t<
1527  std::is_void_v<Duplication>,
1528  typename Kokkos::Impl::Experimental::DefaultDuplication<
1529  typename ViewTraits<RT, RP...>::execution_space>::type,
1530  Duplication>>::type,
1531  Contribution>>
1532 create_scatter_view(View<RT, RP...> const& original_view) {
1533  return original_view; // implicit ScatterView constructor call
1534 }
1535 
1536 template <typename Op, typename RT, typename... RP>
1537 ScatterView<
1538  RT, typename ViewTraits<RT, RP...>::array_layout,
1539  typename ViewTraits<RT, RP...>::device_type, Op,
1540  typename Kokkos::Impl::Experimental::DefaultDuplication<
1541  typename ViewTraits<RT, RP...>::execution_space>::type,
1542  typename Kokkos::Impl::Experimental::DefaultContribution<
1543  typename ViewTraits<RT, RP...>::execution_space,
1544  typename Kokkos::Impl::Experimental::DefaultDuplication<
1545  typename ViewTraits<RT, RP...>::execution_space>::type>::type>
1546 create_scatter_view(Op, View<RT, RP...> const& original_view) {
1547  return original_view; // implicit ScatterView constructor call
1548 }
1549 
1550 template <typename Op, typename Duplication, typename Contribution, typename RT,
1551  typename... RP>
1552 ScatterView<RT, typename ViewTraits<RT, RP...>::array_layout,
1553  typename ViewTraits<RT, RP...>::device_type, Op, Duplication,
1554  Contribution>
1555 create_scatter_view(Op, Duplication, Contribution,
1556  View<RT, RP...> const& original_view) {
1557  return original_view; // implicit ScatterView constructor call
1558 }
1559 
1560 } // namespace Experimental
1561 } // namespace Kokkos
1562 
1563 namespace Kokkos {
1564 namespace Experimental {
1565 
1566 template <typename DT1, typename DT2, typename LY, typename ES, typename OP,
1567  typename CT, typename DP, typename... VP>
1568 void contribute(
1569  typename ES::execution_space const& exec_space, View<DT1, VP...>& dest,
1570  Kokkos::Experimental::ScatterView<DT2, LY, ES, OP, CT, DP> const& src) {
1571  src.contribute_into(exec_space, dest);
1572 }
1573 
1574 template <typename DT1, typename DT2, typename LY, typename ES, typename OP,
1575  typename CT, typename DP, typename... VP>
1576 void contribute(
1577  View<DT1, VP...>& dest,
1578  Kokkos::Experimental::ScatterView<DT2, LY, ES, OP, CT, DP> const& src) {
1579  using execution_space = typename ES::execution_space;
1580  contribute(execution_space{}, dest, src);
1581 }
1582 
1583 } // namespace Experimental
1584 } // namespace Kokkos
1585 
1586 namespace Kokkos {
1587 
1588 template <typename DT, typename LY, typename ES, typename OP, typename CT,
1589  typename DP, typename... IS, class... ViewCtorArgs>
1590 void realloc(
1591  const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1592  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1593  IS... is) {
1594  scatter_view.realloc(arg_prop, is...);
1595 }
1596 
1597 template <typename DT, typename LY, typename ES, typename OP, typename CT,
1598  typename DP, typename... IS>
1599 void realloc(
1600  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1601  IS... is) {
1602  scatter_view.realloc(is...);
1603 }
1604 
1605 template <typename I, typename DT, typename LY, typename ES, typename OP,
1606  typename CT, typename DP, typename... IS>
1607 std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> realloc(
1608  const I& arg_prop,
1609  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1610  IS... is) {
1611  scatter_view.realloc(arg_prop, is...);
1612 }
1613 
1614 template <typename DT, typename LY, typename ES, typename OP, typename CT,
1615  typename DP, typename... IS>
1616 void resize(
1617  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1618  IS... is) {
1619  scatter_view.resize(is...);
1620 }
1621 
1622 template <class... ViewCtorArgs, typename DT, typename LY, typename ES,
1623  typename OP, typename CT, typename DP, typename... IS>
1624 void resize(
1625  const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1626  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1627  IS... is) {
1628  scatter_view.resize(arg_prop, is...);
1629 }
1630 
1631 template <typename I, typename DT, typename LY, typename ES, typename OP,
1632  typename CT, typename DP, typename... IS>
1633 std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> resize(
1634  const I& arg_prop,
1635  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1636  IS... is) {
1637  scatter_view.resize(arg_prop, is...);
1638 }
1639 
1640 } // namespace Kokkos
1641 
1642 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_SCATTERVIEW
1643 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
1644 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_SCATTERVIEW
1645 #endif
1646 #endif
Memory layout tag indicating left-to-right (Fortran scheme) striding of multi-indices.
Can AccessSpace access MemorySpace ?
class to generate unique ids base on the required amount of concurrency
Memory layout tag indicating right-to-left (C or lexigraphical scheme) striding of multi-indices...