Kokkos Core Kernels Package Version of the Day
Loading...
Searching...
No Matches
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
33namespace Kokkos {
34namespace 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 */
41struct ScatterSum {};
42struct ScatterProd {};
43struct ScatterMax {};
44struct ScatterMin {};
45
46struct ScatterNonDuplicated {};
47struct ScatterDuplicated {};
48
49struct ScatterNonAtomic {};
50struct ScatterAtomic {};
51
52} // namespace Experimental
53} // namespace Kokkos
54
55namespace Kokkos {
56namespace Impl {
57namespace Experimental {
58
59template <typename ExecSpace>
60struct DefaultDuplication;
61
62template <typename ExecSpace, typename Duplication>
63struct DefaultContribution;
64
65#ifdef KOKKOS_ENABLE_SERIAL
66template <>
67struct DefaultDuplication<Kokkos::Serial> {
68 using type = Kokkos::Experimental::ScatterNonDuplicated;
69};
70
71template <>
72struct DefaultContribution<Kokkos::Serial,
73 Kokkos::Experimental::ScatterNonDuplicated> {
74 using type = Kokkos::Experimental::ScatterNonAtomic;
75};
76template <>
77struct DefaultContribution<Kokkos::Serial,
78 Kokkos::Experimental::ScatterDuplicated> {
79 using type = Kokkos::Experimental::ScatterNonAtomic;
80};
81#endif
82
83#ifdef KOKKOS_ENABLE_OPENMP
84template <>
85struct DefaultDuplication<Kokkos::OpenMP> {
86 using type = Kokkos::Experimental::ScatterDuplicated;
87};
88template <>
89struct DefaultContribution<Kokkos::OpenMP,
90 Kokkos::Experimental::ScatterNonDuplicated> {
91 using type = Kokkos::Experimental::ScatterAtomic;
92};
93template <>
94struct DefaultContribution<Kokkos::OpenMP,
95 Kokkos::Experimental::ScatterDuplicated> {
96 using type = Kokkos::Experimental::ScatterNonAtomic;
97};
98#endif
99
100#ifdef KOKKOS_ENABLE_OPENMPTARGET
101template <>
102struct DefaultDuplication<Kokkos::Experimental::OpenMPTarget> {
103 using type = Kokkos::Experimental::ScatterNonDuplicated;
104};
105template <>
106struct DefaultContribution<Kokkos::Experimental::OpenMPTarget,
107 Kokkos::Experimental::ScatterNonDuplicated> {
108 using type = Kokkos::Experimental::ScatterAtomic;
109};
110template <>
111struct DefaultContribution<Kokkos::Experimental::OpenMPTarget,
112 Kokkos::Experimental::ScatterDuplicated> {
113 using type = Kokkos::Experimental::ScatterNonAtomic;
114};
115#endif
116
117#ifdef KOKKOS_ENABLE_HPX
118template <>
119struct DefaultDuplication<Kokkos::Experimental::HPX> {
120 using type = Kokkos::Experimental::ScatterDuplicated;
121};
122template <>
123struct DefaultContribution<Kokkos::Experimental::HPX,
124 Kokkos::Experimental::ScatterNonDuplicated> {
125 using type = Kokkos::Experimental::ScatterAtomic;
126};
127template <>
128struct DefaultContribution<Kokkos::Experimental::HPX,
129 Kokkos::Experimental::ScatterDuplicated> {
130 using type = Kokkos::Experimental::ScatterNonAtomic;
131};
132#endif
133
134#ifdef KOKKOS_ENABLE_THREADS
135template <>
136struct DefaultDuplication<Kokkos::Threads> {
137 using type = Kokkos::Experimental::ScatterDuplicated;
138};
139template <>
140struct DefaultContribution<Kokkos::Threads,
141 Kokkos::Experimental::ScatterNonDuplicated> {
142 using type = Kokkos::Experimental::ScatterAtomic;
143};
144template <>
145struct DefaultContribution<Kokkos::Threads,
146 Kokkos::Experimental::ScatterDuplicated> {
147 using type = Kokkos::Experimental::ScatterNonAtomic;
148};
149#endif
150
151#ifdef KOKKOS_ENABLE_CUDA
152template <>
153struct DefaultDuplication<Kokkos::Cuda> {
154 using type = Kokkos::Experimental::ScatterNonDuplicated;
155};
156template <>
157struct DefaultContribution<Kokkos::Cuda,
158 Kokkos::Experimental::ScatterNonDuplicated> {
159 using type = Kokkos::Experimental::ScatterAtomic;
160};
161template <>
162struct DefaultContribution<Kokkos::Cuda,
163 Kokkos::Experimental::ScatterDuplicated> {
164 using type = Kokkos::Experimental::ScatterAtomic;
165};
166#endif
167
168#ifdef KOKKOS_ENABLE_HIP
169template <>
170struct DefaultDuplication<Kokkos::HIP> {
171 using type = Kokkos::Experimental::ScatterNonDuplicated;
172};
173template <>
174struct DefaultContribution<Kokkos::HIP,
175 Kokkos::Experimental::ScatterNonDuplicated> {
176 using type = Kokkos::Experimental::ScatterAtomic;
177};
178template <>
179struct DefaultContribution<Kokkos::HIP,
180 Kokkos::Experimental::ScatterDuplicated> {
181 using type = Kokkos::Experimental::ScatterAtomic;
182};
183#endif
184
185#ifdef KOKKOS_ENABLE_SYCL
186template <>
187struct DefaultDuplication<Kokkos::Experimental::SYCL> {
188 using type = Kokkos::Experimental::ScatterNonDuplicated;
189};
190template <>
191struct DefaultContribution<Kokkos::Experimental::SYCL,
192 Kokkos::Experimental::ScatterNonDuplicated> {
193 using type = Kokkos::Experimental::ScatterAtomic;
194};
195template <>
196struct 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
207template <typename ValueType, typename Op, typename DeviceType,
208 typename Contribution>
209struct 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 ) */
217template <typename ValueType, typename DeviceType>
218struct 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. */
250template <typename ValueType, typename DeviceType>
251struct 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 ) */
294template <typename ValueType, typename DeviceType>
295struct 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. */
325template <typename ValueType, typename DeviceType>
326struct 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 ) */
362template <typename ValueType, typename DeviceType>
363struct 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. */
386template <typename ValueType, typename DeviceType>
387struct 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 ) */
416template <typename ValueType, typename DeviceType>
417struct 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. */
440template <typename ValueType, typename DeviceType>
441struct 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. */
469template <typename T, typename Layout>
470struct DuplicatedDataType;
471
472template <typename T>
473struct DuplicatedDataType<T, Kokkos::LayoutRight> {
474 using value_type = T*; // For LayoutRight, add a star all the way on the left
475};
476
477template <typename T, size_t N>
478struct DuplicatedDataType<T[N], Kokkos::LayoutRight> {
479 using value_type =
480 typename DuplicatedDataType<T, Kokkos::LayoutRight>::value_type[N];
481};
482
483template <typename T>
484struct DuplicatedDataType<T[], Kokkos::LayoutRight> {
485 using value_type =
486 typename DuplicatedDataType<T, Kokkos::LayoutRight>::value_type[];
487};
488
489template <typename T>
490struct DuplicatedDataType<T*, Kokkos::LayoutRight> {
491 using value_type =
492 typename DuplicatedDataType<T, Kokkos::LayoutRight>::value_type*;
493};
494
495template <typename T>
496struct DuplicatedDataType<T, Kokkos::LayoutLeft> {
497 using value_type = T*;
498};
499
500template <typename T, size_t N>
501struct DuplicatedDataType<T[N], Kokkos::LayoutLeft> {
502 using value_type =
503 typename DuplicatedDataType<T, Kokkos::LayoutLeft>::value_type*;
504};
505
506template <typename T>
507struct DuplicatedDataType<T[], Kokkos::LayoutLeft> {
508 using value_type =
509 typename DuplicatedDataType<T, Kokkos::LayoutLeft>::value_type*;
510};
511
512template <typename T>
513struct 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
520template <class T>
521void args_to_array(size_t* array, int pos, T dim0) {
522 array[pos] = dim0;
523}
524template <class T, class... Dims>
525void 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. */
533template <typename Layout, int rank, typename V, typename... Args>
534struct 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
543template <typename V, typename... Args>
544struct 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
552template <typename V, typename... Args>
553struct 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
561template <typename ExecSpace, typename ValueType, typename Op>
562struct ReduceDuplicates;
563
564template <typename ExecSpace, typename ValueType, typename Op>
565struct 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 */
586template <typename ExecSpace, typename ValueType, typename Op>
587struct 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
604template <typename ExecSpace, typename ValueType, typename Op>
605struct ResetDuplicates;
606
607template <typename ExecSpace, typename ValueType, typename Op>
608struct 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 */
624template <typename ExecSpace, typename ValueType, typename Op>
625struct 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
638template <typename... P>
639void 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
652namespace Kokkos {
653namespace Experimental {
654
655template <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>
664class ScatterView;
665
666template <class>
667struct is_scatter_view : public std::false_type {};
668
669template <class D, class... P>
670struct is_scatter_view<ScatterView<D, P...>> : public std::true_type {};
671
672template <class D, class... P>
673struct is_scatter_view<const ScatterView<D, P...>> : public std::true_type {};
674
675template <class T>
676inline constexpr bool is_scatter_view_v = is_scatter_view<T>::value;
677
678template <typename DataType, typename Op, typename DeviceType, typename Layout,
679 typename Duplication, typename Contribution,
680 typename OverrideContribution>
681class ScatterAccess;
682
683// non-duplicated implementation
684template <typename DataType, typename Op, typename DeviceType, typename Layout,
685 typename Contribution>
686class 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(
770 Kokkos::SpaceAccessibility<
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
882template <typename DataType, typename Op, typename DeviceType, typename Layout,
883 typename Contribution, typename OverrideContribution>
884class 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
922template <typename DataType, typename Op, typename DeviceType,
923 typename Contribution>
924class 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 =
931 Kokkos::View<DataType, Kokkos::LayoutRight, device_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(
1057 Kokkos::SpaceAccessibility<
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
1182template <typename DataType, typename Op, typename DeviceType,
1183 typename Contribution>
1184class 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 =
1191 Kokkos::View<DataType, Kokkos::LayoutLeft, device_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(
1343 Kokkos::SpaceAccessibility<
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
1436template <typename DataType, typename Op, typename DeviceType, typename Layout,
1437 typename Contribution, typename OverrideContribution>
1438class 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
1493template <typename Op = Kokkos::Experimental::ScatterSum,
1494 typename Duplication = void, typename Contribution = void,
1495 typename RT, typename... RP>
1496ScatterView<
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>>
1514create_scatter_view(View<RT, RP...> const& original_view) {
1515 return original_view; // implicit ScatterView constructor call
1516}
1517
1518template <typename Op, typename RT, typename... RP>
1519ScatterView<
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>
1528create_scatter_view(Op, View<RT, RP...> const& original_view) {
1529 return original_view; // implicit ScatterView constructor call
1530}
1531
1532template <typename Op, typename Duplication, typename Contribution, typename RT,
1533 typename... RP>
1534ScatterView<RT, typename ViewTraits<RT, RP...>::array_layout,
1535 typename ViewTraits<RT, RP...>::device_type, Op, Duplication,
1536 Contribution>
1537create_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
1545namespace Kokkos {
1546namespace Experimental {
1547
1548template <typename DT1, typename DT2, typename LY, typename ES, typename OP,
1549 typename CT, typename DP, typename... VP>
1550void 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
1556template <typename DT1, typename DT2, typename LY, typename ES, typename OP,
1557 typename CT, typename DP, typename... VP>
1558void 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
1568namespace Kokkos {
1569
1570template <typename DT, typename LY, typename ES, typename OP, typename CT,
1571 typename DP, typename... IS, class... ViewCtorArgs>
1572void 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
1579template <typename DT, typename LY, typename ES, typename OP, typename CT,
1580 typename DP, typename... IS>
1581void realloc(
1582 Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1583 IS... is) {
1584 scatter_view.realloc(is...);
1585}
1586
1587template <typename I, typename DT, typename LY, typename ES, typename OP,
1588 typename CT, typename DP, typename... IS>
1589std::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
1596template <typename DT, typename LY, typename ES, typename OP, typename CT,
1597 typename DP, typename... IS>
1598void resize(
1599 Kokkos::Experimental::ScatterView<DT, LY, ES, OP, CT, DP>& scatter_view,
1600 IS... is) {
1601 scatter_view.resize(is...);
1602}
1603
1604template <class... ViewCtorArgs, typename DT, typename LY, typename ES,
1605 typename OP, typename CT, typename DP, typename... IS>
1606void 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
1613template <typename I, typename DT, typename LY, typename ES, typename OP,
1614 typename CT, typename DP, typename... IS>
1615std::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
ScopeGuard Some user scope issues have been identified with some Kokkos::finalize calls; ScopeGuard a...