/* //@HEADER // ************************************************************************ // // Kokkos v. 2.0 // Copyright (2014) Sandia Corporation // // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation, // the U.S. Government retains certain rights in this software. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are // met: // // 1. Redistributions of source code must retain the above copyright // notice, this list of conditions and the following disclaimer. // // 2. Redistributions in binary form must reproduce the above copyright // notice, this list of conditions and the following disclaimer in the // documentation and/or other materials provided with the distribution. // // 3. Neither the name of the Corporation nor the names of the // contributors may be used to endorse or promote products derived from // this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // // Questions? Contact H. Carter Edwards (hcedwar@sandia.gov) // // ************************************************************************ //@HEADER */ #ifndef KOKKOS_VIEW_HPP #define KOKKOS_VIEW_HPP #include #include #include #include #include #include #include #include #if defined(KOKKOS_ENABLE_PROFILING) #include #endif //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- namespace Kokkos { namespace Impl { template< class DataType > struct ViewArrayAnalysis ; template< class DataType , class ArrayLayout , typename ValueType = typename ViewArrayAnalysis< DataType >::non_const_value_type > struct ViewDataAnalysis ; template< class , class ... > class ViewMapping { public: enum { is_assignable = false }; }; } /* namespace Impl */ } /* namespace Kokkos */ //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- namespace Kokkos { /** \class ViewTraits * \brief Traits class for accessing attributes of a View. * * This is an implementation detail of View. It is only of interest * to developers implementing a new specialization of View. * * Template argument options: * - View< DataType > * - View< DataType , Space > * - View< DataType , Space , MemoryTraits > * - View< DataType , ArrayLayout > * - View< DataType , ArrayLayout , Space > * - View< DataType , ArrayLayout , MemoryTraits > * - View< DataType , ArrayLayout , Space , MemoryTraits > * - View< DataType , MemoryTraits > */ template< class DataType , class ... Properties > struct ViewTraits ; template<> struct ViewTraits< void > { typedef void execution_space ; typedef void memory_space ; typedef void HostMirrorSpace ; typedef void array_layout ; typedef void memory_traits ; }; template< class ... Prop > struct ViewTraits< void , void , Prop ... > { // Ignore an extraneous 'void' typedef typename ViewTraits::execution_space execution_space ; typedef typename ViewTraits::memory_space memory_space ; typedef typename ViewTraits::HostMirrorSpace HostMirrorSpace ; typedef typename ViewTraits::array_layout array_layout ; typedef typename ViewTraits::memory_traits memory_traits ; }; template< class ArrayLayout , class ... Prop > struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_array_layout::value >::type , ArrayLayout , Prop ... > { // Specify layout, keep subsequent space and memory traits arguments typedef typename ViewTraits::execution_space execution_space ; typedef typename ViewTraits::memory_space memory_space ; typedef typename ViewTraits::HostMirrorSpace HostMirrorSpace ; typedef ArrayLayout array_layout ; typedef typename ViewTraits::memory_traits memory_traits ; }; template< class Space , class ... Prop > struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_space::value >::type , Space , Prop ... > { // Specify Space, memory traits should be the only subsequent argument. static_assert( std::is_same< typename ViewTraits::execution_space , void >::value && std::is_same< typename ViewTraits::memory_space , void >::value && std::is_same< typename ViewTraits::HostMirrorSpace , void >::value && std::is_same< typename ViewTraits::array_layout , void >::value , "Only one View Execution or Memory Space template argument" ); typedef typename Space::execution_space execution_space ; typedef typename Space::memory_space memory_space ; typedef typename Kokkos::Impl::HostMirror< Space >::Space HostMirrorSpace ; typedef typename execution_space::array_layout array_layout ; typedef typename ViewTraits::memory_traits memory_traits ; }; template< class MemoryTraits , class ... Prop > struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_memory_traits::value >::type , MemoryTraits , Prop ... > { // Specify memory trait, should not be any subsequent arguments static_assert( std::is_same< typename ViewTraits::execution_space , void >::value && std::is_same< typename ViewTraits::memory_space , void >::value && std::is_same< typename ViewTraits::array_layout , void >::value && std::is_same< typename ViewTraits::memory_traits , void >::value , "MemoryTrait is the final optional template argument for a View" ); typedef void execution_space ; typedef void memory_space ; typedef void HostMirrorSpace ; typedef void array_layout ; typedef MemoryTraits memory_traits ; }; template< class DataType , class ... Properties > struct ViewTraits { private: // Unpack the properties arguments typedef ViewTraits< void , Properties ... > prop ; typedef typename std::conditional< ! std::is_same< typename prop::execution_space , void >::value , typename prop::execution_space , Kokkos::DefaultExecutionSpace >::type ExecutionSpace ; typedef typename std::conditional< ! std::is_same< typename prop::memory_space , void >::value , typename prop::memory_space , typename ExecutionSpace::memory_space >::type MemorySpace ; typedef typename std::conditional< ! std::is_same< typename prop::array_layout , void >::value , typename prop::array_layout , typename ExecutionSpace::array_layout >::type ArrayLayout ; typedef typename std::conditional < ! std::is_same< typename prop::HostMirrorSpace , void >::value , typename prop::HostMirrorSpace , typename Kokkos::Impl::HostMirror< ExecutionSpace >::Space >::type HostMirrorSpace ; typedef typename std::conditional< ! std::is_same< typename prop::memory_traits , void >::value , typename prop::memory_traits , typename Kokkos::MemoryManaged >::type MemoryTraits ; // Analyze data type's properties, // May be specialized based upon the layout and value type typedef Kokkos::Impl::ViewDataAnalysis< DataType , ArrayLayout > data_analysis ; public: //------------------------------------ // Data type traits: typedef typename data_analysis::type data_type ; typedef typename data_analysis::const_type const_data_type ; typedef typename data_analysis::non_const_type non_const_data_type ; //------------------------------------ // Compatible array of trivial type traits: typedef typename data_analysis::scalar_array_type scalar_array_type ; typedef typename data_analysis::const_scalar_array_type const_scalar_array_type ; typedef typename data_analysis::non_const_scalar_array_type non_const_scalar_array_type ; //------------------------------------ // Value type traits: typedef typename data_analysis::value_type value_type ; typedef typename data_analysis::const_value_type const_value_type ; typedef typename data_analysis::non_const_value_type non_const_value_type ; //------------------------------------ // Mapping traits: typedef ArrayLayout array_layout ; typedef typename data_analysis::dimension dimension ; typedef typename data_analysis::specialize specialize /* mapping specialization tag */ ; enum { rank = dimension::rank }; enum { rank_dynamic = dimension::rank_dynamic }; //------------------------------------ // Execution space, memory space, memory access traits, and host mirror space. typedef ExecutionSpace execution_space ; typedef MemorySpace memory_space ; typedef Kokkos::Device device_type ; typedef MemoryTraits memory_traits ; typedef HostMirrorSpace host_mirror_space ; typedef typename MemorySpace::size_type size_type ; enum { is_hostspace = std::is_same< MemorySpace , HostSpace >::value }; enum { is_managed = MemoryTraits::Unmanaged == 0 }; enum { is_random_access = MemoryTraits::RandomAccess == 1 }; //------------------------------------ }; /** \class View * \brief View to an array of data. * * A View represents an array of one or more dimensions. * For details, please refer to Kokkos' tutorial materials. * * \section Kokkos_View_TemplateParameters Template parameters * * This class has both required and optional template parameters. The * \c DataType parameter must always be provided, and must always be * first. The parameters \c Arg1Type, \c Arg2Type, and \c Arg3Type are * placeholders for different template parameters. The default value * of the fifth template parameter \c Specialize suffices for most use * cases. When explaining the template parameters, we won't refer to * \c Arg1Type, \c Arg2Type, and \c Arg3Type; instead, we will refer * to the valid categories of template parameters, in whatever order * they may occur. * * Valid ways in which template arguments may be specified: * - View< DataType > * - View< DataType , Layout > * - View< DataType , Layout , Space > * - View< DataType , Layout , Space , MemoryTraits > * - View< DataType , Space > * - View< DataType , Space , MemoryTraits > * - View< DataType , MemoryTraits > * * \tparam DataType (required) This indicates both the type of each * entry of the array, and the combination of compile-time and * run-time array dimension(s). For example, double* * indicates a one-dimensional array of \c double with run-time * dimension, and int*[3] a two-dimensional array of \c int * with run-time first dimension and compile-time second dimension * (of 3). In general, the run-time dimensions (if any) must go * first, followed by zero or more compile-time dimensions. For * more examples, please refer to the tutorial materials. * * \tparam Space (required) The memory space. * * \tparam Layout (optional) The array's layout in memory. For * example, LayoutLeft indicates a column-major (Fortran style) * layout, and LayoutRight a row-major (C style) layout. If not * specified, this defaults to the preferred layout for the * Space. * * \tparam MemoryTraits (optional) Assertion of the user's intended * access behavior. For example, RandomAccess indicates read-only * access with limited spatial locality, and Unmanaged lets users * wrap externally allocated memory in a View without automatic * deallocation. * * \section Kokkos_View_MT MemoryTraits discussion * * \subsection Kokkos_View_MT_Interp MemoryTraits interpretation depends on Space * * Some \c MemoryTraits options may have different interpretations for * different \c Space types. For example, with the Cuda device, * \c RandomAccess tells Kokkos to fetch the data through the texture * cache, whereas the non-GPU devices have no such hardware construct. * * \subsection Kokkos_View_MT_PrefUse Preferred use of MemoryTraits * * Users should defer applying the optional \c MemoryTraits parameter * until the point at which they actually plan to rely on it in a * computational kernel. This minimizes the number of template * parameters exposed in their code, which reduces the cost of * compilation. Users may always assign a View without specified * \c MemoryTraits to a compatible View with that specification. * For example: * \code * // Pass in the simplest types of View possible. * void * doSomething (View out, * View in) * { * // Assign the "generic" View in to a RandomAccess View in_rr. * // Note that RandomAccess View objects must have const data. * View in_rr = in; * // ... do something with in_rr and out ... * } * \endcode */ template< class DataType , class ... Properties > class View ; } /* namespace Kokkos */ //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- #include #include //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- namespace Kokkos { namespace { constexpr Kokkos::Impl::ALL_t ALL = Kokkos::Impl::ALL_t(); constexpr Kokkos::Impl::WithoutInitializing_t WithoutInitializing = Kokkos::Impl::WithoutInitializing_t(); constexpr Kokkos::Impl::AllowPadding_t AllowPadding = Kokkos::Impl::AllowPadding_t(); } /** \brief Create View allocation parameter bundle from argument list. * * Valid argument list members are: * 1) label as a "string" or std::string * 2) memory space instance of the View::memory_space type * 3) execution space instance compatible with the View::memory_space * 4) Kokkos::WithoutInitializing to bypass initialization * 4) Kokkos::AllowPadding to allow allocation to pad dimensions for memory alignment */ template< class ... Args > inline Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... > view_alloc( Args const & ... args ) { typedef Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... > return_type ; static_assert( ! return_type::has_pointer , "Cannot give pointer-to-memory for view allocation" ); return return_type( args... ); } template< class ... Args > inline Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... > view_wrap( Args const & ... args ) { typedef Impl::ViewCtorProp< typename Impl::ViewCtorProp< void , Args >::type ... > return_type ; static_assert( ! return_type::has_memory_space && ! return_type::has_execution_space && ! return_type::has_label && return_type::has_pointer , "Must only give pointer-to-memory for view wrapping" ); return return_type( args... ); } } /* namespace Kokkos */ //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- namespace Kokkos { template< class DataType , class ... Properties > class View ; template< class > struct is_view : public std::false_type {}; template< class D, class ... P > struct is_view< View > : public std::true_type {}; template< class D, class ... P > struct is_view< const View > : public std::true_type {}; template< class DataType , class ... Properties > class View : public ViewTraits< DataType , Properties ... > { private: template< class , class ... > friend class View ; template< class , class ... > friend class Kokkos::Impl::ViewMapping ; public: typedef ViewTraits< DataType , Properties ... > traits ; private: typedef Kokkos::Impl::ViewMapping< traits , void > map_type ; typedef Kokkos::Impl::SharedAllocationTracker track_type ; track_type m_track ; map_type m_map ; public: //---------------------------------------- /** \brief Compatible view of array of scalar types */ typedef View< typename traits::scalar_array_type , typename traits::array_layout , typename traits::device_type , typename traits::memory_traits > array_type ; /** \brief Compatible view of const data type */ typedef View< typename traits::const_data_type , typename traits::array_layout , typename traits::device_type , typename traits::memory_traits > const_type ; /** \brief Compatible view of non-const data type */ typedef View< typename traits::non_const_data_type , typename traits::array_layout , typename traits::device_type , typename traits::memory_traits > non_const_type ; /** \brief Compatible HostMirror view */ typedef View< typename traits::non_const_data_type , typename traits::array_layout , typename traits::host_mirror_space > HostMirror ; //---------------------------------------- // Domain rank and extents enum { Rank = map_type::Rank }; /** \brief rank() to be implemented */ //KOKKOS_INLINE_FUNCTION //static //constexpr unsigned rank() { return map_type::Rank; } template< typename iType > KOKKOS_INLINE_FUNCTION constexpr typename std::enable_if< std::is_integral::value , size_t >::type extent( const iType & r ) const { return m_map.extent(r); } template< typename iType > KOKKOS_INLINE_FUNCTION constexpr typename std::enable_if< std::is_integral::value , int >::type extent_int( const iType & r ) const { return static_cast(m_map.extent(r)); } KOKKOS_INLINE_FUNCTION constexpr typename traits::array_layout layout() const { return m_map.layout(); } //---------------------------------------- /* Deprecate all 'dimension' functions in favor of * ISO/C++ vocabulary 'extent'. */ template< typename iType > KOKKOS_INLINE_FUNCTION constexpr typename std::enable_if< std::is_integral::value , size_t >::type dimension( const iType & r ) const { return extent( r ); } KOKKOS_INLINE_FUNCTION constexpr size_t dimension_0() const { return m_map.dimension_0(); } KOKKOS_INLINE_FUNCTION constexpr size_t dimension_1() const { return m_map.dimension_1(); } KOKKOS_INLINE_FUNCTION constexpr size_t dimension_2() const { return m_map.dimension_2(); } KOKKOS_INLINE_FUNCTION constexpr size_t dimension_3() const { return m_map.dimension_3(); } KOKKOS_INLINE_FUNCTION constexpr size_t dimension_4() const { return m_map.dimension_4(); } KOKKOS_INLINE_FUNCTION constexpr size_t dimension_5() const { return m_map.dimension_5(); } KOKKOS_INLINE_FUNCTION constexpr size_t dimension_6() const { return m_map.dimension_6(); } KOKKOS_INLINE_FUNCTION constexpr size_t dimension_7() const { return m_map.dimension_7(); } //---------------------------------------- KOKKOS_INLINE_FUNCTION constexpr size_t size() const { return m_map.dimension_0() * m_map.dimension_1() * m_map.dimension_2() * m_map.dimension_3() * m_map.dimension_4() * m_map.dimension_5() * m_map.dimension_6() * m_map.dimension_7(); } KOKKOS_INLINE_FUNCTION constexpr size_t stride_0() const { return m_map.stride_0(); } KOKKOS_INLINE_FUNCTION constexpr size_t stride_1() const { return m_map.stride_1(); } KOKKOS_INLINE_FUNCTION constexpr size_t stride_2() const { return m_map.stride_2(); } KOKKOS_INLINE_FUNCTION constexpr size_t stride_3() const { return m_map.stride_3(); } KOKKOS_INLINE_FUNCTION constexpr size_t stride_4() const { return m_map.stride_4(); } KOKKOS_INLINE_FUNCTION constexpr size_t stride_5() const { return m_map.stride_5(); } KOKKOS_INLINE_FUNCTION constexpr size_t stride_6() const { return m_map.stride_6(); } KOKKOS_INLINE_FUNCTION constexpr size_t stride_7() const { return m_map.stride_7(); } template< typename iType > KOKKOS_INLINE_FUNCTION void stride( iType * const s ) const { m_map.stride(s); } //---------------------------------------- // Range span is the span which contains all members. typedef typename map_type::reference_type reference_type ; typedef typename map_type::pointer_type pointer_type ; enum { reference_type_is_lvalue_reference = std::is_lvalue_reference< reference_type >::value }; KOKKOS_INLINE_FUNCTION constexpr size_t span() const { return m_map.span(); } // Deprecated, use 'span()' instead KOKKOS_INLINE_FUNCTION constexpr size_t capacity() const { return m_map.span(); } KOKKOS_INLINE_FUNCTION constexpr bool span_is_contiguous() const { return m_map.span_is_contiguous(); } KOKKOS_INLINE_FUNCTION constexpr pointer_type data() const { return m_map.data(); } // Deprecated, use 'span_is_contigous()' instead KOKKOS_INLINE_FUNCTION constexpr bool is_contiguous() const { return m_map.span_is_contiguous(); } // Deprecated, use 'data()' instead KOKKOS_INLINE_FUNCTION constexpr pointer_type ptr_on_device() const { return m_map.data(); } //---------------------------------------- // Allow specializations to query their specialized map KOKKOS_INLINE_FUNCTION const Kokkos::Impl::ViewMapping< traits , void > & implementation_map() const { return m_map ; } //---------------------------------------- private: enum { is_layout_left = std::is_same< typename traits::array_layout , Kokkos::LayoutLeft >::value , is_layout_right = std::is_same< typename traits::array_layout , Kokkos::LayoutRight >::value , is_layout_stride = std::is_same< typename traits::array_layout , Kokkos::LayoutStride >::value , is_default_map = std::is_same< typename traits::specialize , void >::value && ( is_layout_left || is_layout_right || is_layout_stride ) }; template< class Space , bool = Kokkos::Impl::MemorySpaceAccess< Space , typename traits::memory_space >::accessible > struct verify_space { KOKKOS_FORCEINLINE_FUNCTION static void check() {} }; template< class Space > struct verify_space { KOKKOS_FORCEINLINE_FUNCTION static void check() { Kokkos::abort("Kokkos::View ERROR: attempt to access inaccessible memory space"); }; }; #if defined( KOKKOS_ENABLE_DEBUG_BOUNDS_CHECK ) #define KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( ARG ) \ View::template verify_space< Kokkos::Impl::ActiveExecutionMemorySpace >::check(); \ Kokkos::Impl::view_verify_operator_bounds< typename traits::memory_space > ARG ; #else #define KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( ARG ) \ View::template verify_space< Kokkos::Impl::ActiveExecutionMemorySpace >::check(); #endif public: //------------------------------ // Rank 0 operator() template< class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if<( Kokkos::Impl::are_integral::value && ( 0 == Rank ) ), reference_type >::type operator()( Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,args...) ) return m_map.reference(); } //------------------------------ // Rank 1 operator() template< typename I0 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 1 == Rank ) && ! is_default_map ), reference_type >::type operator()( const I0 & i0 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,args...) ) return m_map.reference(i0); } template< typename I0 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 1 == Rank ) && is_default_map && ! is_layout_stride ), reference_type >::type operator()( const I0 & i0 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,args...) ) return m_map.m_handle[ i0 ]; } template< typename I0 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 1 == Rank ) && is_default_map && is_layout_stride ), reference_type >::type operator()( const I0 & i0 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,args...) ) return m_map.m_handle[ m_map.m_offset.m_stride.S0 * i0 ]; } //------------------------------ // Rank 1 operator[] template< typename I0 > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 1 == Rank ) && ! is_default_map ), reference_type >::type operator[]( const I0 & i0 ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) ) return m_map.reference(i0); } template< typename I0 > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 1 == Rank ) && is_default_map && ! is_layout_stride ), reference_type >::type operator[]( const I0 & i0 ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) ) return m_map.m_handle[ i0 ]; } template< typename I0 > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 1 == Rank ) && is_default_map && is_layout_stride ), reference_type >::type operator[]( const I0 & i0 ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0) ) return m_map.m_handle[ m_map.m_offset.m_stride.S0 * i0 ]; } //------------------------------ // Rank 2 template< typename I0 , typename I1 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 2 == Rank ) && ! is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) ) return m_map.reference(i0,i1); } template< typename I0 , typename I1 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 2 == Rank ) && is_default_map && is_layout_left && ( traits::rank_dynamic == 0 ) ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) ) return m_map.m_handle[ i0 + m_map.m_offset.m_dim.N0 * i1 ]; } template< typename I0 , typename I1 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 2 == Rank ) && is_default_map && is_layout_left && ( traits::rank_dynamic != 0 ) ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) ) return m_map.m_handle[ i0 + m_map.m_offset.m_stride * i1 ]; } template< typename I0 , typename I1 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 2 == Rank ) && is_default_map && is_layout_right && ( traits::rank_dynamic == 0 ) ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) ) return m_map.m_handle[ i1 + m_map.m_offset.m_dim.N1 * i0 ]; } template< typename I0 , typename I1 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 2 == Rank ) && is_default_map && is_layout_right && ( traits::rank_dynamic != 0 ) ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) ) return m_map.m_handle[ i1 + m_map.m_offset.m_stride * i0 ]; } template< typename I0 , typename I1 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 2 == Rank ) && is_default_map && is_layout_stride ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,args...) ) return m_map.m_handle[ i0 * m_map.m_offset.m_stride.S0 + i1 * m_map.m_offset.m_stride.S1 ]; } //------------------------------ // Rank 3 template< typename I0 , typename I1 , typename I2 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 3 == Rank ) && is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,args...) ) return m_map.m_handle[ m_map.m_offset(i0,i1,i2) ]; } template< typename I0 , typename I1 , typename I2 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 3 == Rank ) && ! is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,args...) ) return m_map.reference(i0,i1,i2); } //------------------------------ // Rank 4 template< typename I0 , typename I1 , typename I2 , typename I3 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 4 == Rank ) && is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,args...) ) return m_map.m_handle[ m_map.m_offset(i0,i1,i2,i3) ]; } template< typename I0 , typename I1 , typename I2 , typename I3 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 4 == Rank ) && ! is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,args...) ) return m_map.reference(i0,i1,i2,i3); } //------------------------------ // Rank 5 template< typename I0 , typename I1 , typename I2 , typename I3 , typename I4 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 5 == Rank ) && is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 , const I4 & i4 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,args...) ) return m_map.m_handle[ m_map.m_offset(i0,i1,i2,i3,i4) ]; } template< typename I0 , typename I1 , typename I2 , typename I3 , typename I4 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 5 == Rank ) && ! is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 , const I4 & i4 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,args...) ) return m_map.reference(i0,i1,i2,i3,i4); } //------------------------------ // Rank 6 template< typename I0 , typename I1 , typename I2 , typename I3 , typename I4 , typename I5 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 6 == Rank ) && is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 , const I4 & i4 , const I5 & i5 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,args...) ) return m_map.m_handle[ m_map.m_offset(i0,i1,i2,i3,i4,i5) ]; } template< typename I0 , typename I1 , typename I2 , typename I3 , typename I4 , typename I5 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 6 == Rank ) && ! is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 , const I4 & i4 , const I5 & i5 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,args...) ) return m_map.reference(i0,i1,i2,i3,i4,i5); } //------------------------------ // Rank 7 template< typename I0 , typename I1 , typename I2 , typename I3 , typename I4 , typename I5 , typename I6 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 7 == Rank ) && is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 , const I4 & i4 , const I5 & i5 , const I6 & i6 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,args...) ) return m_map.m_handle[ m_map.m_offset(i0,i1,i2,i3,i4,i5,i6) ]; } template< typename I0 , typename I1 , typename I2 , typename I3 , typename I4 , typename I5 , typename I6 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 7 == Rank ) && ! is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 , const I4 & i4 , const I5 & i5 , const I6 & i6 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,args...) ) return m_map.reference(i0,i1,i2,i3,i4,i5,i6); } //------------------------------ // Rank 8 template< typename I0 , typename I1 , typename I2 , typename I3 , typename I4 , typename I5 , typename I6 , typename I7 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 8 == Rank ) && is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,i7,args...) ) return m_map.m_handle[ m_map.m_offset(i0,i1,i2,i3,i4,i5,i6,i7) ]; } template< typename I0 , typename I1 , typename I2 , typename I3 , typename I4 , typename I5 , typename I6 , typename I7 , class ... Args > KOKKOS_FORCEINLINE_FUNCTION typename std::enable_if< ( Kokkos::Impl::are_integral::value && ( 8 == Rank ) && ! is_default_map ), reference_type >::type operator()( const I0 & i0 , const I1 & i1 , const I2 & i2 , const I3 & i3 , const I4 & i4 , const I5 & i5 , const I6 & i6 , const I7 & i7 , Args ... args ) const { KOKKOS_IMPL_VIEW_OPERATOR_VERIFY( (m_track,m_map,i0,i1,i2,i3,i4,i5,i6,i7,args...) ) return m_map.reference(i0,i1,i2,i3,i4,i5,i6,i7); } #undef KOKKOS_IMPL_VIEW_OPERATOR_VERIFY //---------------------------------------- // Standard destructor, constructors, and assignment operators KOKKOS_INLINE_FUNCTION ~View() {} KOKKOS_INLINE_FUNCTION View() : m_track(), m_map() {} KOKKOS_INLINE_FUNCTION View( const View & rhs ) : m_track( rhs.m_track ), m_map( rhs.m_map ) {} KOKKOS_INLINE_FUNCTION View( View && rhs ) : m_track( rhs.m_track ), m_map( rhs.m_map ) {} KOKKOS_INLINE_FUNCTION View & operator = ( const View & rhs ) { m_track = rhs.m_track ; m_map = rhs.m_map ; return *this ; } KOKKOS_INLINE_FUNCTION View & operator = ( View && rhs ) { m_track = rhs.m_track ; m_map = rhs.m_map ; return *this ; } //---------------------------------------- // Compatible view copy constructor and assignment // may assign unmanaged from managed. template< class RT , class ... RP > KOKKOS_INLINE_FUNCTION View( const View & rhs ) : m_track( rhs.m_track , traits::is_managed ) , m_map() { typedef typename View::traits SrcTraits ; typedef Kokkos::Impl::ViewMapping< traits , SrcTraits , void > Mapping ; static_assert( Mapping::is_assignable , "Incompatible View copy construction" ); Mapping::assign( m_map , rhs.m_map , rhs.m_track ); } template< class RT , class ... RP > KOKKOS_INLINE_FUNCTION View & operator = ( const View & rhs ) { typedef typename View::traits SrcTraits ; typedef Kokkos::Impl::ViewMapping< traits , SrcTraits , void > Mapping ; static_assert( Mapping::is_assignable , "Incompatible View copy assignment" ); Mapping::assign( m_map , rhs.m_map , rhs.m_track ); m_track.assign( rhs.m_track , traits::is_managed ); return *this ; } //---------------------------------------- // Compatible subview constructor // may assign unmanaged from managed. template< class RT , class ... RP , class Arg0 , class ... Args > KOKKOS_INLINE_FUNCTION View( const View< RT , RP... > & src_view , const Arg0 & arg0 , Args ... args ) : m_track( src_view.m_track , traits::is_managed ) , m_map() { typedef View< RT , RP... > SrcType ; typedef Kokkos::Impl::ViewMapping < void /* deduce destination view type from source view traits */ , typename SrcType::traits , Arg0 , Args... > Mapping ; typedef typename Mapping::type DstType ; static_assert( Kokkos::Impl::ViewMapping< traits , typename DstType::traits , void >::is_assignable , "Subview construction requires compatible view and subview arguments" ); Mapping::assign( m_map, src_view.m_map, arg0 , args... ); } //---------------------------------------- // Allocation tracking properties KOKKOS_INLINE_FUNCTION int use_count() const { return m_track.use_count(); } inline const std::string label() const { return m_track.template get_label< typename traits::memory_space >(); } //---------------------------------------- // Allocation according to allocation properties and array layout template< class ... P > explicit inline View( const Impl::ViewCtorProp< P ... > & arg_prop , typename std::enable_if< ! Impl::ViewCtorProp< P... >::has_pointer , typename traits::array_layout >::type const & arg_layout ) : m_track() , m_map() { // Append layout and spaces if not input typedef Impl::ViewCtorProp< P ... > alloc_prop_input ; // use 'std::integral_constant' for non-types // to avoid duplicate class error. typedef Impl::ViewCtorProp < P ... , typename std::conditional < alloc_prop_input::has_label , std::integral_constant , typename std::string >::type , typename std::conditional < alloc_prop_input::has_memory_space , std::integral_constant , typename traits::device_type::memory_space >::type , typename std::conditional < alloc_prop_input::has_execution_space , std::integral_constant , typename traits::device_type::execution_space >::type > alloc_prop ; static_assert( traits::is_managed , "View allocation constructor requires managed memory" ); if ( alloc_prop::initialize && ! alloc_prop::execution_space::is_initialized() ) { // If initializing view data then // the execution space must be initialized. Kokkos::Impl::throw_runtime_exception("Constructing View and initializing data with uninitialized execution space"); } // Copy the input allocation properties with possibly defaulted properties alloc_prop prop( arg_prop ); //------------------------------------------------------------ #if defined( KOKKOS_ENABLE_CUDA ) // If allocating in CudaUVMSpace must fence before and after // the allocation to protect against possible concurrent access // on the CPU and the GPU. // Fence using the trait's executon space (which will be Kokkos::Cuda) // to avoid incomplete type errors from usng Kokkos::Cuda directly. if ( std::is_same< Kokkos::CudaUVMSpace , typename traits::device_type::memory_space >::value ) { traits::device_type::memory_space::execution_space::fence(); } #endif //------------------------------------------------------------ Kokkos::Impl::SharedAllocationRecord<> * record = m_map.allocate_shared( prop , arg_layout ); //------------------------------------------------------------ #if defined( KOKKOS_ENABLE_CUDA ) if ( std::is_same< Kokkos::CudaUVMSpace , typename traits::device_type::memory_space >::value ) { traits::device_type::memory_space::execution_space::fence(); } #endif //------------------------------------------------------------ // Setup and initialization complete, start tracking m_track.assign_allocated_record_to_uninitialized( record ); } // Wrap memory according to properties and array layout template< class ... P > explicit KOKKOS_INLINE_FUNCTION View( const Impl::ViewCtorProp< P ... > & arg_prop , typename std::enable_if< Impl::ViewCtorProp< P... >::has_pointer , typename traits::array_layout >::type const & arg_layout ) : m_track() // No memory tracking , m_map( arg_prop , arg_layout ) { static_assert( std::is_same< pointer_type , typename Impl::ViewCtorProp< P... >::pointer_type >::value , "Constructing View to wrap user memory must supply matching pointer type" ); } // Simple dimension-only layout template< class ... P > explicit inline View( const Impl::ViewCtorProp< P ... > & arg_prop , typename std::enable_if< ! Impl::ViewCtorProp< P... >::has_pointer , size_t >::type const arg_N0 = 0 , const size_t arg_N1 = 0 , const size_t arg_N2 = 0 , const size_t arg_N3 = 0 , const size_t arg_N4 = 0 , const size_t arg_N5 = 0 , const size_t arg_N6 = 0 , const size_t arg_N7 = 0 ) : View( arg_prop , typename traits::array_layout ( arg_N0 , arg_N1 , arg_N2 , arg_N3 , arg_N4 , arg_N5 , arg_N6 , arg_N7 ) ) {} template< class ... P > explicit KOKKOS_INLINE_FUNCTION View( const Impl::ViewCtorProp< P ... > & arg_prop , typename std::enable_if< Impl::ViewCtorProp< P... >::has_pointer , size_t >::type const arg_N0 = 0 , const size_t arg_N1 = 0 , const size_t arg_N2 = 0 , const size_t arg_N3 = 0 , const size_t arg_N4 = 0 , const size_t arg_N5 = 0 , const size_t arg_N6 = 0 , const size_t arg_N7 = 0 ) : View( arg_prop , typename traits::array_layout ( arg_N0 , arg_N1 , arg_N2 , arg_N3 , arg_N4 , arg_N5 , arg_N6 , arg_N7 ) ) {} // Allocate with label and layout template< typename Label > explicit inline View( const Label & arg_label , typename std::enable_if< Kokkos::Impl::is_view_label