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