Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_DynamicView.hpp
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 3.0
6 // Copyright (2020) National Technology & Engineering
7 // Solutions of Sandia, LLC (NTESS).
8 //
9 // Under the terms of Contract DE-NA0003525 with NTESS,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
40 //
41 // ************************************************************************
42 //@HEADER
43 */
44 
45 #ifndef KOKKOS_DYNAMIC_VIEW_HPP
46 #define KOKKOS_DYNAMIC_VIEW_HPP
47 
48 #include <cstdio>
49 
50 #include <Kokkos_Core.hpp>
51 #include <impl/Kokkos_Error.hpp>
52 
53 namespace Kokkos {
54 namespace Experimental {
55 
56 // Simple metafunction for choosing memory space
57 // In the current implementation, if memory_space == CudaSpace,
58 // use CudaUVMSpace for the chunk 'array' allocation, which
59 // contains will contain pointers to chunks of memory allocated
60 // in CudaSpace
61 namespace Impl {
62 template <class MemSpace>
63 struct ChunkArraySpace {
64  using memory_space = MemSpace;
65 };
66 
67 #ifdef KOKKOS_ENABLE_CUDA
68 template <>
69 struct ChunkArraySpace<Kokkos::CudaSpace> {
70  using memory_space = typename Kokkos::CudaUVMSpace;
71 };
72 #endif
73 #ifdef KOKKOS_ENABLE_HIP
74 template <>
75 struct ChunkArraySpace<Kokkos::Experimental::HIPSpace> {
76  using memory_space = typename Kokkos::Experimental::HIPHostPinnedSpace;
77 };
78 #endif
79 } // end namespace Impl
80 
85 template <typename DataType, typename... P>
86 class DynamicView : public Kokkos::ViewTraits<DataType, P...> {
87  public:
88  typedef Kokkos::ViewTraits<DataType, P...> traits;
89 
90  private:
91  template <class, class...>
92  friend class DynamicView;
93 
94  typedef Kokkos::Impl::SharedAllocationTracker track_type;
95 
96  static_assert(traits::rank == 1 && traits::rank_dynamic == 1,
97  "DynamicView must be rank-one");
98 
99  // It is assumed that the value_type is trivially copyable;
100  // when this is not the case, potential problems can occur.
101  static_assert(std::is_same<typename traits::specialize, void>::value,
102  "DynamicView only implemented for non-specialized View type");
103 
104  template <class Space, bool = Kokkos::Impl::MemorySpaceAccess<
105  Space, typename traits::memory_space>::accessible>
106  struct verify_space {
107  KOKKOS_FORCEINLINE_FUNCTION static void check() {}
108  };
109 
110  template <class Space>
111  struct verify_space<Space, false> {
112  KOKKOS_FORCEINLINE_FUNCTION static void check() {
113  Kokkos::abort(
114  "Kokkos::DynamicView ERROR: attempt to access inaccessible memory "
115  "space");
116  };
117  };
118 
119  private:
120  track_type m_track;
121  typename traits::value_type**
122  m_chunks; // array of pointers to 'chunks' of memory
123  unsigned m_chunk_shift; // ceil(log2(m_chunk_size))
124  unsigned m_chunk_mask; // m_chunk_size - 1
125  unsigned m_chunk_max; // number of entries in the chunk array - each pointing
126  // to a chunk of extent == m_chunk_size entries
127  unsigned m_chunk_size; // 2 << (m_chunk_shift - 1)
128 
129  public:
130  //----------------------------------------------------------------------
131 
135 
137  typedef DynamicView<typename traits::const_data_type,
138  typename traits::device_type>
140 
142  typedef DynamicView<typename traits::non_const_data_type,
143  typename traits::device_type>
145 
148 
150  typedef Kokkos::Device<typename traits::device_type::execution_space,
151  Kokkos::AnonymousSpace>
153  typedef array_type uniform_type;
165 
166  //----------------------------------------------------------------------
167 
168  enum { Rank = 1 };
169 
170  KOKKOS_INLINE_FUNCTION
171  size_t allocation_extent() const noexcept {
172  uintptr_t n = *reinterpret_cast<const uintptr_t*>(m_chunks + m_chunk_max);
173  return (n << m_chunk_shift);
174  }
175 
176  KOKKOS_INLINE_FUNCTION
177  size_t chunk_size() const noexcept { return m_chunk_size; }
178 
179  KOKKOS_INLINE_FUNCTION
180  size_t size() const noexcept {
181  size_t extent_0 =
182  *reinterpret_cast<const size_t*>(m_chunks + m_chunk_max + 1);
183  return extent_0;
184  }
185 
186  template <typename iType>
187  KOKKOS_INLINE_FUNCTION size_t extent(const iType& r) const {
188  return r == 0 ? size() : 1;
189  }
190 
191  template <typename iType>
192  KOKKOS_INLINE_FUNCTION size_t extent_int(const iType& r) const {
193  return r == 0 ? size() : 1;
194  }
195 
196 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
197  KOKKOS_INLINE_FUNCTION size_t dimension_0() const { return size(); }
198  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_1() const { return 1; }
199  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_2() const { return 1; }
200  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_3() const { return 1; }
201  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_4() const { return 1; }
202  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_5() const { return 1; }
203  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_6() const { return 1; }
204  KOKKOS_INLINE_FUNCTION constexpr size_t dimension_7() const { return 1; }
205 #endif
206 
207  KOKKOS_INLINE_FUNCTION constexpr size_t stride_0() const { return 0; }
208  KOKKOS_INLINE_FUNCTION constexpr size_t stride_1() const { return 0; }
209  KOKKOS_INLINE_FUNCTION constexpr size_t stride_2() const { return 0; }
210  KOKKOS_INLINE_FUNCTION constexpr size_t stride_3() const { return 0; }
211  KOKKOS_INLINE_FUNCTION constexpr size_t stride_4() const { return 0; }
212  KOKKOS_INLINE_FUNCTION constexpr size_t stride_5() const { return 0; }
213  KOKKOS_INLINE_FUNCTION constexpr size_t stride_6() const { return 0; }
214  KOKKOS_INLINE_FUNCTION constexpr size_t stride_7() const { return 0; }
215 
216  template <typename iType>
217  KOKKOS_INLINE_FUNCTION void stride(iType* const s) const {
218  *s = 0;
219  }
220 
221  //----------------------------------------
222  // Allocation tracking properties
223 
224  KOKKOS_INLINE_FUNCTION
225  int use_count() const { return m_track.use_count(); }
226 
227  inline const std::string label() const {
228  return m_track.template get_label<typename traits::memory_space>();
229  }
230 
231  //----------------------------------------------------------------------
232  // Range span is the span which contains all members.
233 
234  typedef typename traits::value_type& reference_type;
235  typedef typename traits::value_type* pointer_type;
236 
237  enum {
238  reference_type_is_lvalue_reference =
239  std::is_lvalue_reference<reference_type>::value
240  };
241 
242  KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const {
243  return false;
244  }
245  KOKKOS_INLINE_FUNCTION constexpr size_t span() const { return 0; }
246  KOKKOS_INLINE_FUNCTION constexpr pointer_type data() const { return 0; }
247 
248  //----------------------------------------
249 
250  template <typename I0, class... Args>
251  KOKKOS_INLINE_FUNCTION reference_type
252  operator()(const I0& i0, const Args&... /*args*/) const {
253  static_assert(Kokkos::Impl::are_integral<I0, Args...>::value,
254  "Indices must be integral type");
255 
256  DynamicView::template verify_space<
257  Kokkos::Impl::ActiveExecutionMemorySpace>::check();
258 
259  // Which chunk is being indexed.
260  const uintptr_t ic = uintptr_t(i0 >> m_chunk_shift);
261 
262  typename traits::value_type* volatile* const ch = m_chunks + ic;
263 
264  // Do bounds checking if enabled or if the chunk pointer is zero.
265  // If not bounds checking then we assume a non-zero pointer is valid.
266 
267 #if !defined(KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK)
268  if (nullptr == *ch)
269 #endif
270  {
271  // Verify that allocation of the requested chunk in in progress.
272 
273  // The allocated chunk counter is m_chunks[ m_chunk_max ]
274  const uintptr_t n =
275  *reinterpret_cast<uintptr_t volatile*>(m_chunks + m_chunk_max);
276 
277  if (n <= ic) {
278  Kokkos::abort("Kokkos::DynamicView array bounds error");
279  }
280 
281  // Allocation of this chunk is in progress
282  // so wait for allocation to complete.
283  while (nullptr == *ch)
284  ;
285  }
286 
287  return (*ch)[i0 & m_chunk_mask];
288  }
289 
290  //----------------------------------------
294  template <typename IntType>
295  inline typename std::enable_if<
296  std::is_integral<IntType>::value &&
299  typename Impl::ChunkArraySpace<
300  typename traits::memory_space>::memory_space>::accessible>::type
301  resize_serial(IntType const& n) {
302  typedef typename traits::value_type local_value_type;
303  typedef local_value_type* value_pointer_type;
304 
305  const uintptr_t NC =
306  (n + m_chunk_mask) >>
307  m_chunk_shift; // New total number of chunks needed for resize
308 
309  if (m_chunk_max < NC) {
310  Kokkos::abort("DynamicView::resize_serial exceeded maximum size");
311  }
312 
313  // *m_chunks[m_chunk_max] stores the current number of chunks being used
314  uintptr_t* const pc = reinterpret_cast<uintptr_t*>(m_chunks + m_chunk_max);
315 
316  if (*pc < NC) {
317  while (*pc < NC) {
318  m_chunks[*pc] = reinterpret_cast<value_pointer_type>(
319  typename traits::memory_space().allocate(sizeof(local_value_type)
320  << m_chunk_shift));
321  ++*pc;
322  }
323  } else {
324  while (NC + 1 <= *pc) {
325  --*pc;
326  typename traits::memory_space().deallocate(
327  m_chunks[*pc], sizeof(local_value_type) << m_chunk_shift);
328  m_chunks[*pc] = nullptr;
329  }
330  }
331  // *m_chunks[m_chunk_max+1] stores the 'extent' requested by resize
332  *(pc + 1) = n;
333  }
334 
335  //----------------------------------------------------------------------
336 
337  ~DynamicView() = default;
338  DynamicView() = default;
339  DynamicView(DynamicView&&) = default;
340  DynamicView(const DynamicView&) = default;
341  DynamicView& operator=(DynamicView&&) = default;
342  DynamicView& operator=(const DynamicView&) = default;
343 
344  template <class RT, class... RP>
346  : m_track(rhs.m_track),
347  m_chunks((typename traits::value_type**)rhs.m_chunks),
348  m_chunk_shift(rhs.m_chunk_shift),
349  m_chunk_mask(rhs.m_chunk_mask),
350  m_chunk_max(rhs.m_chunk_max),
351  m_chunk_size(rhs.m_chunk_size) {
352  typedef typename DynamicView<RT, RP...>::traits SrcTraits;
353  typedef Kokkos::Impl::ViewMapping<traits, SrcTraits, void> Mapping;
354  static_assert(Mapping::is_assignable,
355  "Incompatible DynamicView copy construction");
356  }
357 
358  //----------------------------------------------------------------------
359 
360  struct Destroy {
361  typename traits::value_type** m_chunks;
362  unsigned m_chunk_max;
363  bool m_destroy;
364  unsigned m_chunk_size;
365 
366  // Initialize or destroy array of chunk pointers.
367  // Two entries beyond the max chunks are allocation counters.
368  inline void operator()(unsigned i) const {
369  if (m_destroy && i < m_chunk_max && nullptr != m_chunks[i]) {
370  typename traits::memory_space().deallocate(m_chunks[i], m_chunk_size);
371  }
372  m_chunks[i] = nullptr;
373  }
374 
375  void execute(bool arg_destroy) {
377  // typedef Kokkos::RangePolicy< typename Impl::ChunkArraySpace< typename
378  // traits::memory_space >::memory_space::execution_space > Range ;
379 
380  m_destroy = arg_destroy;
381 
383  *this,
384  Range(0, m_chunk_max + 2)); // Add 2 to 'destroy' extra slots storing
385  // num_chunks and extent; previously + 1
386 
387  closure.execute();
388 
389  typename traits::execution_space().fence();
390  // Impl::ChunkArraySpace< typename traits::memory_space
391  // >::memory_space::execution_space().fence();
392  }
393 
394  void construct_shared_allocation() { execute(false); }
395 
396  void destroy_shared_allocation() { execute(true); }
397 
398  Destroy() = default;
399  Destroy(Destroy&&) = default;
400  Destroy(const Destroy&) = default;
401  Destroy& operator=(Destroy&&) = default;
402  Destroy& operator=(const Destroy&) = default;
403 
404  Destroy(typename traits::value_type** arg_chunk,
405  const unsigned arg_chunk_max, const unsigned arg_chunk_size)
406  : m_chunks(arg_chunk),
407  m_chunk_max(arg_chunk_max),
408  m_destroy(false),
409  m_chunk_size(arg_chunk_size) {}
410  };
411 
418  explicit inline DynamicView(const std::string& arg_label,
419  const unsigned min_chunk_size,
420  const unsigned max_extent)
421  : m_track(),
422  m_chunks(nullptr)
423  // The chunk size is guaranteed to be a power of two
424  ,
425  m_chunk_shift(Kokkos::Impl::integral_power_of_two_that_contains(
426  min_chunk_size)) // div ceil(log2(min_chunk_size))
427  ,
428  m_chunk_mask((1 << m_chunk_shift) - 1) // mod
429  ,
430  m_chunk_max((max_extent + m_chunk_mask) >>
431  m_chunk_shift) // max num pointers-to-chunks in array
432  ,
433  m_chunk_size(2 << (m_chunk_shift - 1)) {
434  typedef typename Impl::ChunkArraySpace<
435  typename traits::memory_space>::memory_space chunk_array_memory_space;
436  // A functor to deallocate all of the chunks upon final destruction
437  typedef Kokkos::Impl::SharedAllocationRecord<chunk_array_memory_space,
438  Destroy>
439  record_type;
440 
441  // Allocate chunk pointers and allocation counter
442  record_type* const record =
443  record_type::allocate(chunk_array_memory_space(), arg_label,
444  (sizeof(pointer_type) * (m_chunk_max + 2)));
445  // Allocate + 2 extra slots so that *m_chunk[m_chunk_max] ==
446  // num_chunks_alloc and *m_chunk[m_chunk_max+1] == extent This must match in
447  // Destroy's execute(...) method
448 
449  m_chunks = reinterpret_cast<pointer_type*>(record->data());
450 
451  record->m_destroy = Destroy(m_chunks, m_chunk_max, m_chunk_size);
452 
453  // Initialize to zero
454  record->m_destroy.construct_shared_allocation();
455 
456  m_track.assign_allocated_record_to_uninitialized(record);
457  }
458 };
459 
460 } // namespace Experimental
461 } // namespace Kokkos
462 
463 namespace Kokkos {
464 
465 template <class T, class... P>
466 inline typename Kokkos::Experimental::DynamicView<T, P...>::HostMirror
467 create_mirror_view(const Kokkos::Experimental::DynamicView<T, P...>& src) {
468  return src;
469 }
470 
471 template <class T, class... DP, class... SP>
472 inline void deep_copy(const View<T, DP...>& dst,
474  typedef View<T, DP...> dst_type;
475  typedef Kokkos::Experimental::DynamicView<T, SP...> src_type;
476 
477  typedef typename ViewTraits<T, DP...>::execution_space dst_execution_space;
478  typedef typename ViewTraits<T, SP...>::memory_space src_memory_space;
479 
480  enum {
481  DstExecCanAccessSrc =
482  Kokkos::Impl::SpaceAccessibility<dst_execution_space,
483  src_memory_space>::accessible
484  };
485 
486  if (DstExecCanAccessSrc) {
487  // Copying data between views in accessible memory spaces and either
488  // non-contiguous or incompatible shape.
489  Kokkos::Impl::ViewRemap<dst_type, src_type>(dst, src);
490  } else {
491  Kokkos::Impl::throw_runtime_exception(
492  "deep_copy given views that would require a temporary allocation");
493  }
494 }
495 
496 template <class T, class... DP, class... SP>
498  const View<T, SP...>& src) {
499  typedef Kokkos::Experimental::DynamicView<T, SP...> dst_type;
500  typedef View<T, DP...> src_type;
501 
502  typedef typename ViewTraits<T, DP...>::execution_space dst_execution_space;
503  typedef typename ViewTraits<T, SP...>::memory_space src_memory_space;
504 
505  enum {
506  DstExecCanAccessSrc =
507  Kokkos::Impl::SpaceAccessibility<dst_execution_space,
508  src_memory_space>::accessible
509  };
510 
511  if (DstExecCanAccessSrc) {
512  // Copying data between views in accessible memory spaces and either
513  // non-contiguous or incompatible shape.
514  Kokkos::Impl::ViewRemap<dst_type, src_type>(dst, src);
515  } else {
516  Kokkos::Impl::throw_runtime_exception(
517  "deep_copy given views that would require a temporary allocation");
518  }
519 }
520 
521 namespace Impl {
522 template <class Arg0, class... DP, class... SP>
523 struct CommonSubview<Kokkos::Experimental::DynamicView<DP...>,
524  Kokkos::Experimental::DynamicView<SP...>, 1, Arg0> {
525  typedef Kokkos::Experimental::DynamicView<DP...> DstType;
526  typedef Kokkos::Experimental::DynamicView<SP...> SrcType;
527  typedef DstType dst_subview_type;
528  typedef SrcType src_subview_type;
529  dst_subview_type dst_sub;
530  src_subview_type src_sub;
531  CommonSubview(const DstType& dst, const SrcType& src, const Arg0& /*arg0*/)
532  : dst_sub(dst), src_sub(src) {}
533 };
534 
535 template <class... DP, class SrcType, class Arg0>
536 struct CommonSubview<Kokkos::Experimental::DynamicView<DP...>, SrcType, 1,
537  Arg0> {
538  typedef Kokkos::Experimental::DynamicView<DP...> DstType;
539  typedef DstType dst_subview_type;
540  typedef typename Kokkos::Subview<SrcType, Arg0> src_subview_type;
541  dst_subview_type dst_sub;
542  src_subview_type src_sub;
543  CommonSubview(const DstType& dst, const SrcType& src, const Arg0& arg0)
544  : dst_sub(dst), src_sub(src, arg0) {}
545 };
546 
547 template <class DstType, class... SP, class Arg0>
548 struct CommonSubview<DstType, Kokkos::Experimental::DynamicView<SP...>, 1,
549  Arg0> {
550  typedef Kokkos::Experimental::DynamicView<SP...> SrcType;
551  typedef typename Kokkos::Subview<DstType, Arg0> dst_subview_type;
552  typedef SrcType src_subview_type;
553  dst_subview_type dst_sub;
554  src_subview_type src_sub;
555  CommonSubview(const DstType& dst, const SrcType& src, const Arg0& arg0)
556  : dst_sub(dst, arg0), src_sub(src) {}
557 };
558 
559 template <class... DP, class ViewTypeB, class Layout, class ExecSpace,
560  typename iType>
561 struct ViewCopy<Kokkos::Experimental::DynamicView<DP...>, ViewTypeB, Layout,
562  ExecSpace, 1, iType, false> {
564  ViewTypeB b;
565 
567 
568  ViewCopy(const Kokkos::Experimental::DynamicView<DP...>& a_,
569  const ViewTypeB& b_)
570  : a(a_), b(b_) {
571  Kokkos::parallel_for("Kokkos::ViewCopy-1D", policy_type(0, b.extent(0)),
572  *this);
573  }
574 
575  KOKKOS_INLINE_FUNCTION
576  void operator()(const iType& i0) const { a(i0) = b(i0); };
577 };
578 
579 template <class... DP, class... SP, class Layout, class ExecSpace,
580  typename iType>
581 struct ViewCopy<Kokkos::Experimental::DynamicView<DP...>,
582  Kokkos::Experimental::DynamicView<SP...>, Layout, ExecSpace, 1,
583  iType, false> {
586 
588 
589  ViewCopy(const Kokkos::Experimental::DynamicView<DP...>& a_,
591  : a(a_), b(b_) {
592  const iType n = std::min(a.extent(0), b.extent(0));
593  Kokkos::parallel_for("Kokkos::ViewCopy-1D", policy_type(0, n), *this);
594  }
595 
596  KOKKOS_INLINE_FUNCTION
597  void operator()(const iType& i0) const { a(i0) = b(i0); };
598 };
599 
600 } // namespace Impl
601 } // namespace Kokkos
602 
603 #endif /* #ifndef KOKKOS_DYNAMIC_VIEW_HPP */
DynamicView(const std::string &arg_label, const unsigned min_chunk_size, const unsigned max_extent)
Allocation constructor.
DynamicView< typename traits::non_const_data_type, typename traits::device_type > non_const_type
Compatible view of non-const data type.
void deep_copy(const View< DT, DP...> &dst, typename ViewTraits< DT, DP...>::const_value_type &value, typename std::enable_if< std::is_same< typename ViewTraits< DT, DP...>::specialize, void >::value >::type *=nullptr)
Deep copy a value from Host memory into a view.
Dynamic views are restricted to rank-one and no layout. Resize only occurs on host outside of paralle...
Can AccessSpace access MemorySpace ?
Memory management for host memory.
DynamicView HostMirror
Must be accessible everywhere.
Implementation of the ParallelFor operator that has a partial specialization for the device...
void parallel_for(const ExecPolicy &policy, const FunctorType &functor, const std::string &str="", typename std::enable_if< Kokkos::Impl::is_execution_policy< ExecPolicy >::value >::type *=nullptr)
Execute functor in parallel according to the execution policy.
DynamicView< typename traits::data_type, typename traits::device_type > array_type
Compatible view of array of scalar types.
Execution policy for work over a range of an integral type.
DynamicView< typename traits::const_data_type, typename traits::device_type > const_type
Compatible view of const data type.
Traits class for accessing attributes of a View.
std::enable_if< std::is_integral< IntType >::value &&Kokkos::Impl::MemorySpaceAccess< Kokkos::HostSpace, typename Impl::ChunkArraySpace< typename traits::memory_space >::memory_space >::accessible >::type resize_serial(IntType const &n)
Resizing in serial can grow or shrink the array size up to the maximum number of chunks.
Kokkos::Device< typename traits::device_type::execution_space, Kokkos::AnonymousSpace > uniform_device
Unified types.
Access relationship between DstMemorySpace and SrcMemorySpace.