Kokkos Core Kernels Package Version of the Day
Loading...
Searching...
No Matches
Kokkos_OffsetView.hpp
1//@HEADER
2// ************************************************************************
3//
4// Kokkos v. 4.0
5// Copyright (2022) National Technology & Engineering
6// Solutions of Sandia, LLC (NTESS).
7//
8// Under the terms of Contract DE-NA0003525 with NTESS,
9// the U.S. Government retains certain rights in this software.
10//
11// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12// See https://kokkos.org/LICENSE for license information.
13// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14//
15//@HEADER
16
17#ifndef KOKKOS_OFFSETVIEW_HPP_
18#define KOKKOS_OFFSETVIEW_HPP_
19#ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
20#define KOKKOS_IMPL_PUBLIC_INCLUDE
21#define KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_OFFSETVIEW
22#endif
23
24#include <Kokkos_Core.hpp>
25
26#include <Kokkos_View.hpp>
27
28namespace Kokkos {
29
30namespace Experimental {
31//----------------------------------------------------------------------------
32//----------------------------------------------------------------------------
33
34template <class DataType, class... Properties>
35class OffsetView;
36
37template <class>
38struct is_offset_view : public std::false_type {};
39
40template <class D, class... P>
41struct is_offset_view<OffsetView<D, P...>> : public std::true_type {};
42
43template <class D, class... P>
44struct is_offset_view<const OffsetView<D, P...>> : public std::true_type {};
45
46#define KOKKOS_INVALID_OFFSET int64_t(0x7FFFFFFFFFFFFFFFLL)
47#define KOKKOS_INVALID_INDEX_RANGE \
48 { KOKKOS_INVALID_OFFSET, KOKKOS_INVALID_OFFSET }
49
50template <typename iType, std::enable_if_t<std::is_integral<iType>::value &&
51 std::is_signed<iType>::value,
52 iType> = 0>
53using IndexRange = Kokkos::Array<iType, 2>;
54
55using index_list_type = std::initializer_list<int64_t>;
56
57// template <typename iType,
58// std::enable_if_t< std::is_integral<iType>::value &&
59// std::is_signed<iType>::value, iType > = 0> using min_index_type =
60// std::initializer_list<iType>;
61
62namespace Impl {
63
64template <class ViewType>
65struct GetOffsetViewTypeFromViewType {
66 using type =
67 OffsetView<typename ViewType::data_type, typename ViewType::array_layout,
68 typename ViewType::device_type,
69 typename ViewType::memory_traits>;
70};
71
72template <unsigned, class MapType, class BeginsType>
73KOKKOS_INLINE_FUNCTION bool offsetview_verify_operator_bounds(
74 const MapType&, const BeginsType&) {
75 return true;
76}
77
78template <unsigned R, class MapType, class BeginsType, class iType,
79 class... Args>
80KOKKOS_INLINE_FUNCTION bool offsetview_verify_operator_bounds(
81 const MapType& map, const BeginsType& begins, const iType& i,
82 Args... args) {
83 const bool legalIndex =
84 (int64_t(i) >= begins[R]) &&
85 (int64_t(i) <= int64_t(begins[R] + map.extent(R) - 1));
86 return legalIndex &&
87 offsetview_verify_operator_bounds<R + 1>(map, begins, args...);
88}
89template <unsigned, class MapType, class BeginsType>
90inline void offsetview_error_operator_bounds(char*, int, const MapType&,
91 const BeginsType&) {}
92
93template <unsigned R, class MapType, class BeginsType, class iType,
94 class... Args>
95inline void offsetview_error_operator_bounds(char* buf, int len,
96 const MapType& map,
97 const BeginsType begins,
98 const iType& i, Args... args) {
99 const int64_t b = begins[R];
100 const int64_t e = b + map.extent(R) - 1;
101 const int n =
102 snprintf(buf, len, " %ld <= %ld <= %ld %c", static_cast<unsigned long>(b),
103 static_cast<unsigned long>(i), static_cast<unsigned long>(e),
104 (sizeof...(Args) ? ',' : ')'));
105 offsetview_error_operator_bounds<R + 1>(buf + n, len - n, map, begins,
106 args...);
107}
108
109template <class MemorySpace, class MapType, class BeginsType, class... Args>
110KOKKOS_INLINE_FUNCTION void offsetview_verify_operator_bounds(
111 Kokkos::Impl::SharedAllocationTracker const& tracker, const MapType& map,
112 const BeginsType& begins, Args... args) {
113 if (!offsetview_verify_operator_bounds<0>(map, begins, args...)) {
114 KOKKOS_IF_ON_HOST(
115 (enum {LEN = 1024}; char buffer[LEN];
116 const std::string label = tracker.template get_label<MemorySpace>();
117 int n = snprintf(buffer, LEN,
118 "OffsetView bounds error of view labeled %s (",
119 label.c_str());
120 offsetview_error_operator_bounds<0>(buffer + n, LEN - n, map, begins,
121 args...);
122 Kokkos::Impl::throw_runtime_exception(std::string(buffer));))
123
124 KOKKOS_IF_ON_DEVICE((
125 /* Check #1: is there a SharedAllocationRecord?
126 (we won't use it, but if it is not there then there isn't
127 a corresponding SharedAllocationHeader containing a label).
128 This check should cover the case of Views that don't
129 have the Unmanaged trait but were initialized by pointer. */
130 if (tracker.has_record()) {
131 Kokkos::Impl::operator_bounds_error_on_device(map);
132 } else { Kokkos::abort("OffsetView bounds error"); }))
133 }
134}
135
136inline void runtime_check_rank_host(const size_t rank_dynamic,
137 const size_t rank,
138 const index_list_type minIndices,
139 const std::string& label) {
140 bool isBad = false;
141 std::string message =
142 "Kokkos::Experimental::OffsetView ERROR: for OffsetView labeled '" +
143 label + "':";
144 if (rank_dynamic != rank) {
145 message +=
146 "The full rank must be the same as the dynamic rank. full rank = ";
147 message += std::to_string(rank) +
148 " dynamic rank = " + std::to_string(rank_dynamic) + "\n";
149 isBad = true;
150 }
151
152 size_t numOffsets = 0;
153 for (size_t i = 0; i < minIndices.size(); ++i) {
154 if (minIndices.begin()[i] != KOKKOS_INVALID_OFFSET) numOffsets++;
155 }
156 if (numOffsets != rank_dynamic) {
157 message += "The number of offsets provided ( " +
158 std::to_string(numOffsets) +
159 " ) must equal the dynamic rank ( " +
160 std::to_string(rank_dynamic) + " ).";
161 isBad = true;
162 }
163
164 if (isBad) Kokkos::abort(message.c_str());
165}
166
167KOKKOS_INLINE_FUNCTION
168void runtime_check_rank_device(const size_t rank_dynamic, const size_t rank,
169 const index_list_type minIndices) {
170 if (rank_dynamic != rank) {
171 Kokkos::abort(
172 "The full rank of an OffsetView must be the same as the dynamic rank.");
173 }
174 size_t numOffsets = 0;
175 for (size_t i = 0; i < minIndices.size(); ++i) {
176 if (minIndices.begin()[i] != KOKKOS_INVALID_OFFSET) numOffsets++;
177 }
178 if (numOffsets != rank) {
179 Kokkos::abort(
180 "The number of offsets provided to an OffsetView constructor must "
181 "equal the dynamic rank.");
182 }
183}
184} // namespace Impl
185
186template <class DataType, class... Properties>
187class OffsetView : public ViewTraits<DataType, Properties...> {
188 public:
189 using traits = ViewTraits<DataType, Properties...>;
190
191 private:
192 template <class, class...>
193 friend class OffsetView;
194 template <class, class...>
195 friend class View; // FIXME delete this line
196 template <class, class...>
197 friend class Kokkos::Impl::ViewMapping;
198
199 using map_type = Kokkos::Impl::ViewMapping<traits, void>;
200 using track_type = Kokkos::Impl::SharedAllocationTracker;
201
202 public:
203 enum { Rank = map_type::Rank };
204 using begins_type = Kokkos::Array<int64_t, Rank>;
205
206 template <typename iType,
207 std::enable_if_t<std::is_integral<iType>::value, iType> = 0>
208 KOKKOS_FUNCTION int64_t begin(const iType local_dimension) const {
209 return local_dimension < Rank ? m_begins[local_dimension]
210 : KOKKOS_INVALID_OFFSET;
211 }
212
213 KOKKOS_FUNCTION
214 begins_type begins() const { return m_begins; }
215
216 template <typename iType,
217 std::enable_if_t<std::is_integral<iType>::value, iType> = 0>
218 KOKKOS_FUNCTION int64_t end(const iType local_dimension) const {
219 return begin(local_dimension) + m_map.extent(local_dimension);
220 }
221
222 private:
223 track_type m_track;
224 map_type m_map;
225 begins_type m_begins;
226
227 public:
228 //----------------------------------------
230 using array_type =
231 OffsetView<typename traits::scalar_array_type,
232 typename traits::array_layout, typename traits::device_type,
233 typename traits::memory_traits>;
234
236 using const_type =
237 OffsetView<typename traits::const_data_type,
238 typename traits::array_layout, typename traits::device_type,
239 typename traits::memory_traits>;
240
242 using non_const_type =
243 OffsetView<typename traits::non_const_data_type,
244 typename traits::array_layout, typename traits::device_type,
245 typename traits::memory_traits>;
246
248 using HostMirror = OffsetView<typename traits::non_const_data_type,
249 typename traits::array_layout,
250 typename traits::host_mirror_space>;
251
252 //----------------------------------------
253 // Domain rank and extents
254
257 // KOKKOS_FUNCTION
258 // static
259 // constexpr unsigned rank() { return map_type::Rank; }
260
261 template <typename iType>
262 KOKKOS_FUNCTION constexpr std::enable_if_t<std::is_integral<iType>::value,
263 size_t>
264 extent(const iType& r) const {
265 return m_map.extent(r);
266 }
267
268 template <typename iType>
269 KOKKOS_FUNCTION constexpr std::enable_if_t<std::is_integral<iType>::value,
270 int>
271 extent_int(const iType& r) const {
272 return static_cast<int>(m_map.extent(r));
273 }
274
275 KOKKOS_FUNCTION constexpr typename traits::array_layout layout() const {
276 return m_map.layout();
277 }
278
279 KOKKOS_FUNCTION constexpr size_t size() const {
280 return m_map.dimension_0() * m_map.dimension_1() * m_map.dimension_2() *
281 m_map.dimension_3() * m_map.dimension_4() * m_map.dimension_5() *
282 m_map.dimension_6() * m_map.dimension_7();
283 }
284
285 KOKKOS_FUNCTION constexpr size_t stride_0() const { return m_map.stride_0(); }
286 KOKKOS_FUNCTION constexpr size_t stride_1() const { return m_map.stride_1(); }
287 KOKKOS_FUNCTION constexpr size_t stride_2() const { return m_map.stride_2(); }
288 KOKKOS_FUNCTION constexpr size_t stride_3() const { return m_map.stride_3(); }
289 KOKKOS_FUNCTION constexpr size_t stride_4() const { return m_map.stride_4(); }
290 KOKKOS_FUNCTION constexpr size_t stride_5() const { return m_map.stride_5(); }
291 KOKKOS_FUNCTION constexpr size_t stride_6() const { return m_map.stride_6(); }
292 KOKKOS_FUNCTION constexpr size_t stride_7() const { return m_map.stride_7(); }
293
294 template <typename iType>
295 KOKKOS_FUNCTION constexpr std::enable_if_t<std::is_integral<iType>::value,
296 size_t>
297 stride(iType r) const {
298 return (
299 r == 0
300 ? m_map.stride_0()
301 : (r == 1
302 ? m_map.stride_1()
303 : (r == 2
304 ? m_map.stride_2()
305 : (r == 3
306 ? m_map.stride_3()
307 : (r == 4
308 ? m_map.stride_4()
309 : (r == 5
310 ? m_map.stride_5()
311 : (r == 6
312 ? m_map.stride_6()
313 : m_map.stride_7())))))));
314 }
315
316 template <typename iType>
317 KOKKOS_FUNCTION void stride(iType* const s) const {
318 m_map.stride(s);
319 }
320
321 //----------------------------------------
322 // Range span is the span which contains all members.
323
324 using reference_type = typename map_type::reference_type;
325 using pointer_type = typename map_type::pointer_type;
326
327 enum {
328 reference_type_is_lvalue_reference =
329 std::is_lvalue_reference<reference_type>::value
330 };
331
332 KOKKOS_FUNCTION constexpr size_t span() const { return m_map.span(); }
333 KOKKOS_FUNCTION bool span_is_contiguous() const {
334 return m_map.span_is_contiguous();
335 }
336 KOKKOS_FUNCTION constexpr bool is_allocated() const {
337 return m_map.data() != nullptr;
338 }
339 KOKKOS_FUNCTION constexpr pointer_type data() const { return m_map.data(); }
340
341 //----------------------------------------
342 // Allow specializations to query their specialized map
343
344 KOKKOS_FUNCTION
345 const Kokkos::Impl::ViewMapping<traits, void>& implementation_map() const {
346 return m_map;
347 }
348
349 //----------------------------------------
350
351 private:
352 static constexpr bool is_layout_left =
353 std::is_same<typename traits::array_layout, Kokkos::LayoutLeft>::value;
354
355 static constexpr bool is_layout_right =
356 std::is_same<typename traits::array_layout, Kokkos::LayoutRight>::value;
357
358 static constexpr bool is_layout_stride =
359 std::is_same<typename traits::array_layout, Kokkos::LayoutStride>::value;
360
361 static constexpr bool is_default_map =
362 std::is_void<typename traits::specialize>::value &&
363 (is_layout_left || is_layout_right || is_layout_stride);
364
365#if defined(KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK)
366
367#define KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(ARG) \
368 Kokkos::Impl::runtime_check_memory_access_violation< \
369 typename traits::memory_space>( \
370 "Kokkos::OffsetView ERROR: attempt to access inaccessible memory " \
371 "space"); \
372 Kokkos::Experimental::Impl::offsetview_verify_operator_bounds< \
373 typename traits::memory_space> \
374 ARG;
375
376#else
377
378#define KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(ARG) \
379 Kokkos::Impl::runtime_check_memory_access_violation< \
380 typename traits::memory_space>( \
381 "Kokkos::OffsetView ERROR: attempt to access inaccessible memory " \
382 "space");
383
384#endif
385 public:
386 //------------------------------
387 // Rank 0 operator()
388
389 KOKKOS_FORCEINLINE_FUNCTION
390 reference_type operator()() const { return m_map.reference(); }
391 //------------------------------
392 // Rank 1 operator()
393
394 template <typename I0>
395 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
396 (Kokkos::Impl::are_integral<I0>::value && (1 == Rank) && !is_default_map),
397 reference_type>
398 operator()(const I0& i0) const {
399 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
400 const size_t j0 = i0 - m_begins[0];
401 return m_map.reference(j0);
402 }
403
404 template <typename I0>
405 KOKKOS_FORCEINLINE_FUNCTION
406 std::enable_if_t<(Kokkos::Impl::are_integral<I0>::value && (1 == Rank) &&
407 is_default_map && !is_layout_stride),
408 reference_type>
409 operator()(const I0& i0) const {
410 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
411 const size_t j0 = i0 - m_begins[0];
412 return m_map.m_impl_handle[j0];
413 }
414
415 template <typename I0>
416 KOKKOS_FORCEINLINE_FUNCTION
417 std::enable_if_t<(Kokkos::Impl::are_integral<I0>::value && (1 == Rank) &&
418 is_default_map && is_layout_stride),
419 reference_type>
420 operator()(const I0& i0) const {
421 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
422 const size_t j0 = i0 - m_begins[0];
423 return m_map.m_impl_handle[m_map.m_impl_offset.m_stride.S0 * j0];
424 }
425 //------------------------------
426 // Rank 1 operator[]
427
428 template <typename I0>
429 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
430 (Kokkos::Impl::are_integral<I0>::value && (1 == Rank) && !is_default_map),
431 reference_type>
432 operator[](const I0& i0) const {
433 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
434 const size_t j0 = i0 - m_begins[0];
435 return m_map.reference(j0);
436 }
437
438 template <typename I0>
439 KOKKOS_FORCEINLINE_FUNCTION
440 std::enable_if_t<(Kokkos::Impl::are_integral<I0>::value && (1 == Rank) &&
441 is_default_map && !is_layout_stride),
442 reference_type>
443 operator[](const I0& i0) const {
444 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
445 const size_t j0 = i0 - m_begins[0];
446 return m_map.m_impl_handle[j0];
447 }
448
449 template <typename I0>
450 KOKKOS_FORCEINLINE_FUNCTION
451 std::enable_if_t<(Kokkos::Impl::are_integral<I0>::value && (1 == Rank) &&
452 is_default_map && is_layout_stride),
453 reference_type>
454 operator[](const I0& i0) const {
455 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0))
456 const size_t j0 = i0 - m_begins[0];
457 return m_map.m_impl_handle[m_map.m_impl_offset.m_stride.S0 * j0];
458 }
459
460 //------------------------------
461 // Rank 2
462
463 template <typename I0, typename I1>
464 KOKKOS_FORCEINLINE_FUNCTION
465 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1>::value &&
466 (2 == Rank) && !is_default_map),
467 reference_type>
468 operator()(const I0& i0, const I1& i1) const {
469 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
470 const size_t j0 = i0 - m_begins[0];
471 const size_t j1 = i1 - m_begins[1];
472 return m_map.reference(j0, j1);
473 }
474
475 template <typename I0, typename I1>
476 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
477 (Kokkos::Impl::are_integral<I0, I1>::value && (2 == Rank) &&
478 is_default_map && is_layout_left && (traits::rank_dynamic == 0)),
479 reference_type>
480 operator()(const I0& i0, const I1& i1) const {
481 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
482 const size_t j0 = i0 - m_begins[0];
483 const size_t j1 = i1 - m_begins[1];
484 return m_map.m_impl_handle[j0 + m_map.m_impl_offset.m_dim.N0 * j1];
485 }
486
487 template <typename I0, typename I1>
488 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
489 (Kokkos::Impl::are_integral<I0, I1>::value && (2 == Rank) &&
490 is_default_map && is_layout_left && (traits::rank_dynamic != 0)),
491 reference_type>
492 operator()(const I0& i0, const I1& i1) const {
493 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
494 const size_t j0 = i0 - m_begins[0];
495 const size_t j1 = i1 - m_begins[1];
496 return m_map.m_impl_handle[j0 + m_map.m_impl_offset.m_stride * j1];
497 }
498
499 template <typename I0, typename I1>
500 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
501 (Kokkos::Impl::are_integral<I0, I1>::value && (2 == Rank) &&
502 is_default_map && is_layout_right && (traits::rank_dynamic == 0)),
503 reference_type>
504 operator()(const I0& i0, const I1& i1) const {
505 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
506 const size_t j0 = i0 - m_begins[0];
507 const size_t j1 = i1 - m_begins[1];
508 return m_map.m_impl_handle[j1 + m_map.m_impl_offset.m_dim.N1 * j0];
509 }
510
511 template <typename I0, typename I1>
512 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
513 (Kokkos::Impl::are_integral<I0, I1>::value && (2 == Rank) &&
514 is_default_map && is_layout_right && (traits::rank_dynamic != 0)),
515 reference_type>
516 operator()(const I0& i0, const I1& i1) const {
517 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
518 const size_t j0 = i0 - m_begins[0];
519 const size_t j1 = i1 - m_begins[1];
520 return m_map.m_impl_handle[j1 + m_map.m_impl_offset.m_stride * j0];
521 }
522
523 template <typename I0, typename I1>
524 KOKKOS_FORCEINLINE_FUNCTION
525 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1>::value &&
526 (2 == Rank) && is_default_map && is_layout_stride),
527 reference_type>
528 operator()(const I0& i0, const I1& i1) const {
529 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY((m_track, m_map, m_begins, i0, i1))
530 const size_t j0 = i0 - m_begins[0];
531 const size_t j1 = i1 - m_begins[1];
532 return m_map.m_impl_handle[j0 * m_map.m_impl_offset.m_stride.S0 +
533 j1 * m_map.m_impl_offset.m_stride.S1];
534 }
535
536 //------------------------------
537 // Rank 3
538
539 template <typename I0, typename I1, typename I2>
540 KOKKOS_FORCEINLINE_FUNCTION
541 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2>::value &&
542 (3 == Rank) && is_default_map),
543 reference_type>
544 operator()(const I0& i0, const I1& i1, const I2& i2) const {
545 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
546 (m_track, m_map, m_begins, i0, i1, i2))
547 const size_t j0 = i0 - m_begins[0];
548 const size_t j1 = i1 - m_begins[1];
549 const size_t j2 = i2 - m_begins[2];
550 return m_map.m_impl_handle[m_map.m_impl_offset(j0, j1, j2)];
551 }
552
553 template <typename I0, typename I1, typename I2>
554 KOKKOS_FORCEINLINE_FUNCTION
555 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2>::value &&
556 (3 == Rank) && !is_default_map),
557 reference_type>
558 operator()(const I0& i0, const I1& i1, const I2& i2) const {
559 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
560 (m_track, m_map, m_begins, i0, i1, i2))
561 const size_t j0 = i0 - m_begins[0];
562 const size_t j1 = i1 - m_begins[1];
563 const size_t j2 = i2 - m_begins[2];
564 return m_map.reference(j0, j1, j2);
565 }
566
567 //------------------------------
568 // Rank 4
569
570 template <typename I0, typename I1, typename I2, typename I3>
571 KOKKOS_FORCEINLINE_FUNCTION
572 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2, I3>::value &&
573 (4 == Rank) && is_default_map),
574 reference_type>
575 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3) const {
576 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
577 (m_track, m_map, m_begins, i0, i1, i2, i3))
578 const size_t j0 = i0 - m_begins[0];
579 const size_t j1 = i1 - m_begins[1];
580 const size_t j2 = i2 - m_begins[2];
581 const size_t j3 = i3 - m_begins[3];
582 return m_map.m_impl_handle[m_map.m_impl_offset(j0, j1, j2, j3)];
583 }
584
585 template <typename I0, typename I1, typename I2, typename I3>
586 KOKKOS_FORCEINLINE_FUNCTION
587 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2, I3>::value &&
588 (4 == Rank) && !is_default_map),
589 reference_type>
590 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3) const {
591 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
592 (m_track, m_map, m_begins, i0, i1, i2, i3))
593 const size_t j0 = i0 - m_begins[0];
594 const size_t j1 = i1 - m_begins[1];
595 const size_t j2 = i2 - m_begins[2];
596 const size_t j3 = i3 - m_begins[3];
597 return m_map.reference(j0, j1, j2, j3);
598 }
599
600 //------------------------------
601 // Rank 5
602
603 template <typename I0, typename I1, typename I2, typename I3, typename I4>
604 KOKKOS_FORCEINLINE_FUNCTION
605 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2, I3, I4>::value &&
606 (5 == Rank) && is_default_map),
607 reference_type>
608 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
609 const I4& i4) const {
610 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
611 (m_track, m_map, m_begins, i0, i1, i2, i3, i4))
612 const size_t j0 = i0 - m_begins[0];
613 const size_t j1 = i1 - m_begins[1];
614 const size_t j2 = i2 - m_begins[2];
615 const size_t j3 = i3 - m_begins[3];
616 const size_t j4 = i4 - m_begins[4];
617 return m_map.m_impl_handle[m_map.m_impl_offset(j0, j1, j2, j3, j4)];
618 }
619
620 template <typename I0, typename I1, typename I2, typename I3, typename I4>
621 KOKKOS_FORCEINLINE_FUNCTION
622 std::enable_if_t<(Kokkos::Impl::are_integral<I0, I1, I2, I3, I4>::value &&
623 (5 == Rank) && !is_default_map),
624 reference_type>
625 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
626 const I4& i4) const {
627 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
628 (m_track, m_map, m_begins, i0, i1, i2, i3, i4))
629 const size_t j0 = i0 - m_begins[0];
630 const size_t j1 = i1 - m_begins[1];
631 const size_t j2 = i2 - m_begins[2];
632 const size_t j3 = i3 - m_begins[3];
633 const size_t j4 = i4 - m_begins[4];
634 return m_map.reference(j0, j1, j2, j3, j4);
635 }
636
637 //------------------------------
638 // Rank 6
639
640 template <typename I0, typename I1, typename I2, typename I3, typename I4,
641 typename I5>
642 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
643 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5>::value &&
644 (6 == Rank) && is_default_map),
645 reference_type>
646 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
647 const I4& i4, const I5& i5) const {
648 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
649 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5))
650 const size_t j0 = i0 - m_begins[0];
651 const size_t j1 = i1 - m_begins[1];
652 const size_t j2 = i2 - m_begins[2];
653 const size_t j3 = i3 - m_begins[3];
654 const size_t j4 = i4 - m_begins[4];
655 const size_t j5 = i5 - m_begins[5];
656 return m_map.m_impl_handle[m_map.m_impl_offset(j0, j1, j2, j3, j4, j5)];
657 }
658
659 template <typename I0, typename I1, typename I2, typename I3, typename I4,
660 typename I5>
661 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
662 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5>::value &&
663 (6 == Rank) && !is_default_map),
664 reference_type>
665 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
666 const I4& i4, const I5& i5) const {
667 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
668 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5))
669 const size_t j0 = i0 - m_begins[0];
670 const size_t j1 = i1 - m_begins[1];
671 const size_t j2 = i2 - m_begins[2];
672 const size_t j3 = i3 - m_begins[3];
673 const size_t j4 = i4 - m_begins[4];
674 const size_t j5 = i5 - m_begins[5];
675 return m_map.reference(j0, j1, j2, j3, j4, j5);
676 }
677
678 //------------------------------
679 // Rank 7
680
681 template <typename I0, typename I1, typename I2, typename I3, typename I4,
682 typename I5, typename I6>
683 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
684 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5, I6>::value &&
685 (7 == Rank) && is_default_map),
686 reference_type>
687 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
688 const I4& i4, const I5& i5, const I6& i6) const {
689 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
690 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5, i6))
691 const size_t j0 = i0 - m_begins[0];
692 const size_t j1 = i1 - m_begins[1];
693 const size_t j2 = i2 - m_begins[2];
694 const size_t j3 = i3 - m_begins[3];
695 const size_t j4 = i4 - m_begins[4];
696 const size_t j5 = i5 - m_begins[5];
697 const size_t j6 = i6 - m_begins[6];
698 return m_map.m_impl_handle[m_map.m_impl_offset(j0, j1, j2, j3, j4, j5, j6)];
699 }
700
701 template <typename I0, typename I1, typename I2, typename I3, typename I4,
702 typename I5, typename I6>
703 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
704 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5, I6>::value &&
705 (7 == Rank) && !is_default_map),
706 reference_type>
707 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
708 const I4& i4, const I5& i5, const I6& i6) const {
709 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
710 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5, i6))
711 const size_t j0 = i0 - m_begins[0];
712 const size_t j1 = i1 - m_begins[1];
713 const size_t j2 = i2 - m_begins[2];
714 const size_t j3 = i3 - m_begins[3];
715 const size_t j4 = i4 - m_begins[4];
716 const size_t j5 = i5 - m_begins[5];
717 const size_t j6 = i6 - m_begins[6];
718 return m_map.reference(j0, j1, j2, j3, j4, j5, j6);
719 }
720
721 //------------------------------
722 // Rank 8
723
724 template <typename I0, typename I1, typename I2, typename I3, typename I4,
725 typename I5, typename I6, typename I7>
726 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
727 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5, I6, I7>::value &&
728 (8 == Rank) && is_default_map),
729 reference_type>
730 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
731 const I4& i4, const I5& i5, const I6& i6, const I7& i7) const {
732 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
733 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5, i6, i7))
734 const size_t j0 = i0 - m_begins[0];
735 const size_t j1 = i1 - m_begins[1];
736 const size_t j2 = i2 - m_begins[2];
737 const size_t j3 = i3 - m_begins[3];
738 const size_t j4 = i4 - m_begins[4];
739 const size_t j5 = i5 - m_begins[5];
740 const size_t j6 = i6 - m_begins[6];
741 const size_t j7 = i7 - m_begins[7];
742 return m_map
743 .m_impl_handle[m_map.m_impl_offset(j0, j1, j2, j3, j4, j5, j6, j7)];
744 }
745
746 template <typename I0, typename I1, typename I2, typename I3, typename I4,
747 typename I5, typename I6, typename I7>
748 KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
749 (Kokkos::Impl::are_integral<I0, I1, I2, I3, I4, I5, I6, I7>::value &&
750 (8 == Rank) && !is_default_map),
751 reference_type>
752 operator()(const I0& i0, const I1& i1, const I2& i2, const I3& i3,
753 const I4& i4, const I5& i5, const I6& i6, const I7& i7) const {
754 KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY(
755 (m_track, m_map, m_begins, i0, i1, i2, i3, i4, i5, i6, i7))
756 const size_t j0 = i0 - m_begins[0];
757 const size_t j1 = i1 - m_begins[1];
758 const size_t j2 = i2 - m_begins[2];
759 const size_t j3 = i3 - m_begins[3];
760 const size_t j4 = i4 - m_begins[4];
761 const size_t j5 = i5 - m_begins[5];
762 const size_t j6 = i6 - m_begins[6];
763 const size_t j7 = i7 - m_begins[7];
764 return m_map.reference(j0, j1, j2, j3, j4, j5, j6, j7);
765 }
766
767#undef KOKKOS_IMPL_OFFSETVIEW_OPERATOR_VERIFY
768
769 //----------------------------------------
770 // Standard destructor, constructors, and assignment operators
771
772 KOKKOS_DEFAULTED_FUNCTION
773 ~OffsetView() = default;
774
775 KOKKOS_FUNCTION
776 OffsetView() : m_track(), m_map() {
777 for (size_t i = 0; i < Rank; ++i) m_begins[i] = KOKKOS_INVALID_OFFSET;
778 }
779
780 KOKKOS_FUNCTION
781 OffsetView(const OffsetView& rhs)
782 : m_track(rhs.m_track, traits::is_managed),
783 m_map(rhs.m_map),
784 m_begins(rhs.m_begins) {}
785
786 KOKKOS_FUNCTION
787 OffsetView(OffsetView&& rhs)
788 : m_track(std::move(rhs.m_track)),
789 m_map(std::move(rhs.m_map)),
790 m_begins(std::move(rhs.m_begins)) {}
791
792 KOKKOS_FUNCTION
793 OffsetView& operator=(const OffsetView& rhs) {
794 m_track = rhs.m_track;
795 m_map = rhs.m_map;
796 m_begins = rhs.m_begins;
797 return *this;
798 }
799
800 KOKKOS_FUNCTION
801 OffsetView& operator=(OffsetView&& rhs) {
802 m_track = std::move(rhs.m_track);
803 m_map = std::move(rhs.m_map);
804 m_begins = std::move(rhs.m_begins);
805 return *this;
806 }
807
808 // interoperability with View
809 private:
810 using view_type =
811 View<typename traits::scalar_array_type, typename traits::array_layout,
812 typename traits::device_type, typename traits::memory_traits>;
813
814 public:
815 KOKKOS_FUNCTION
816 view_type view() const {
817 view_type v(m_track, m_map);
818 return v;
819 }
820
821 template <class RT, class... RP>
822 KOKKOS_FUNCTION OffsetView(const View<RT, RP...>& aview)
823 : m_track(aview.impl_track()), m_map() {
824 using SrcTraits = typename OffsetView<RT, RP...>::traits;
825 using Mapping = Kokkos::Impl::ViewMapping<traits, SrcTraits, void>;
826 static_assert(Mapping::is_assignable,
827 "Incompatible OffsetView copy construction");
828 Mapping::assign(m_map, aview.impl_map(), m_track);
829
830 for (int i = 0; i < aview.Rank; ++i) {
831 m_begins[i] = 0;
832 }
833 }
834
835 template <class RT, class... RP>
836 KOKKOS_FUNCTION OffsetView(const View<RT, RP...>& aview,
837 const index_list_type& minIndices)
838 : m_track(aview.impl_track()), m_map() {
839 using SrcTraits = typename OffsetView<RT, RP...>::traits;
840 using Mapping = Kokkos::Impl::ViewMapping<traits, SrcTraits, void>;
841 static_assert(Mapping::is_assignable,
842 "Incompatible OffsetView copy construction");
843 Mapping::assign(m_map, aview.impl_map(), m_track);
844
845 KOKKOS_IF_ON_HOST((Kokkos::Experimental::Impl::runtime_check_rank_host(
846 traits::rank_dynamic, Rank, minIndices, label());))
847
848 KOKKOS_IF_ON_DEVICE((Kokkos::Experimental::Impl::runtime_check_rank_device(
849 traits::rank_dynamic, Rank, minIndices);))
850
851 for (size_t i = 0; i < minIndices.size(); ++i) {
852 m_begins[i] = minIndices.begin()[i];
853 }
854 }
855 template <class RT, class... RP>
856 KOKKOS_FUNCTION OffsetView(const View<RT, RP...>& aview,
857 const begins_type& beg)
858 : m_track(aview.impl_track()), m_map(), m_begins(beg) {
859 using SrcTraits = typename OffsetView<RT, RP...>::traits;
860 using Mapping = Kokkos::Impl::ViewMapping<traits, SrcTraits, void>;
861 static_assert(Mapping::is_assignable,
862 "Incompatible OffsetView copy construction");
863 Mapping::assign(m_map, aview.impl_map(), m_track);
864 }
865
866 // may assign unmanaged from managed.
867
868 template <class RT, class... RP>
869 KOKKOS_FUNCTION OffsetView(const OffsetView<RT, RP...>& rhs)
870 : m_track(rhs.m_track, traits::is_managed),
871 m_map(),
872 m_begins(rhs.m_begins) {
873 using SrcTraits = typename OffsetView<RT, RP...>::traits;
874 using Mapping = Kokkos::Impl::ViewMapping<traits, SrcTraits, void>;
875 static_assert(Mapping::is_assignable,
876 "Incompatible OffsetView copy construction");
877 Mapping::assign(m_map, rhs.m_map, rhs.m_track); // swb what about assign?
878 }
879
880 private:
881 enum class subtraction_failure {
882 none,
883 negative,
884 overflow,
885 };
886
887 // Subtraction should return a non-negative number and not overflow
888 KOKKOS_FUNCTION static subtraction_failure check_subtraction(int64_t lhs,
889 int64_t rhs) {
890 if (lhs < rhs) return subtraction_failure::negative;
891
892 if (static_cast<uint64_t>(-1) / static_cast<uint64_t>(2) <
893 static_cast<uint64_t>(lhs) - static_cast<uint64_t>(rhs))
894 return subtraction_failure::overflow;
895
896 return subtraction_failure::none;
897 }
898
899 // Need a way to get at an element from both begins_type (aka Kokkos::Array
900 // which doesn't have iterators) and index_list_type (aka
901 // std::initializer_list which doesn't have .data() or operator[]).
902 // Returns by value
903 KOKKOS_FUNCTION
904 static int64_t at(const begins_type& a, size_t pos) { return a[pos]; }
905
906 KOKKOS_FUNCTION
907 static int64_t at(index_list_type a, size_t pos) {
908 return *(a.begin() + pos);
909 }
910
911 // Check that begins < ends for all elements
912 // B, E can be begins_type and/or index_list_type
913 template <typename B, typename E>
914 static subtraction_failure runtime_check_begins_ends_host(const B& begins,
915 const E& ends) {
916 std::string message;
917 if (begins.size() != Rank)
918 message +=
919 "begins.size() "
920 "(" +
921 std::to_string(begins.size()) +
922 ")"
923 " != Rank "
924 "(" +
925 std::to_string(Rank) +
926 ")"
927 "\n";
928
929 if (ends.size() != Rank)
930 message +=
931 "ends.size() "
932 "(" +
933 std::to_string(begins.size()) +
934 ")"
935 " != Rank "
936 "(" +
937 std::to_string(Rank) +
938 ")"
939 "\n";
940
941 // If there are no errors so far, then rank == Rank
942 // Otherwise, check as much as possible
943 size_t rank = begins.size() < ends.size() ? begins.size() : ends.size();
944 for (size_t i = 0; i != rank; ++i) {
945 subtraction_failure sf = check_subtraction(at(ends, i), at(begins, i));
946 if (sf != subtraction_failure::none) {
947 message +=
948 "("
949 "ends[" +
950 std::to_string(i) +
951 "]"
952 " "
953 "(" +
954 std::to_string(at(ends, i)) +
955 ")"
956 " - "
957 "begins[" +
958 std::to_string(i) +
959 "]"
960 " "
961 "(" +
962 std::to_string(at(begins, i)) +
963 ")"
964 ")";
965 switch (sf) {
966 case subtraction_failure::negative:
967 message += " must be non-negative\n";
968 break;
969 case subtraction_failure::overflow: message += " overflows\n"; break;
970 default: break;
971 }
972 }
973 }
974
975 if (!message.empty()) {
976 message =
977 "Kokkos::Experimental::OffsetView ERROR: for unmanaged OffsetView\n" +
978 message;
979 Kokkos::Impl::throw_runtime_exception(message);
980 }
981
982 return subtraction_failure::none;
983 }
984
985 // Check the begins < ends for all elements
986 template <typename B, typename E>
987 KOKKOS_FUNCTION static subtraction_failure runtime_check_begins_ends_device(
988 const B& begins, const E& ends) {
989 if (begins.size() != Rank)
990 Kokkos::abort(
991 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
992 "OffsetView: begins has bad Rank");
993 if (ends.size() != Rank)
994 Kokkos::abort(
995 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
996 "OffsetView: ends has bad Rank");
997
998 for (size_t i = 0; i != begins.size(); ++i) {
999 switch (check_subtraction(at(ends, i), at(begins, i))) {
1000 case subtraction_failure::negative:
1001 Kokkos::abort(
1002 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
1003 "OffsetView: bad range");
1004 break;
1005 case subtraction_failure::overflow:
1006 Kokkos::abort(
1007 "Kokkos::Experimental::OffsetView ERROR: for unmanaged "
1008 "OffsetView: range overflows");
1009 break;
1010 default: break;
1011 }
1012 }
1013
1014 return subtraction_failure::none;
1015 }
1016
1017 template <typename B, typename E>
1018 KOKKOS_FUNCTION static subtraction_failure runtime_check_begins_ends(
1019 const B& begins, const E& ends) {
1020 KOKKOS_IF_ON_HOST((return runtime_check_begins_ends_host(begins, ends);))
1021 KOKKOS_IF_ON_DEVICE(
1022 (return runtime_check_begins_ends_device(begins, ends);))
1023 }
1024
1025 // Constructor around unmanaged data after checking begins < ends for all
1026 // elements
1027 // Each of B, E can be begins_type and/or index_list_type
1028 // Precondition: begins.size() == ends.size() == m_begins.size() == Rank
1029 template <typename B, typename E>
1030 KOKKOS_FUNCTION OffsetView(const pointer_type& p, const B& begins_,
1031 const E& ends_,
1032 subtraction_failure)
1033 : m_track() // no tracking
1034 ,
1035 m_map(Kokkos::Impl::ViewCtorProp<pointer_type>(p),
1036 typename traits::array_layout(
1037 Rank > 0 ? at(ends_, 0) - at(begins_, 0) : 0,
1038 Rank > 1 ? at(ends_, 1) - at(begins_, 1) : 0,
1039 Rank > 2 ? at(ends_, 2) - at(begins_, 2) : 0,
1040 Rank > 3 ? at(ends_, 3) - at(begins_, 3) : 0,
1041 Rank > 4 ? at(ends_, 4) - at(begins_, 4) : 0,
1042 Rank > 5 ? at(ends_, 5) - at(begins_, 5) : 0,
1043 Rank > 6 ? at(ends_, 6) - at(begins_, 6) : 0,
1044 Rank > 7 ? at(ends_, 7) - at(begins_, 7) : 0)) {
1045 for (size_t i = 0; i != m_begins.size(); ++i) {
1046 m_begins[i] = at(begins_, i);
1047 };
1048 }
1049
1050 public:
1051 // Constructor around unmanaged data
1052 // Four overloads, as both begins and ends can be either
1053 // begins_type or index_list_type
1054 KOKKOS_FUNCTION
1055 OffsetView(const pointer_type& p, const begins_type& begins_,
1056 const begins_type& ends_)
1057 : OffsetView(p, begins_, ends_,
1058 runtime_check_begins_ends(begins_, ends_)) {}
1059
1060 KOKKOS_FUNCTION
1061 OffsetView(const pointer_type& p, const begins_type& begins_,
1062 index_list_type ends_)
1063 : OffsetView(p, begins_, ends_,
1064 runtime_check_begins_ends(begins_, ends_)) {}
1065
1066 KOKKOS_FUNCTION
1067 OffsetView(const pointer_type& p, index_list_type begins_,
1068 const begins_type& ends_)
1069 : OffsetView(p, begins_, ends_,
1070 runtime_check_begins_ends(begins_, ends_)) {}
1071
1072 KOKKOS_FUNCTION
1073 OffsetView(const pointer_type& p, index_list_type begins_,
1074 index_list_type ends_)
1075 : OffsetView(p, begins_, ends_,
1076 runtime_check_begins_ends(begins_, ends_)) {}
1077
1078 //----------------------------------------
1079 // Allocation tracking properties
1080 KOKKOS_FUNCTION
1081 int use_count() const { return m_track.use_count(); }
1082
1083 const std::string label() const {
1084 return m_track.template get_label<typename traits::memory_space>();
1085 }
1086
1087 // Choosing std::pair as type for the arguments allows constructing an
1088 // OffsetView using list initialization syntax, e.g.,
1089 // OffsetView dummy("dummy", {-1, 3}, {-2,2});
1090 // We could allow arbitrary types RangeType that support
1091 // std::get<{0,1}>(RangeType const&) with std::tuple_size<RangeType>::value==2
1092 // but this wouldn't allow using the syntax in the example above.
1093 template <typename Label>
1094 explicit OffsetView(
1095 const Label& arg_label,
1096 std::enable_if_t<Kokkos::Impl::is_view_label<Label>::value,
1097 const std::pair<int64_t, int64_t>>
1098 range0,
1099 const std::pair<int64_t, int64_t> range1 = KOKKOS_INVALID_INDEX_RANGE,
1100 const std::pair<int64_t, int64_t> range2 = KOKKOS_INVALID_INDEX_RANGE,
1101 const std::pair<int64_t, int64_t> range3 = KOKKOS_INVALID_INDEX_RANGE,
1102 const std::pair<int64_t, int64_t> range4 = KOKKOS_INVALID_INDEX_RANGE,
1103 const std::pair<int64_t, int64_t> range5 = KOKKOS_INVALID_INDEX_RANGE,
1104 const std::pair<int64_t, int64_t> range6 = KOKKOS_INVALID_INDEX_RANGE,
1105 const std::pair<int64_t, int64_t> range7 = KOKKOS_INVALID_INDEX_RANGE
1106
1107 )
1108 : OffsetView(
1109 Kokkos::Impl::ViewCtorProp<std::string>(arg_label),
1110 typename traits::array_layout(range0.second - range0.first + 1,
1111 range1.second - range1.first + 1,
1112 range2.second - range2.first + 1,
1113 range3.second - range3.first + 1,
1114 range4.second - range4.first + 1,
1115 range5.second - range5.first + 1,
1116 range6.second - range6.first + 1,
1117 range7.second - range7.first + 1),
1118 {range0.first, range1.first, range2.first, range3.first,
1119 range4.first, range5.first, range6.first, range7.first}) {}
1120
1121 template <class... P>
1122 explicit OffsetView(
1123 const Kokkos::Impl::ViewCtorProp<P...>& arg_prop,
1124 const std::pair<int64_t, int64_t> range0 = KOKKOS_INVALID_INDEX_RANGE,
1125 const std::pair<int64_t, int64_t> range1 = KOKKOS_INVALID_INDEX_RANGE,
1126 const std::pair<int64_t, int64_t> range2 = KOKKOS_INVALID_INDEX_RANGE,
1127 const std::pair<int64_t, int64_t> range3 = KOKKOS_INVALID_INDEX_RANGE,
1128 const std::pair<int64_t, int64_t> range4 = KOKKOS_INVALID_INDEX_RANGE,
1129 const std::pair<int64_t, int64_t> range5 = KOKKOS_INVALID_INDEX_RANGE,
1130 const std::pair<int64_t, int64_t> range6 = KOKKOS_INVALID_INDEX_RANGE,
1131 const std::pair<int64_t, int64_t> range7 = KOKKOS_INVALID_INDEX_RANGE)
1132 : OffsetView(
1133 arg_prop,
1134 typename traits::array_layout(range0.second - range0.first + 1,
1135 range1.second - range1.first + 1,
1136 range2.second - range2.first + 1,
1137 range3.second - range3.first + 1,
1138 range4.second - range4.first + 1,
1139 range5.second - range5.first + 1,
1140 range6.second - range6.first + 1,
1141 range7.second - range7.first + 1),
1142 {range0.first, range1.first, range2.first, range3.first,
1143 range4.first, range5.first, range6.first, range7.first}) {}
1144
1145 template <class... P>
1146 explicit KOKKOS_FUNCTION OffsetView(
1147 const Kokkos::Impl::ViewCtorProp<P...>& arg_prop,
1148 std::enable_if_t<Kokkos::Impl::ViewCtorProp<P...>::has_pointer,
1149 typename traits::array_layout> const& arg_layout,
1150 const index_list_type minIndices)
1151 : m_track() // No memory tracking
1152 ,
1153 m_map(arg_prop, arg_layout) {
1154 for (size_t i = 0; i < minIndices.size(); ++i) {
1155 m_begins[i] = minIndices.begin()[i];
1156 }
1157 static_assert(
1158 std::is_same<pointer_type, typename Kokkos::Impl::ViewCtorProp<
1159 P...>::pointer_type>::value,
1160 "When constructing OffsetView to wrap user memory, you must supply "
1161 "matching pointer type");
1162 }
1163
1164 template <class... P>
1165 explicit OffsetView(
1166 const Kokkos::Impl::ViewCtorProp<P...>& arg_prop,
1167 std::enable_if_t<!Kokkos::Impl::ViewCtorProp<P...>::has_pointer,
1168 typename traits::array_layout> const& arg_layout,
1169 const index_list_type minIndices)
1170 : m_track(),
1171 m_map()
1172
1173 {
1174 for (size_t i = 0; i < Rank; ++i) m_begins[i] = minIndices.begin()[i];
1175
1176 // Copy the input allocation properties with possibly defaulted properties
1177 auto prop_copy = Kokkos::Impl::with_properties_if_unset(
1178 arg_prop, std::string{}, typename traits::device_type::memory_space{},
1179 typename traits::device_type::execution_space{});
1180 using alloc_prop = decltype(prop_copy);
1181
1182 static_assert(traits::is_managed,
1183 "OffsetView allocation constructor requires managed memory");
1184
1185 if (alloc_prop::initialize &&
1186 !alloc_prop::execution_space::impl_is_initialized()) {
1187 // If initializing view data then
1188 // the execution space must be initialized.
1189 Kokkos::Impl::throw_runtime_exception(
1190 "Constructing OffsetView and initializing data with uninitialized "
1191 "execution space");
1192 }
1193
1194 //------------------------------------------------------------
1195#if defined(KOKKOS_ENABLE_CUDA)
1196 // If allocating in CudaUVMSpace must fence before and after
1197 // the allocation to protect against possible concurrent access
1198 // on the CPU and the GPU.
1199 // Fence using the trait's executon space (which will be Kokkos::Cuda)
1200 // to avoid incomplete type errors from usng Kokkos::Cuda directly.
1201 if (std::is_same<Kokkos::CudaUVMSpace,
1202 typename traits::device_type::memory_space>::value) {
1203 typename traits::device_type::memory_space::execution_space().fence(
1204 "Kokkos::OffsetView::OffsetView(): fence before UVM allocation");
1205 }
1206#endif
1207 //------------------------------------------------------------
1208
1209 Kokkos::Impl::SharedAllocationRecord<>* record = m_map.allocate_shared(
1210 prop_copy, arg_layout,
1211 Kokkos::Impl::ViewCtorProp<P...>::has_execution_space);
1212
1213 //------------------------------------------------------------
1214#if defined(KOKKOS_ENABLE_CUDA)
1215 if (std::is_same<Kokkos::CudaUVMSpace,
1216 typename traits::device_type::memory_space>::value) {
1217 typename traits::device_type::memory_space::execution_space().fence(
1218 "Kokkos::OffsetView::OffsetView(): fence after UVM allocation");
1219 }
1220#endif
1221 //------------------------------------------------------------
1222
1223 // Setup and initialization complete, start tracking
1224 m_track.assign_allocated_record_to_uninitialized(record);
1225
1226 KOKKOS_IF_ON_HOST((Kokkos::Experimental::Impl::runtime_check_rank_host(
1227 traits::rank_dynamic, Rank, minIndices, label());))
1228
1229 KOKKOS_IF_ON_DEVICE((Kokkos::Experimental::Impl::runtime_check_rank_device(
1230 traits::rank_dynamic, Rank, minIndices);))
1231 }
1232};
1233
1238template <typename D, class... P>
1239KOKKOS_INLINE_FUNCTION constexpr unsigned rank(const OffsetView<D, P...>& V) {
1240 return V.Rank;
1241} // Temporary until added to view
1242
1243//----------------------------------------------------------------------------
1244//----------------------------------------------------------------------------
1245namespace Impl {
1246
1247template <class T>
1248KOKKOS_INLINE_FUNCTION std::enable_if_t<std::is_integral<T>::value, T>
1249shift_input(const T arg, const int64_t offset) {
1250 return arg - offset;
1251}
1252
1253KOKKOS_INLINE_FUNCTION
1254Kokkos::Impl::ALL_t shift_input(const Kokkos::Impl::ALL_t arg,
1255 const int64_t /*offset*/) {
1256 return arg;
1257}
1258
1259template <class T>
1260KOKKOS_INLINE_FUNCTION
1261 std::enable_if_t<std::is_integral<T>::value, Kokkos::pair<T, T>>
1262 shift_input(const Kokkos::pair<T, T> arg, const int64_t offset) {
1263 return Kokkos::make_pair<T, T>(arg.first - offset, arg.second - offset);
1264}
1265template <class T>
1266inline std::enable_if_t<std::is_integral<T>::value, std::pair<T, T>>
1267shift_input(const std::pair<T, T> arg, const int64_t offset) {
1268 return std::make_pair<T, T>(arg.first - offset, arg.second - offset);
1269}
1270
1271template <size_t N, class Arg, class A>
1272KOKKOS_INLINE_FUNCTION void map_arg_to_new_begin(
1273 const size_t i, Kokkos::Array<int64_t, N>& subviewBegins,
1274 std::enable_if_t<N != 0, const Arg> shiftedArg, const Arg arg,
1275 const A viewBegins, size_t& counter) {
1276 if (!std::is_integral<Arg>::value) {
1277 subviewBegins[counter] = shiftedArg == arg ? viewBegins[i] : 0;
1278 counter++;
1279 }
1280}
1281
1282template <size_t N, class Arg, class A>
1283KOKKOS_INLINE_FUNCTION void map_arg_to_new_begin(
1284 const size_t /*i*/, Kokkos::Array<int64_t, N>& /*subviewBegins*/,
1285 std::enable_if_t<N == 0, const Arg> /*shiftedArg*/, const Arg /*arg*/,
1286 const A /*viewBegins*/, size_t& /*counter*/) {}
1287
1288template <class D, class... P, class T>
1289KOKKOS_INLINE_FUNCTION
1290 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1291 typename Kokkos::Impl::ViewMapping<void /* deduce subview type from
1292 source view traits */
1293 ,
1294 ViewTraits<D, P...>, T>::type>::type
1295 subview_offset(const OffsetView<D, P...>& src, T arg) {
1296 auto theView = src.view();
1297 auto begins = src.begins();
1298
1299 T shiftedArg = shift_input(arg, begins[0]);
1300
1301 constexpr size_t rank =
1302 Kokkos::Impl::ViewMapping<void /* deduce subview type from source view
1303 traits */
1304 ,
1305 ViewTraits<D, P...>, T>::type::Rank;
1306
1307 auto theSubview = Kokkos::subview(theView, shiftedArg);
1308
1309 Kokkos::Array<int64_t, rank> subviewBegins;
1310 size_t counter = 0;
1311 Kokkos::Experimental::Impl::map_arg_to_new_begin(0, subviewBegins, shiftedArg,
1312 arg, begins, counter);
1313
1314 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1315 typename Kokkos::Impl::ViewMapping<void /* deduce subview type from source
1316 view traits */
1317 ,
1318 ViewTraits<D, P...>, T>::type>::type
1319 offsetView(theSubview, subviewBegins);
1320
1321 return offsetView;
1322}
1323
1324template <class D, class... P, class T0, class T1>
1325KOKKOS_INLINE_FUNCTION
1326 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1327 typename Kokkos::Impl::ViewMapping<
1328 void /* deduce subview type from source view traits */
1329 ,
1330 ViewTraits<D, P...>, T0, T1>::type>::type
1331 subview_offset(const Kokkos::Experimental::OffsetView<D, P...>& src,
1332 T0 arg0, T1 arg1) {
1333 auto theView = src.view();
1334 auto begins = src.begins();
1335
1336 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1337 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1338
1339 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1);
1340 constexpr size_t rank =
1341 Kokkos::Impl::ViewMapping<void /* deduce subview type from source view
1342 traits */
1343 ,
1344 ViewTraits<D, P...>, T0, T1>::type::Rank;
1345
1346 Kokkos::Array<int64_t, rank> subviewBegins;
1347 size_t counter = 0;
1348 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1349 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1350 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1351 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1352
1353 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1354 typename Kokkos::Impl::ViewMapping<
1355 void /* deduce subview type from source view traits */
1356 ,
1357 ViewTraits<D, P...>, T0, T1>::type>::type offsetView(theSubview,
1358 subviewBegins);
1359
1360 return offsetView;
1361}
1362
1363template <class D, class... P, class T0, class T1, class T2>
1364KOKKOS_INLINE_FUNCTION
1365 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1366 typename Kokkos::Impl::ViewMapping<
1367 void /* deduce subview type from source view traits */
1368 ,
1369 ViewTraits<D, P...>, T0, T1, T2>::type>::type
1370 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2) {
1371 auto theView = src.view();
1372 auto begins = src.begins();
1373
1374 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1375 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1376 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1377
1378 auto theSubview =
1379 Kokkos::subview(theView, shiftedArg0, shiftedArg1, shiftedArg2);
1380
1381 constexpr size_t rank =
1382 Kokkos::Impl::ViewMapping<void /* deduce subview type from source view
1383 traits */
1384 ,
1385 ViewTraits<D, P...>, T0, T1, T2>::type::Rank;
1386
1387 Kokkos::Array<int64_t, rank> subviewBegins;
1388
1389 size_t counter = 0;
1390 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1391 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1392 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1393 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1394 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1395 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1396
1397 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1398 typename Kokkos::Impl::ViewMapping<
1399 void /* deduce subview type from source view traits */
1400 ,
1401 ViewTraits<D, P...>, T0, T1, T2>::type>::type
1402 offsetView(theSubview, subviewBegins);
1403
1404 return offsetView;
1405}
1406
1407template <class D, class... P, class T0, class T1, class T2, class T3>
1408KOKKOS_INLINE_FUNCTION
1409 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1410 typename Kokkos::Impl::ViewMapping<
1411 void /* deduce subview type from source view traits */
1412 ,
1413 ViewTraits<D, P...>, T0, T1, T2, T3>::type>::type
1414 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1415 T3 arg3) {
1416 auto theView = src.view();
1417 auto begins = src.begins();
1418
1419 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1420 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1421 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1422 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1423
1424 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1,
1425 shiftedArg2, shiftedArg3);
1426
1427 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1428 void /* deduce subview type from source view traits */
1429 ,
1430 ViewTraits<D, P...>, T0, T1, T2, T3>::type::Rank;
1431 Kokkos::Array<int64_t, rank> subviewBegins;
1432
1433 size_t counter = 0;
1434 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1435 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1436 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1437 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1438 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1439 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1440 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1441 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1442
1443 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1444 typename Kokkos::Impl::ViewMapping<
1445 void /* deduce subview type from source view traits */
1446 ,
1447 ViewTraits<D, P...>, T0, T1, T2, T3>::type>::type
1448 offsetView(theSubview, subviewBegins);
1449
1450 return offsetView;
1451}
1452
1453template <class D, class... P, class T0, class T1, class T2, class T3, class T4>
1454KOKKOS_INLINE_FUNCTION
1455 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1456 typename Kokkos::Impl::ViewMapping<
1457 void /* deduce subview type from source view traits */
1458 ,
1459 ViewTraits<D, P...>, T0, T1, T2, T3, T4>::type>::type
1460 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1461 T3 arg3, T4 arg4) {
1462 auto theView = src.view();
1463 auto begins = src.begins();
1464
1465 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1466 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1467 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1468 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1469 T4 shiftedArg4 = shift_input(arg4, begins[4]);
1470
1471 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1,
1472 shiftedArg2, shiftedArg3, shiftedArg4);
1473
1474 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1475 void /* deduce subview type from source view traits */
1476 ,
1477 ViewTraits<D, P...>, T0, T1, T2, T3, T4>::type::Rank;
1478 Kokkos::Array<int64_t, rank> subviewBegins;
1479
1480 size_t counter = 0;
1481 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1482 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1483 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1484 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1485 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1486 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1487 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1488 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1489 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1490 4, subviewBegins, shiftedArg4, arg4, begins, counter);
1491
1492 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1493 typename Kokkos::Impl::ViewMapping<
1494 void /* deduce subview type from source view traits */
1495 ,
1496 ViewTraits<D, P...>, T0, T1, T2, T3, T4>::type>::type
1497 offsetView(theSubview, subviewBegins);
1498
1499 return offsetView;
1500}
1501
1502template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
1503 class T5>
1504KOKKOS_INLINE_FUNCTION
1505 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1506 typename Kokkos::Impl::ViewMapping<
1507 void /* deduce subview type from source view traits */
1508 ,
1509 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5>::type>::type
1510 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1511 T3 arg3, T4 arg4, T5 arg5) {
1512 auto theView = src.view();
1513 auto begins = src.begins();
1514
1515 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1516 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1517 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1518 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1519 T4 shiftedArg4 = shift_input(arg4, begins[4]);
1520 T5 shiftedArg5 = shift_input(arg5, begins[5]);
1521
1522 auto theSubview =
1523 Kokkos::subview(theView, shiftedArg0, shiftedArg1, shiftedArg2,
1524 shiftedArg3, shiftedArg4, shiftedArg5);
1525
1526 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1527 void /* deduce subview type from source view traits */
1528 ,
1529 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5>::type::Rank;
1530
1531 Kokkos::Array<int64_t, rank> subviewBegins;
1532
1533 size_t counter = 0;
1534 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1535 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1536 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1537 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1538 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1539 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1540 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1541 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1542 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1543 4, subviewBegins, shiftedArg4, arg4, begins, counter);
1544 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1545 5, subviewBegins, shiftedArg5, arg5, begins, counter);
1546
1547 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1548 typename Kokkos::Impl::ViewMapping<
1549 void /* deduce subview type from source view traits */
1550 ,
1551 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5>::type>::type
1552 offsetView(theSubview, subviewBegins);
1553
1554 return offsetView;
1555}
1556template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
1557 class T5, class T6>
1558KOKKOS_INLINE_FUNCTION
1559 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1560 typename Kokkos::Impl::ViewMapping<
1561 void /* deduce subview type from source view traits */
1562 ,
1563 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6>::type>::type
1564 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1565 T3 arg3, T4 arg4, T5 arg5, T6 arg6) {
1566 auto theView = src.view();
1567 auto begins = src.begins();
1568
1569 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1570 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1571 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1572 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1573 T4 shiftedArg4 = shift_input(arg4, begins[4]);
1574 T5 shiftedArg5 = shift_input(arg5, begins[5]);
1575 T6 shiftedArg6 = shift_input(arg6, begins[6]);
1576
1577 auto theSubview =
1578 Kokkos::subview(theView, shiftedArg0, shiftedArg1, shiftedArg2,
1579 shiftedArg3, shiftedArg4, shiftedArg5, shiftedArg6);
1580
1581 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1582 void /* deduce subview type from source view traits */
1583 ,
1584 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6>::type::Rank;
1585
1586 Kokkos::Array<int64_t, rank> subviewBegins;
1587
1588 size_t counter = 0;
1589 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1590 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1591 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1592 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1593 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1594 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1595 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1596 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1597 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1598 4, subviewBegins, shiftedArg4, arg4, begins, counter);
1599 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1600 5, subviewBegins, shiftedArg5, arg5, begins, counter);
1601 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1602 6, subviewBegins, shiftedArg6, arg6, begins, counter);
1603
1604 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1605 typename Kokkos::Impl::ViewMapping<
1606 void /* deduce subview type from source view traits */
1607 ,
1608 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6>::type>::type
1609 offsetView(theSubview, subviewBegins);
1610
1611 return offsetView;
1612}
1613
1614template <class D, class... P, class T0, class T1, class T2, class T3, class T4,
1615 class T5, class T6, class T7>
1616KOKKOS_INLINE_FUNCTION
1617 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1618 typename Kokkos::Impl::ViewMapping<
1619 void /* deduce subview type from source view traits */
1620 ,
1621 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6, T7>::type>::type
1622 subview_offset(const OffsetView<D, P...>& src, T0 arg0, T1 arg1, T2 arg2,
1623 T3 arg3, T4 arg4, T5 arg5, T6 arg6, T7 arg7) {
1624 auto theView = src.view();
1625 auto begins = src.begins();
1626
1627 T0 shiftedArg0 = shift_input(arg0, begins[0]);
1628 T1 shiftedArg1 = shift_input(arg1, begins[1]);
1629 T2 shiftedArg2 = shift_input(arg2, begins[2]);
1630 T3 shiftedArg3 = shift_input(arg3, begins[3]);
1631 T4 shiftedArg4 = shift_input(arg4, begins[4]);
1632 T5 shiftedArg5 = shift_input(arg5, begins[5]);
1633 T6 shiftedArg6 = shift_input(arg6, begins[6]);
1634 T7 shiftedArg7 = shift_input(arg7, begins[7]);
1635
1636 auto theSubview = Kokkos::subview(theView, shiftedArg0, shiftedArg1,
1637 shiftedArg2, shiftedArg3, shiftedArg4,
1638 shiftedArg5, shiftedArg6, shiftedArg7);
1639
1640 constexpr size_t rank = Kokkos::Impl::ViewMapping<
1641 void /* deduce subview type from source view traits */
1642 ,
1643 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6, T7>::type::Rank;
1644
1645 Kokkos::Array<int64_t, rank> subviewBegins;
1646
1647 size_t counter = 0;
1648 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1649 0, subviewBegins, shiftedArg0, arg0, begins, counter);
1650 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1651 1, subviewBegins, shiftedArg1, arg1, begins, counter);
1652 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1653 2, subviewBegins, shiftedArg2, arg2, begins, counter);
1654 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1655 3, subviewBegins, shiftedArg3, arg3, begins, counter);
1656 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1657 4, subviewBegins, shiftedArg4, arg4, begins, counter);
1658 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1659 5, subviewBegins, shiftedArg5, arg5, begins, counter);
1660 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1661 6, subviewBegins, shiftedArg6, arg6, begins, counter);
1662 Kokkos::Experimental::Impl::map_arg_to_new_begin(
1663 7, subviewBegins, shiftedArg7, arg7, begins, counter);
1664
1665 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1666 typename Kokkos::Impl::ViewMapping<
1667 void /* deduce subview type from source view traits */
1668 ,
1669 ViewTraits<D, P...>, T0, T1, T2, T3, T4, T5, T6, T7>::type>::type
1670 offsetView(theSubview, subviewBegins);
1671
1672 return offsetView;
1673}
1674} // namespace Impl
1675
1676template <class D, class... P, class... Args>
1677KOKKOS_INLINE_FUNCTION
1678 typename Kokkos::Experimental::Impl::GetOffsetViewTypeFromViewType<
1679 typename Kokkos::Impl::ViewMapping<
1680 void /* deduce subview type from source view traits */
1681 ,
1682 ViewTraits<D, P...>, Args...>::type>::type
1683 subview(const OffsetView<D, P...>& src, Args... args) {
1684 static_assert(
1685 OffsetView<D, P...>::Rank == sizeof...(Args),
1686 "subview requires one argument for each source OffsetView rank");
1687
1688 return Kokkos::Experimental::Impl::subview_offset(src, args...);
1689}
1690
1691} // namespace Experimental
1692} // namespace Kokkos
1693//----------------------------------------------------------------------------
1694//----------------------------------------------------------------------------
1695
1696namespace Kokkos {
1697namespace Experimental {
1698template <class LT, class... LP, class RT, class... RP>
1699KOKKOS_INLINE_FUNCTION bool operator==(const OffsetView<LT, LP...>& lhs,
1700 const OffsetView<RT, RP...>& rhs) {
1701 // Same data, layout, dimensions
1702 using lhs_traits = ViewTraits<LT, LP...>;
1703 using rhs_traits = ViewTraits<RT, RP...>;
1704
1705 return std::is_same<typename lhs_traits::const_value_type,
1706 typename rhs_traits::const_value_type>::value &&
1707 std::is_same<typename lhs_traits::array_layout,
1708 typename rhs_traits::array_layout>::value &&
1709 std::is_same<typename lhs_traits::memory_space,
1710 typename rhs_traits::memory_space>::value &&
1711 unsigned(lhs_traits::rank) == unsigned(rhs_traits::rank) &&
1712 lhs.data() == rhs.data() && lhs.span() == rhs.span() &&
1713 lhs.extent(0) == rhs.extent(0) && lhs.extent(1) == rhs.extent(1) &&
1714 lhs.extent(2) == rhs.extent(2) && lhs.extent(3) == rhs.extent(3) &&
1715 lhs.extent(4) == rhs.extent(4) && lhs.extent(5) == rhs.extent(5) &&
1716 lhs.extent(6) == rhs.extent(6) && lhs.extent(7) == rhs.extent(7) &&
1717 lhs.begin(0) == rhs.begin(0) && lhs.begin(1) == rhs.begin(1) &&
1718 lhs.begin(2) == rhs.begin(2) && lhs.begin(3) == rhs.begin(3) &&
1719 lhs.begin(4) == rhs.begin(4) && lhs.begin(5) == rhs.begin(5) &&
1720 lhs.begin(6) == rhs.begin(6) && lhs.begin(7) == rhs.begin(7);
1721}
1722
1723template <class LT, class... LP, class RT, class... RP>
1724KOKKOS_INLINE_FUNCTION bool operator!=(const OffsetView<LT, LP...>& lhs,
1725 const OffsetView<RT, RP...>& rhs) {
1726 return !(operator==(lhs, rhs));
1727}
1728
1729template <class LT, class... LP, class RT, class... RP>
1730KOKKOS_INLINE_FUNCTION bool operator==(const View<LT, LP...>& lhs,
1731 const OffsetView<RT, RP...>& rhs) {
1732 // Same data, layout, dimensions
1733 using lhs_traits = ViewTraits<LT, LP...>;
1734 using rhs_traits = ViewTraits<RT, RP...>;
1735
1736 return std::is_same<typename lhs_traits::const_value_type,
1737 typename rhs_traits::const_value_type>::value &&
1738 std::is_same<typename lhs_traits::array_layout,
1739 typename rhs_traits::array_layout>::value &&
1740 std::is_same<typename lhs_traits::memory_space,
1741 typename rhs_traits::memory_space>::value &&
1742 unsigned(lhs_traits::rank) == unsigned(rhs_traits::rank) &&
1743 lhs.data() == rhs.data() && lhs.span() == rhs.span() &&
1744 lhs.extent(0) == rhs.extent(0) && lhs.extent(1) == rhs.extent(1) &&
1745 lhs.extent(2) == rhs.extent(2) && lhs.extent(3) == rhs.extent(3) &&
1746 lhs.extent(4) == rhs.extent(4) && lhs.extent(5) == rhs.extent(5) &&
1747 lhs.extent(6) == rhs.extent(6) && lhs.extent(7) == rhs.extent(7);
1748}
1749
1750template <class LT, class... LP, class RT, class... RP>
1751KOKKOS_INLINE_FUNCTION bool operator==(const OffsetView<LT, LP...>& lhs,
1752 const View<RT, RP...>& rhs) {
1753 return rhs == lhs;
1754}
1755
1756} // namespace Experimental
1757} /* namespace Kokkos */
1758
1759//----------------------------------------------------------------------------
1760//----------------------------------------------------------------------------
1761
1762namespace Kokkos {
1763
1764template <class DT, class... DP>
1765inline void deep_copy(
1766 const Experimental::OffsetView<DT, DP...>& dst,
1767 typename ViewTraits<DT, DP...>::const_value_type& value,
1768 std::enable_if_t<std::is_same<typename ViewTraits<DT, DP...>::specialize,
1769 void>::value>* = nullptr) {
1770 static_assert(
1771 std::is_same<typename ViewTraits<DT, DP...>::non_const_value_type,
1772 typename ViewTraits<DT, DP...>::value_type>::value,
1773 "deep_copy requires non-const type");
1774
1775 auto dstView = dst.view();
1776 Kokkos::deep_copy(dstView, value);
1777}
1778
1779template <class DT, class... DP, class ST, class... SP>
1780inline void deep_copy(
1781 const Experimental::OffsetView<DT, DP...>& dst,
1782 const Experimental::OffsetView<ST, SP...>& value,
1783 std::enable_if_t<std::is_same<typename ViewTraits<DT, DP...>::specialize,
1784 void>::value>* = nullptr) {
1785 static_assert(
1786 std::is_same<typename ViewTraits<DT, DP...>::value_type,
1787 typename ViewTraits<ST, SP...>::non_const_value_type>::value,
1788 "deep_copy requires matching non-const destination type");
1789
1790 auto dstView = dst.view();
1791 Kokkos::deep_copy(dstView, value.view());
1792}
1793template <class DT, class... DP, class ST, class... SP>
1794inline void deep_copy(
1795 const Experimental::OffsetView<DT, DP...>& dst,
1796 const View<ST, SP...>& value,
1797 std::enable_if_t<std::is_same<typename ViewTraits<DT, DP...>::specialize,
1798 void>::value>* = nullptr) {
1799 static_assert(
1800 std::is_same<typename ViewTraits<DT, DP...>::value_type,
1801 typename ViewTraits<ST, SP...>::non_const_value_type>::value,
1802 "deep_copy requires matching non-const destination type");
1803
1804 auto dstView = dst.view();
1805 Kokkos::deep_copy(dstView, value);
1806}
1807
1808template <class DT, class... DP, class ST, class... SP>
1809inline void deep_copy(
1810 const View<DT, DP...>& dst,
1811 const Experimental::OffsetView<ST, SP...>& value,
1812 std::enable_if_t<std::is_same<typename ViewTraits<DT, DP...>::specialize,
1813 void>::value>* = nullptr) {
1814 static_assert(
1815 std::is_same<typename ViewTraits<DT, DP...>::value_type,
1816 typename ViewTraits<ST, SP...>::non_const_value_type>::value,
1817 "deep_copy requires matching non-const destination type");
1818
1819 Kokkos::deep_copy(dst, value.view());
1820}
1821
1822namespace Impl {
1823
1824// Deduce Mirror Types
1825template <class Space, class T, class... P>
1826struct MirrorOffsetViewType {
1827 // The incoming view_type
1828 using src_view_type = typename Kokkos::Experimental::OffsetView<T, P...>;
1829 // The memory space for the mirror view
1830 using memory_space = typename Space::memory_space;
1831 // Check whether it is the same memory space
1832 enum {
1833 is_same_memspace =
1834 std::is_same<memory_space, typename src_view_type::memory_space>::value
1835 };
1836 // The array_layout
1837 using array_layout = typename src_view_type::array_layout;
1838 // The data type (we probably want it non-const since otherwise we can't even
1839 // deep_copy to it.)
1840 using data_type = typename src_view_type::non_const_data_type;
1841 // The destination view type if it is not the same memory space
1842 using dest_view_type =
1843 Kokkos::Experimental::OffsetView<data_type, array_layout, Space>;
1844 // If it is the same memory_space return the existing view_type
1845 // This will also keep the unmanaged trait if necessary
1846 using view_type =
1847 std::conditional_t<is_same_memspace, src_view_type, dest_view_type>;
1848};
1849
1850template <class Space, class T, class... P>
1851struct MirrorOffsetType {
1852 // The incoming view_type
1853 using src_view_type = typename Kokkos::Experimental::OffsetView<T, P...>;
1854 // The memory space for the mirror view
1855 using memory_space = typename Space::memory_space;
1856 // Check whether it is the same memory space
1857 enum {
1858 is_same_memspace =
1859 std::is_same<memory_space, typename src_view_type::memory_space>::value
1860 };
1861 // The array_layout
1862 using array_layout = typename src_view_type::array_layout;
1863 // The data type (we probably want it non-const since otherwise we can't even
1864 // deep_copy to it.)
1865 using data_type = typename src_view_type::non_const_data_type;
1866 // The destination view type if it is not the same memory space
1867 using view_type =
1868 Kokkos::Experimental::OffsetView<data_type, array_layout, Space>;
1869};
1870
1871} // namespace Impl
1872
1873namespace Impl {
1874template <class T, class... P, class... ViewCtorArgs>
1875inline std::enable_if_t<
1876 !Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space,
1877 typename Kokkos::Experimental::OffsetView<T, P...>::HostMirror>
1878create_mirror(const Kokkos::Experimental::OffsetView<T, P...>& src,
1879 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
1880 return typename Kokkos::Experimental::OffsetView<T, P...>::HostMirror(
1881 Kokkos::create_mirror(arg_prop, src.view()), src.begins());
1882}
1883
1884template <class T, class... P, class... ViewCtorArgs,
1885 class = std::enable_if_t<
1886 Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space>>
1887inline auto create_mirror(const Kokkos::Experimental::OffsetView<T, P...>& src,
1888 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
1889 using alloc_prop_input = Impl::ViewCtorProp<ViewCtorArgs...>;
1890 using Space = typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space;
1891
1892 static_assert(
1893 !alloc_prop_input::has_label,
1894 "The view constructor arguments passed to Kokkos::create_mirror "
1895 "must not include a label!");
1896 static_assert(
1897 !alloc_prop_input::has_pointer,
1898 "The view constructor arguments passed to Kokkos::create_mirror must "
1899 "not include a pointer!");
1900 static_assert(
1901 !alloc_prop_input::allow_padding,
1902 "The view constructor arguments passed to Kokkos::create_mirror must "
1903 "not explicitly allow padding!");
1904
1905 auto prop_copy = Impl::with_properties_if_unset(
1906 arg_prop, std::string(src.label()).append("_mirror"));
1907
1908 return typename Kokkos::Impl::MirrorOffsetType<Space, T, P...>::view_type(
1909 prop_copy, src.layout(),
1910 {src.begin(0), src.begin(1), src.begin(2), src.begin(3), src.begin(4),
1911 src.begin(5), src.begin(6), src.begin(7)});
1912}
1913} // namespace Impl
1914
1915// Create a mirror in host space
1916template <class T, class... P>
1917inline auto create_mirror(
1918 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1919 return Impl::create_mirror(src, Impl::ViewCtorProp<>{});
1920}
1921
1922template <class T, class... P>
1923inline auto create_mirror(
1924 Kokkos::Impl::WithoutInitializing_t wi,
1925 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1926 return Impl::create_mirror(src, Kokkos::view_alloc(wi));
1927}
1928
1929// Create a mirror in a new space
1930template <class Space, class T, class... P,
1931 typename Enable = std::enable_if_t<Kokkos::is_space<Space>::value>>
1932inline auto create_mirror(
1933 const Space&, const Kokkos::Experimental::OffsetView<T, P...>& src) {
1934 return Impl::create_mirror(
1935 src, Kokkos::view_alloc(typename Space::memory_space{}));
1936}
1937
1938template <class Space, class T, class... P>
1939typename Kokkos::Impl::MirrorOffsetType<Space, T, P...>::view_type
1940create_mirror(Kokkos::Impl::WithoutInitializing_t wi, const Space&,
1941 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1942 return Impl::create_mirror(
1943 src, Kokkos::view_alloc(typename Space::memory_space{}, wi));
1944}
1945
1946template <class T, class... P, class... ViewCtorArgs>
1947inline auto create_mirror(
1948 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
1949 const Kokkos::Experimental::OffsetView<T, P...>& src) {
1950 return Impl::create_mirror(src, arg_prop);
1951}
1952
1953namespace Impl {
1954template <class T, class... P, class... ViewCtorArgs>
1955inline std::enable_if_t<
1956 !Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space &&
1957 (std::is_same<
1958 typename Kokkos::Experimental::OffsetView<T, P...>::memory_space,
1959 typename Kokkos::Experimental::OffsetView<
1960 T, P...>::HostMirror::memory_space>::value &&
1961 std::is_same<
1962 typename Kokkos::Experimental::OffsetView<T, P...>::data_type,
1963 typename Kokkos::Experimental::OffsetView<
1964 T, P...>::HostMirror::data_type>::value),
1965 typename Kokkos::Experimental::OffsetView<T, P...>::HostMirror>
1966create_mirror_view(const Kokkos::Experimental::OffsetView<T, P...>& src,
1967 const Impl::ViewCtorProp<ViewCtorArgs...>&) {
1968 return src;
1969}
1970
1971template <class T, class... P, class... ViewCtorArgs>
1972inline std::enable_if_t<
1973 !Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space &&
1974 !(std::is_same<
1975 typename Kokkos::Experimental::OffsetView<T, P...>::memory_space,
1976 typename Kokkos::Experimental::OffsetView<
1977 T, P...>::HostMirror::memory_space>::value &&
1978 std::is_same<
1979 typename Kokkos::Experimental::OffsetView<T, P...>::data_type,
1980 typename Kokkos::Experimental::OffsetView<
1981 T, P...>::HostMirror::data_type>::value),
1982 typename Kokkos::Experimental::OffsetView<T, P...>::HostMirror>
1983create_mirror_view(const Kokkos::Experimental::OffsetView<T, P...>& src,
1984 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
1985 return Kokkos::create_mirror(arg_prop, src);
1986}
1987
1988template <class T, class... P, class... ViewCtorArgs,
1989 class = std::enable_if_t<
1990 Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space>>
1991std::enable_if_t<Impl::MirrorOffsetViewType<
1992 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space,
1993 T, P...>::is_same_memspace,
1994 typename Impl::MirrorOffsetViewType<
1995 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space,
1996 T, P...>::view_type>
1997create_mirror_view(const Kokkos::Experimental::OffsetView<T, P...>& src,
1998 const Impl::ViewCtorProp<ViewCtorArgs...>&) {
1999 return src;
2000}
2001
2002template <class T, class... P, class... ViewCtorArgs,
2003 class = std::enable_if_t<
2004 Impl::ViewCtorProp<ViewCtorArgs...>::has_memory_space>>
2005std::enable_if_t<!Impl::MirrorOffsetViewType<
2006 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space,
2007 T, P...>::is_same_memspace,
2008 typename Impl::MirrorOffsetViewType<
2009 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space,
2010 T, P...>::view_type>
2011create_mirror_view(const Kokkos::Experimental::OffsetView<T, P...>& src,
2012 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop) {
2013 return Kokkos::Impl::create_mirror(src, arg_prop);
2014}
2015} // namespace Impl
2016
2017// Create a mirror view in host space
2018template <class T, class... P>
2019inline auto create_mirror_view(
2020 const typename Kokkos::Experimental::OffsetView<T, P...>& src) {
2021 return Impl::create_mirror_view(src, Impl::ViewCtorProp<>{});
2022}
2023
2024template <class T, class... P>
2025inline auto create_mirror_view(
2026 Kokkos::Impl::WithoutInitializing_t wi,
2027 const typename Kokkos::Experimental::OffsetView<T, P...>& src) {
2028 return Impl::create_mirror_view(src, Kokkos::view_alloc(wi));
2029}
2030
2031// Create a mirror view in a new space
2032template <class Space, class T, class... P,
2033 typename Enable = std::enable_if_t<Kokkos::is_space<Space>::value>>
2034inline auto create_mirror_view(
2035 const Space&, const Kokkos::Experimental::OffsetView<T, P...>& src) {
2036 return Impl::create_mirror_view(
2037 src, Kokkos::view_alloc(typename Space::memory_space{}));
2038}
2039
2040template <class Space, class T, class... P>
2041inline auto create_mirror_view(
2042 Kokkos::Impl::WithoutInitializing_t wi, const Space&,
2043 const Kokkos::Experimental::OffsetView<T, P...>& src) {
2044 return Impl::create_mirror_view(
2045 src, Kokkos::view_alloc(typename Space::memory_space{}, wi));
2046}
2047
2048template <class T, class... P, class... ViewCtorArgs>
2049inline auto create_mirror_view(
2050 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
2051 const Kokkos::Experimental::OffsetView<T, P...>& src) {
2052 return Impl::create_mirror_view(src, arg_prop);
2053}
2054
2055// Create a mirror view and deep_copy in a new space
2056template <class... ViewCtorArgs, class T, class... P>
2057typename Kokkos::Impl::MirrorOffsetViewType<
2058 typename Impl::ViewCtorProp<ViewCtorArgs...>::memory_space, T,
2059 P...>::view_type
2060create_mirror_view_and_copy(
2061 const Impl::ViewCtorProp<ViewCtorArgs...>& arg_prop,
2062 const Kokkos::Experimental::OffsetView<T, P...>& src) {
2063 return {create_mirror_view_and_copy(arg_prop, src.view()), src.begins()};
2064}
2065
2066template <class Space, class T, class... P>
2067typename Kokkos::Impl::MirrorOffsetViewType<Space, T, P...>::view_type
2068create_mirror_view_and_copy(
2069 const Space& space, const Kokkos::Experimental::OffsetView<T, P...>& src,
2070 std::string const& name = "") {
2071 return {create_mirror_view_and_copy(space, src.view(), name), src.begins()};
2072}
2073} /* namespace Kokkos */
2074
2075//----------------------------------------------------------------------------
2076//----------------------------------------------------------------------------
2077
2078#ifdef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_OFFSETVIEW
2079#undef KOKKOS_IMPL_PUBLIC_INCLUDE
2080#undef KOKKOS_IMPL_PUBLIC_INCLUDE_NOTDEFINED_OFFSETVIEW
2081#endif
2082#endif /* KOKKOS_OFFSETVIEW_HPP_ */
View
Derived from the C++17 'std::array'. Dropping the iterator interface.
Replacement for std::pair that works on CUDA devices.
Definition: Kokkos_Pair.hpp:43
first_type first
The first element of the pair.
Definition: Kokkos_Pair.hpp:50
second_type second
The second element of the pair.
Definition: Kokkos_Pair.hpp:52