Kokkos Core Kernels Package  Version of the Day
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::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::Impl::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 <typename DataType, typename Op, typename DeviceType, typename Layout,
667  typename Duplication, typename Contribution,
668  typename OverrideContribution>
669 class ScatterAccess;
670 
671 // non-duplicated implementation
672 template <typename DataType, typename Op, typename DeviceType, typename Layout,
673  typename Contribution>
674 class ScatterView<DataType, Layout, DeviceType, Op, ScatterNonDuplicated,
675  Contribution> {
676  public:
677  using execution_space = typename DeviceType::execution_space;
678  using memory_space = typename DeviceType::memory_space;
679  using device_type = Kokkos::Device<execution_space, memory_space>;
680  using original_view_type = Kokkos::View<DataType, Layout, device_type>;
681  using original_value_type = typename original_view_type::value_type;
682  using original_reference_type = typename original_view_type::reference_type;
683  friend class ScatterAccess<DataType, Op, DeviceType, Layout,
684  ScatterNonDuplicated, Contribution,
685  ScatterNonAtomic>;
686  friend class ScatterAccess<DataType, Op, DeviceType, Layout,
687  ScatterNonDuplicated, Contribution, ScatterAtomic>;
688  template <class, class, class, class, class, class>
689  friend class ScatterView;
690 
691  ScatterView() = default;
692 
693  template <typename RT, typename... RP>
694  ScatterView(View<RT, RP...> const& original_view)
695  : internal_view(original_view) {}
696 
697  template <typename RT, typename... P, typename... RP>
698  ScatterView(execution_space const& /* exec_space */,
699  View<RT, RP...> const& original_view)
700  : internal_view(original_view) {}
701 
702  template <typename... Dims>
703  ScatterView(std::string const& name, Dims... dims)
704  : internal_view(name, dims...) {}
705 
706  // This overload allows specifying an execution space instance to be
707  // used by passing, e.g., Kokkos::view_alloc(exec_space, "label") as
708  // first argument.
709  template <typename... P, typename... Dims>
710  ScatterView(::Kokkos::Impl::ViewCtorProp<P...> const& arg_prop, Dims... dims)
711  : internal_view(arg_prop, dims...) {
712  using ::Kokkos::Impl::Experimental::
713  check_scatter_view_allocation_properties_argument;
714  check_scatter_view_allocation_properties_argument(arg_prop);
715  }
716 
717  template <typename OtherDataType, typename OtherDeviceType>
718  KOKKOS_FUNCTION ScatterView(
719  const ScatterView<OtherDataType, Layout, OtherDeviceType, Op,
720  ScatterNonDuplicated, Contribution>& other_view)
721  : internal_view(other_view.internal_view) {}
722 
723  template <typename OtherDataType, typename OtherDeviceType>
724  KOKKOS_FUNCTION void operator=(
725  const ScatterView<OtherDataType, Layout, OtherDeviceType, Op,
726  ScatterNonDuplicated, Contribution>& other_view) {
727  internal_view = other_view.internal_view;
728  }
729 
730  template <typename OverrideContribution = Contribution>
731  KOKKOS_FORCEINLINE_FUNCTION
732  ScatterAccess<DataType, Op, DeviceType, Layout, ScatterNonDuplicated,
733  Contribution, OverrideContribution>
734  access() const {
735  return ScatterAccess<DataType, Op, DeviceType, Layout, ScatterNonDuplicated,
736  Contribution, OverrideContribution>(*this);
737  }
738 
739  original_view_type subview() const { return internal_view; }
740 
741  KOKKOS_INLINE_FUNCTION constexpr bool is_allocated() const {
742  return internal_view.is_allocated();
743  }
744 
745  template <typename DT, typename... RP>
746  void contribute_into(View<DT, RP...> const& dest) const {
747  contribute_into(execution_space(), dest);
748  }
749 
750  template <typename DT, typename... RP>
751  void contribute_into(execution_space const& exec_space,
752  View<DT, RP...> const& dest) const {
753  using dest_type = View<DT, RP...>;
754  static_assert(std::is_same<typename dest_type::array_layout, Layout>::value,
755  "ScatterView contribute destination has different layout");
756  static_assert(
758  execution_space, typename dest_type::memory_space>::accessible,
759  "ScatterView contribute destination memory space not accessible");
760  if (dest.data() == internal_view.data()) return;
761  Kokkos::Impl::Experimental::ReduceDuplicates<execution_space,
762  original_value_type, Op>(
763  exec_space, internal_view.data(), dest.data(), 0, 0, 1,
764  internal_view.label());
765  }
766 
767  void reset(execution_space const& exec_space = execution_space()) {
768  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
769  original_value_type, Op>(
770  exec_space, internal_view.data(), internal_view.size(),
771  internal_view.label());
772  }
773  template <typename DT, typename... RP>
774  void reset_except(View<DT, RP...> const& view) {
775  reset_except(execution_space(), view);
776  }
777 
778  template <typename DT, typename... RP>
779  void reset_except(const execution_space& exec_space,
780  View<DT, RP...> const& view) {
781  if (view.data() != internal_view.data()) reset(exec_space);
782  }
783 
784  void resize(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
785  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
786  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
787  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
788  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
789  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
790  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
791  const size_t n7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
792  ::Kokkos::resize(internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
793  }
794 
795  template <class... ViewCtorArgs>
796  void resize(const ::Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
797  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(arg_prop, internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
806  }
807 
808  template <class I>
809  std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> resize(
810  const I& arg_prop, 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... ViewCtorArgs>
822  void realloc(const Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
823  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::realloc(arg_prop, internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
832  }
833 
834  void realloc(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::realloc(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> realloc(
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::realloc(arg_prop, internal_view, n0, n1, n2, n3, n4, n5, n6, n7);
856  }
857 
858  protected:
859  template <typename... Args>
860  KOKKOS_FORCEINLINE_FUNCTION original_reference_type at(Args... args) const {
861  return internal_view(args...);
862  }
863 
864  private:
865  using internal_view_type = original_view_type;
866  internal_view_type internal_view;
867 };
868 
869 template <typename DataType, typename Op, typename DeviceType, typename Layout,
870  typename Contribution, typename OverrideContribution>
871 class ScatterAccess<DataType, Op, DeviceType, Layout, ScatterNonDuplicated,
872  Contribution, OverrideContribution> {
873  public:
874  using view_type = ScatterView<DataType, Layout, DeviceType, Op,
875  ScatterNonDuplicated, Contribution>;
876  using original_value_type = typename view_type::original_value_type;
877  using value_type = Kokkos::Impl::Experimental::ScatterValue<
878  original_value_type, Op, DeviceType, OverrideContribution>;
879 
880  KOKKOS_INLINE_FUNCTION
881  ScatterAccess() : view(view_type()) {}
882 
883  KOKKOS_INLINE_FUNCTION
884  ScatterAccess(view_type const& view_in) : view(view_in) {}
885  KOKKOS_DEFAULTED_FUNCTION
886  ~ScatterAccess() = default;
887 
888  template <typename... Args>
889  KOKKOS_FORCEINLINE_FUNCTION value_type operator()(Args... args) const {
890  return view.at(args...);
891  }
892 
893  template <typename Arg>
894  KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
895  view_type::original_view_type::rank == 1 && std::is_integral<Arg>::value,
896  value_type>
897  operator[](Arg arg) const {
898  return view.at(arg);
899  }
900 
901  private:
902  view_type const& view;
903 };
904 
905 // duplicated implementation
906 // LayoutLeft and LayoutRight are different enough that we'll just specialize
907 // each
908 
909 template <typename DataType, typename Op, typename DeviceType,
910  typename Contribution>
911 class ScatterView<DataType, Kokkos::LayoutRight, DeviceType, Op,
912  ScatterDuplicated, Contribution> {
913  public:
914  using execution_space = typename DeviceType::execution_space;
915  using memory_space = typename DeviceType::memory_space;
916  using device_type = Kokkos::Device<execution_space, memory_space>;
917  using original_view_type =
919  using original_value_type = typename original_view_type::value_type;
920  using original_reference_type = typename original_view_type::reference_type;
921  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
922  ScatterDuplicated, Contribution, ScatterNonAtomic>;
923  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
924  ScatterDuplicated, Contribution, ScatterAtomic>;
925  template <class, class, class, class, class, class>
926  friend class ScatterView;
927 
928  using data_type_info =
929  typename Kokkos::Impl::Experimental::DuplicatedDataType<
930  DataType, Kokkos::LayoutRight>;
931  using internal_data_type = typename data_type_info::value_type;
932  using internal_view_type =
933  Kokkos::View<internal_data_type, Kokkos::LayoutRight, device_type>;
934 
935  ScatterView() = default;
936 
937  template <typename OtherDataType, typename OtherDeviceType>
938  KOKKOS_FUNCTION ScatterView(
939  const ScatterView<OtherDataType, Kokkos::LayoutRight, OtherDeviceType, Op,
940  ScatterDuplicated, Contribution>& other_view)
941  : unique_token(other_view.unique_token),
942  internal_view(other_view.internal_view) {}
943 
944  template <typename OtherDataType, typename OtherDeviceType>
945  KOKKOS_FUNCTION void operator=(
946  const ScatterView<OtherDataType, Kokkos::LayoutRight, OtherDeviceType, Op,
947  ScatterDuplicated, Contribution>& other_view) {
948  unique_token = other_view.unique_token;
949  internal_view = other_view.internal_view;
950  }
951 
952  template <typename RT, typename... RP>
953  ScatterView(View<RT, RP...> const& original_view)
954  : ScatterView(execution_space(), original_view) {}
955 
956  template <typename RT, typename... P, typename... RP>
957  ScatterView(execution_space const& exec_space,
958  View<RT, RP...> const& original_view)
959  : unique_token(),
960  internal_view(
961  view_alloc(WithoutInitializing,
962  std::string("duplicated_") + original_view.label(),
963  exec_space),
964  unique_token.size(),
965  original_view.rank_dynamic > 0 ? original_view.extent(0)
966  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
967  original_view.rank_dynamic > 1 ? original_view.extent(1)
968  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
969  original_view.rank_dynamic > 2 ? original_view.extent(2)
970  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
971  original_view.rank_dynamic > 3 ? original_view.extent(3)
972  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
973  original_view.rank_dynamic > 4 ? original_view.extent(4)
974  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
975  original_view.rank_dynamic > 5 ? original_view.extent(5)
976  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
977  original_view.rank_dynamic > 6 ? original_view.extent(6)
978  : KOKKOS_IMPL_CTOR_DEFAULT_ARG)
979 
980  {
981  reset(exec_space);
982  }
983 
984  template <typename... Dims>
985  ScatterView(std::string const& name, Dims... dims)
986  : ScatterView(view_alloc(execution_space(), name), dims...) {}
987 
988  // This overload allows specifying an execution space instance to be
989  // used by passing, e.g., Kokkos::view_alloc(exec_space, "label") as
990  // first argument.
991  template <typename... P, typename... Dims>
992  ScatterView(::Kokkos::Impl::ViewCtorProp<P...> const& arg_prop, Dims... dims)
993  : internal_view(view_alloc(WithoutInitializing,
994  static_cast<::Kokkos::Impl::ViewCtorProp<
995  void, std::string> const&>(arg_prop)
996  .value),
997  unique_token.size(), dims...) {
998  using ::Kokkos::Impl::Experimental::
999  check_scatter_view_allocation_properties_argument;
1000  check_scatter_view_allocation_properties_argument(arg_prop);
1001 
1002  auto const& exec_space =
1003  Kokkos::Impl::get_property<Kokkos::Impl::ExecutionSpaceTag>(arg_prop);
1004  reset(exec_space);
1005  }
1006 
1007  template <typename OverrideContribution = Contribution>
1008  KOKKOS_FORCEINLINE_FUNCTION
1009  ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
1010  ScatterDuplicated, Contribution, OverrideContribution>
1011  access() const {
1012  return ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutRight,
1013  ScatterDuplicated, Contribution, OverrideContribution>(
1014  *this);
1015  }
1016 
1017  typename Kokkos::Impl::Experimental::Slice<Kokkos::LayoutRight,
1018  internal_view_type::rank,
1019  internal_view_type>::value_type
1020  subview() const {
1021  return Kokkos::Impl::Experimental::Slice<
1022  Kokkos::LayoutRight, internal_view_type::Rank,
1023  internal_view_type>::get(internal_view, 0);
1024  }
1025 
1026  KOKKOS_INLINE_FUNCTION constexpr bool is_allocated() const {
1027  return internal_view.is_allocated();
1028  }
1029 
1030  template <typename DT, typename... RP>
1031  void contribute_into(View<DT, RP...> const& dest) const {
1032  contribute_into(execution_space(), dest);
1033  }
1034 
1035  template <typename DT, typename... RP>
1036  void contribute_into(execution_space const& exec_space,
1037  View<DT, RP...> const& dest) const {
1038  using dest_type = View<DT, RP...>;
1039  static_assert(std::is_same<typename dest_type::array_layout,
1040  Kokkos::LayoutRight>::value,
1041  "ScatterView deep_copy destination has different layout");
1042  static_assert(
1044  execution_space, typename dest_type::memory_space>::accessible,
1045  "ScatterView deep_copy destination memory space not accessible");
1046  bool is_equal = (dest.data() == internal_view.data());
1047  size_t start = is_equal ? 1 : 0;
1048  Kokkos::Impl::Experimental::ReduceDuplicates<execution_space,
1049  original_value_type, Op>(
1050  exec_space, internal_view.data(), dest.data(), internal_view.stride(0),
1051  start, internal_view.extent(0), internal_view.label());
1052  }
1053 
1054  void reset(execution_space const& exec_space = execution_space()) {
1055  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1056  original_value_type, Op>(
1057  exec_space, internal_view.data(), internal_view.size(),
1058  internal_view.label());
1059  }
1060 
1061  template <typename DT, typename... RP>
1062  void reset_except(View<DT, RP...> const& view) {
1063  reset_except(execution_space(), view);
1064  }
1065 
1066  template <typename DT, typename... RP>
1067  void reset_except(execution_space const& exec_space,
1068  View<DT, RP...> const& view) {
1069  if (view.data() != internal_view.data()) {
1070  reset(exec_space);
1071  return;
1072  }
1073  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1074  original_value_type, Op>(
1075  exec_space, internal_view.data() + view.size(),
1076  internal_view.size() - view.size(), internal_view.label());
1077  }
1078 
1079  void resize(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1080  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1081  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1082  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1083  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1084  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1085  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1086  ::Kokkos::resize(internal_view, unique_token.size(), n0, n1, n2, n3, n4, n5,
1087  n6);
1088  }
1089 
1090  template <class... ViewCtorArgs>
1091  void resize(const ::Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1092  const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1093  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1094  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1095  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1096  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1097  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1098  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1099  ::Kokkos::resize(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1100  n3, n4, n5, n6);
1101  }
1102 
1103  template <class I>
1104  std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> resize(
1105  const I& arg_prop, const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1106  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1107  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1108  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1109  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1110  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1111  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1112  ::Kokkos::resize(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1113  n3, n4, n5, n6);
1114  }
1115 
1116  template <class... ViewCtorArgs>
1117  void realloc(const ::Kokkos::Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1118  const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1119  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1120  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1121  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1122  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1123  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1124  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1125  ::Kokkos::realloc(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1126  n3, n4, n5, n6);
1127  }
1128 
1129  void realloc(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1130  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1131  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1132  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1133  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1134  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1135  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1136  ::Kokkos::realloc(internal_view, unique_token.size(), n0, n1, n2, n3, n4,
1137  n5, n6);
1138  }
1139 
1140  template <class I>
1141  std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> realloc(
1142  const I& arg_prop, const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1143  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1144  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1145  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1146  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1147  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1148  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1149  ::Kokkos::realloc(arg_prop, internal_view, unique_token.size(), n0, n1, n2,
1150  n3, n4, n5, n6);
1151  }
1152 
1153  protected:
1154  template <typename... Args>
1155  KOKKOS_FORCEINLINE_FUNCTION original_reference_type at(int rank,
1156  Args... args) const {
1157  return internal_view(rank, args...);
1158  }
1159 
1160  protected:
1161  using unique_token_type = Kokkos::Experimental::UniqueToken<
1162  execution_space, Kokkos::Experimental::UniqueTokenScope::Global>;
1163 
1164  unique_token_type unique_token;
1165  internal_view_type internal_view;
1166 };
1167 
1168 template <typename DataType, typename Op, typename DeviceType,
1169  typename Contribution>
1170 class ScatterView<DataType, Kokkos::LayoutLeft, DeviceType, Op,
1171  ScatterDuplicated, Contribution> {
1172  public:
1173  using execution_space = typename DeviceType::execution_space;
1174  using memory_space = typename DeviceType::memory_space;
1175  using device_type = Kokkos::Device<execution_space, memory_space>;
1176  using original_view_type =
1178  using original_value_type = typename original_view_type::value_type;
1179  using original_reference_type = typename original_view_type::reference_type;
1180  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1181  ScatterDuplicated, Contribution, ScatterNonAtomic>;
1182  friend class ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1183  ScatterDuplicated, Contribution, ScatterAtomic>;
1184  template <class, class, class, class, class, class>
1185  friend class ScatterView;
1186 
1187  using data_type_info =
1188  typename Kokkos::Impl::Experimental::DuplicatedDataType<
1189  DataType, Kokkos::LayoutLeft>;
1190  using internal_data_type = typename data_type_info::value_type;
1191  using internal_view_type =
1192  Kokkos::View<internal_data_type, Kokkos::LayoutLeft, device_type>;
1193 
1194  ScatterView() = default;
1195 
1196  template <typename RT, typename... RP>
1197  ScatterView(View<RT, RP...> const& original_view)
1198  : ScatterView(execution_space(), original_view) {}
1199 
1200  template <typename RT, typename... P, typename... RP>
1201  ScatterView(execution_space const& exec_space,
1202  View<RT, RP...> const& original_view)
1203  : unique_token() {
1204  size_t arg_N[8] = {original_view.rank > 0 ? original_view.extent(0)
1205  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1206  original_view.rank > 1 ? original_view.extent(1)
1207  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1208  original_view.rank > 2 ? original_view.extent(2)
1209  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1210  original_view.rank > 3 ? original_view.extent(3)
1211  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1212  original_view.rank > 4 ? original_view.extent(4)
1213  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1214  original_view.rank > 5 ? original_view.extent(5)
1215  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1216  original_view.rank > 6 ? original_view.extent(6)
1217  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1218  KOKKOS_IMPL_CTOR_DEFAULT_ARG};
1219  arg_N[internal_view_type::rank - 1] = unique_token.size();
1220  internal_view = internal_view_type(
1221  view_alloc(WithoutInitializing,
1222  std::string("duplicated_") + original_view.label(),
1223  exec_space),
1224  arg_N[0], arg_N[1], arg_N[2], arg_N[3], arg_N[4], arg_N[5], arg_N[6],
1225  arg_N[7]);
1226  reset(exec_space);
1227  }
1228 
1229  template <typename... Dims>
1230  ScatterView(std::string const& name, Dims... dims)
1231  : ScatterView(view_alloc(execution_space(), name), dims...) {}
1232 
1233  // This overload allows specifying an execution space instance to be
1234  // used by passing, e.g., Kokkos::view_alloc(exec_space, "label") as
1235  // first argument.
1236  template <typename... P, typename... Dims>
1237  ScatterView(::Kokkos::Impl::ViewCtorProp<P...> const& arg_prop,
1238  Dims... dims) {
1239  using ::Kokkos::Impl::Experimental::
1240  check_scatter_view_allocation_properties_argument;
1241  check_scatter_view_allocation_properties_argument(arg_prop);
1242 
1243  original_view_type original_view;
1244  size_t arg_N[8] = {original_view.rank > 0 ? original_view.static_extent(0)
1245  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1246  original_view.rank > 1 ? original_view.static_extent(1)
1247  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1248  original_view.rank > 2 ? original_view.static_extent(2)
1249  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1250  original_view.rank > 3 ? original_view.static_extent(3)
1251  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1252  original_view.rank > 4 ? original_view.static_extent(4)
1253  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1254  original_view.rank > 5 ? original_view.static_extent(5)
1255  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1256  original_view.rank > 6 ? original_view.static_extent(6)
1257  : KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1258  KOKKOS_IMPL_CTOR_DEFAULT_ARG};
1259  Kokkos::Impl::Experimental::args_to_array(arg_N, 0, dims...);
1260  arg_N[internal_view_type::rank - 1] = unique_token.size();
1261 
1262  auto const& name =
1263  Kokkos::Impl::get_property<Kokkos::Impl::LabelTag>(arg_prop);
1264  internal_view = internal_view_type(view_alloc(WithoutInitializing, name),
1265  arg_N[0], arg_N[1], arg_N[2], arg_N[3],
1266  arg_N[4], arg_N[5], arg_N[6], arg_N[7]);
1267 
1268  auto const& exec_space =
1269  Kokkos::Impl::get_property<Kokkos::Impl::ExecutionSpaceTag>(arg_prop);
1270  reset(exec_space);
1271  }
1272 
1273  template <typename OtherDataType, typename OtherDeviceType>
1274  KOKKOS_FUNCTION ScatterView(
1275  const ScatterView<OtherDataType, Kokkos::LayoutLeft, OtherDeviceType, Op,
1276  ScatterDuplicated, Contribution>& other_view)
1277  : unique_token(other_view.unique_token),
1278  internal_view(other_view.internal_view) {}
1279 
1280  template <typename OtherDataType, typename OtherDeviceType>
1281  KOKKOS_FUNCTION void operator=(
1282  const ScatterView<OtherDataType, Kokkos::LayoutLeft, OtherDeviceType, Op,
1283  ScatterDuplicated, Contribution>& other_view) {
1284  unique_token = other_view.unique_token;
1285  internal_view = other_view.internal_view;
1286  }
1287 
1288  template <typename OverrideContribution = Contribution>
1289  KOKKOS_FORCEINLINE_FUNCTION
1290  ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1291  ScatterDuplicated, Contribution, OverrideContribution>
1292  access() const {
1293  return ScatterAccess<DataType, Op, DeviceType, Kokkos::LayoutLeft,
1294  ScatterDuplicated, Contribution, OverrideContribution>(
1295  *this);
1296  }
1297 
1298  typename Kokkos::Impl::Experimental::Slice<Kokkos::LayoutLeft,
1299  internal_view_type::rank,
1300  internal_view_type>::value_type
1301  subview() const {
1302  return Kokkos::Impl::Experimental::Slice<
1303  Kokkos::LayoutLeft, internal_view_type::rank,
1304  internal_view_type>::get(internal_view, 0);
1305  }
1306 
1307  KOKKOS_INLINE_FUNCTION constexpr bool is_allocated() const {
1308  return internal_view.is_allocated();
1309  }
1310 
1311  template <typename... RP>
1312  void contribute_into(View<RP...> const& dest) const {
1313  contribute_into(execution_space(), dest);
1314  }
1315 
1316  template <typename... RP>
1317  void contribute_into(execution_space const& exec_space,
1318  View<RP...> const& dest) const {
1319  using dest_type = View<RP...>;
1320  static_assert(
1321  std::is_same<typename dest_type::value_type,
1322  typename original_view_type::non_const_value_type>::value,
1323  "ScatterView deep_copy destination has wrong value_type");
1324  static_assert(std::is_same<typename dest_type::array_layout,
1325  Kokkos::LayoutLeft>::value,
1326  "ScatterView deep_copy destination has different layout");
1327  static_assert(
1329  execution_space, typename dest_type::memory_space>::accessible,
1330  "ScatterView deep_copy destination memory space not accessible");
1331  auto extent = internal_view.extent(internal_view_type::rank - 1);
1332  bool is_equal = (dest.data() == internal_view.data());
1333  size_t start = is_equal ? 1 : 0;
1334  Kokkos::Impl::Experimental::ReduceDuplicates<execution_space,
1335  original_value_type, Op>(
1336  exec_space, internal_view.data(), dest.data(),
1337  internal_view.stride(internal_view_type::rank - 1), start, extent,
1338  internal_view.label());
1339  }
1340 
1341  void reset(execution_space const& exec_space = execution_space()) {
1342  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1343  original_value_type, Op>(
1344  exec_space, internal_view.data(), internal_view.size(),
1345  internal_view.label());
1346  }
1347 
1348  template <typename DT, typename... RP>
1349  void reset_except(View<DT, RP...> const& view) {
1350  reset_except(execution_space(), view);
1351  }
1352 
1353  template <typename DT, typename... RP>
1354  void reset_except(execution_space const& exec_space,
1355  View<DT, RP...> const& view) {
1356  if (view.data() != internal_view.data()) {
1357  reset(exec_space);
1358  return;
1359  }
1360  Kokkos::Impl::Experimental::ResetDuplicates<execution_space,
1361  original_value_type, Op>(
1362  exec_space, internal_view.data() + view.size(),
1363  internal_view.size() - view.size(), internal_view.label());
1364  }
1365 
1366  void resize(const size_t n0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1367  const size_t n1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1368  const size_t n2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1369  const size_t n3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1370  const size_t n4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1371  const size_t n5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1372  const size_t n6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG) {
1373  size_t arg_N[8] = {n0, n1, n2, n3, n4, n5, n6, 0};
1374  const int i = internal_view.rank - 1;
1375  arg_N[i] = unique_token.size();
1376 
1377  ::Kokkos::resize(internal_view, arg_N[0], arg_N[1], arg_N[2], arg_N[3],
1378  arg_N[4], arg_N[5], arg_N[6], arg_N[7]);
1379  }
1380 
1381  void realloc(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::realloc(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  protected:
1397  template <typename... Args>
1398  KOKKOS_FORCEINLINE_FUNCTION original_reference_type at(int thread_id,
1399  Args... args) const {
1400  return internal_view(args..., thread_id);
1401  }
1402 
1403  protected:
1404  using unique_token_type = Kokkos::Experimental::UniqueToken<
1405  execution_space, Kokkos::Experimental::UniqueTokenScope::Global>;
1406 
1407  unique_token_type unique_token;
1408  internal_view_type internal_view;
1409 };
1410 
1411 /* This object has to be separate in order to store the thread ID, which cannot
1412  be obtained until one is inside a parallel construct, and may be relatively
1413  expensive to obtain at every contribution
1414  (calls a non-inlined function, looks up a thread-local variable).
1415  Due to the expense, it is sensible to query it at most once per parallel
1416  iterate (ideally once per thread, but parallel_for doesn't expose that) and
1417  then store it in a stack variable.
1418  ScatterAccess serves as a non-const object on the stack which can store the
1419  thread ID */
1420 
1421 template <typename DataType, typename Op, typename DeviceType, typename Layout,
1422  typename Contribution, typename OverrideContribution>
1423 class ScatterAccess<DataType, Op, DeviceType, Layout, ScatterDuplicated,
1424  Contribution, OverrideContribution> {
1425  public:
1426  using view_type = ScatterView<DataType, Layout, DeviceType, Op,
1427  ScatterDuplicated, Contribution>;
1428  using original_value_type = typename view_type::original_value_type;
1429  using value_type = Kokkos::Impl::Experimental::ScatterValue<
1430  original_value_type, Op, DeviceType, OverrideContribution>;
1431 
1432  KOKKOS_FORCEINLINE_FUNCTION
1433  ScatterAccess(view_type const& view_in)
1434  : view(view_in), thread_id(view_in.unique_token.acquire()) {}
1435 
1436  KOKKOS_FORCEINLINE_FUNCTION
1437  ~ScatterAccess() {
1438  if (thread_id != ~thread_id_type(0)) view.unique_token.release(thread_id);
1439  }
1440 
1441  template <typename... Args>
1442  KOKKOS_FORCEINLINE_FUNCTION value_type operator()(Args... args) const {
1443  return view.at(thread_id, args...);
1444  }
1445 
1446  template <typename Arg>
1447  KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
1448  view_type::original_view_type::rank == 1 && std::is_integral<Arg>::value,
1449  value_type>
1450  operator[](Arg arg) const {
1451  return view.at(thread_id, arg);
1452  }
1453 
1454  private:
1455  view_type const& view;
1456 
1457  // simplify RAII by disallowing copies
1458  ScatterAccess(ScatterAccess const& other) = delete;
1459  ScatterAccess& operator=(ScatterAccess const& other) = delete;
1460  ScatterAccess& operator=(ScatterAccess&& other) = delete;
1461 
1462  public:
1463  // do need to allow moves though, for the common
1464  // auto b = a.access();
1465  // that assignments turns into a move constructor call
1466  KOKKOS_FORCEINLINE_FUNCTION
1467  ScatterAccess(ScatterAccess&& other)
1468  : view(other.view), thread_id(other.thread_id) {
1469  other.thread_id = ~thread_id_type(0);
1470  }
1471 
1472  private:
1473  using unique_token_type = typename view_type::unique_token_type;
1474  using thread_id_type = typename unique_token_type::size_type;
1475  thread_id_type thread_id;
1476 };
1477 
1478 template <typename Op = Kokkos::Experimental::ScatterSum,
1479  typename Duplication = void, typename Contribution = void,
1480  typename RT, typename... RP>
1481 ScatterView<
1482  RT, typename ViewTraits<RT, RP...>::array_layout,
1483  typename ViewTraits<RT, RP...>::device_type, Op,
1484  std::conditional_t<
1485  std::is_void<Duplication>::value,
1486  typename Kokkos::Impl::Experimental::DefaultDuplication<
1487  typename ViewTraits<RT, RP...>::execution_space>::type,
1488  Duplication>,
1489  std::conditional_t<
1490  std::is_void<Contribution>::value,
1491  typename Kokkos::Impl::Experimental::DefaultContribution<
1492  typename ViewTraits<RT, RP...>::execution_space,
1493  typename std::conditional_t<
1494  std::is_void<Duplication>::value,
1495  typename Kokkos::Impl::Experimental::DefaultDuplication<
1496  typename ViewTraits<RT, RP...>::execution_space>::type,
1497  Duplication>>::type,
1498  Contribution>>
1499 create_scatter_view(View<RT, RP...> const& original_view) {
1500  return original_view; // implicit ScatterView constructor call
1501 }
1502 
1503 template <typename Op, typename RT, typename... RP>
1504 ScatterView<
1505  RT, typename ViewTraits<RT, RP...>::array_layout,
1506  typename ViewTraits<RT, RP...>::device_type, Op,
1507  typename Kokkos::Impl::Experimental::DefaultDuplication<
1508  typename ViewTraits<RT, RP...>::execution_space>::type,
1509  typename Kokkos::Impl::Experimental::DefaultContribution<
1510  typename ViewTraits<RT, RP...>::execution_space,
1511  typename Kokkos::Impl::Experimental::DefaultDuplication<
1512  typename ViewTraits<RT, RP...>::execution_space>::type>::type>
1513 create_scatter_view(Op, View<RT, RP...> const& original_view) {
1514  return original_view; // implicit ScatterView constructor call
1515 }
1516 
1517 template <typename Op, typename Duplication, typename Contribution, typename RT,
1518  typename... RP>
1519 ScatterView<RT, typename ViewTraits<RT, RP...>::array_layout,
1520  typename ViewTraits<RT, RP...>::device_type, Op, Duplication,
1521  Contribution>
1522 create_scatter_view(Op, Duplication, Contribution,
1523  View<RT, RP...> const& original_view) {
1524  return original_view; // implicit ScatterView constructor call
1525 }
1526 
1527 } // namespace Experimental
1528 } // namespace Kokkos
1529 
1530 namespace Kokkos {
1531 namespace Experimental {
1532 
1533 template <typename DT1, typename DT2, typename LY, typename ES, typename OP,
1534  typename CT, typename DP, typename... VP>
1535 void contribute(
1536  typename ES::execution_space const& exec_space, View<DT1, VP...>& dest,
1537  Kokkos::Experimental::ScatterView<DT2, LY, ES, OP, CT, DP> const& src) {
1538  src.contribute_into(exec_space, dest);
1539 }
1540 
1541 template <typename DT1, typename DT2, typename LY, typename ES, typename OP,
1542  typename CT, typename DP, typename... VP>
1543 void contribute(
1544  View<DT1, VP...>& dest,
1545  Kokkos::Experimental::ScatterView<DT2, LY, ES, OP, CT, DP> const& src) {
1546  using execution_space = typename ES::execution_space;
1547  contribute(execution_space{}, dest, src);
1548 }
1549 
1550 } // namespace Experimental
1551 } // namespace Kokkos
1552 
1553 namespace Kokkos {
1554 
1555 template <typename DT, typename LY, typename ES, typename OP, typename CT,
1556  typename DP, typename... IS, class... ViewCtorArgs>
1557 void realloc(
1558  const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1559  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1560  IS... is) {
1561  scatter_view.realloc(arg_prop, is...);
1562 }
1563 
1564 template <typename DT, typename LY, typename ES, typename OP, typename CT,
1565  typename DP, typename... IS>
1566 void realloc(
1567  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1568  IS... is) {
1569  scatter_view.realloc(is...);
1570 }
1571 
1572 template <typename I, typename DT, typename LY, typename ES, typename OP,
1573  typename CT, typename DP, typename... IS>
1574 std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> realloc(
1575  const I& arg_prop,
1576  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1577  IS... is) {
1578  scatter_view.realloc(arg_prop, is...);
1579 }
1580 
1581 template <typename DT, typename LY, typename ES, typename OP, typename CT,
1582  typename DP, typename... IS>
1583 void resize(
1584  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1585  IS... is) {
1586  scatter_view.resize(is...);
1587 }
1588 
1589 template <class... ViewCtorArgs, typename DT, typename LY, typename ES,
1590  typename OP, typename CT, typename DP, typename... IS>
1591 void resize(
1592  const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1593  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1594  IS... is) {
1595  scatter_view.resize(arg_prop, is...);
1596 }
1597 
1598 template <typename I, typename DT, typename LY, typename ES, typename OP,
1599  typename CT, typename DP, typename... IS>
1600 std::enable_if_t<Kokkos::Impl::is_view_ctor_property<I>::value> resize(
1601  const I& arg_prop,
1602  Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1603  IS... is) {
1604  scatter_view.resize(arg_prop, is...);
1605 }
1606 
1607 } // namespace Kokkos
1608 
1609 #ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_SCATTERVIEW
1610 #undef KOKKOS_IMPL_PUBLIC_INCLUDE
1611 #undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_SCATTERVIEW
1612 #endif
1613 #endif
View
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...
Definition: dummy.cpp:17