45 #ifndef KOKKOS_DYNAMIC_VIEW_HPP 46 #define KOKKOS_DYNAMIC_VIEW_HPP 50 #include <Kokkos_Core.hpp> 51 #include <impl/Kokkos_Error.hpp> 62 template <
class MemSpace>
63 struct ChunkArraySpace {
64 using memory_space = MemSpace;
67 #ifdef KOKKOS_ENABLE_CUDA 69 struct ChunkArraySpace<
Kokkos::CudaSpace> {
70 using memory_space =
typename Kokkos::CudaUVMSpace;
73 #ifdef KOKKOS_ENABLE_HIP 75 struct ChunkArraySpace<
Kokkos::Experimental::HIPSpace> {
76 using memory_space =
typename Kokkos::Experimental::HIPHostPinnedSpace;
79 #ifdef KOKKOS_ENABLE_SYCL 81 struct ChunkArraySpace<
Kokkos::Experimental::SYCLDeviceUSMSpace> {
82 using memory_space =
typename Kokkos::Experimental::SYCLSharedUSMSpace;
91 template <
typename DataType,
typename... P>
97 template <
class,
class...>
100 using track_type = Kokkos::Impl::SharedAllocationTracker;
102 static_assert(traits::rank == 1 && traits::rank_dynamic == 1,
103 "DynamicView must be rank-one");
107 static_assert(std::is_same<typename traits::specialize, void>::value,
108 "DynamicView only implemented for non-specialized View type");
111 Space,
typename traits::memory_space>::accessible>
112 struct verify_space {
113 KOKKOS_FORCEINLINE_FUNCTION
static void check() {}
116 template <
class Space>
117 struct verify_space<Space, false> {
118 KOKKOS_FORCEINLINE_FUNCTION
static void check() {
120 "Kokkos::DynamicView ERROR: attempt to access inaccessible memory " 127 typename traits::value_type** m_chunks =
129 unsigned m_chunk_shift;
130 unsigned m_chunk_mask;
131 unsigned m_chunk_max;
133 unsigned m_chunk_size;
144 typename traits::device_type>;
148 typename traits::device_type>;
155 Kokkos::Device<
typename traits::device_type::execution_space,
156 Kokkos::AnonymousSpace>;
174 KOKKOS_INLINE_FUNCTION
175 size_t allocation_extent() const noexcept {
176 uintptr_t n = *
reinterpret_cast<const uintptr_t*
>(m_chunks + m_chunk_max);
177 return (n << m_chunk_shift);
180 KOKKOS_INLINE_FUNCTION
181 size_t chunk_size() const noexcept {
return m_chunk_size; }
183 KOKKOS_INLINE_FUNCTION
184 size_t size() const noexcept {
186 *
reinterpret_cast<const size_t*
>(m_chunks + m_chunk_max + 1);
190 template <
typename iType>
191 KOKKOS_INLINE_FUNCTION
size_t extent(
const iType& r)
const {
192 return r == 0 ? size() : 1;
195 template <
typename iType>
196 KOKKOS_INLINE_FUNCTION
size_t extent_int(
const iType& r)
const {
197 return r == 0 ? size() : 1;
200 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_0()
const {
return 0; }
201 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_1()
const {
return 0; }
202 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_2()
const {
return 0; }
203 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_3()
const {
return 0; }
204 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_4()
const {
return 0; }
205 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_5()
const {
return 0; }
206 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_6()
const {
return 0; }
207 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_7()
const {
return 0; }
209 template <
typename iType>
210 KOKKOS_INLINE_FUNCTION
void stride(iType*
const s)
const {
217 KOKKOS_INLINE_FUNCTION
218 int use_count()
const {
return m_track.use_count(); }
220 inline const std::string label()
const {
221 return m_track.template get_label<typename traits::memory_space>();
227 using reference_type =
typename traits::value_type&;
228 using pointer_type =
typename traits::value_type*;
231 reference_type_is_lvalue_reference =
232 std::is_lvalue_reference<reference_type>::value
235 KOKKOS_INLINE_FUNCTION constexpr
bool span_is_contiguous()
const {
238 KOKKOS_INLINE_FUNCTION constexpr
size_t span()
const {
return 0; }
239 KOKKOS_INLINE_FUNCTION constexpr pointer_type data()
const {
return 0; }
243 template <
typename I0,
class... Args>
244 KOKKOS_INLINE_FUNCTION reference_type
245 operator()(
const I0& i0,
const Args&... )
const {
246 static_assert(Kokkos::Impl::are_integral<I0, Args...>::value,
247 "Indices must be integral type");
249 DynamicView::template verify_space<
250 Kokkos::Impl::ActiveExecutionMemorySpace>::check();
253 const uintptr_t ic = uintptr_t(i0 >> m_chunk_shift);
255 typename traits::value_type*
volatile*
const ch = m_chunks + ic;
260 #if !defined(KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK) 268 *
reinterpret_cast<uintptr_t volatile*
>(m_chunks + m_chunk_max);
271 Kokkos::abort(
"Kokkos::DynamicView array bounds error");
276 while (
nullptr == *ch)
280 return (*ch)[i0 & m_chunk_mask];
287 template <
typename IntType>
288 inline typename std::enable_if<
289 std::is_integral<IntType>::value &&
292 typename Impl::ChunkArraySpace<
293 typename traits::memory_space>::memory_space>::accessible>::type
295 using local_value_type =
typename traits::value_type;
296 using value_pointer_type = local_value_type*;
299 (n + m_chunk_mask) >>
302 if (m_chunk_max < NC) {
303 Kokkos::abort(
"DynamicView::resize_serial exceeded maximum size");
307 uintptr_t*
const pc =
reinterpret_cast<uintptr_t*
>(m_chunks + m_chunk_max);
309 m_track.template get_label<typename traits::memory_space>();
312 m_chunks[*pc] =
reinterpret_cast<value_pointer_type
>(
313 typename traits::memory_space().allocate(
314 _label.c_str(),
sizeof(local_value_type) << m_chunk_shift));
318 while (NC + 1 <= *pc) {
320 typename traits::memory_space().deallocate(
321 _label.c_str(), m_chunks[*pc],
322 sizeof(local_value_type) << m_chunk_shift);
323 m_chunks[*pc] =
nullptr;
330 KOKKOS_INLINE_FUNCTION
bool is_allocated()
const {
331 if (m_chunks ==
nullptr) {
335 uintptr_t*
const pc =
336 reinterpret_cast<uintptr_t*
>(m_chunks + m_chunk_max);
337 return (*(pc + 1) > 0);
343 ~DynamicView() =
default;
344 DynamicView() =
default;
345 DynamicView(DynamicView&&) =
default;
346 DynamicView(
const DynamicView&) =
default;
347 DynamicView& operator=(DynamicView&&) =
default;
348 DynamicView& operator=(
const DynamicView&) =
default;
350 template <
class RT,
class... RP>
351 DynamicView(
const DynamicView<RT, RP...>& rhs)
352 : m_track(rhs.m_track),
353 m_chunks((typename traits::value_type**)rhs.m_chunks),
354 m_chunk_shift(rhs.m_chunk_shift),
355 m_chunk_mask(rhs.m_chunk_mask),
356 m_chunk_max(rhs.m_chunk_max),
357 m_chunk_size(rhs.m_chunk_size) {
358 using SrcTraits =
typename DynamicView<RT, RP...>::traits;
359 using Mapping = Kokkos::Impl::ViewMapping<traits, SrcTraits, void>;
360 static_assert(Mapping::is_assignable,
361 "Incompatible DynamicView copy construction");
367 using local_value_type =
typename traits::value_type;
369 local_value_type** m_chunks;
370 unsigned m_chunk_max;
372 unsigned m_chunk_size;
376 inline void operator()(
unsigned i)
const {
377 if (m_destroy && i < m_chunk_max &&
nullptr != m_chunks[i]) {
378 typename traits::memory_space().deallocate(
379 m_label.c_str(), m_chunks[i],
380 sizeof(local_value_type) * m_chunk_size);
382 m_chunks[i] =
nullptr;
385 void execute(
bool arg_destroy) {
388 m_destroy = arg_destroy;
392 Range(0, m_chunk_max + 2));
397 typename traits::execution_space().fence();
402 void construct_shared_allocation() { execute(
false); }
404 void destroy_shared_allocation() { execute(
true); }
407 Destroy(Destroy&&) =
default;
408 Destroy(
const Destroy&) =
default;
409 Destroy& operator=(Destroy&&) =
default;
410 Destroy& operator=(
const Destroy&) =
default;
412 Destroy(std::string label,
typename traits::value_type** arg_chunk,
413 const unsigned arg_chunk_max,
const unsigned arg_chunk_size)
416 m_chunk_max(arg_chunk_max),
418 m_chunk_size(arg_chunk_size) {}
428 const unsigned min_chunk_size,
429 const unsigned max_extent)
434 m_chunk_shift(
Kokkos::Impl::integral_power_of_two_that_contains(
437 m_chunk_mask((1 << m_chunk_shift) - 1)
439 m_chunk_max((max_extent + m_chunk_mask) >>
442 m_chunk_size(2 << (m_chunk_shift - 1)) {
443 using chunk_array_memory_space =
typename Impl::ChunkArraySpace<
444 typename traits::memory_space>::memory_space;
447 Kokkos::Impl::SharedAllocationRecord<chunk_array_memory_space, Destroy>;
450 record_type*
const record =
451 record_type::allocate(chunk_array_memory_space(), arg_label,
452 (
sizeof(pointer_type) * (m_chunk_max + 2)));
457 m_chunks =
reinterpret_cast<pointer_type*
>(record->data());
459 record->m_destroy = Destroy(arg_label, m_chunks, m_chunk_max, m_chunk_size);
462 record->m_destroy.construct_shared_allocation();
464 m_track.assign_allocated_record_to_uninitialized(record);
473 template <
class T,
class... P>
479 template <
class T,
class... DP,
class... SP>
480 inline void deep_copy(
const View<T, DP...>& dst,
482 using dst_type =
View<T, DP...>;
485 using dst_execution_space =
typename ViewTraits<T, DP...>::execution_space;
486 using src_memory_space =
typename ViewTraits<T, SP...>::memory_space;
489 DstExecCanAccessSrc =
491 src_memory_space>::accessible
494 if (DstExecCanAccessSrc) {
497 Kokkos::Impl::ViewRemap<dst_type, src_type>(dst, src);
499 Kokkos::Impl::throw_runtime_exception(
500 "deep_copy given views that would require a temporary allocation");
504 template <
class T,
class... DP,
class... SP>
506 const View<T, SP...>& src) {
508 using src_type =
View<T, DP...>;
510 using dst_execution_space =
typename ViewTraits<T, DP...>::execution_space;
511 using src_memory_space =
typename ViewTraits<T, SP...>::memory_space;
514 DstExecCanAccessSrc =
516 src_memory_space>::accessible
519 if (DstExecCanAccessSrc) {
522 Kokkos::Impl::ViewRemap<dst_type, src_type>(dst, src);
524 Kokkos::Impl::throw_runtime_exception(
525 "deep_copy given views that would require a temporary allocation");
530 template <
class Arg0,
class... DP,
class... SP>
531 struct CommonSubview<
Kokkos::Experimental::DynamicView<DP...>,
535 using dst_subview_type = DstType;
536 using src_subview_type = SrcType;
537 dst_subview_type dst_sub;
538 src_subview_type src_sub;
539 CommonSubview(
const DstType& dst,
const SrcType& src,
const Arg0& )
540 : dst_sub(dst), src_sub(src) {}
543 template <
class... DP,
class SrcType,
class Arg0>
544 struct CommonSubview<
Kokkos::Experimental::DynamicView<DP...>, SrcType, 1,
547 using dst_subview_type = DstType;
548 using src_subview_type =
typename Kokkos::Subview<SrcType, Arg0>;
549 dst_subview_type dst_sub;
550 src_subview_type src_sub;
551 CommonSubview(
const DstType& dst,
const SrcType& src,
const Arg0& arg0)
552 : dst_sub(dst), src_sub(src, arg0) {}
555 template <
class DstType,
class... SP,
class Arg0>
556 struct CommonSubview<DstType,
Kokkos::Experimental::DynamicView<SP...>, 1,
559 using dst_subview_type =
typename Kokkos::Subview<DstType, Arg0>;
560 using src_subview_type = SrcType;
561 dst_subview_type dst_sub;
562 src_subview_type src_sub;
563 CommonSubview(
const DstType& dst,
const SrcType& src,
const Arg0& arg0)
564 : dst_sub(dst, arg0), src_sub(src) {}
567 template <
class... DP,
class ViewTypeB,
class Layout,
class ExecSpace,
569 struct ViewCopy<
Kokkos::Experimental::DynamicView<DP...>, ViewTypeB, Layout,
570 ExecSpace, 1, iType> {
579 Kokkos::parallel_for(
"Kokkos::ViewCopy-1D", policy_type(0, b.extent(0)),
583 KOKKOS_INLINE_FUNCTION
584 void operator()(
const iType& i0)
const { a(i0) = b(i0); };
587 template <
class... DP,
class... SP,
class Layout,
class ExecSpace,
589 struct ViewCopy<
Kokkos::Experimental::DynamicView<DP...>,
600 const iType n = std::min(a.extent(0), b.extent(0));
601 Kokkos::parallel_for(
"Kokkos::ViewCopy-1D", policy_type(0, n), *
this);
604 KOKKOS_INLINE_FUNCTION
605 void operator()(
const iType& i0)
const { a(i0) = b(i0); };
DynamicView(const std::string &arg_label, const unsigned min_chunk_size, const unsigned max_extent)
Allocation constructor.
DynamicView< typename traits::data_type, typename traits::device_type > array_type
Compatible view of array of scalar types.
Dynamic views are restricted to rank-one and no layout. Resize only occurs on host outside of paralle...
Can AccessSpace access MemorySpace ?
Kokkos::Device< typename traits::device_type::execution_space, Kokkos::AnonymousSpace > uniform_device
Unified types.
DynamicView< typename traits::const_data_type, typename traits::device_type > const_type
Compatible view of const data type.
Memory management for host memory.
Implementation of the ParallelFor operator that has a partial specialization for the device...
Execution policy for work over a range of an integral 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.
Access relationship between DstMemorySpace and SrcMemorySpace.