Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_ScatterView.hpp
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::Experimental::SYCL> {
188  using type = Kokkos::Experimental::ScatterNonDuplicated;
189 };
190 template <>
191 struct DefaultContribution<Kokkos::Experimental::SYCL,
192  Kokkos::Experimental::ScatterNonDuplicated> {
193  using type = Kokkos::Experimental::ScatterAtomic;
194 };
195 template <>
196 struct DefaultContribution<Kokkos::Experimental::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  using value_type = typename next::value_type;
537 
538  static value_type get(V const& src, const size_t i, Args... args) {
539  return next::get(src, i, Kokkos::ALL, args...);
540  }
541 };
542 
543 template <typename V, typename... Args>
544 struct Slice<Kokkos::LayoutRight, 1, V, Args...> {
545  using value_type =
546  typename Kokkos::Impl::ViewMapping<void, V, const size_t, Args...>::type;
547  static value_type get(V const& src, const size_t i, Args... args) {
548  return Kokkos::subview(src, i, args...);
549  }
550 };
551 
552 template <typename V, typename... Args>
553 struct Slice<Kokkos::LayoutLeft, 1, V, Args...> {
554  using value_type =
555  typename Kokkos::Impl::ViewMapping<void, V, Args..., const size_t>::type;
556  static value_type get(V const& src, const size_t i, Args... args) {
557  return Kokkos::subview(src, args..., i);
558  }
559 };
560 
561 template <typename ExecSpace, typename ValueType, typename Op>
562 struct ReduceDuplicates;
563 
564 template <typename ExecSpace, typename ValueType, typename Op>
565 struct ReduceDuplicatesBase {
566  using Derived = ReduceDuplicates<ExecSpace, ValueType, Op>;
567  ValueType const* src;
568  ValueType* dst;
569  size_t stride;
570  size_t start;
571  size_t n;
572  ReduceDuplicatesBase(ExecSpace const& exec_space, ValueType const* src_in,
573  ValueType* dest_in, size_t stride_in, size_t start_in,
574  size_t n_in, std::string const& name)
575  : src(src_in), dst(dest_in), stride(stride_in), start(start_in), n(n_in) {
576  parallel_for(
577  std::string("Kokkos::ScatterView::ReduceDuplicates [") + name + "]",
578  RangePolicy<ExecSpace, size_t>(exec_space, 0, stride),
579  static_cast<Derived const&>(*this));
580  }
581 };
582 
583 /* ReduceDuplicates -- Perform reduction on destination array using strided
584  * source Use ScatterValue<> specific to operation to wrap destination array so
585  * that the reduction operation can be accessed via the update(rhs) function */
586 template <typename ExecSpace, typename ValueType, typename Op>
587 struct ReduceDuplicates
588  : public ReduceDuplicatesBase<ExecSpace, ValueType, Op> {
589  using Base = ReduceDuplicatesBase<ExecSpace, ValueType, Op>;
590  ReduceDuplicates(ExecSpace const& exec_space, ValueType const* src_in,
591  ValueType* dst_in, size_t stride_in, size_t start_in,
592  size_t n_in, std::string const& name)
593  : Base(exec_space, src_in, dst_in, stride_in, start_in, n_in, name) {}
594  KOKKOS_FORCEINLINE_FUNCTION void operator()(size_t i) const {
595  for (size_t j = Base::start; j < Base::n; ++j) {
596  ScatterValue<ValueType, Op, ExecSpace,
597  Kokkos::Experimental::ScatterNonAtomic>
598  sv(Base::dst[i]);
599  sv.update(Base::src[i + Base::stride * j]);
600  }
601  }
602 };
603 
604 template <typename ExecSpace, typename ValueType, typename Op>
605 struct ResetDuplicates;
606 
607 template <typename ExecSpace, typename ValueType, typename Op>
608 struct ResetDuplicatesBase {
609  using Derived = ResetDuplicates<ExecSpace, ValueType, Op>;
610  ValueType* data;
611  ResetDuplicatesBase(ExecSpace const& exec_space, ValueType* data_in,
612  size_t size_in, std::string const& name)
613  : data(data_in) {
614  parallel_for(
615  std::string("Kokkos::ScatterView::ResetDuplicates [") + name + "]",
616  RangePolicy<ExecSpace, size_t>(exec_space, 0, size_in),
617  static_cast<Derived const&>(*this));
618  }
619 };
620 
621 /* ResetDuplicates -- Perform reset on destination array
622  * Use ScatterValue<> specific to operation to wrap destination array so that
623  * the reset operation can be accessed via the reset() function */
624 template <typename ExecSpace, typename ValueType, typename Op>
625 struct ResetDuplicates : public ResetDuplicatesBase<ExecSpace, ValueType, Op> {
626  using Base = ResetDuplicatesBase<ExecSpace, ValueType, Op>;
627  ResetDuplicates(ExecSpace const& exec_space, ValueType* data_in,
628  size_t size_in, std::string const& name)
629  : Base(exec_space, data_in, size_in, name) {}
630  KOKKOS_FORCEINLINE_FUNCTION void operator()(size_t i) const {
631  ScatterValue<ValueType, Op, ExecSpace,
632  Kokkos::Experimental::ScatterNonAtomic>
633  sv(Base::data[i]);
634  sv.reset();
635  }
636 };
637 
638 template <typename... P>
639 void check_scatter_view_allocation_properties_argument(
640  ViewCtorProp<P...> const&) {
641  static_assert(ViewCtorProp<P...>::has_execution_space &&
642  ViewCtorProp<P...>::has_label &&
643  ViewCtorProp<P...>::initialize,
644  "Allocation property must have an execution name as well as a "
645  "label, and must perform the view initialization");
646 }
647 
648 } // namespace Experimental
649 } // namespace Impl
650 } // namespace Kokkos
651 
652 namespace Kokkos {
653 namespace Experimental {
654 
655 template <typename DataType,
656  typename Layout = Kokkos::DefaultExecutionSpace::array_layout,
657  typename DeviceType = Kokkos::DefaultExecutionSpace,
658  typename Op = Kokkos::Experimental::ScatterSum,
659  typename Duplication = typename Kokkos::Impl::Experimental::
660  DefaultDuplication<typename DeviceType::execution_space>::type,
661  typename Contribution =
662  typename Kokkos::Impl::Experimental::DefaultContribution<
663  typename DeviceType::execution_space, Duplication>::type>
664 class ScatterView;
665 
666 template <class>
667 struct is_scatter_view : public std::false_type {};
668 
669 template <class D, class... P>
670 struct is_scatter_view<ScatterView<D, P...>> : public std::true_type {};
671 
672 template <class D, class... P>
673 struct is_scatter_view<const ScatterView<D, P...>> : public std::true_type {};
674 
675 template <class T>
676 inline constexpr bool is_scatter_view_v = is_scatter_view<T>::value;
677 
678 template <typename DataType, typename Op, typename DeviceType, typename Layout,
679  typename Duplication, typename Contribution,
680  typename OverrideContribution>
681 class ScatterAccess;
682 
683 // non-duplicated implementation
684 template <typename DataType, typename Op, typename DeviceType, typename Layout,
685  typename Contribution>
686 class ScatterView<DataType, Layout, DeviceType, Op, ScatterNonDuplicated,
687  Contribution> {
688  public:
689  using execution_space = typename DeviceType::execution_space;
690  using memory_space = typename DeviceType::memory_space;
691  using device_type = Kokkos::Device<execution_space, memory_space>;
692  using original_view_type = Kokkos::View<DataType, Layout, device_type>;
693  using original_value_type = typename original_view_type::value_type;
694  using original_reference_type = typename original_view_type::reference_type;
695  friend class ScatterAccess<DataType, Op, DeviceType, Layout,
696  ScatterNonDuplicated, Contribution,
697  ScatterNonAtomic>;
698  friend class ScatterAccess<DataType, Op, DeviceType, Layout,
699  ScatterNonDuplicated, Contribution, ScatterAtomic>;
700  template <class, class, class, class, class, class>
701  friend class ScatterView;
702 
703  ScatterView() = default;
704 
705  template <typename RT, typename... RP>
706  ScatterView(View<RT, RP...> const& original_view)
707  : internal_view(original_view) {}
708 
709  template <typename RT, typename... P, typename... RP>
710  ScatterView(execution_space const& /* exec_space */,
711  View<RT, RP...> const& original_view)
712  : internal_view(original_view) {}
713 
714  template <typename... Dims>
715  ScatterView(std::string const& name, Dims... dims)
716  : internal_view(name, dims...) {}
717 
718  // This overload allows specifying an execution space instance to be
719  // used by passing, e.g., Kokkos::view_alloc(exec_space, "label") as
720  // first argument.
721  template <typename... P, typename... Dims>
722  ScatterView(::Kokkos::Impl::ViewCtorProp<P...> const& arg_prop, Dims... dims)
723  : internal_view(arg_prop, dims...) {
724  using ::Kokkos::Impl::Experimental::
725  check_scatter_view_allocation_properties_argument;
726  check_scatter_view_allocation_properties_argument(arg_prop);
727  }
728 
729  template <typename OtherDataType, typename OtherDeviceType>
730  KOKKOS_FUNCTION ScatterView(
731  const ScatterView<OtherDataType, Layout, OtherDeviceType, Op,
732  ScatterNonDuplicated, Contribution>& other_view)
733  : internal_view(other_view.internal_view) {}
734 
735  template <typename OtherDataType, typename OtherDeviceType>
736  KOKKOS_FUNCTION ScatterView& operator=(
737  const ScatterView<OtherDataType, Layout, OtherDeviceType, Op,
738  ScatterNonDuplicated, Contribution>& other_view) {
739  internal_view = other_view.internal_view;
740  return *this;
741  }
742 
743  template <typename OverrideContribution = Contribution>
744  KOKKOS_FORCEINLINE_FUNCTION
745  ScatterAccess<DataType, Op, DeviceType, Layout, ScatterNonDuplicated,
746  Contribution, OverrideContribution>
747  access() const {
748  return ScatterAccess<DataType, Op, DeviceType, Layout, ScatterNonDuplicated,
749  Contribution, OverrideContribution>(*this);
750  }
751 
752  original_view_type subview() const { return internal_view; }
753 
754  KOKKOS_INLINE_FUNCTION constexpr bool is_allocated() const {
755  return internal_view.is_allocated();
756  }
757 
758  template <typename DT, typename... RP>
759  void contribute_into(View<DT, RP...> const& dest) const {
760  contribute_into(execution_space(), dest);
761  }
762 
763  template <typename DT, typename... RP>
764  void contribute_into(execution_space const& exec_space,
765  View<DT, RP...> const& dest) const {
766  using dest_type = View<DT, RP...>;
767  static_assert(std::is_same<typename dest_type::array_layout, Layout>::value,
768  "ScatterView contribute destination has different layout");
769  static_assert(
771  execution_space, typename dest_type::memory_space>::accessible,
772  "ScatterView contribute destination memory space not accessible");
773  if (dest.data() == internal_view.data()) return;
774  Kokkos::Impl::Experimental::ReduceDuplicates<execution_space,
775  original_value_type, Op>(
776  exec_space, internal_view.data(), dest.data(), 0, 0, 1,
777  internal_view.label());
778  }
779 
780  void reset(execution_space const& exec_space = execution_space()) {
781  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
782  original_value_type, Op>(
783  exec_space, internal_view.data(), internal_view.size(),
784  internal_view.label());
785  }
786  template <typename DT, typename... RP>
787  void reset_except(View<DT, RP...> const& view) {
788  reset_except(execution_space(), view);
789  }
790 
791  template <typename DT, typename... RP>
792  void reset_except(const execution_space& exec_space,
793  View<DT, RP...> const& view) {
794  if (view.data() != internal_view.data()) reset(exec_space);
795  }
796 
797  void resize(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
798  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
799  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
800  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
801  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
802  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
803  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
804  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
805  ::Kokkos::resize(internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
806  }
807 
808  template <class... ViewCtorArgs>
809  void resize(const ::Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
810  const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
811  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
812  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
813  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
814  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
815  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
816  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
817  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
818  ::Kokkos::resize(arg_prop, internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
819  }
820 
821  template <class I>
822  std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> resize(
823  const I& arg_prop, const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
824  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
825  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
826  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
827  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
828  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
829  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
830  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
831  ::Kokkos::resize(arg_prop, internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
832  }
833 
834  template <class... ViewCtorArgs>
835  void realloc(const Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
836  const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
837  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
838  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
839  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
840  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
841  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
842  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
843  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
844  ::Kokkos::realloc(arg_prop, internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
845  }
846 
847  void realloc(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::realloc(internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
856  }
857 
858  template <class I>
859  std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> realloc(
860  const I& arg_prop, 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  protected:
872  template <typename... Args>
873  KOKKOS_FORCEINLINE_FUNCTION original_reference_type at(Args... args) const {
874  return internal_view(args...);
875  }
876 
877  private:
878  using internal_view_type = original_view_type;
879  internal_view_type internal_view;
880 };
881 
882 template <typename DataType, typename Op, typename DeviceType, typename Layout,
883  typename Contribution, typename OverrideContribution>
884 class ScatterAccess<DataType, Op, DeviceType, Layout, ScatterNonDuplicated,
885  Contribution, OverrideContribution> {
886  public:
887  using view_type = ScatterView<DataType, Layout, DeviceType, Op,
888  ScatterNonDuplicated, Contribution>;
889  using original_value_type = typename view_type::original_value_type;
890  using value_type = Kokkos::Impl::Experimental::ScatterValue<
891  original_value_type, Op, DeviceType, OverrideContribution>;
892 
893  KOKKOS_INLINE_FUNCTION
894  ScatterAccess() : view(view_type()) {}
895 
896  KOKKOS_INLINE_FUNCTION
897  ScatterAccess(view_type const& view_in) : view(view_in) {}
898  KOKKOS_DEFAULTED_FUNCTION
899  ~ScatterAccess() = default;
900 
901  template <typename... Args>
902  KOKKOS_FORCEINLINE_FUNCTION value_type operator()(Args... args) const {
903  return view.at(args...);
904  }
905 
906  template <typename Arg>
907  KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
908  view_type::original_view_type::rank == 1 && std::is_integral<Arg>::value,
909  value_type>
910  operator[](Arg arg) const {
911  return view.at(arg);
912  }
913 
914  private:
915  view_type const& view;
916 };
917 
918 // duplicated implementation
919 // LayoutLeft and LayoutRight are different enough that we'll just specialize
920 // each
921 
922 template <typename DataType, typename Op, typename DeviceType,
923  typename Contribution>
924 class ScatterView<DataType, Kokkos::LayoutRight, DeviceType, Op,
925  ScatterDuplicated, Contribution> {
926  public:
927  using execution_space = typename DeviceType::execution_space;
928  using memory_space = typename DeviceType::memory_space;
929  using device_type = Kokkos::Device<execution_space, memory_space>;
930  using original_view_type =
932  using original_value_type = typename original_view_type::value_type;
933  using original_reference_type = typename original_view_type::reference_type;
934  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
935  ScatterDuplicated, Contribution, ScatterNonAtomic>;
936  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
937  ScatterDuplicated, Contribution, ScatterAtomic>;
938  template <class, class, class, class, class, class>
939  friend class ScatterView;
940 
941  using data_type_info =
942  typename Kokkos::Impl::Experimental::DuplicatedDataType<
943  DataType, Kokkos::LayoutRight>;
944  using internal_data_type = typename data_type_info::value_type;
945  using internal_view_type =
946  Kokkos::View<internal_data_type, Kokkos::LayoutRight, device_type>;
947 
948  ScatterView() = default;
949 
950  template <typename OtherDataType, typename OtherDeviceType>
951  KOKKOS_FUNCTION ScatterView(
952  const ScatterView<OtherDataType, Kokkos::LayoutRight, OtherDeviceType, Op,
953  ScatterDuplicated, Contribution>& other_view)
954  : unique_token(other_view.unique_token),
955  internal_view(other_view.internal_view) {}
956 
957  template <typename OtherDataType, typename OtherDeviceType>
958  KOKKOS_FUNCTION ScatterView& operator=(
959  const ScatterView<OtherDataType, Kokkos::LayoutRight, OtherDeviceType, Op,
960  ScatterDuplicated, Contribution>& other_view) {
961  unique_token = other_view.unique_token;
962  internal_view = other_view.internal_view;
963  return *this;
964  }
965 
966  template <typename RT, typename... RP>
967  ScatterView(View<RT, RP...> const& original_view)
968  : ScatterView(execution_space(), original_view) {}
969 
970  template <typename RT, typename... P, typename... RP>
971  ScatterView(execution_space const& exec_space,
972  View<RT, RP...> const& original_view)
973  : unique_token(),
974  internal_view(
975  view_alloc(WithoutInitializing,
976  std::string("duplicated_") + original_view.label(),
977  exec_space),
978  unique_token.size(),
979  original_view.rank_dynamic > 0 ? original_view.extent(0)
980  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
981  original_view.rank_dynamic > 1 ? original_view.extent(1)
982  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
983  original_view.rank_dynamic > 2 ? original_view.extent(2)
984  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
985  original_view.rank_dynamic > 3 ? original_view.extent(3)
986  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
987  original_view.rank_dynamic > 4 ? original_view.extent(4)
988  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
989  original_view.rank_dynamic > 5 ? original_view.extent(5)
990  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
991  original_view.rank_dynamic > 6 ? original_view.extent(6)
992  : KOKKOS_IMPL_CTOR_DEFAULT_ARG)
993 
994  {
995  reset(exec_space);
996  }
997 
998  template <typename... Dims>
999  ScatterView(std::string const& name, Dims... dims)
1000  : ScatterView(view_alloc(execution_space(), name), dims...) {}
1001 
1002  // This overload allows specifying an execution space instance to be
1003  // used by passing, e.g., Kokkos::view_alloc(exec_space, "label") as
1004  // first argument.
1005  template <typename... P, typename... Dims>
1006  ScatterView(::Kokkos::Impl::ViewCtorProp<P...> const& arg_prop, Dims... dims)
1007  : internal_view(view_alloc(WithoutInitializing,
1008  static_cast<::Kokkos::Impl::ViewCtorProp<
1009  void, std::string> const&>(arg_prop)
1010  .value),
1011  unique_token.size(), dims...) {
1012  using ::Kokkos::Impl::Experimental::
1013  check_scatter_view_allocation_properties_argument;
1014  check_scatter_view_allocation_properties_argument(arg_prop);
1015 
1016  auto const& exec_space =
1017  Kokkos::Impl::get_property<Kokkos::Impl::ExecutionSpaceTag>(arg_prop);
1018  reset(exec_space);
1019  }
1020 
1021  template <typename OverrideContribution = Contribution>
1022  KOKKOS_FORCEINLINE_FUNCTION
1023  ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
1024  ScatterDuplicated, Contribution, OverrideContribution>
1025  access() const {
1026  return ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
1027  ScatterDuplicated, Contribution, OverrideContribution>(
1028  *this);
1029  }
1030 
1031  typename Kokkos::Impl::Experimental::Slice<Kokkos::LayoutRight,
1032  internal_view_type::rank,
1033  internal_view_type>::value_type
1034  subview() const {
1035  return Kokkos::Impl::Experimental::Slice<
1036  Kokkos::LayoutRight, internal_view_type::rank,
1037  internal_view_type>::get(internal_view, 0);
1038  }
1039 
1040  KOKKOS_INLINE_FUNCTION constexpr bool is_allocated() const {
1041  return internal_view.is_allocated();
1042  }
1043 
1044  template <typename DT, typename... RP>
1045  void contribute_into(View<DT, RP...> const& dest) const {
1046  contribute_into(execution_space(), dest);
1047  }
1048 
1049  template <typename DT, typename... RP>
1050  void contribute_into(execution_space const& exec_space,
1051  View<DT, RP...> const& dest) const {
1052  using dest_type = View<DT, RP...>;
1053  static_assert(std::is_same<typename dest_type::array_layout,
1054  Kokkos::LayoutRight>::value,
1055  "ScatterView deep_copy destination has different layout");
1056  static_assert(
1058  execution_space, typename dest_type::memory_space>::accessible,
1059  "ScatterView deep_copy destination memory space not accessible");
1060  bool is_equal = (dest.data() == internal_view.data());
1061  size_t start = is_equal ? 1 : 0;
1062  Kokkos::Impl::Experimental::ReduceDuplicates<execution_space,
1063  original_value_type, Op>(
1064  exec_space, internal_view.data(), dest.data(), internal_view.stride(0),
1065  start, internal_view.extent(0), internal_view.label());
1066  }
1067 
1068  void reset(execution_space const& exec_space = execution_space()) {
1069  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1070  original_value_type, Op>(
1071  exec_space, internal_view.data(), internal_view.size(),
1072  internal_view.label());
1073  }
1074 
1075  template <typename DT, typename... RP>
1076  void reset_except(View<DT, RP...> const& view) {
1077  reset_except(execution_space(), view);
1078  }
1079 
1080  template <typename DT, typename... RP>
1081  void reset_except(execution_space const& exec_space,
1082  View<DT, RP...> const& view) {
1083  if (view.data() != internal_view.data()) {
1084  reset(exec_space);
1085  return;
1086  }
1087  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1088  original_value_type, Op>(
1089  exec_space, internal_view.data() + view.size(),
1090  internal_view.size() - view.size(), internal_view.label());
1091  }
1092 
1093  void resize(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1094  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1095  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1096  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1097  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1098  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1099  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1100  ::Kokkos::resize(internal_view, unique_token.size(), n0, n1, n2, n3, n4, n5,
1101  n6);
1102  }
1103 
1104  template <class... ViewCtorArgs>
1105  void resize(const ::Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1106  const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1107  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1108  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1109  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1110  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1111  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1112  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1113  ::Kokkos::resize(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1114  n3, n4, n5, n6);
1115  }
1116 
1117  template <class I>
1118  std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> resize(
1119  const I& arg_prop, const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1120  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1121  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1122  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1123  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1124  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1125  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1126  ::Kokkos::resize(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1127  n3, n4, n5, n6);
1128  }
1129 
1130  template <class... ViewCtorArgs>
1131  void realloc(const ::Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1132  const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1133  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1134  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1135  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1136  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1137  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1138  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1139  ::Kokkos::realloc(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1140  n3, n4, n5, n6);
1141  }
1142 
1143  void realloc(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1144  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1145  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1146  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1147  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1148  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1149  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1150  ::Kokkos::realloc(internal_view, unique_token.size(), n0, n1, n2, n3, n4,
1151  n5, n6);
1152  }
1153 
1154  template <class I>
1155  std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> realloc(
1156  const I& arg_prop, const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1157  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1158  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1159  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1160  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1161  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1162  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1163  ::Kokkos::realloc(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1164  n3, n4, n5, n6);
1165  }
1166 
1167  protected:
1168  template <typename... Args>
1169  KOKKOS_FORCEINLINE_FUNCTION original_reference_type at(int rank,
1170  Args... args) const {
1171  return internal_view(rank, args...);
1172  }
1173 
1174  protected:
1175  using unique_token_type = Kokkos::Experimental::UniqueToken<
1176  execution_space, Kokkos::Experimental::UniqueTokenScope::Global>;
1177 
1178  unique_token_type unique_token;
1179  internal_view_type internal_view;
1180 };
1181 
1182 template <typename DataType, typename Op, typename DeviceType,
1183  typename Contribution>
1184 class ScatterView<DataType, Kokkos::LayoutLeft, DeviceType, Op,
1185  ScatterDuplicated, Contribution> {
1186  public:
1187  using execution_space = typename DeviceType::execution_space;
1188  using memory_space = typename DeviceType::memory_space;
1189  using device_type = Kokkos::Device<execution_space, memory_space>;
1190  using original_view_type =
1192  using original_value_type = typename original_view_type::value_type;
1193  using original_reference_type = typename original_view_type::reference_type;
1194  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1195  ScatterDuplicated, Contribution, ScatterNonAtomic>;
1196  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1197  ScatterDuplicated, Contribution, ScatterAtomic>;
1198  template <class, class, class, class, class, class>
1199  friend class ScatterView;
1200 
1201  using data_type_info =
1202  typename Kokkos::Impl::Experimental::DuplicatedDataType<
1203  DataType, Kokkos::LayoutLeft>;
1204  using internal_data_type = typename data_type_info::value_type;
1205  using internal_view_type =
1206  Kokkos::View<internal_data_type, Kokkos::LayoutLeft, device_type>;
1207 
1208  ScatterView() = default;
1209 
1210  template <typename RT, typename... RP>
1211  ScatterView(View<RT, RP...> const& original_view)
1212  : ScatterView(execution_space(), original_view) {}
1213 
1214  template <typename RT, typename... P, typename... RP>
1215  ScatterView(execution_space const& exec_space,
1216  View<RT, RP...> const& original_view)
1217  : unique_token() {
1218  size_t arg_N[8] = {original_view.rank > 0 ? original_view.extent(0)
1219  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1220  original_view.rank > 1 ? original_view.extent(1)
1221  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1222  original_view.rank > 2 ? original_view.extent(2)
1223  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1224  original_view.rank > 3 ? original_view.extent(3)
1225  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1226  original_view.rank > 4 ? original_view.extent(4)
1227  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1228  original_view.rank > 5 ? original_view.extent(5)
1229  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1230  original_view.rank > 6 ? original_view.extent(6)
1231  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1232  KOKKOS_IMPL_CTOR_DEFAULT_ARG};
1233  arg_N[internal_view_type::rank - 1] = unique_token.size();
1234  internal_view = internal_view_type(
1235  view_alloc(WithoutInitializing,
1236  std::string("duplicated_") + original_view.label(),
1237  exec_space),
1238  arg_N[0], arg_N[1], arg_N[2], arg_N[3], arg_N[4], arg_N[5], arg_N[6],
1239  arg_N[7]);
1240  reset(exec_space);
1241  }
1242 
1243  template <typename... Dims>
1244  ScatterView(std::string const& name, Dims... dims)
1245  : ScatterView(view_alloc(execution_space(), name), dims...) {}
1246 
1247  // This overload allows specifying an execution space instance to be
1248  // used by passing, e.g., Kokkos::view_alloc(exec_space, "label") as
1249  // first argument.
1250  template <typename... P, typename... Dims>
1251  ScatterView(::Kokkos::Impl::ViewCtorProp<P...> const& arg_prop,
1252  Dims... dims) {
1253  using ::Kokkos::Impl::Experimental::
1254  check_scatter_view_allocation_properties_argument;
1255  check_scatter_view_allocation_properties_argument(arg_prop);
1256 
1257  original_view_type original_view;
1258  size_t arg_N[8] = {original_view.rank > 0 ? original_view.static_extent(0)
1259  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1260  original_view.rank > 1 ? original_view.static_extent(1)
1261  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1262  original_view.rank > 2 ? original_view.static_extent(2)
1263  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1264  original_view.rank > 3 ? original_view.static_extent(3)
1265  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1266  original_view.rank > 4 ? original_view.static_extent(4)
1267  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1268  original_view.rank > 5 ? original_view.static_extent(5)
1269  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1270  original_view.rank > 6 ? original_view.static_extent(6)
1271  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1272  KOKKOS_IMPL_CTOR_DEFAULT_ARG};
1273  Kokkos::Impl::Experimental::args_to_array(arg_N, 0, dims...);
1274  arg_N[internal_view_type::rank - 1] = unique_token.size();
1275 
1276  auto const& name =
1277  Kokkos::Impl::get_property<Kokkos::Impl::LabelTag>(arg_prop);
1278  internal_view = internal_view_type(view_alloc(WithoutInitializing, name),
1279  arg_N[0], arg_N[1], arg_N[2], arg_N[3],
1280  arg_N[4], arg_N[5], arg_N[6], arg_N[7]);
1281 
1282  auto const& exec_space =
1283  Kokkos::Impl::get_property<Kokkos::Impl::ExecutionSpaceTag>(arg_prop);
1284  reset(exec_space);
1285  }
1286 
1287  template <typename OtherDataType, typename OtherDeviceType>
1288  KOKKOS_FUNCTION ScatterView(
1289  const ScatterView<OtherDataType, Kokkos::LayoutLeft, OtherDeviceType, Op,
1290  ScatterDuplicated, Contribution>& other_view)
1291  : unique_token(other_view.unique_token),
1292  internal_view(other_view.internal_view) {}
1293 
1294  template <typename OtherDataType, typename OtherDeviceType>
1295  KOKKOS_FUNCTION ScatterView& operator=(
1296  const ScatterView<OtherDataType, Kokkos::LayoutLeft, OtherDeviceType, Op,
1297  ScatterDuplicated, Contribution>& other_view) {
1298  unique_token = other_view.unique_token;
1299  internal_view = other_view.internal_view;
1300  return *this;
1301  }
1302 
1303  template <typename OverrideContribution = Contribution>
1304  KOKKOS_FORCEINLINE_FUNCTION
1305  ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1306  ScatterDuplicated, Contribution, OverrideContribution>
1307  access() const {
1308  return ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1309  ScatterDuplicated, Contribution, OverrideContribution>(
1310  *this);
1311  }
1312 
1313  typename Kokkos::Impl::Experimental::Slice<Kokkos::LayoutLeft,
1314  internal_view_type::rank,
1315  internal_view_type>::value_type
1316  subview() const {
1317  return Kokkos::Impl::Experimental::Slice<
1318  Kokkos::LayoutLeft, internal_view_type::rank,
1319  internal_view_type>::get(internal_view, 0);
1320  }
1321 
1322  KOKKOS_INLINE_FUNCTION constexpr bool is_allocated() const {
1323  return internal_view.is_allocated();
1324  }
1325 
1326  template <typename... RP>
1327  void contribute_into(View<RP...> const& dest) const {
1328  contribute_into(execution_space(), dest);
1329  }
1330 
1331  template <typename... RP>
1332  void contribute_into(execution_space const& exec_space,
1333  View<RP...> const& dest) const {
1334  using dest_type = View<RP...>;
1335  static_assert(
1336  std::is_same<typename dest_type::value_type,
1337  typename original_view_type::non_const_value_type>::value,
1338  "ScatterView deep_copy destination has wrong value_type");
1339  static_assert(std::is_same<typename dest_type::array_layout,
1340  Kokkos::LayoutLeft>::value,
1341  "ScatterView deep_copy destination has different layout");
1342  static_assert(
1344  execution_space, typename dest_type::memory_space>::accessible,
1345  "ScatterView deep_copy destination memory space not accessible");
1346  auto extent = internal_view.extent(internal_view_type::rank - 1);
1347  bool is_equal = (dest.data() == internal_view.data());
1348  size_t start = is_equal ? 1 : 0;
1349  Kokkos::Impl::Experimental::ReduceDuplicates<execution_space,
1350  original_value_type, Op>(
1351  exec_space, internal_view.data(), dest.data(),
1352  internal_view.stride(internal_view_type::rank - 1), start, extent,
1353  internal_view.label());
1354  }
1355 
1356  void reset(execution_space const& exec_space = execution_space()) {
1357  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1358  original_value_type, Op>(
1359  exec_space, internal_view.data(), internal_view.size(),
1360  internal_view.label());
1361  }
1362 
1363  template <typename DT, typename... RP>
1364  void reset_except(View<DT, RP...> const& view) {
1365  reset_except(execution_space(), view);
1366  }
1367 
1368  template <typename DT, typename... RP>
1369  void reset_except(execution_space const& exec_space,
1370  View<DT, RP...> const& view) {
1371  if (view.data() != internal_view.data()) {
1372  reset(exec_space);
1373  return;
1374  }
1375  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1376  original_value_type, Op>(
1377  exec_space, internal_view.data() + view.size(),
1378  internal_view.size() - view.size(), internal_view.label());
1379  }
1380 
1381  void resize(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1382  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1383  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1384  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1385  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1386  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1387  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1388  size_t arg_N[8] = {n0, n1, n2, n3, n4, n5, n6, 0};
1389  const int i = internal_view.rank - 1;
1390  arg_N[i] = unique_token.size();
1391 
1392  ::Kokkos::resize(internal_view, arg_N[0], arg_N[1], arg_N[2], arg_N[3],
1393  arg_N[4], arg_N[5], arg_N[6], arg_N[7]);
1394  }
1395 
1396  void realloc(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1397  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1398  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1399  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1400  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1401  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1402  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1403  size_t arg_N[8] = {n0, n1, n2, n3, n4, n5, n6, 0};
1404  const int i = internal_view.rank - 1;
1405  arg_N[i] = unique_token.size();
1406 
1407  ::Kokkos::realloc(internal_view, arg_N[0], arg_N[1], arg_N[2], arg_N[3],
1408  arg_N[4], arg_N[5], arg_N[6], arg_N[7]);
1409  }
1410 
1411  protected:
1412  template <typename... Args>
1413  KOKKOS_FORCEINLINE_FUNCTION original_reference_type at(int thread_id,
1414  Args... args) const {
1415  return internal_view(args..., thread_id);
1416  }
1417 
1418  protected:
1419  using unique_token_type = Kokkos::Experimental::UniqueToken<
1420  execution_space, Kokkos::Experimental::UniqueTokenScope::Global>;
1421 
1422  unique_token_type unique_token;
1423  internal_view_type internal_view;
1424 };
1425 
1426 /* This object has to be separate in order to store the thread ID, which cannot
1427  be obtained until one is inside a parallel construct, and may be relatively
1428  expensive to obtain at every contribution
1429  (calls a non-inlined function, looks up a thread-local variable).
1430  Due to the expense, it is sensible to query it at most once per parallel
1431  iterate (ideally once per thread, but parallel_for doesn't expose that) and
1432  then store it in a stack variable.
1433  ScatterAccess serves as a non-const object on the stack which can store the
1434  thread ID */
1435 
1436 template <typename DataType, typename Op, typename DeviceType, typename Layout,
1437  typename Contribution, typename OverrideContribution>
1438 class ScatterAccess<DataType, Op, DeviceType, Layout, ScatterDuplicated,
1439  Contribution, OverrideContribution> {
1440  public:
1441  using view_type = ScatterView<DataType, Layout, DeviceType, Op,
1442  ScatterDuplicated, Contribution>;
1443  using original_value_type = typename view_type::original_value_type;
1444  using value_type = Kokkos::Impl::Experimental::ScatterValue<
1445  original_value_type, Op, DeviceType, OverrideContribution>;
1446 
1447  KOKKOS_FORCEINLINE_FUNCTION
1448  ScatterAccess(view_type const& view_in)
1449  : view(view_in), thread_id(view_in.unique_token.acquire()) {}
1450 
1451  KOKKOS_FORCEINLINE_FUNCTION
1452  ~ScatterAccess() {
1453  if (thread_id != ~thread_id_type(0)) view.unique_token.release(thread_id);
1454  }
1455 
1456  template <typename... Args>
1457  KOKKOS_FORCEINLINE_FUNCTION value_type operator()(Args... args) const {
1458  return view.at(thread_id, args...);
1459  }
1460 
1461  template <typename Arg>
1462  KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
1463  view_type::original_view_type::rank == 1 && std::is_integral<Arg>::value,
1464  value_type>
1465  operator[](Arg arg) const {
1466  return view.at(thread_id, arg);
1467  }
1468 
1469  private:
1470  view_type const& view;
1471 
1472  // simplify RAII by disallowing copies
1473  ScatterAccess(ScatterAccess const& other) = delete;
1474  ScatterAccess& operator=(ScatterAccess const& other) = delete;
1475  ScatterAccess& operator=(ScatterAccess&& other) = delete;
1476 
1477  public:
1478  // do need to allow moves though, for the common
1479  // auto b = a.access();
1480  // that assignments turns into a move constructor call
1481  KOKKOS_FORCEINLINE_FUNCTION
1482  ScatterAccess(ScatterAccess&& other)
1483  : view(other.view), thread_id(other.thread_id) {
1484  other.thread_id = ~thread_id_type(0);
1485  }
1486 
1487  private:
1488  using unique_token_type = typename view_type::unique_token_type;
1489  using thread_id_type = typename unique_token_type::size_type;
1490  thread_id_type thread_id;
1491 };
1492 
1493 template <typename Op = Kokkos::Experimental::ScatterSum,
1494  typename Duplication = void, typename Contribution = void,
1495  typename RT, typename... RP>
1496 ScatterView<
1497  RT, typename ViewTraits<RT, RP...>::array_layout,
1498  typename ViewTraits<RT, RP...>::device_type, Op,
1499  std::conditional_t<
1500  std::is_void<Duplication>::value,
1501  typename Kokkos::Impl::Experimental::DefaultDuplication<
1502  typename ViewTraits<RT, RP...>::execution_space>::type,
1503  Duplication>,
1504  std::conditional_t<
1505  std::is_void<Contribution>::value,
1506  typename Kokkos::Impl::Experimental::DefaultContribution<
1507  typename ViewTraits<RT, RP...>::execution_space,
1508  typename std::conditional_t<
1509  std::is_void<Duplication>::value,
1510  typename Kokkos::Impl::Experimental::DefaultDuplication<
1511  typename ViewTraits<RT, RP...>::execution_space>::type,
1512  Duplication>>::type,
1513  Contribution>>
1514 create_scatter_view(View<RT, RP...> const& original_view) {
1515  return original_view; // implicit ScatterView constructor call
1516 }
1517 
1518 template <typename Op, typename RT, typename... RP>
1519 ScatterView<
1520  RT, typename ViewTraits<RT, RP...>::array_layout,
1521  typename ViewTraits<RT, RP...>::device_type, Op,
1522  typename Kokkos::Impl::Experimental::DefaultDuplication<
1523  typename ViewTraits<RT, RP...>::execution_space>::type,
1524  typename Kokkos::Impl::Experimental::DefaultContribution<
1525  typename ViewTraits<RT, RP...>::execution_space,
1526  typename Kokkos::Impl::Experimental::DefaultDuplication<
1527  typename ViewTraits<RT, RP...>::execution_space>::type>::type>
1528 create_scatter_view(Op, View<RT, RP...> const& original_view) {
1529  return original_view; // implicit ScatterView constructor call
1530 }
1531 
1532 template <typename Op, typename Duplication, typename Contribution, typename RT,
1533  typename... RP>
1534 ScatterView<RT, typename ViewTraits<RT, RP...>::array_layout,
1535  typename ViewTraits<RT, RP...>::device_type, Op, Duplication,
1536  Contribution>
1537 create_scatter_view(Op, Duplication, Contribution,
1538  View<RT, RP...> const& original_view) {
1539  return original_view; // implicit ScatterView constructor call
1540 }
1541 
1542 } // namespace Experimental
1543 } // namespace Kokkos
1544 
1545 namespace Kokkos {
1546 namespace Experimental {
1547 
1548 template <typename DT1, typename DT2, typename LY, typename ES, typename OP,
1549  typename CT, typename DP, typename... VP>
1550 void contribute(
1551  typename ES::execution_space const& exec_space, View<DT1, VP...>& dest,
1552  Kokkos::Experimental::ScatterView<DT2, LY, ES, OP, CT, DP> const& src) {
1553  src.contribute_into(exec_space, dest);
1554 }
1555 
1556 template <typename DT1, typename DT2, typename LY, typename ES, typename OP,
1557  typename CT, typename DP, typename... VP>
1558 void contribute(
1559  View<DT1, VP...>& dest,
1560  Kokkos::Experimental::ScatterView<DT2, LY, ES, OP, CT, DP> const& src) {
1561  using execution_space = typename ES::execution_space;
1562  contribute(execution_space{}, dest, src);
1563 }
1564 
1565 } // namespace Experimental
1566 } // namespace Kokkos
1567 
1568 namespace Kokkos {
1569 
1570 template <typename DT, typename LY, typename ES, typename OP, typename CT,
1571  typename DP, typename... IS, class... ViewCtorArgs>
1572 void realloc(
1573  const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1574  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1575  IS... is) {
1576  scatter_view.realloc(arg_prop, is...);
1577 }
1578 
1579 template <typename DT, typename LY, typename ES, typename OP, typename CT,
1580  typename DP, typename... IS>
1581 void realloc(
1582  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1583  IS... is) {
1584  scatter_view.realloc(is...);
1585 }
1586 
1587 template <typename I, typename DT, typename LY, typename ES, typename OP,
1588  typename CT, typename DP, typename... IS>
1589 std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> realloc(
1590  const I& arg_prop,
1591  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1592  IS... is) {
1593  scatter_view.realloc(arg_prop, is...);
1594 }
1595 
1596 template <typename DT, typename LY, typename ES, typename OP, typename CT,
1597  typename DP, typename... IS>
1598 void resize(
1599  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1600  IS... is) {
1601  scatter_view.resize(is...);
1602 }
1603 
1604 template <class... ViewCtorArgs, typename DT, typename LY, typename ES,
1605  typename OP, typename CT, typename DP, typename... IS>
1606 void resize(
1607  const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1608  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1609  IS... is) {
1610  scatter_view.resize(arg_prop, is...);
1611 }
1612 
1613 template <typename I, typename DT, typename LY, typename ES, typename OP,
1614  typename CT, typename DP, typename... IS>
1615 std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> resize(
1616  const I& arg_prop,
1617  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1618  IS... is) {
1619  scatter_view.resize(arg_prop, is...);
1620 }
1621 
1622 } // namespace Kokkos
1623 
1624 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_SCATTERVIEW
1625 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
1626 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_SCATTERVIEW
1627 #endif
1628 #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
View to an array of data.
Memory layout tag indicating right-to-left (C or lexigraphical scheme) striding of multi-indices...