44 #ifndef KOKKOS_DYNAMIC_VIEW_HPP
45 #define KOKKOS_DYNAMIC_VIEW_HPP
49 #include <Kokkos_Core.hpp>
50 #include <impl/Kokkos_Error.hpp>
53 namespace Experimental {
61 template <
class MemSpace >
62 struct ChunkArraySpace {
63 using memory_space = MemSpace;
66 #ifdef KOKKOS_ENABLE_CUDA
68 struct ChunkArraySpace< Kokkos::CudaSpace > {
69 using memory_space =
typename Kokkos::CudaUVMSpace;
72 #ifdef KOKKOS_ENABLE_ROCM
74 struct ChunkArraySpace< Kokkos::Experimental::ROCmSpace > {
75 using memory_space =
typename Kokkos::Experimental::ROCmHostPinnedSpace;
84 template<
typename DataType ,
typename ... P >
93 template< class ,
class ... >
friend class DynamicView ;
95 typedef Kokkos::Impl::SharedAllocationTracker track_type ;
97 static_assert( traits::rank == 1 && traits::rank_dynamic == 1
98 ,
"DynamicView must be rank-one" );
102 static_assert( std::is_same< typename traits::specialize , void >::value
103 ,
"DynamicView only implemented for non-specialized View type");
106 template< class Space , bool = Kokkos::Impl::MemorySpaceAccess< Space , typename traits::memory_space >::accessible >
struct verify_space
107 { KOKKOS_FORCEINLINE_FUNCTION
static void check() {} };
109 template<
class Space >
struct verify_space<Space,false>
110 { KOKKOS_FORCEINLINE_FUNCTION
static void check()
111 { Kokkos::abort(
"Kokkos::DynamicView ERROR: attempt to access inaccessible memory space"); };
117 typename traits::value_type ** m_chunks ;
118 unsigned m_chunk_shift ;
119 unsigned m_chunk_mask ;
120 unsigned m_chunk_max ;
121 unsigned m_chunk_size ;
129 typename traits::device_type >
133 typedef DynamicView<
typename traits::const_data_type ,
134 typename traits::device_type >
138 typedef DynamicView<
typename traits::non_const_data_type ,
139 typename traits::device_type >
146 typedef Kokkos::Device<typename traits::device_type::execution_space, Kokkos::AnonymousSpace>
uniform_device;
160 KOKKOS_INLINE_FUNCTION
161 size_t allocation_extent() const noexcept
163 uintptr_t n = *
reinterpret_cast<const uintptr_t*
>( m_chunks + m_chunk_max );
164 return (n << m_chunk_shift);
167 KOKKOS_INLINE_FUNCTION
168 size_t chunk_size() const noexcept
173 KOKKOS_INLINE_FUNCTION
174 size_t size() const noexcept
176 size_t extent_0 = *
reinterpret_cast<const size_t*
>( m_chunks + m_chunk_max +1 );
180 template<
typename iType >
181 KOKKOS_INLINE_FUNCTION
182 size_t extent(
const iType & r )
const
183 {
return r == 0 ? size() : 1 ; }
185 template<
typename iType >
186 KOKKOS_INLINE_FUNCTION
187 size_t extent_int(
const iType & r )
const
188 {
return r == 0 ? size() : 1 ; }
190 #ifdef KOKKOS_ENABLE_DEPRECATED_CODE
191 KOKKOS_INLINE_FUNCTION
size_t dimension_0()
const {
return size(); }
192 KOKKOS_INLINE_FUNCTION constexpr
size_t dimension_1()
const {
return 1 ; }
193 KOKKOS_INLINE_FUNCTION constexpr
size_t dimension_2()
const {
return 1 ; }
194 KOKKOS_INLINE_FUNCTION constexpr
size_t dimension_3()
const {
return 1 ; }
195 KOKKOS_INLINE_FUNCTION constexpr
size_t dimension_4()
const {
return 1 ; }
196 KOKKOS_INLINE_FUNCTION constexpr
size_t dimension_5()
const {
return 1 ; }
197 KOKKOS_INLINE_FUNCTION constexpr
size_t dimension_6()
const {
return 1 ; }
198 KOKKOS_INLINE_FUNCTION constexpr
size_t dimension_7()
const {
return 1 ; }
201 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_0()
const {
return 0 ; }
202 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_1()
const {
return 0 ; }
203 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_2()
const {
return 0 ; }
204 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_3()
const {
return 0 ; }
205 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_4()
const {
return 0 ; }
206 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_5()
const {
return 0 ; }
207 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_6()
const {
return 0 ; }
208 KOKKOS_INLINE_FUNCTION constexpr
size_t stride_7()
const {
return 0 ; }
210 template<
typename iType >
211 KOKKOS_INLINE_FUNCTION
void stride( iType *
const s )
const { *s = 0 ; }
216 KOKKOS_INLINE_FUNCTION
217 int use_count()
const
218 {
return m_track.use_count(); }
221 const std::string label()
const
222 {
return m_track.template get_label< typename traits::memory_space >(); }
227 typedef typename traits::value_type & reference_type ;
228 typedef typename traits::value_type * pointer_type ;
230 enum { reference_type_is_lvalue_reference = std::is_lvalue_reference< reference_type >::value };
232 KOKKOS_INLINE_FUNCTION constexpr
bool span_is_contiguous()
const {
return false ; }
233 KOKKOS_INLINE_FUNCTION constexpr
size_t span()
const {
return 0 ; }
234 KOKKOS_INLINE_FUNCTION constexpr pointer_type data()
const {
return 0 ; }
238 template<
typename I0 ,
class ... Args >
239 KOKKOS_INLINE_FUNCTION
240 reference_type operator()(
const I0 & i0 ,
const Args & ... args )
const
242 static_assert( Kokkos::Impl::are_integral<I0,Args...>::value
243 ,
"Indices must be integral type" );
245 DynamicView::template verify_space< Kokkos::Impl::ActiveExecutionMemorySpace >::check();
248 const uintptr_t ic = uintptr_t( i0 >> m_chunk_shift );
250 typename traits::value_type *
volatile *
const ch = m_chunks + ic ;
255 #if ! defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK )
263 *
reinterpret_cast<uintptr_t
volatile *
>( m_chunks + m_chunk_max );
266 Kokkos::abort(
"Kokkos::DynamicView array bounds error");
274 return (*ch)[ i0 & m_chunk_mask ];
281 template<
typename IntType >
283 typename std::enable_if
284 < std::is_integral<IntType>::value &&
286 ,
typename Impl::ChunkArraySpace< typename traits::memory_space >::memory_space
291 typedef typename traits::value_type value_type ;
292 typedef value_type * value_pointer_type ;
294 const uintptr_t NC = ( n + m_chunk_mask ) >> m_chunk_shift ;
296 if ( m_chunk_max < NC ) {
297 Kokkos::abort(
"DynamicView::resize_serial exceeded maximum size");
301 uintptr_t *
const pc =
302 reinterpret_cast<uintptr_t*
>( m_chunks + m_chunk_max );
306 m_chunks[*pc] =
reinterpret_cast<value_pointer_type
>
308 typename traits::memory_space().allocate(
sizeof(value_type) << m_chunk_shift )
314 while ( NC + 1 <= *pc ) {
316 typename traits::memory_space().deallocate( m_chunks[*pc]
317 ,
sizeof(value_type) << m_chunk_shift );
334 template<
class RT ,
class ... RP >
336 : m_track( rhs.m_track )
337 , m_chunks( (typename traits::value_type **) rhs.m_chunks )
338 , m_chunk_shift( rhs.m_chunk_shift )
339 , m_chunk_mask( rhs.m_chunk_mask )
340 , m_chunk_max( rhs.m_chunk_max )
341 , m_chunk_size( rhs.m_chunk_size )
343 typedef typename DynamicView<RT,RP...>::traits SrcTraits ;
344 typedef Kokkos::Impl::ViewMapping< traits , SrcTraits , void > Mapping ;
345 static_assert( Mapping::is_assignable ,
"Incompatible DynamicView copy construction" );
351 typename traits::value_type ** m_chunks ;
352 unsigned m_chunk_max ;
354 unsigned m_chunk_size ;
359 void operator()(
unsigned i )
const
361 if ( m_destroy && i < m_chunk_max && 0 != m_chunks[i] ) {
362 typename traits::memory_space().deallocate( m_chunks[i], m_chunk_size );
367 void execute(
bool arg_destroy )
372 m_destroy = arg_destroy ;
375 closure( *
this , Range(0, m_chunk_max + 2) );
379 traits::execution_space::fence();
383 void construct_shared_allocation()
384 { execute(
false ); }
386 void destroy_shared_allocation()
389 Destroy() = default ;
390 Destroy( Destroy && ) = default ;
391 Destroy(
const Destroy & ) = default ;
392 Destroy & operator = ( Destroy && ) = default ;
393 Destroy & operator = (
const Destroy & ) = default ;
395 Destroy(
typename traits::value_type ** arg_chunk
396 ,
const unsigned arg_chunk_max
397 ,
const unsigned arg_chunk_size )
398 : m_chunks( arg_chunk )
399 , m_chunk_max( arg_chunk_max )
401 , m_chunk_size( arg_chunk_size )
414 ,
const unsigned min_chunk_size
415 ,
const unsigned max_extent )
420 Kokkos::Impl::integral_power_of_two_that_contains( min_chunk_size ) )
421 , m_chunk_mask( ( 1 << m_chunk_shift ) - 1 )
422 , m_chunk_max( ( max_extent + m_chunk_mask ) >> m_chunk_shift )
423 , m_chunk_size ( 2 << (m_chunk_shift - 1) )
425 typedef typename Impl::ChunkArraySpace< typename traits::memory_space >::memory_space chunk_array_memory_space;
427 typedef Kokkos::Impl::SharedAllocationRecord< chunk_array_memory_space , Destroy > record_type ;
430 record_type *
const record =
431 record_type::allocate( chunk_array_memory_space()
433 , (
sizeof(pointer_type) * ( m_chunk_max + 2 ) ) );
437 m_chunks =
reinterpret_cast<pointer_type*
>( record->data() );
439 record->m_destroy = Destroy( m_chunks , m_chunk_max, m_chunk_size );
442 record->m_destroy.construct_shared_allocation();
444 m_track.assign_allocated_record_to_uninitialized( record );
454 template<
class T ,
class ... P >
462 template<
class T ,
class ... DP ,
class ... SP >
464 void deep_copy(
const View<T,DP...> & dst
468 typedef View<T,DP...> dst_type ;
471 typedef typename ViewTraits<T,DP...>::execution_space dst_execution_space ;
472 typedef typename ViewTraits<T,SP...>::memory_space src_memory_space ;
474 enum { DstExecCanAccessSrc =
477 if ( DstExecCanAccessSrc ) {
479 Kokkos::Impl::ViewRemap< dst_type , src_type >( dst , src );
482 Kokkos::Impl::throw_runtime_exception(
"deep_copy given views that would require a temporary allocation");
486 template<
class T ,
class ... DP ,
class ... SP >
489 ,
const View<T,SP...> & src
493 typedef View<T,DP...> src_type ;
495 typedef typename ViewTraits<T,DP...>::execution_space dst_execution_space ;
496 typedef typename ViewTraits<T,SP...>::memory_space src_memory_space ;
498 enum { DstExecCanAccessSrc =
501 if ( DstExecCanAccessSrc ) {
503 Kokkos::Impl::ViewRemap< dst_type , src_type >( dst , src );
506 Kokkos::Impl::throw_runtime_exception(
"deep_copy given views that would require a temporary allocation");
511 template<
class Arg0,
class ... DP ,
class ... SP>
515 typedef DstType dst_subview_type;
516 typedef SrcType src_subview_type;
517 dst_subview_type dst_sub;
518 src_subview_type src_sub;
519 CommonSubview(
const DstType& dst,
const SrcType& src,
const Arg0& arg0):
520 dst_sub(dst),src_sub(src) {}
523 template<
class ...DP,
class SrcType,
class Arg0>
524 struct CommonSubview<Kokkos::Experimental::DynamicView<DP...>,SrcType,1,Arg0> {
526 typedef DstType dst_subview_type;
527 typedef typename Kokkos::Subview<SrcType,Arg0> src_subview_type;
528 dst_subview_type dst_sub;
529 src_subview_type src_sub;
530 CommonSubview(
const DstType& dst,
const SrcType& src,
const Arg0& arg0):
531 dst_sub(dst),src_sub(src,arg0) {}
534 template<
class DstType,
class ...SP,
class Arg0>
535 struct CommonSubview<DstType,Kokkos::Experimental::DynamicView<SP...>,1,Arg0> {
537 typedef typename Kokkos::Subview<DstType,Arg0> dst_subview_type;
538 typedef SrcType src_subview_type;
539 dst_subview_type dst_sub;
540 src_subview_type src_sub;
541 CommonSubview(
const DstType& dst,
const SrcType& src,
const Arg0& arg0):
542 dst_sub(dst,arg0),src_sub(src) {}
545 template<
class ...DP,
class ViewTypeB,
class Layout,
class ExecSpace,
typename iType>
546 struct ViewCopy<Kokkos::Experimental::DynamicView<DP...>,ViewTypeB,Layout,ExecSpace,1,iType,false> {
554 policy_type(0,b.extent(0)),*
this);
557 KOKKOS_INLINE_FUNCTION
558 void operator() (
const iType& i0)
const {
563 template<
class ...DP,
class ...SP,
class Layout,
class ExecSpace,
typename iType>
564 struct ViewCopy<Kokkos::Experimental::DynamicView<DP...>,
573 const iType n = std::min(a.extent(0),b.extent(0));
575 policy_type(0,n),*
this);
578 KOKKOS_INLINE_FUNCTION
579 void operator() (
const iType& i0)
const {
DynamicView< typename traits::data_type, typename traits::device_type > array_type
Compatible view of array of scalar types.
DynamicView(const std::string &arg_label, const unsigned min_chunk_size, const unsigned max_extent)
Allocation constructor.
void parallel_for(const ExecPolicy &policy, const FunctorType &functor, const std::string &str="", typename Impl::enable_if< Kokkos::Impl::is_execution_policy< ExecPolicy >::value >::type *=0)
Execute functor in parallel according to the execution policy.
Dynamic views are restricted to rank-one and no layout. Resize only occurs on host outside of paralle...
Can AccessSpace access MemorySpace ?
DynamicView< typename traits::const_data_type, typename traits::device_type > const_type
Compatible view of 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 *=0)
Deep copy a value from Host memory into a view.
Memory management for host memory.
DynamicView HostMirror
Must be accessible everywhere.
Implementation of the ParallelFor operator that has a partial specialization for the device...
Execution policy for work over a range of an integral type.
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.
Traits class for accessing attributes of a View.
Kokkos::Device< typename traits::device_type::execution_space, Kokkos::AnonymousSpace > uniform_device
Unified types.
Access relationship between DstMemorySpace and SrcMemorySpace.
DynamicView< typename traits::non_const_data_type, typename traits::device_type > non_const_type
Compatible view of non-const data type.