Line data Source code
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_IMPL_PUBLIC_INCLUDE
18 : #include <Kokkos_Macros.hpp>
19 : static_assert(false,
20 : "Including non-public Kokkos header files is not allowed.");
21 : #endif
22 : #ifndef KOKKOS_VIEWLEGACY_HPP
23 : #define KOKKOS_VIEWLEGACY_HPP
24 :
25 : #include <type_traits>
26 : #include <string>
27 : #include <algorithm>
28 : #include <initializer_list>
29 :
30 : #include <Kokkos_Core_fwd.hpp>
31 : #include <Kokkos_HostSpace.hpp>
32 : #include <Kokkos_MemoryTraits.hpp>
33 : #include <Kokkos_ExecPolicy.hpp>
34 : #include <View/Hooks/Kokkos_ViewHooks.hpp>
35 :
36 : #include <impl/Kokkos_Tools.hpp>
37 : #include <impl/Kokkos_Utilities.hpp>
38 :
39 : #ifdef KOKKOS_ENABLE_IMPL_MDSPAN
40 : #include <View/MDSpan/Kokkos_MDSpan_Extents.hpp>
41 : #include <View/MDSpan/Kokkos_MDSpan_Layout.hpp>
42 : #include <View/MDSpan/Kokkos_MDSpan_Accessor.hpp>
43 : #endif
44 : #include <Kokkos_MinMax.hpp>
45 :
46 : #include <View/Kokkos_ViewTraits.hpp>
47 :
48 : //----------------------------------------------------------------------------
49 : //----------------------------------------------------------------------------
50 :
51 : namespace Kokkos {
52 :
53 : /** \class View
54 : * \brief View to an array of data.
55 : *
56 : * A View represents an array of one or more dimensions.
57 : * For details, please refer to Kokkos' tutorial materials.
58 : *
59 : * \section Kokkos_View_TemplateParameters Template parameters
60 : *
61 : * This class has both required and optional template parameters. The
62 : * \c DataType parameter must always be provided, and must always be
63 : * first. The parameters \c Arg1Type, \c Arg2Type, and \c Arg3Type are
64 : * placeholders for different template parameters. The default value
65 : * of the fifth template parameter \c Specialize suffices for most use
66 : * cases. When explaining the template parameters, we won't refer to
67 : * \c Arg1Type, \c Arg2Type, and \c Arg3Type; instead, we will refer
68 : * to the valid categories of template parameters, in whatever order
69 : * they may occur.
70 : *
71 : * Valid ways in which template arguments may be specified:
72 : * - View< DataType >
73 : * - View< DataType , Layout >
74 : * - View< DataType , Layout , Space >
75 : * - View< DataType , Layout , Space , MemoryTraits >
76 : * - View< DataType , Space >
77 : * - View< DataType , Space , MemoryTraits >
78 : * - View< DataType , MemoryTraits >
79 : *
80 : * \tparam DataType (required) This indicates both the type of each
81 : * entry of the array, and the combination of compile-time and
82 : * run-time array dimension(s). For example, <tt>double*</tt>
83 : * indicates a one-dimensional array of \c double with run-time
84 : * dimension, and <tt>int*[3]</tt> a two-dimensional array of \c int
85 : * with run-time first dimension and compile-time second dimension
86 : * (of 3). In general, the run-time dimensions (if any) must go
87 : * first, followed by zero or more compile-time dimensions. For
88 : * more examples, please refer to the tutorial materials.
89 : *
90 : * \tparam Space (required) The memory space.
91 : *
92 : * \tparam Layout (optional) The array's layout in memory. For
93 : * example, LayoutLeft indicates a column-major (Fortran style)
94 : * layout, and LayoutRight a row-major (C style) layout. If not
95 : * specified, this defaults to the preferred layout for the
96 : * <tt>Space</tt>.
97 : *
98 : * \tparam MemoryTraits (optional) Assertion of the user's intended
99 : * access behavior. For example, RandomAccess indicates read-only
100 : * access with limited spatial locality, and Unmanaged lets users
101 : * wrap externally allocated memory in a View without automatic
102 : * deallocation.
103 : *
104 : * \section Kokkos_View_MT MemoryTraits discussion
105 : *
106 : * \subsection Kokkos_View_MT_Interp MemoryTraits interpretation depends on
107 : * Space
108 : *
109 : * Some \c MemoryTraits options may have different interpretations for
110 : * different \c Space types. For example, with the Cuda device,
111 : * \c RandomAccess tells Kokkos to fetch the data through the texture
112 : * cache, whereas the non-GPU devices have no such hardware construct.
113 : *
114 : * \subsection Kokkos_View_MT_PrefUse Preferred use of MemoryTraits
115 : *
116 : * Users should defer applying the optional \c MemoryTraits parameter
117 : * until the point at which they actually plan to rely on it in a
118 : * computational kernel. This minimizes the number of template
119 : * parameters exposed in their code, which reduces the cost of
120 : * compilation. Users may always assign a View without specified
121 : * \c MemoryTraits to a compatible View with that specification.
122 : * For example:
123 : * \code
124 : * // Pass in the simplest types of View possible.
125 : * void
126 : * doSomething (View<double*, Cuda> out,
127 : * View<const double*, Cuda> in)
128 : * {
129 : * // Assign the "generic" View in to a RandomAccess View in_rr.
130 : * // Note that RandomAccess View objects must have const data.
131 : * View<const double*, Cuda, RandomAccess> in_rr = in;
132 : * // ... do something with in_rr and out ...
133 : * }
134 : * \endcode
135 : */
136 :
137 : } // namespace Kokkos
138 :
139 : namespace Kokkos {
140 :
141 : template <class T1, class T2>
142 : struct is_always_assignable_impl;
143 :
144 : template <class... ViewTDst, class... ViewTSrc>
145 : struct is_always_assignable_impl<Kokkos::View<ViewTDst...>,
146 : Kokkos::View<ViewTSrc...>> {
147 : using mapping_type = Kokkos::Impl::ViewMapping<
148 : typename Kokkos::View<ViewTDst...>::traits,
149 : typename Kokkos::View<ViewTSrc...>::traits,
150 : typename Kokkos::View<ViewTDst...>::traits::specialize>;
151 :
152 : constexpr static bool value =
153 : mapping_type::is_assignable &&
154 : static_cast<int>(Kokkos::View<ViewTDst...>::rank_dynamic) >=
155 : static_cast<int>(Kokkos::View<ViewTSrc...>::rank_dynamic);
156 : };
157 :
158 : template <class View1, class View2>
159 : using is_always_assignable = is_always_assignable_impl<
160 : std::remove_reference_t<View1>,
161 : std::remove_const_t<std::remove_reference_t<View2>>>;
162 :
163 : template <class T1, class T2>
164 : inline constexpr bool is_always_assignable_v =
165 : is_always_assignable<T1, T2>::value;
166 :
167 : template <class... ViewTDst, class... ViewTSrc>
168 : constexpr bool is_assignable(const Kokkos::View<ViewTDst...>& dst,
169 : const Kokkos::View<ViewTSrc...>& src) {
170 : using DstTraits = typename Kokkos::View<ViewTDst...>::traits;
171 : using SrcTraits = typename Kokkos::View<ViewTSrc...>::traits;
172 : using mapping_type =
173 : Kokkos::Impl::ViewMapping<DstTraits, SrcTraits,
174 : typename DstTraits::specialize>;
175 :
176 : return is_always_assignable_v<Kokkos::View<ViewTDst...>,
177 : Kokkos::View<ViewTSrc...>> ||
178 : (mapping_type::is_assignable &&
179 : ((DstTraits::dimension::rank_dynamic >= 1) ||
180 : (dst.static_extent(0) == src.extent(0))) &&
181 : ((DstTraits::dimension::rank_dynamic >= 2) ||
182 : (dst.static_extent(1) == src.extent(1))) &&
183 : ((DstTraits::dimension::rank_dynamic >= 3) ||
184 : (dst.static_extent(2) == src.extent(2))) &&
185 : ((DstTraits::dimension::rank_dynamic >= 4) ||
186 : (dst.static_extent(3) == src.extent(3))) &&
187 : ((DstTraits::dimension::rank_dynamic >= 5) ||
188 : (dst.static_extent(4) == src.extent(4))) &&
189 : ((DstTraits::dimension::rank_dynamic >= 6) ||
190 : (dst.static_extent(5) == src.extent(5))) &&
191 : ((DstTraits::dimension::rank_dynamic >= 7) ||
192 : (dst.static_extent(6) == src.extent(6))) &&
193 : ((DstTraits::dimension::rank_dynamic >= 8) ||
194 : (dst.static_extent(7) == src.extent(7))));
195 : }
196 :
197 : } /* namespace Kokkos */
198 :
199 : //----------------------------------------------------------------------------
200 : //----------------------------------------------------------------------------
201 :
202 : #include <View/Kokkos_ViewMapping.hpp>
203 :
204 : //----------------------------------------------------------------------------
205 : //----------------------------------------------------------------------------
206 :
207 : namespace Kokkos {
208 :
209 : template <class DataType, class... Properties>
210 : class View;
211 :
212 : template <class>
213 : struct is_view : public std::false_type {};
214 :
215 : template <class D, class... P>
216 : struct is_view<View<D, P...>> : public std::true_type {};
217 :
218 : template <class D, class... P>
219 : struct is_view<const View<D, P...>> : public std::true_type {};
220 :
221 : template <class T>
222 : inline constexpr bool is_view_v = is_view<T>::value;
223 :
224 : template <class DataType, class... Properties>
225 : class View : public ViewTraits<DataType, Properties...> {
226 : private:
227 : template <class, class...>
228 : friend class View;
229 : template <class, class...>
230 : friend class Kokkos::Impl::ViewMapping;
231 :
232 : using view_tracker_type = Kokkos::Impl::ViewTracker<View>;
233 :
234 : public:
235 : using traits = ViewTraits<DataType, Properties...>;
236 :
237 : private:
238 : using map_type =
239 : Kokkos::Impl::ViewMapping<traits, typename traits::specialize>;
240 : template <typename V>
241 : friend struct Kokkos::Impl::ViewTracker;
242 : using hooks_policy = typename traits::hooks_policy;
243 :
244 : view_tracker_type m_track;
245 : map_type m_map;
246 :
247 : public:
248 : //----------------------------------------
249 : /** \brief Compatible view of array of scalar types */
250 : using array_type =
251 : View<typename traits::scalar_array_type, typename traits::array_layout,
252 : typename traits::device_type, typename traits::hooks_policy,
253 : typename traits::memory_traits>;
254 :
255 : /** \brief Compatible view of const data type */
256 : using const_type =
257 : View<typename traits::const_data_type, typename traits::array_layout,
258 : typename traits::device_type, typename traits::hooks_policy,
259 : typename traits::memory_traits>;
260 :
261 : /** \brief Compatible view of non-const data type */
262 : using non_const_type =
263 : View<typename traits::non_const_data_type, typename traits::array_layout,
264 : typename traits::device_type, typename traits::hooks_policy,
265 : typename traits::memory_traits>;
266 :
267 : /** \brief Compatible host mirror view */
268 : using host_mirror_type =
269 : View<typename traits::non_const_data_type, typename traits::array_layout,
270 : Device<DefaultHostExecutionSpace,
271 : typename traits::host_mirror_space::memory_space>,
272 : typename traits::hooks_policy>;
273 :
274 : /** \brief Compatible host mirror view */
275 : using HostMirror = host_mirror_type;
276 :
277 : /** \brief Unified types */
278 : using uniform_type = typename Impl::ViewUniformType<View, 0>::type;
279 : using uniform_const_type =
280 : typename Impl::ViewUniformType<View, 0>::const_type;
281 : using uniform_runtime_type =
282 : typename Impl::ViewUniformType<View, 0>::runtime_type;
283 : using uniform_runtime_const_type =
284 : typename Impl::ViewUniformType<View, 0>::runtime_const_type;
285 : using uniform_nomemspace_type =
286 : typename Impl::ViewUniformType<View, 0>::nomemspace_type;
287 : using uniform_const_nomemspace_type =
288 : typename Impl::ViewUniformType<View, 0>::const_nomemspace_type;
289 : using uniform_runtime_nomemspace_type =
290 : typename Impl::ViewUniformType<View, 0>::runtime_nomemspace_type;
291 : using uniform_runtime_const_nomemspace_type =
292 : typename Impl::ViewUniformType<View, 0>::runtime_const_nomemspace_type;
293 :
294 : using reference_type = typename map_type::reference_type;
295 : using pointer_type = typename map_type::pointer_type;
296 :
297 : // Typedefs from mdspan
298 : // using extents_type -> not applicable
299 : // Defining layout_type here made MSVC+CUDA fail
300 : // using layout_type = typename traits::array_layout;
301 : // using accessor_type -> not applicable
302 : // using mapping_type -> not applicable
303 : using element_type = typename traits::value_type;
304 : // using value_type -> conflicts with traits::value_type
305 : using index_type = typename traits::memory_space::size_type;
306 : // using size_type -> already from traits::size_type; where it is
307 : // memory_space::size_type
308 : using rank_type = size_t;
309 : using data_handle_type = pointer_type;
310 : using reference = reference_type;
311 :
312 : //----------------------------------------
313 : // Domain rank and extents
314 :
315 : static constexpr Impl::integral_constant<size_t, traits::dimension::rank>
316 : rank = {};
317 : static constexpr Impl::integral_constant<size_t,
318 : traits::dimension::rank_dynamic>
319 : rank_dynamic = {};
320 : #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
321 : enum {Rank KOKKOS_DEPRECATED_WITH_COMMENT("Use rank instead.") =
322 : map_type::Rank};
323 : #endif
324 :
325 : template <typename iType>
326 : KOKKOS_INLINE_FUNCTION constexpr std::enable_if_t<std::is_integral_v<iType>,
327 : size_t>
328 : extent(const iType& r) const noexcept {
329 : return m_map.extent(r);
330 : }
331 :
332 : static KOKKOS_INLINE_FUNCTION constexpr size_t static_extent(
333 : const unsigned r) noexcept {
334 : return map_type::static_extent(r);
335 : }
336 :
337 : template <typename iType>
338 : KOKKOS_INLINE_FUNCTION constexpr std::enable_if_t<std::is_integral_v<iType>,
339 : int>
340 : extent_int(const iType& r) const noexcept {
341 : return static_cast<int>(m_map.extent(r));
342 : }
343 :
344 : KOKKOS_INLINE_FUNCTION constexpr typename traits::array_layout layout()
345 : const {
346 : return m_map.layout();
347 : }
348 :
349 : //----------------------------------------
350 : /* Deprecate all 'dimension' functions in favor of
351 : * ISO/C++ vocabulary 'extent'.
352 : */
353 :
354 1378872 : KOKKOS_INLINE_FUNCTION constexpr size_t size() const {
355 1378872 : return m_map.dimension_0() * m_map.dimension_1() * m_map.dimension_2() *
356 : m_map.dimension_3() * m_map.dimension_4() * m_map.dimension_5() *
357 : m_map.dimension_6() * m_map.dimension_7();
358 : }
359 :
360 : KOKKOS_INLINE_FUNCTION constexpr size_t stride_0() const {
361 : return m_map.stride_0();
362 : }
363 : KOKKOS_INLINE_FUNCTION constexpr size_t stride_1() const {
364 : return m_map.stride_1();
365 : }
366 : KOKKOS_INLINE_FUNCTION constexpr size_t stride_2() const {
367 : return m_map.stride_2();
368 : }
369 : KOKKOS_INLINE_FUNCTION constexpr size_t stride_3() const {
370 : return m_map.stride_3();
371 : }
372 : KOKKOS_INLINE_FUNCTION constexpr size_t stride_4() const {
373 : return m_map.stride_4();
374 : }
375 : KOKKOS_INLINE_FUNCTION constexpr size_t stride_5() const {
376 : return m_map.stride_5();
377 : }
378 : KOKKOS_INLINE_FUNCTION constexpr size_t stride_6() const {
379 : return m_map.stride_6();
380 : }
381 : KOKKOS_INLINE_FUNCTION constexpr size_t stride_7() const {
382 : return m_map.stride_7();
383 : }
384 :
385 : template <typename iType>
386 : KOKKOS_INLINE_FUNCTION constexpr std::enable_if_t<std::is_integral_v<iType>,
387 : size_t>
388 : stride(iType r) const {
389 : return (
390 : r == 0
391 : ? m_map.stride_0()
392 : : (r == 1
393 : ? m_map.stride_1()
394 : : (r == 2
395 : ? m_map.stride_2()
396 : : (r == 3
397 : ? m_map.stride_3()
398 : : (r == 4
399 : ? m_map.stride_4()
400 : : (r == 5
401 : ? m_map.stride_5()
402 : : (r == 6
403 : ? m_map.stride_6()
404 : : m_map.stride_7())))))));
405 : }
406 :
407 : template <typename iType>
408 : KOKKOS_INLINE_FUNCTION void stride(iType* const s) const {
409 : m_map.stride(s);
410 : }
411 :
412 : //----------------------------------------
413 : // Range span is the span which contains all members.
414 :
415 : enum {
416 : reference_type_is_lvalue_reference =
417 : std::is_lvalue_reference_v<reference_type>
418 : };
419 :
420 : KOKKOS_INLINE_FUNCTION constexpr size_t span() const { return m_map.span(); }
421 : KOKKOS_INLINE_FUNCTION bool span_is_contiguous() const {
422 : return m_map.span_is_contiguous();
423 : }
424 : KOKKOS_INLINE_FUNCTION constexpr bool is_allocated() const {
425 : return m_map.data() != nullptr;
426 : }
427 : KOKKOS_INLINE_FUNCTION constexpr pointer_type data() const {
428 : return m_map.data();
429 : }
430 :
431 : //----------------------------------------
432 : // Allow specializations to query their specialized map
433 :
434 : KOKKOS_INLINE_FUNCTION
435 : const Kokkos::Impl::ViewMapping<traits, typename traits::specialize>&
436 : impl_map() const {
437 : return m_map;
438 : }
439 : KOKKOS_INLINE_FUNCTION
440 : const Kokkos::Impl::SharedAllocationTracker& impl_track() const {
441 : return m_track.m_tracker;
442 : }
443 : //----------------------------------------
444 :
445 : private:
446 : static constexpr bool is_layout_left =
447 : std::is_same_v<typename traits::array_layout, Kokkos::LayoutLeft>;
448 :
449 : static constexpr bool is_layout_right =
450 : std::is_same_v<typename traits::array_layout, Kokkos::LayoutRight>;
451 :
452 : static constexpr bool is_layout_stride =
453 : std::is_same_v<typename traits::array_layout, Kokkos::LayoutStride>;
454 :
455 : static constexpr bool is_default_map =
456 : std::is_void_v<typename traits::specialize> &&
457 : (is_layout_left || is_layout_right || is_layout_stride);
458 :
459 : #if defined(KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK)
460 :
461 : #define KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(...) \
462 : Kokkos::Impl::runtime_check_memory_access_violation< \
463 : typename traits::memory_space>( \
464 : "Kokkos::View ERROR: attempt to access inaccessible memory space", \
465 : __VA_ARGS__); \
466 : Kokkos::Impl::view_verify_operator_bounds<typename traits::memory_space>( \
467 : __VA_ARGS__);
468 :
469 : #else
470 :
471 : #define KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(...) \
472 : Kokkos::Impl::runtime_check_memory_access_violation< \
473 : typename traits::memory_space>( \
474 : "Kokkos::View ERROR: attempt to access inaccessible memory space", \
475 : __VA_ARGS__);
476 :
477 : #endif
478 :
479 : template <typename... Is>
480 : static KOKKOS_FUNCTION void check_access_member_function_valid_args(Is...) {
481 : static_assert(rank <= sizeof...(Is));
482 : static_assert(sizeof...(Is) <= 8);
483 : static_assert(Kokkos::Impl::are_integral<Is...>::value);
484 : }
485 :
486 : template <typename... Is>
487 35966367 : static KOKKOS_FUNCTION void check_operator_parens_valid_args(Is...) {
488 : static_assert(rank == sizeof...(Is));
489 : static_assert(Kokkos::Impl::are_integral<Is...>::value);
490 35966367 : }
491 :
492 : public:
493 : //------------------------------
494 : // Rank 1 default map operator()
495 :
496 : template <typename I0>
497 : KOKKOS_FORCEINLINE_FUNCTION
498 : std::enable_if_t<(Kokkos::Impl::always_true<I0>::value && //
499 : (1 == rank) && is_default_map && !is_layout_stride),
500 : reference_type>
501 20798117 : operator()(I0 i0) const {
502 17985781 : check_operator_parens_valid_args(i0);
503 20798117 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0)
504 19590436 : return m_map.m_impl_handle[i0];
505 : }
506 :
507 : template <typename I0>
508 : KOKKOS_FORCEINLINE_FUNCTION
509 : std::enable_if_t<(Kokkos::Impl::always_true<I0>::value && //
510 : (1 == rank) && is_default_map && is_layout_stride),
511 : reference_type>
512 : operator()(I0 i0) const {
513 : check_operator_parens_valid_args(i0);
514 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0)
515 : return m_map.m_impl_handle[m_map.m_impl_offset.m_stride.S0 * i0];
516 : }
517 :
518 : //------------------------------
519 : // Rank 1 operator[]
520 :
521 : template <typename I0>
522 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
523 : ((1 == rank) && Kokkos::Impl::are_integral<I0>::value && !is_default_map),
524 : reference_type>
525 : operator[](I0 i0) const {
526 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0)
527 : return m_map.reference(i0);
528 : }
529 :
530 : template <typename I0>
531 : KOKKOS_FORCEINLINE_FUNCTION
532 : std::enable_if_t<((1 == rank) && Kokkos::Impl::are_integral<I0>::value &&
533 : is_default_map && !is_layout_stride),
534 : reference_type>
535 : operator[](I0 i0) const {
536 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0)
537 : return m_map.m_impl_handle[i0];
538 : }
539 :
540 : template <typename I0>
541 : KOKKOS_FORCEINLINE_FUNCTION
542 : std::enable_if_t<((1 == rank) && Kokkos::Impl::are_integral<I0>::value &&
543 : is_default_map && is_layout_stride),
544 : reference_type>
545 : operator[](I0 i0) const {
546 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0)
547 : return m_map.m_impl_handle[m_map.m_impl_offset.m_stride.S0 * i0];
548 : }
549 :
550 : //------------------------------
551 : // Rank 2 default map operator()
552 :
553 : template <typename I0, typename I1>
554 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
555 : (Kokkos::Impl::always_true<I0, I1>::value && //
556 : (2 == rank) && is_default_map &&
557 : (is_layout_left || is_layout_right || is_layout_stride)),
558 : reference_type>
559 17980586 : operator()(I0 i0, I1 i1) const {
560 17980586 : check_operator_parens_valid_args(i0, i1);
561 17980586 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1)
562 : if constexpr (is_layout_left) {
563 : if constexpr (rank_dynamic == 0)
564 : return m_map.m_impl_handle[i0 + m_map.m_impl_offset.m_dim.N0 * i1];
565 : else
566 : return m_map.m_impl_handle[i0 + m_map.m_impl_offset.m_stride * i1];
567 : } else if constexpr (is_layout_right) {
568 : if constexpr (rank_dynamic == 0)
569 : return m_map.m_impl_handle[i1 + m_map.m_impl_offset.m_dim.N1 * i0];
570 : else
571 17980586 : return m_map.m_impl_handle[i1 + m_map.m_impl_offset.m_stride * i0];
572 : } else {
573 : static_assert(is_layout_stride);
574 : return m_map.m_impl_handle[i0 * m_map.m_impl_offset.m_stride.S0 +
575 : i1 * m_map.m_impl_offset.m_stride.S1];
576 : }
577 : }
578 :
579 : // Rank 0 -> 8 operator() except for rank-1 and rank-2 with default map which
580 : // have "inlined" versions above
581 :
582 : template <typename... Is>
583 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
584 : (Kokkos::Impl::always_true<Is...>::value && //
585 : (2 != rank) && (1 != rank) && (0 != rank) && is_default_map),
586 : reference_type>
587 : operator()(Is... indices) const {
588 : check_operator_parens_valid_args(indices...);
589 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, indices...)
590 : return m_map.m_impl_handle[m_map.m_impl_offset(indices...)];
591 : }
592 :
593 : template <typename... Is>
594 : KOKKOS_FORCEINLINE_FUNCTION
595 : std::enable_if_t<(Kokkos::Impl::always_true<Is...>::value && //
596 : ((0 == rank) || !is_default_map)),
597 : reference_type>
598 : operator()(Is... indices) const {
599 : check_operator_parens_valid_args(indices...);
600 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, indices...)
601 : return m_map.reference(indices...);
602 : }
603 :
604 : //------------------------------
605 : // Rank 0
606 :
607 : template <typename... Is>
608 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
609 : (Kokkos::Impl::always_true<Is...>::value && (0 == rank)), reference_type>
610 : access(Is... extra) const {
611 : check_access_member_function_valid_args(extra...);
612 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, extra...)
613 : return m_map.reference();
614 : }
615 :
616 : //------------------------------
617 : // Rank 1
618 :
619 : template <typename I0, typename... Is>
620 : KOKKOS_FORCEINLINE_FUNCTION
621 : std::enable_if_t<(Kokkos::Impl::always_true<I0, Is...>::value &&
622 : (1 == rank) && !is_default_map),
623 : reference_type>
624 : access(I0 i0, Is... extra) const {
625 : check_access_member_function_valid_args(i0, extra...);
626 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, extra...)
627 : return m_map.reference(i0);
628 : }
629 :
630 : template <typename I0, typename... Is>
631 : KOKKOS_FORCEINLINE_FUNCTION
632 : std::enable_if_t<(Kokkos::Impl::always_true<I0, Is...>::value &&
633 : (1 == rank) && is_default_map && !is_layout_stride),
634 : reference_type>
635 : access(I0 i0, Is... extra) const {
636 : check_access_member_function_valid_args(i0, extra...);
637 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, extra...)
638 : return m_map.m_impl_handle[i0];
639 : }
640 :
641 : template <typename I0, typename... Is>
642 : KOKKOS_FORCEINLINE_FUNCTION
643 : std::enable_if_t<(Kokkos::Impl::always_true<I0, Is...>::value &&
644 : (1 == rank) && is_default_map && is_layout_stride),
645 : reference_type>
646 : access(I0 i0, Is... extra) const {
647 : check_access_member_function_valid_args(i0, extra...);
648 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, extra...)
649 : return m_map.m_impl_handle[m_map.m_impl_offset.m_stride.S0 * i0];
650 : }
651 :
652 : //------------------------------
653 : // Rank 2
654 :
655 : template <typename I0, typename I1, typename... Is>
656 : KOKKOS_FORCEINLINE_FUNCTION
657 : std::enable_if_t<(Kokkos::Impl::always_true<I0, I1, Is...>::value &&
658 : (2 == rank) && !is_default_map),
659 : reference_type>
660 : access(I0 i0, I1 i1, Is... extra) const {
661 : check_access_member_function_valid_args(i0, i1, extra...);
662 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, extra...)
663 : return m_map.reference(i0, i1);
664 : }
665 :
666 : template <typename I0, typename I1, typename... Is>
667 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
668 : (Kokkos::Impl::always_true<I0, I1, Is...>::value && (2 == rank) &&
669 : is_default_map &&
670 : (is_layout_left || is_layout_right || is_layout_stride)),
671 : reference_type>
672 : access(I0 i0, I1 i1, Is... extra) const {
673 : check_access_member_function_valid_args(i0, i1, extra...);
674 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, extra...)
675 : if constexpr (is_layout_left) {
676 : if constexpr (rank_dynamic == 0)
677 : return m_map.m_impl_handle[i0 + m_map.m_impl_offset.m_dim.N0 * i1];
678 : else
679 : return m_map.m_impl_handle[i0 + m_map.m_impl_offset.m_stride * i1];
680 : } else if constexpr (is_layout_right) {
681 : if constexpr (rank_dynamic == 0)
682 : return m_map.m_impl_handle[i1 + m_map.m_impl_offset.m_dim.N1 * i0];
683 : else
684 : return m_map.m_impl_handle[i1 + m_map.m_impl_offset.m_stride * i0];
685 : } else {
686 : static_assert(is_layout_stride);
687 : return m_map.m_impl_handle[i0 * m_map.m_impl_offset.m_stride.S0 +
688 : i1 * m_map.m_impl_offset.m_stride.S1];
689 : }
690 : }
691 :
692 : //------------------------------
693 : // Rank 3
694 :
695 : template <typename I0, typename I1, typename I2, typename... Is>
696 : KOKKOS_FORCEINLINE_FUNCTION
697 : std::enable_if_t<(Kokkos::Impl::always_true<I0, I1, I2, Is...>::value &&
698 : (3 == rank) && is_default_map),
699 : reference_type>
700 : access(I0 i0, I1 i1, I2 i2, Is... extra) const {
701 : check_access_member_function_valid_args(i0, i1, i2, extra...);
702 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, extra...)
703 : return m_map.m_impl_handle[m_map.m_impl_offset(i0, i1, i2)];
704 : }
705 :
706 : template <typename I0, typename I1, typename I2, typename... Is>
707 : KOKKOS_FORCEINLINE_FUNCTION
708 : std::enable_if_t<(Kokkos::Impl::always_true<I0, I1, I2, Is...>::value &&
709 : (3 == rank) && !is_default_map),
710 : reference_type>
711 : access(I0 i0, I1 i1, I2 i2, Is... extra) const {
712 : check_access_member_function_valid_args(i0, i1, i2, extra...);
713 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, extra...)
714 : return m_map.reference(i0, i1, i2);
715 : }
716 :
717 : //------------------------------
718 : // Rank 4
719 :
720 : template <typename I0, typename I1, typename I2, typename I3, typename... Is>
721 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
722 : (Kokkos::Impl::always_true<I0, I1, I2, I3, Is...>::value && (4 == rank) &&
723 : is_default_map),
724 : reference_type>
725 : access(I0 i0, I1 i1, I2 i2, I3 i3, Is... extra) const {
726 : check_access_member_function_valid_args(i0, i1, i2, i3, extra...);
727 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, i3, extra...)
728 : return m_map.m_impl_handle[m_map.m_impl_offset(i0, i1, i2, i3)];
729 : }
730 :
731 : template <typename I0, typename I1, typename I2, typename I3, typename... Is>
732 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
733 : (Kokkos::Impl::always_true<I0, I1, I2, I3, Is...>::value && (4 == rank) &&
734 : !is_default_map),
735 : reference_type>
736 : access(I0 i0, I1 i1, I2 i2, I3 i3, Is... extra) const {
737 : check_access_member_function_valid_args(i0, i1, i2, i3, extra...);
738 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, i3, extra...)
739 : return m_map.reference(i0, i1, i2, i3);
740 : }
741 :
742 : //------------------------------
743 : // Rank 5
744 :
745 : template <typename I0, typename I1, typename I2, typename I3, typename I4,
746 : typename... Is>
747 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
748 : (Kokkos::Impl::always_true<I0, I1, I2, I3, I4, Is...>::value &&
749 : (5 == rank) && is_default_map),
750 : reference_type>
751 : access(I0 i0, I1 i1, I2 i2, I3 i3, I4 i4, Is... extra) const {
752 : check_access_member_function_valid_args(i0, i1, i2, i3, i4, extra...);
753 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, i3, i4,
754 : extra...)
755 : return m_map.m_impl_handle[m_map.m_impl_offset(i0, i1, i2, i3, i4)];
756 : }
757 :
758 : template <typename I0, typename I1, typename I2, typename I3, typename I4,
759 : typename... Is>
760 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
761 : (Kokkos::Impl::always_true<I0, I1, I2, I3, I4, Is...>::value &&
762 : (5 == rank) && !is_default_map),
763 : reference_type>
764 : access(I0 i0, I1 i1, I2 i2, I3 i3, I4 i4, Is... extra) const {
765 : check_access_member_function_valid_args(i0, i1, i2, i3, i4, extra...);
766 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, i3, i4,
767 : extra...)
768 : return m_map.reference(i0, i1, i2, i3, i4);
769 : }
770 :
771 : //------------------------------
772 : // Rank 6
773 :
774 : template <typename I0, typename I1, typename I2, typename I3, typename I4,
775 : typename I5, typename... Is>
776 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
777 : (Kokkos::Impl::always_true<I0, I1, I2, I3, I4, I5, Is...>::value &&
778 : (6 == rank) && is_default_map),
779 : reference_type>
780 : access(I0 i0, I1 i1, I2 i2, I3 i3, I4 i4, I5 i5, Is... extra) const {
781 : check_access_member_function_valid_args(i0, i1, i2, i3, i4, i5, extra...);
782 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, i3, i4, i5,
783 : extra...)
784 : return m_map.m_impl_handle[m_map.m_impl_offset(i0, i1, i2, i3, i4, i5)];
785 : }
786 :
787 : template <typename I0, typename I1, typename I2, typename I3, typename I4,
788 : typename I5, typename... Is>
789 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
790 : (Kokkos::Impl::always_true<I0, I1, I2, I3, I4, I5, Is...>::value &&
791 : (6 == rank) && !is_default_map),
792 : reference_type>
793 : access(I0 i0, I1 i1, I2 i2, I3 i3, I4 i4, I5 i5, Is... extra) const {
794 : check_access_member_function_valid_args(i0, i1, i2, i3, i4, i5, extra...);
795 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, i3, i4, i5,
796 : extra...)
797 : return m_map.reference(i0, i1, i2, i3, i4, i5);
798 : }
799 :
800 : //------------------------------
801 : // Rank 7
802 :
803 : template <typename I0, typename I1, typename I2, typename I3, typename I4,
804 : typename I5, typename I6, typename... Is>
805 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
806 : (Kokkos::Impl::always_true<I0, I1, I2, I3, I4, I5, I6, Is...>::value &&
807 : (7 == rank) && is_default_map),
808 : reference_type>
809 : access(I0 i0, I1 i1, I2 i2, I3 i3, I4 i4, I5 i5, I6 i6, Is... extra) const {
810 : check_access_member_function_valid_args(i0, i1, i2, i3, i4, i5, i6,
811 : extra...);
812 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, i3, i4, i5, i6,
813 : extra...)
814 : return m_map.m_impl_handle[m_map.m_impl_offset(i0, i1, i2, i3, i4, i5, i6)];
815 : }
816 :
817 : template <typename I0, typename I1, typename I2, typename I3, typename I4,
818 : typename I5, typename I6, typename... Is>
819 : KOKKOS_FORCEINLINE_FUNCTION std::enable_if_t<
820 : (Kokkos::Impl::always_true<I0, I1, I2, I3, I4, I5, I6, Is...>::value &&
821 : (7 == rank) && !is_default_map),
822 : reference_type>
823 : access(I0 i0, I1 i1, I2 i2, I3 i3, I4 i4, I5 i5, I6 i6, Is... extra) const {
824 : check_access_member_function_valid_args(i0, i1, i2, i3, i4, i5, i6,
825 : extra...);
826 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, i3, i4, i5, i6,
827 : extra...)
828 : return m_map.reference(i0, i1, i2, i3, i4, i5, i6);
829 : }
830 :
831 : //------------------------------
832 : // Rank 8
833 :
834 : template <typename I0, typename I1, typename I2, typename I3, typename I4,
835 : typename I5, typename I6, typename I7, typename... Is>
836 : KOKKOS_FORCEINLINE_FUNCTION
837 : std::enable_if_t<(Kokkos::Impl::always_true<I0, I1, I2, I3, I4, I5, I6,
838 : I7, Is...>::value &&
839 : (8 == rank) && is_default_map),
840 : reference_type>
841 : access(I0 i0, I1 i1, I2 i2, I3 i3, I4 i4, I5 i5, I6 i6, I7 i7,
842 : Is... extra) const {
843 : check_access_member_function_valid_args(i0, i1, i2, i3, i4, i5, i6, i7,
844 : extra...);
845 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, i3, i4, i5, i6,
846 : i7, extra...)
847 : return m_map
848 : .m_impl_handle[m_map.m_impl_offset(i0, i1, i2, i3, i4, i5, i6, i7)];
849 : }
850 :
851 : template <typename I0, typename I1, typename I2, typename I3, typename I4,
852 : typename I5, typename I6, typename I7, typename... Is>
853 : KOKKOS_FORCEINLINE_FUNCTION
854 : std::enable_if_t<(Kokkos::Impl::always_true<I0, I1, I2, I3, I4, I5, I6,
855 : I7, Is...>::value &&
856 : (8 == rank) && !is_default_map),
857 : reference_type>
858 : access(I0 i0, I1 i1, I2 i2, I3 i3, I4 i4, I5 i5, I6 i6, I7 i7,
859 : Is... extra) const {
860 : check_access_member_function_valid_args(i0, i1, i2, i3, i4, i5, i6, i7,
861 : extra...);
862 : KOKKOS_IMPL_VIEW_OPERATOR_VERIFY(m_track, m_map, i0, i1, i2, i3, i4, i5, i6,
863 : i7, extra...)
864 : return m_map.reference(i0, i1, i2, i3, i4, i5, i6, i7);
865 : }
866 :
867 : #undef KOKKOS_IMPL_VIEW_OPERATOR_VERIFY
868 :
869 : //----------------------------------------
870 : // Standard destructor, constructors, and assignment operators
871 :
872 : KOKKOS_DEFAULTED_FUNCTION
873 : ~View() = default;
874 :
875 : KOKKOS_DEFAULTED_FUNCTION
876 : View() = default;
877 :
878 : KOKKOS_FUNCTION
879 : View(const View& other) : m_track(other.m_track), m_map(other.m_map) {
880 : KOKKOS_IF_ON_HOST((hooks_policy::copy_construct(*this, other);))
881 : }
882 :
883 : KOKKOS_FUNCTION
884 : View(View&& other)
885 : : m_track{std::move(other.m_track)}, m_map{std::move(other.m_map)} {
886 : KOKKOS_IF_ON_HOST((hooks_policy::move_construct(*this, other);))
887 : }
888 :
889 : KOKKOS_FUNCTION
890 : View& operator=(const View& other) {
891 : m_map = other.m_map;
892 : m_track = other.m_track;
893 :
894 : KOKKOS_IF_ON_HOST((hooks_policy::copy_assign(*this, other);))
895 :
896 : return *this;
897 : }
898 :
899 : KOKKOS_FUNCTION
900 : View& operator=(View&& other) {
901 : m_map = std::move(other.m_map);
902 : m_track = std::move(other.m_track);
903 :
904 : KOKKOS_IF_ON_HOST((hooks_policy::move_assign(*this, other);))
905 :
906 : return *this;
907 : }
908 :
909 : //----------------------------------------
910 : // Compatible view copy constructor and assignment
911 : // may assign unmanaged from managed.
912 :
913 : template <class RT, class... RP>
914 : KOKKOS_INLINE_FUNCTION View(
915 : const View<RT, RP...>& rhs,
916 : std::enable_if_t<Kokkos::Impl::ViewMapping<
917 : traits, typename View<RT, RP...>::traits,
918 : typename traits::specialize>::is_assignable_data_type>* = nullptr)
919 : : m_track(rhs), m_map() {
920 : using SrcTraits = typename View<RT, RP...>::traits;
921 : using Mapping = Kokkos::Impl::ViewMapping<traits, SrcTraits,
922 : typename traits::specialize>;
923 : static_assert(Mapping::is_assignable,
924 : "Incompatible View copy construction");
925 : Mapping::assign(m_map, rhs.m_map, rhs.m_track.m_tracker);
926 : }
927 :
928 : template <class RT, class... RP>
929 : KOKKOS_INLINE_FUNCTION std::enable_if_t<
930 : Kokkos::Impl::ViewMapping<
931 : traits, typename View<RT, RP...>::traits,
932 : typename traits::specialize>::is_assignable_data_type,
933 : View>&
934 : operator=(const View<RT, RP...>& rhs) {
935 : using SrcTraits = typename View<RT, RP...>::traits;
936 : using Mapping = Kokkos::Impl::ViewMapping<traits, SrcTraits,
937 : typename traits::specialize>;
938 : static_assert(Mapping::is_assignable, "Incompatible View copy assignment");
939 : Mapping::assign(m_map, rhs.m_map, rhs.m_track.m_tracker);
940 : m_track.assign(rhs);
941 : return *this;
942 : }
943 :
944 : //----------------------------------------
945 : // Compatible subview constructor
946 : // may assign unmanaged from managed.
947 :
948 : template <class RT, class... RP, class Arg0, class... Args>
949 : KOKKOS_INLINE_FUNCTION View(const View<RT, RP...>& src_view, const Arg0 arg0,
950 : Args... args)
951 : : m_track(src_view), m_map() {
952 : using SrcType = View<RT, RP...>;
953 :
954 : using Mapping = Kokkos::Impl::ViewMapping<void, typename SrcType::traits,
955 : Arg0, Args...>;
956 :
957 : using DstType = typename Mapping::type;
958 :
959 : static_assert(
960 : Kokkos::Impl::ViewMapping<traits, typename DstType::traits,
961 : typename traits::specialize>::is_assignable,
962 : "Subview construction requires compatible view and subview arguments");
963 :
964 : Mapping::assign(m_map, src_view.m_map, arg0, args...);
965 : }
966 :
967 : //----------------------------------------
968 : // Allocation tracking properties
969 :
970 : KOKKOS_INLINE_FUNCTION
971 : int use_count() const { return m_track.m_tracker.use_count(); }
972 :
973 : inline const std::string label() const {
974 : return m_track.m_tracker
975 : .template get_label<typename traits::memory_space>();
976 : }
977 :
978 : public:
979 : //----------------------------------------
980 : // Allocation according to allocation properties and array layout
981 :
982 : template <class... P>
983 : explicit inline View(
984 : const Impl::ViewCtorProp<P...>& arg_prop,
985 : std::enable_if_t<!Impl::ViewCtorProp<P...>::has_pointer,
986 : typename traits::array_layout> const& arg_layout)
987 : : m_track(), m_map() {
988 : // Copy the input allocation properties with possibly defaulted properties
989 : // We need to split it in two to avoid MSVC compiler errors
990 : auto prop_copy_tmp =
991 : Impl::with_properties_if_unset(arg_prop, std::string{});
992 : auto prop_copy = Impl::with_properties_if_unset(
993 : prop_copy_tmp, typename traits::device_type::memory_space{},
994 : typename traits::device_type::execution_space{});
995 : using alloc_prop = decltype(prop_copy);
996 :
997 : static_assert(traits::is_managed,
998 : "View allocation constructor requires managed memory");
999 :
1000 : if (alloc_prop::initialize &&
1001 : !alloc_prop::execution_space::impl_is_initialized()) {
1002 : // If initializing view data then
1003 : // the execution space must be initialized.
1004 : Kokkos::abort(
1005 : "Constructing View and initializing data with uninitialized "
1006 : "execution space");
1007 : }
1008 :
1009 : #ifdef KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK
1010 : if constexpr (std::is_same_v<typename traits::array_layout,
1011 : Kokkos::LayoutLeft> ||
1012 : std::is_same_v<typename traits::array_layout,
1013 : Kokkos::LayoutRight> ||
1014 : std::is_same_v<typename traits::array_layout,
1015 : Kokkos::LayoutStride>) {
1016 : size_t i0 = arg_layout.dimension[0];
1017 : size_t i1 = arg_layout.dimension[1];
1018 : size_t i2 = arg_layout.dimension[2];
1019 : size_t i3 = arg_layout.dimension[3];
1020 : size_t i4 = arg_layout.dimension[4];
1021 : size_t i5 = arg_layout.dimension[5];
1022 : size_t i6 = arg_layout.dimension[6];
1023 : size_t i7 = arg_layout.dimension[7];
1024 :
1025 : const std::string& alloc_name =
1026 : Impl::get_property<Impl::LabelTag>(prop_copy);
1027 : Impl::runtime_check_rank(
1028 : *this, std::is_same_v<typename traits::specialize, void>, i0, i1, i2,
1029 : i3, i4, i5, i6, i7, alloc_name.c_str());
1030 : }
1031 : #endif
1032 :
1033 : Kokkos::Impl::SharedAllocationRecord<>* record = m_map.allocate_shared(
1034 : prop_copy, arg_layout, Impl::ViewCtorProp<P...>::has_execution_space);
1035 :
1036 : // Setup and initialization complete, start tracking
1037 : m_track.m_tracker.assign_allocated_record_to_uninitialized(record);
1038 : }
1039 :
1040 : KOKKOS_INLINE_FUNCTION
1041 : void assign_data(pointer_type arg_data) {
1042 : m_track.m_tracker.clear();
1043 : m_map.assign_data(arg_data);
1044 : }
1045 :
1046 : // Wrap memory according to properties and array layout
1047 : template <class... P>
1048 : explicit KOKKOS_INLINE_FUNCTION View(
1049 : const Impl::ViewCtorProp<P...>& arg_prop,
1050 : std::enable_if_t<Impl::ViewCtorProp<P...>::has_pointer,
1051 : typename traits::array_layout> const& arg_layout)
1052 : : m_track() // No memory tracking
1053 : ,
1054 : m_map(arg_prop, arg_layout) {
1055 : static_assert(
1056 : std::is_same_v<pointer_type,
1057 : typename Impl::ViewCtorProp<P...>::pointer_type>,
1058 : "Constructing View to wrap user memory must supply matching pointer "
1059 : "type");
1060 :
1061 : #ifdef KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK
1062 : if constexpr (std::is_same_v<typename traits::array_layout,
1063 : Kokkos::LayoutLeft> ||
1064 : std::is_same_v<typename traits::array_layout,
1065 : Kokkos::LayoutRight> ||
1066 : std::is_same_v<typename traits::array_layout,
1067 : Kokkos::LayoutStride>) {
1068 : size_t i0 = arg_layout.dimension[0];
1069 : size_t i1 = arg_layout.dimension[1];
1070 : size_t i2 = arg_layout.dimension[2];
1071 : size_t i3 = arg_layout.dimension[3];
1072 : size_t i4 = arg_layout.dimension[4];
1073 : size_t i5 = arg_layout.dimension[5];
1074 : size_t i6 = arg_layout.dimension[6];
1075 : size_t i7 = arg_layout.dimension[7];
1076 :
1077 : Impl::runtime_check_rank(
1078 : *this, std::is_same_v<typename traits::specialize, void>, i0, i1, i2,
1079 : i3, i4, i5, i6, i7, "UNMANAGED");
1080 : }
1081 : #endif
1082 : }
1083 :
1084 : // Simple dimension-only layout
1085 : template <class... P>
1086 : explicit inline View(
1087 : const Impl::ViewCtorProp<P...>& arg_prop,
1088 : std::enable_if_t<!Impl::ViewCtorProp<P...>::has_pointer, size_t> const
1089 : arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1090 : const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1091 : const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1092 : const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1093 : const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1094 : const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1095 : const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1096 : const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
1097 : : View(arg_prop,
1098 : typename traits::array_layout(arg_N0, arg_N1, arg_N2, arg_N3,
1099 : arg_N4, arg_N5, arg_N6, arg_N7)) {
1100 : static_assert(traits::array_layout::is_extent_constructible,
1101 : "Layout is not constructible from extent arguments. Use "
1102 : "overload taking a layout object instead.");
1103 : }
1104 :
1105 : template <class... P>
1106 : explicit KOKKOS_INLINE_FUNCTION View(
1107 : const Impl::ViewCtorProp<P...>& arg_prop,
1108 : std::enable_if_t<Impl::ViewCtorProp<P...>::has_pointer, size_t> const
1109 : arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1110 : const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1111 : const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1112 : const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1113 : const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1114 : const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1115 : const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1116 : const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
1117 : : View(arg_prop,
1118 : typename traits::array_layout(arg_N0, arg_N1, arg_N2, arg_N3,
1119 : arg_N4, arg_N5, arg_N6, arg_N7)) {
1120 : static_assert(traits::array_layout::is_extent_constructible,
1121 : "Layout is not constructible from extent arguments. Use "
1122 : "overload taking a layout object instead.");
1123 : }
1124 :
1125 : // Allocate with label and layout
1126 : template <typename Label>
1127 : explicit inline View(
1128 : const Label& arg_label,
1129 : std::enable_if_t<Kokkos::Impl::is_view_label<Label>::value,
1130 : typename traits::array_layout> const& arg_layout)
1131 : : View(Impl::ViewCtorProp<std::string>(arg_label), arg_layout) {}
1132 :
1133 : // Allocate label and layout, must disambiguate from subview constructor.
1134 : template <typename Label>
1135 : explicit inline View(
1136 : const Label& arg_label,
1137 : std::enable_if_t<Kokkos::Impl::is_view_label<Label>::value, const size_t>
1138 : arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1139 : const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1140 : const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1141 : const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1142 : const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1143 : const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1144 : const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1145 : const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
1146 : : View(Impl::ViewCtorProp<std::string>(arg_label),
1147 : typename traits::array_layout(arg_N0, arg_N1, arg_N2, arg_N3,
1148 : arg_N4, arg_N5, arg_N6, arg_N7)) {
1149 : static_assert(traits::array_layout::is_extent_constructible,
1150 : "Layout is not constructible from extent arguments. Use "
1151 : "overload taking a layout object instead.");
1152 : }
1153 :
1154 : // Construct view from ViewTracker and map
1155 : // This should be the preferred method because future extensions may need to
1156 : // use the ViewTracker class.
1157 : template <class Traits>
1158 : KOKKOS_INLINE_FUNCTION View(
1159 : const view_tracker_type& track,
1160 : const Kokkos::Impl::ViewMapping<Traits, typename Traits::specialize>& map)
1161 : : m_track(track), m_map() {
1162 : using Mapping =
1163 : Kokkos::Impl::ViewMapping<traits, Traits, typename traits::specialize>;
1164 : static_assert(Mapping::is_assignable,
1165 : "Incompatible View copy construction");
1166 : Mapping::assign(m_map, map, track.m_tracker);
1167 : }
1168 :
1169 : // Construct View from internal shared allocation tracker object and map
1170 : // This is here for backwards compatibility for classes that derive from
1171 : // Kokkos::View
1172 : template <class Traits>
1173 : KOKKOS_INLINE_FUNCTION View(
1174 : const typename view_tracker_type::track_type& track,
1175 : const Kokkos::Impl::ViewMapping<Traits, typename Traits::specialize>& map)
1176 : : m_track(track), m_map() {
1177 : using Mapping =
1178 : Kokkos::Impl::ViewMapping<traits, Traits, typename traits::specialize>;
1179 : static_assert(Mapping::is_assignable,
1180 : "Incompatible View copy construction");
1181 : Mapping::assign(m_map, map, track);
1182 : }
1183 :
1184 : //----------------------------------------
1185 : // Memory span required to wrap these dimensions.
1186 : static constexpr size_t required_allocation_size(
1187 : typename traits::array_layout const& layout) {
1188 : return map_type::memory_span(layout);
1189 : }
1190 :
1191 : static constexpr size_t required_allocation_size(
1192 : const size_t arg_N0 = 0, const size_t arg_N1 = 0, const size_t arg_N2 = 0,
1193 : const size_t arg_N3 = 0, const size_t arg_N4 = 0, const size_t arg_N5 = 0,
1194 : const size_t arg_N6 = 0, const size_t arg_N7 = 0) {
1195 : static_assert(traits::array_layout::is_extent_constructible,
1196 : "Layout is not constructible from extent arguments. Use "
1197 : "overload taking a layout object instead.");
1198 : return map_type::memory_span(typename traits::array_layout(
1199 : arg_N0, arg_N1, arg_N2, arg_N3, arg_N4, arg_N5, arg_N6, arg_N7));
1200 : }
1201 :
1202 : explicit KOKKOS_INLINE_FUNCTION View(
1203 : pointer_type arg_ptr, const size_t arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1204 : const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1205 : const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1206 : const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1207 : const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1208 : const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1209 : const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1210 : const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
1211 : : View(Impl::ViewCtorProp<pointer_type>(arg_ptr),
1212 : typename traits::array_layout(arg_N0, arg_N1, arg_N2, arg_N3,
1213 : arg_N4, arg_N5, arg_N6, arg_N7)) {
1214 : static_assert(traits::array_layout::is_extent_constructible,
1215 : "Layout is not constructible from extent arguments. Use "
1216 : "overload taking a layout object instead.");
1217 : }
1218 :
1219 : explicit KOKKOS_INLINE_FUNCTION View(
1220 : pointer_type arg_ptr, const typename traits::array_layout& arg_layout)
1221 : : View(Impl::ViewCtorProp<pointer_type>(arg_ptr), arg_layout) {}
1222 :
1223 : //----------------------------------------
1224 : // Shared scratch memory constructor
1225 :
1226 : static KOKKOS_INLINE_FUNCTION size_t
1227 : shmem_size(const size_t arg_N0 = KOKKOS_INVALID_INDEX,
1228 : const size_t arg_N1 = KOKKOS_INVALID_INDEX,
1229 : const size_t arg_N2 = KOKKOS_INVALID_INDEX,
1230 : const size_t arg_N3 = KOKKOS_INVALID_INDEX,
1231 : const size_t arg_N4 = KOKKOS_INVALID_INDEX,
1232 : const size_t arg_N5 = KOKKOS_INVALID_INDEX,
1233 : const size_t arg_N6 = KOKKOS_INVALID_INDEX,
1234 : const size_t arg_N7 = KOKKOS_INVALID_INDEX) {
1235 : static_assert(traits::array_layout::is_extent_constructible,
1236 : "Layout is not constructible from extent arguments. Use "
1237 : "overload taking a layout object instead.");
1238 : const size_t num_passed_args = Impl::count_valid_integers(
1239 : arg_N0, arg_N1, arg_N2, arg_N3, arg_N4, arg_N5, arg_N6, arg_N7);
1240 :
1241 : if (std::is_void_v<typename traits::specialize> &&
1242 : num_passed_args != rank_dynamic) {
1243 : Kokkos::abort(
1244 : "Kokkos::View::shmem_size() rank_dynamic != number of arguments.\n");
1245 : }
1246 :
1247 : return View::shmem_size(typename traits::array_layout(
1248 : arg_N0, arg_N1, arg_N2, arg_N3, arg_N4, arg_N5, arg_N6, arg_N7));
1249 : }
1250 :
1251 : private:
1252 : // Want to be able to align to minimum scratch alignment or sizeof or alignof
1253 : // elements
1254 : static constexpr size_t scratch_value_alignment =
1255 : max({sizeof(typename traits::value_type),
1256 : alignof(typename traits::value_type),
1257 : static_cast<size_t>(
1258 : traits::execution_space::scratch_memory_space::ALIGN)});
1259 :
1260 : public:
1261 : static KOKKOS_INLINE_FUNCTION size_t
1262 : shmem_size(typename traits::array_layout const& arg_layout) {
1263 : return map_type::memory_span(arg_layout) + scratch_value_alignment;
1264 : }
1265 :
1266 : explicit KOKKOS_INLINE_FUNCTION View(
1267 : const typename traits::execution_space::scratch_memory_space& arg_space,
1268 : const typename traits::array_layout& arg_layout)
1269 : : View(Impl::ViewCtorProp<pointer_type>(reinterpret_cast<pointer_type>(
1270 : arg_space.get_shmem_aligned(map_type::memory_span(arg_layout),
1271 : scratch_value_alignment))),
1272 : arg_layout) {}
1273 :
1274 : explicit KOKKOS_INLINE_FUNCTION View(
1275 : const typename traits::execution_space::scratch_memory_space& arg_space,
1276 : const size_t arg_N0 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1277 : const size_t arg_N1 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1278 : const size_t arg_N2 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1279 : const size_t arg_N3 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1280 : const size_t arg_N4 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1281 : const size_t arg_N5 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1282 : const size_t arg_N6 = KOKKOS_IMPL_CTOR_DEFAULT_ARG,
1283 : const size_t arg_N7 = KOKKOS_IMPL_CTOR_DEFAULT_ARG)
1284 : : View(Impl::ViewCtorProp<pointer_type>(
1285 : reinterpret_cast<pointer_type>(arg_space.get_shmem_aligned(
1286 : map_type::memory_span(typename traits::array_layout(
1287 : arg_N0, arg_N1, arg_N2, arg_N3, arg_N4, arg_N5, arg_N6,
1288 : arg_N7)),
1289 : scratch_value_alignment))),
1290 : typename traits::array_layout(arg_N0, arg_N1, arg_N2, arg_N3,
1291 : arg_N4, arg_N5, arg_N6, arg_N7)) {
1292 : static_assert(traits::array_layout::is_extent_constructible,
1293 : "Layout is not constructible from extent arguments. Use "
1294 : "overload taking a layout object instead.");
1295 : }
1296 :
1297 : //----------------------------------------
1298 : // MDSpan converting constructors
1299 : #ifdef KOKKOS_ENABLE_IMPL_MDSPAN
1300 : template <typename U = typename Impl::MDSpanViewTraits<traits>::mdspan_type>
1301 : KOKKOS_INLINE_FUNCTION
1302 : #ifndef KOKKOS_ENABLE_CXX17
1303 : explicit(traits::is_managed)
1304 : #endif
1305 : View(const typename Impl::MDSpanViewTraits<traits>::mdspan_type& mds,
1306 : std::enable_if_t<
1307 : !std::is_same_v<Impl::UnsupportedKokkosArrayLayout, U>>* =
1308 : nullptr)
1309 : : View(mds.data_handle(),
1310 : Impl::array_layout_from_mapping<
1311 : typename traits::array_layout,
1312 : typename Impl::MDSpanViewTraits<traits>::mdspan_type>(
1313 : mds.mapping())) {
1314 : }
1315 :
1316 : template <class ElementType, class ExtentsType, class LayoutType,
1317 : class AccessorType>
1318 : KOKKOS_INLINE_FUNCTION
1319 : #ifndef KOKKOS_ENABLE_CXX17
1320 : explicit(!std::is_convertible_v<
1321 : Kokkos::mdspan<ElementType, ExtentsType, LayoutType,
1322 : AccessorType>,
1323 : typename Impl::MDSpanViewTraits<traits>::mdspan_type>)
1324 : #endif
1325 : View(const Kokkos::mdspan<ElementType, ExtentsType, LayoutType,
1326 : AccessorType>& mds)
1327 : : View(typename Impl::MDSpanViewTraits<traits>::mdspan_type(mds)) {
1328 : }
1329 :
1330 : //----------------------------------------
1331 : // Conversion to MDSpan
1332 : template <class OtherElementType, class OtherExtents, class OtherLayoutPolicy,
1333 : class OtherAccessor,
1334 : class ImplNaturalMDSpanType =
1335 : typename Impl::MDSpanViewTraits<traits>::mdspan_type,
1336 : typename = std::enable_if_t<std::conditional_t<
1337 : std::is_same_v<Impl::UnsupportedKokkosArrayLayout,
1338 : ImplNaturalMDSpanType>,
1339 : std::false_type,
1340 : std::is_assignable<mdspan<OtherElementType, OtherExtents,
1341 : OtherLayoutPolicy, OtherAccessor>,
1342 : ImplNaturalMDSpanType>>::value>>
1343 : KOKKOS_INLINE_FUNCTION constexpr operator mdspan<
1344 : OtherElementType, OtherExtents, OtherLayoutPolicy, OtherAccessor>() {
1345 : using mdspan_type = typename Impl::MDSpanViewTraits<traits>::mdspan_type;
1346 : return mdspan_type{data(),
1347 : Impl::mapping_from_view_mapping<mdspan_type>(m_map)};
1348 : }
1349 :
1350 : template <class OtherAccessorType = Impl::SpaceAwareAccessor<
1351 : typename traits::memory_space,
1352 : Kokkos::default_accessor<typename traits::value_type>>,
1353 : typename = std::enable_if_t<std::is_assignable_v<
1354 : typename traits::value_type*&,
1355 : typename OtherAccessorType::data_handle_type>>>
1356 : KOKKOS_INLINE_FUNCTION constexpr auto to_mdspan(
1357 : const OtherAccessorType& other_accessor =
1358 : typename Impl::MDSpanViewTraits<traits>::accessor_type()) {
1359 : using mdspan_type = typename Impl::MDSpanViewTraits<traits>::mdspan_type;
1360 : using ret_mdspan_type =
1361 : mdspan<typename mdspan_type::element_type,
1362 : typename mdspan_type::extents_type,
1363 : typename mdspan_type::layout_type, OtherAccessorType>;
1364 : return ret_mdspan_type{data(),
1365 : Impl::mapping_from_view_mapping<mdspan_type>(m_map),
1366 : other_accessor};
1367 : }
1368 : #endif // KOKKOS_ENABLE_IMPL_MDSPAN
1369 : };
1370 :
1371 : template <typename D, class... P>
1372 : KOKKOS_INLINE_FUNCTION constexpr unsigned rank(const View<D, P...>&) {
1373 : return View<D, P...>::rank();
1374 : }
1375 :
1376 : namespace Impl {
1377 :
1378 : template <typename ValueType, unsigned int Rank>
1379 : struct RankDataType {
1380 : using type = typename RankDataType<ValueType, Rank - 1>::type*;
1381 : };
1382 :
1383 : template <typename ValueType>
1384 : struct RankDataType<ValueType, 0> {
1385 : using type = ValueType;
1386 : };
1387 :
1388 : template <unsigned N, typename... Args>
1389 : KOKKOS_FUNCTION std::enable_if_t<
1390 : N == View<Args...>::rank() &&
1391 : std::is_same_v<typename ViewTraits<Args...>::specialize, void>,
1392 : View<Args...>>
1393 : as_view_of_rank_n(View<Args...> v) {
1394 : return v;
1395 : }
1396 :
1397 : // Placeholder implementation to compile generic code for DynRankView; should
1398 : // never be called
1399 : template <unsigned N, typename T, typename... Args>
1400 : KOKKOS_FUNCTION std::enable_if_t<
1401 : N != View<T, Args...>::rank() &&
1402 : std::is_same_v<typename ViewTraits<T, Args...>::specialize, void>,
1403 : View<typename RankDataType<typename View<T, Args...>::value_type, N>::type,
1404 : Args...>>
1405 : as_view_of_rank_n(View<T, Args...>) {
1406 : Kokkos::abort("Trying to get at a View of the wrong rank");
1407 : return {};
1408 : }
1409 :
1410 : template <typename Function, typename... Args>
1411 : void apply_to_view_of_static_rank(Function&& f, View<Args...> a) {
1412 : f(a);
1413 : }
1414 :
1415 : } // namespace Impl
1416 :
1417 : template <class D, class... P, class... Args>
1418 : KOKKOS_INLINE_FUNCTION auto subview(const View<D, P...>& src, Args... args) {
1419 : static_assert(View<D, P...>::rank == sizeof...(Args),
1420 : "subview requires one argument for each source View rank");
1421 :
1422 : return typename Kokkos::Impl::ViewMapping<
1423 : void /* deduce subview type from source view traits */
1424 : ,
1425 : typename Impl::RemoveAlignedMemoryTrait<D, P...>::type,
1426 : Args...>::type(src, args...);
1427 : }
1428 :
1429 : #ifdef KOKKOS_ENABLE_DEPRECATED_CODE_4
1430 : template <class MemoryTraits, class D, class... P, class... Args>
1431 : KOKKOS_DEPRECATED KOKKOS_INLINE_FUNCTION auto subview(const View<D, P...>& src,
1432 : Args... args) {
1433 : static_assert(View<D, P...>::rank == sizeof...(Args),
1434 : "subview requires one argument for each source View rank");
1435 : static_assert(Kokkos::is_memory_traits<MemoryTraits>::value);
1436 :
1437 : return typename Kokkos::Impl::ViewMapping<
1438 : void /* deduce subview type from source view traits */
1439 : ,
1440 : typename Impl::RemoveAlignedMemoryTrait<D, P..., MemoryTraits>::type,
1441 : Args...>::type(src, args...);
1442 : }
1443 : #endif
1444 :
1445 : template <class V, class... Args>
1446 : using Subview = decltype(subview(std::declval<V>(), std::declval<Args>()...));
1447 :
1448 : } /* namespace Kokkos */
1449 :
1450 : //----------------------------------------------------------------------------
1451 : //----------------------------------------------------------------------------
1452 :
1453 : namespace Kokkos {
1454 :
1455 : template <class LT, class... LP, class RT, class... RP>
1456 : KOKKOS_INLINE_FUNCTION bool operator==(const View<LT, LP...>& lhs,
1457 : const View<RT, RP...>& rhs) {
1458 : // Same data, layout, dimensions
1459 : using lhs_traits = ViewTraits<LT, LP...>;
1460 : using rhs_traits = ViewTraits<RT, RP...>;
1461 :
1462 : return std::is_same_v<typename lhs_traits::const_value_type,
1463 : typename rhs_traits::const_value_type> &&
1464 : std::is_same_v<typename lhs_traits::array_layout,
1465 : typename rhs_traits::array_layout> &&
1466 : std::is_same_v<typename lhs_traits::memory_space,
1467 : typename rhs_traits::memory_space> &&
1468 : View<LT, LP...>::rank() == View<RT, RP...>::rank() &&
1469 : lhs.data() == rhs.data() && lhs.span() == rhs.span() &&
1470 : lhs.extent(0) == rhs.extent(0) && lhs.extent(1) == rhs.extent(1) &&
1471 : lhs.extent(2) == rhs.extent(2) && lhs.extent(3) == rhs.extent(3) &&
1472 : lhs.extent(4) == rhs.extent(4) && lhs.extent(5) == rhs.extent(5) &&
1473 : lhs.extent(6) == rhs.extent(6) && lhs.extent(7) == rhs.extent(7);
1474 : }
1475 :
1476 : template <class LT, class... LP, class RT, class... RP>
1477 : KOKKOS_INLINE_FUNCTION bool operator!=(const View<LT, LP...>& lhs,
1478 : const View<RT, RP...>& rhs) {
1479 : return !(operator==(lhs, rhs));
1480 : }
1481 :
1482 : } /* namespace Kokkos */
1483 :
1484 : #include <View/Kokkos_ViewCommonType.hpp>
1485 : #include <View/Kokkos_ViewUniformType.hpp>
1486 : #include <View/Kokkos_ViewAtomic.hpp>
1487 :
1488 : //----------------------------------------------------------------------------
1489 : //----------------------------------------------------------------------------
1490 :
1491 : #endif /* #ifndef KOKKOS_VIEWLEGACY_HPP */
|