Files
lammps/lib/kokkos/core/src/Kokkos_View.hpp
2017-07-31 10:34:21 -06:00

2578 lines
93 KiB
C++

/*
//@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 <type_traits>
#include <string>
#include <algorithm>
#include <initializer_list>
#include <Kokkos_Core_fwd.hpp>
#include <Kokkos_HostSpace.hpp>
#include <Kokkos_MemoryTraits.hpp>
#include <Kokkos_ExecPolicy.hpp>
#if defined(KOKKOS_ENABLE_PROFILING)
#include <impl/Kokkos_Profiling_Interface.hpp>
#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<void,Prop...>::execution_space execution_space ;
typedef typename ViewTraits<void,Prop...>::memory_space memory_space ;
typedef typename ViewTraits<void,Prop...>::HostMirrorSpace HostMirrorSpace ;
typedef typename ViewTraits<void,Prop...>::array_layout array_layout ;
typedef typename ViewTraits<void,Prop...>::memory_traits memory_traits ;
};
template< class ArrayLayout , class ... Prop >
struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_array_layout<ArrayLayout>::value >::type , ArrayLayout , Prop ... >
{
// Specify layout, keep subsequent space and memory traits arguments
typedef typename ViewTraits<void,Prop...>::execution_space execution_space ;
typedef typename ViewTraits<void,Prop...>::memory_space memory_space ;
typedef typename ViewTraits<void,Prop...>::HostMirrorSpace HostMirrorSpace ;
typedef ArrayLayout array_layout ;
typedef typename ViewTraits<void,Prop...>::memory_traits memory_traits ;
};
template< class Space , class ... Prop >
struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_space<Space>::value >::type , Space , Prop ... >
{
// Specify Space, memory traits should be the only subsequent argument.
static_assert( std::is_same< typename ViewTraits<void,Prop...>::execution_space , void >::value &&
std::is_same< typename ViewTraits<void,Prop...>::memory_space , void >::value &&
std::is_same< typename ViewTraits<void,Prop...>::HostMirrorSpace , void >::value &&
std::is_same< typename ViewTraits<void,Prop...>::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<void,Prop...>::memory_traits memory_traits ;
};
template< class MemoryTraits , class ... Prop >
struct ViewTraits< typename std::enable_if< Kokkos::Impl::is_memory_traits<MemoryTraits>::value >::type , MemoryTraits , Prop ... >
{
// Specify memory trait, should not be any subsequent arguments
static_assert( std::is_same< typename ViewTraits<void,Prop...>::execution_space , void >::value &&
std::is_same< typename ViewTraits<void,Prop...>::memory_space , void >::value &&
std::is_same< typename ViewTraits<void,Prop...>::array_layout , void >::value &&
std::is_same< typename ViewTraits<void,Prop...>::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<ExecutionSpace,MemorySpace> 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, <tt>double*</tt>
* indicates a one-dimensional array of \c double with run-time
* dimension, and <tt>int*[3]</tt> 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
* <tt>Space</tt>.
*
* \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<double*, Cuda> out,
* View<const double*, Cuda> in)
* {
* // Assign the "generic" View in to a RandomAccess View in_rr.
* // Note that RandomAccess View objects must have const data.
* View<const double*, Cuda, RandomAccess> in_rr = in;
* // ... do something with in_rr and out ...
* }
* \endcode
*/
template< class DataType , class ... Properties >
class View ;
} /* namespace Kokkos */
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#include <impl/Kokkos_ViewMapping.hpp>
#include <impl/Kokkos_ViewArray.hpp>
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
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<D,P...> > : public std::true_type {};
template< class D, class ... P >
struct is_view< const View<D,P...> > : 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<iType>::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<iType>::value , int >::type
extent_int( const iType & r ) const
{ return static_cast<int>(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<iType>::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<Space,false>
{ 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<Args...>::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<I0,Args...>::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<I0,Args...>::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<I0,Args...>::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<I0>::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<I0>::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<I0>::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<I0,I1,Args...>::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<I0,I1,Args...>::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<I0,I1,Args...>::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<I0,I1,Args...>::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<I0,I1,Args...>::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<I0,I1,Args...>::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<I0,I1,I2,Args...>::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<I0,I1,I2,Args...>::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<I0,I1,I2,I3,Args...>::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<I0,I1,I2,I3,Args...>::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<I0,I1,I2,I3,I4,Args...>::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<I0,I1,I2,I3,I4,Args...>::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<I0,I1,I2,I3,I4,I5,Args...>::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<I0,I1,I2,I3,I4,I5,Args...>::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<I0,I1,I2,I3,I4,I5,I6,Args...>::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<I0,I1,I2,I3,I4,I5,I6,Args...>::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<I0,I1,I2,I3,I4,I5,I6,I7,Args...>::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<I0,I1,I2,I3,I4,I5,I6,I7,Args...>::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<RT,RP...> & rhs )
: m_track( rhs.m_track , traits::is_managed )
, m_map()
{
typedef typename View<RT,RP...>::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<RT,RP...> & rhs )
{
typedef typename View<RT,RP...>::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<unsigned,I>' for non-types
// to avoid duplicate class error.
typedef Impl::ViewCtorProp
< P ...
, typename std::conditional
< alloc_prop_input::has_label
, std::integral_constant<unsigned,0>
, typename std::string
>::type
, typename std::conditional
< alloc_prop_input::has_memory_space
, std::integral_constant<unsigned,1>
, typename traits::device_type::memory_space
>::type
, typename std::conditional
< alloc_prop_input::has_execution_space
, std::integral_constant<unsigned,2>
, 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<Label>::value ,
typename traits::array_layout >::type const & arg_layout
)
: View( Impl::ViewCtorProp< std::string >( arg_label ) , arg_layout )
{}
// Allocate label and layout, must disambiguate from subview constructor.
template< typename Label >
explicit inline
View( const Label & arg_label
, typename std::enable_if<
Kokkos::Impl::is_view_label<Label>::value ,
const size_t >::type 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( Impl::ViewCtorProp< std::string >( arg_label )
, typename traits::array_layout
( arg_N0 , arg_N1 , arg_N2 , arg_N3
, arg_N4 , arg_N5 , arg_N6 , arg_N7 )
)
{}
// For backward compatibility
explicit inline
View( const ViewAllocateWithoutInitializing & arg_prop
, const typename traits::array_layout & arg_layout
)
: View( Impl::ViewCtorProp< std::string , Kokkos::Impl::WithoutInitializing_t >( arg_prop.label , Kokkos::WithoutInitializing )
, arg_layout
)
{}
explicit inline
View( const ViewAllocateWithoutInitializing & arg_prop
, const size_t 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( Impl::ViewCtorProp< std::string , Kokkos::Impl::WithoutInitializing_t >( arg_prop.label , Kokkos::WithoutInitializing )
, typename traits::array_layout
( arg_N0 , arg_N1 , arg_N2 , arg_N3
, arg_N4 , arg_N5 , arg_N6 , arg_N7 )
)
{}
//----------------------------------------
// Memory span required to wrap these dimensions.
static constexpr size_t required_allocation_size(
const size_t 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
)
{
return map_type::memory_span(
typename traits::array_layout
( arg_N0 , arg_N1 , arg_N2 , arg_N3
, arg_N4 , arg_N5 , arg_N6 , arg_N7 ) );
}
explicit KOKKOS_INLINE_FUNCTION
View( pointer_type arg_ptr
, const size_t 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( Impl::ViewCtorProp<pointer_type>(arg_ptr)
, typename traits::array_layout
( arg_N0 , arg_N1 , arg_N2 , arg_N3
, arg_N4 , arg_N5 , arg_N6 , arg_N7 )
)
{}
explicit KOKKOS_INLINE_FUNCTION
View( pointer_type arg_ptr
, const typename traits::array_layout & arg_layout
)
: View( Impl::ViewCtorProp<pointer_type>(arg_ptr) , arg_layout )
{}
//----------------------------------------
// Shared scratch memory constructor
static inline
size_t shmem_size( const size_t arg_N0 = ~size_t(0) ,
const size_t arg_N1 = ~size_t(0) ,
const size_t arg_N2 = ~size_t(0) ,
const size_t arg_N3 = ~size_t(0) ,
const size_t arg_N4 = ~size_t(0) ,
const size_t arg_N5 = ~size_t(0) ,
const size_t arg_N6 = ~size_t(0) ,
const size_t arg_N7 = ~size_t(0) )
{
const size_t num_passed_args =
( arg_N0 != ~size_t(0) ) + ( arg_N1 != ~size_t(0) ) + ( arg_N2 != ~size_t(0) ) +
( arg_N3 != ~size_t(0) ) + ( arg_N4 != ~size_t(0) ) + ( arg_N5 != ~size_t(0) ) +
( arg_N6 != ~size_t(0) ) + ( arg_N7 != ~size_t(0) );
if ( std::is_same<typename traits::specialize,void>::value && num_passed_args != traits::rank_dynamic ) {
Kokkos::abort( "Kokkos::View::shmem_size() rank_dynamic != number of arguments.\n" );
}
return map_type::memory_span(
typename traits::array_layout
( arg_N0 , arg_N1 , arg_N2 , arg_N3
, arg_N4 , arg_N5 , arg_N6 , arg_N7 ) );
}
explicit KOKKOS_INLINE_FUNCTION
View( const typename traits::execution_space::scratch_memory_space & arg_space
, const typename traits::array_layout & arg_layout )
: View( Impl::ViewCtorProp<pointer_type>(
reinterpret_cast<pointer_type>(
arg_space.get_shmem( map_type::memory_span( arg_layout ) ) ) )
, arg_layout )
{}
explicit KOKKOS_INLINE_FUNCTION
View( const typename traits::execution_space::scratch_memory_space & arg_space
, const size_t 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( Impl::ViewCtorProp<pointer_type>(
reinterpret_cast<pointer_type>(
arg_space.get_shmem(
map_type::memory_span(
typename traits::array_layout
( arg_N0 , arg_N1 , arg_N2 , arg_N3
, arg_N4 , arg_N5 , arg_N6 , arg_N7 ) ) ) ) )
, typename traits::array_layout
( arg_N0 , arg_N1 , arg_N2 , arg_N3
, arg_N4 , arg_N5 , arg_N6 , arg_N7 )
)
{}
};
/** \brief Temporary free function rank()
* until rank() is implemented
* in the View
*/
template < typename D , class ... P >
KOKKOS_INLINE_FUNCTION
constexpr unsigned rank( const View<D , P...> & V ) { return V.Rank; } //Temporary until added to view
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
template< class V , class ... Args >
using Subview =
typename Kokkos::Impl::ViewMapping
< void /* deduce subview type from source view traits */
, typename V::traits
, Args ...
>::type ;
template< class D, class ... P , class ... Args >
KOKKOS_INLINE_FUNCTION
typename Kokkos::Impl::ViewMapping
< void /* deduce subview type from source view traits */
, ViewTraits< D , P... >
, Args ...
>::type
subview( const View< D, P... > & src , Args ... args )
{
static_assert( View< D , P... >::Rank == sizeof...(Args) ,
"subview requires one argument for each source View rank" );
return typename
Kokkos::Impl::ViewMapping
< void /* deduce subview type from source view traits */
, ViewTraits< D , P ... >
, Args ... >::type( src , args ... );
}
template< class MemoryTraits , class D, class ... P , class ... Args >
KOKKOS_INLINE_FUNCTION
typename Kokkos::Impl::ViewMapping
< void /* deduce subview type from source view traits */
, ViewTraits< D , P... >
, Args ...
>::template apply< MemoryTraits >::type
subview( const View< D, P... > & src , Args ... args )
{
static_assert( View< D , P... >::Rank == sizeof...(Args) ,
"subview requires one argument for each source View rank" );
return typename
Kokkos::Impl::ViewMapping
< void /* deduce subview type from source view traits */
, ViewTraits< D , P ... >
, Args ... >
::template apply< MemoryTraits >
::type( src , args ... );
}
} /* namespace Kokkos */
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
template< class LT , class ... LP , class RT , class ... RP >
KOKKOS_INLINE_FUNCTION
bool operator == ( const View<LT,LP...> & lhs ,
const View<RT,RP...> & rhs )
{
// Same data, layout, dimensions
typedef ViewTraits<LT,LP...> lhs_traits ;
typedef ViewTraits<RT,RP...> rhs_traits ;
return
std::is_same< typename lhs_traits::const_value_type ,
typename rhs_traits::const_value_type >::value &&
std::is_same< typename lhs_traits::array_layout ,
typename rhs_traits::array_layout >::value &&
std::is_same< typename lhs_traits::memory_space ,
typename rhs_traits::memory_space >::value &&
unsigned(lhs_traits::rank) == unsigned(rhs_traits::rank) &&
lhs.data() == rhs.data() &&
lhs.span() == rhs.span() &&
lhs.dimension_0() == rhs.dimension_0() &&
lhs.dimension_1() == rhs.dimension_1() &&
lhs.dimension_2() == rhs.dimension_2() &&
lhs.dimension_3() == rhs.dimension_3() &&
lhs.dimension_4() == rhs.dimension_4() &&
lhs.dimension_5() == rhs.dimension_5() &&
lhs.dimension_6() == rhs.dimension_6() &&
lhs.dimension_7() == rhs.dimension_7();
}
template< class LT , class ... LP , class RT , class ... RP >
KOKKOS_INLINE_FUNCTION
bool operator != ( const View<LT,LP...> & lhs ,
const View<RT,RP...> & rhs )
{
return ! ( operator==(lhs,rhs) );
}
} /* namespace Kokkos */
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
namespace Impl {
inline
void shared_allocation_tracking_disable()
{ Kokkos::Impl::SharedAllocationRecord<void,void>::tracking_disable(); }
inline
void shared_allocation_tracking_enable()
{ Kokkos::Impl::SharedAllocationRecord<void,void>::tracking_enable(); }
} /* namespace Impl */
} /* namespace Kokkos */
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
namespace Impl {
template< class OutputView , typename Enable = void >
struct ViewFill {
typedef typename OutputView::const_value_type const_value_type ;
const OutputView output ;
const_value_type input ;
KOKKOS_INLINE_FUNCTION
void operator()( const size_t i0 ) const
{
const size_t n1 = output.dimension_1();
const size_t n2 = output.dimension_2();
const size_t n3 = output.dimension_3();
const size_t n4 = output.dimension_4();
const size_t n5 = output.dimension_5();
const size_t n6 = output.dimension_6();
const size_t n7 = output.dimension_7();
for ( size_t i1 = 0 ; i1 < n1 ; ++i1 ) {
for ( size_t i2 = 0 ; i2 < n2 ; ++i2 ) {
for ( size_t i3 = 0 ; i3 < n3 ; ++i3 ) {
for ( size_t i4 = 0 ; i4 < n4 ; ++i4 ) {
for ( size_t i5 = 0 ; i5 < n5 ; ++i5 ) {
for ( size_t i6 = 0 ; i6 < n6 ; ++i6 ) {
for ( size_t i7 = 0 ; i7 < n7 ; ++i7 ) {
output(i0,i1,i2,i3,i4,i5,i6,i7) = input ;
}}}}}}}
}
ViewFill( const OutputView & arg_out , const_value_type & arg_in )
: output( arg_out ), input( arg_in )
{
typedef typename OutputView::execution_space execution_space ;
typedef Kokkos::RangePolicy< execution_space > Policy ;
const Kokkos::Impl::ParallelFor< ViewFill , Policy > closure( *this , Policy( 0 , output.dimension_0() ) );
closure.execute();
execution_space::fence();
}
};
template< class OutputView >
struct ViewFill< OutputView , typename std::enable_if< OutputView::Rank == 0 >::type > {
ViewFill( const OutputView & dst , const typename OutputView::const_value_type & src )
{
Kokkos::Impl::DeepCopy< typename OutputView::memory_space , Kokkos::HostSpace >
( dst.data() , & src , sizeof(typename OutputView::const_value_type) );
}
};
template< class OutputView , class InputView , class ExecSpace = typename OutputView::execution_space >
struct ViewRemap {
const OutputView output ;
const InputView input ;
const size_t n0 ;
const size_t n1 ;
const size_t n2 ;
const size_t n3 ;
const size_t n4 ;
const size_t n5 ;
const size_t n6 ;
const size_t n7 ;
ViewRemap( const OutputView & arg_out , const InputView & arg_in )
: output( arg_out ), input( arg_in )
, n0( std::min( (size_t)arg_out.dimension_0() , (size_t)arg_in.dimension_0() ) )
, n1( std::min( (size_t)arg_out.dimension_1() , (size_t)arg_in.dimension_1() ) )
, n2( std::min( (size_t)arg_out.dimension_2() , (size_t)arg_in.dimension_2() ) )
, n3( std::min( (size_t)arg_out.dimension_3() , (size_t)arg_in.dimension_3() ) )
, n4( std::min( (size_t)arg_out.dimension_4() , (size_t)arg_in.dimension_4() ) )
, n5( std::min( (size_t)arg_out.dimension_5() , (size_t)arg_in.dimension_5() ) )
, n6( std::min( (size_t)arg_out.dimension_6() , (size_t)arg_in.dimension_6() ) )
, n7( std::min( (size_t)arg_out.dimension_7() , (size_t)arg_in.dimension_7() ) )
{
typedef Kokkos::RangePolicy< ExecSpace > Policy ;
const Kokkos::Impl::ParallelFor< ViewRemap , Policy > closure( *this , Policy( 0 , n0 ) );
closure.execute();
}
KOKKOS_INLINE_FUNCTION
void operator()( const size_t i0 ) const
{
for ( size_t i1 = 0 ; i1 < n1 ; ++i1 ) {
for ( size_t i2 = 0 ; i2 < n2 ; ++i2 ) {
for ( size_t i3 = 0 ; i3 < n3 ; ++i3 ) {
for ( size_t i4 = 0 ; i4 < n4 ; ++i4 ) {
for ( size_t i5 = 0 ; i5 < n5 ; ++i5 ) {
for ( size_t i6 = 0 ; i6 < n6 ; ++i6 ) {
for ( size_t i7 = 0 ; i7 < n7 ; ++i7 ) {
output(i0,i1,i2,i3,i4,i5,i6,i7) = input(i0,i1,i2,i3,i4,i5,i6,i7);
}}}}}}}
}
};
} /* namespace Impl */
} /* namespace Kokkos */
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
/** \brief Deep copy a value from Host memory into a view. */
template< class DT , class ... DP >
inline
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 )
{
static_assert(
std::is_same< typename ViewTraits<DT,DP...>::non_const_value_type ,
typename ViewTraits<DT,DP...>::value_type >::value
, "deep_copy requires non-const type" );
Kokkos::Impl::ViewFill< View<DT,DP...> >( dst , value );
}
/** \brief Deep copy into a value in Host memory from a view. */
template< class ST , class ... SP >
inline
void deep_copy
( typename ViewTraits<ST,SP...>::non_const_value_type & dst
, const View<ST,SP...> & src
, typename std::enable_if<
std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value
>::type * = 0 )
{
static_assert( ViewTraits<ST,SP...>::rank == 0
, "ERROR: Non-rank-zero view in deep_copy( value , View )" );
typedef ViewTraits<ST,SP...> src_traits ;
typedef typename src_traits::memory_space src_memory_space ;
Kokkos::Impl::DeepCopy< HostSpace , src_memory_space >( & dst , src.data() , sizeof(ST) );
}
//----------------------------------------------------------------------------
/** \brief A deep copy between views of compatible type, and rank zero. */
template< class DT , class ... DP , class ST , class ... SP >
inline
void deep_copy
( const View<DT,DP...> & dst
, const View<ST,SP...> & src
, typename std::enable_if<(
std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value &&
std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value &&
( unsigned(ViewTraits<DT,DP...>::rank) == unsigned(0) &&
unsigned(ViewTraits<ST,SP...>::rank) == unsigned(0) )
)>::type * = 0 )
{
static_assert(
std::is_same< typename ViewTraits<DT,DP...>::value_type ,
typename ViewTraits<ST,SP...>::non_const_value_type >::value
, "deep_copy requires matching non-const destination type" );
typedef View<DT,DP...> dst_type ;
typedef View<ST,SP...> src_type ;
typedef typename dst_type::value_type value_type ;
typedef typename dst_type::memory_space dst_memory_space ;
typedef typename src_type::memory_space src_memory_space ;
if ( dst.data() != src.data() ) {
Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space >( dst.data() , src.data() , sizeof(value_type) );
}
}
//----------------------------------------------------------------------------
/** \brief A deep copy between views of the default specialization, compatible type,
* same non-zero rank, same contiguous layout.
*/
template< class DT , class ... DP , class ST , class ... SP >
inline
void deep_copy
( const View<DT,DP...> & dst
, const View<ST,SP...> & src
, typename std::enable_if<(
std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value &&
std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value &&
( unsigned(ViewTraits<DT,DP...>::rank) != 0 ||
unsigned(ViewTraits<ST,SP...>::rank) != 0 )
)>::type * = 0 )
{
static_assert(
std::is_same< typename ViewTraits<DT,DP...>::value_type ,
typename ViewTraits<DT,DP...>::non_const_value_type >::value
, "deep_copy requires non-const destination type" );
static_assert(
( unsigned(ViewTraits<DT,DP...>::rank) ==
unsigned(ViewTraits<ST,SP...>::rank) )
, "deep_copy requires Views of equal rank" );
typedef View<DT,DP...> dst_type ;
typedef View<ST,SP...> src_type ;
typedef typename dst_type::execution_space dst_execution_space ;
typedef typename src_type::execution_space src_execution_space ;
typedef typename dst_type::memory_space dst_memory_space ;
typedef typename src_type::memory_space src_memory_space ;
enum { DstExecCanAccessSrc =
Kokkos::Impl::SpaceAccessibility< dst_execution_space , src_memory_space >::accessible };
enum { SrcExecCanAccessDst =
Kokkos::Impl::SpaceAccessibility< src_execution_space , dst_memory_space >::accessible };
if ( (void *) dst.data() != (void*) src.data() ) {
#if defined(KOKKOS_ENABLE_PROFILING)
if (Kokkos::Profiling::profileLibraryLoaded()) {
const size_t nbytes = sizeof(typename dst_type::value_type) * dst.span();
Kokkos::Profiling::beginDeepCopy(
Kokkos::Profiling::SpaceHandle(dst_memory_space::name()),
dst.label(),
dst.data(),
Kokkos::Profiling::SpaceHandle(src_memory_space::name()),
src.label(),
src.data(),
nbytes);
}
#endif
// Concern: If overlapping views then a parallel copy will be erroneous.
// ...
// If same type, equal layout, equal dimensions, equal span, and contiguous memory then can byte-wise copy
if ( std::is_same< typename ViewTraits<DT,DP...>::value_type ,
typename ViewTraits<ST,SP...>::non_const_value_type >::value &&
(
( std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
typename ViewTraits<ST,SP...>::array_layout >::value
&&
( std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
typename Kokkos::LayoutLeft>::value
||
std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
typename Kokkos::LayoutRight>::value
)
)
||
( ViewTraits<DT,DP...>::rank == 1 &&
ViewTraits<ST,SP...>::rank == 1 )
) &&
dst.span_is_contiguous() &&
src.span_is_contiguous() &&
dst.span() == src.span() &&
dst.dimension_0() == src.dimension_0() &&
dst.dimension_1() == src.dimension_1() &&
dst.dimension_2() == src.dimension_2() &&
dst.dimension_3() == src.dimension_3() &&
dst.dimension_4() == src.dimension_4() &&
dst.dimension_5() == src.dimension_5() &&
dst.dimension_6() == src.dimension_6() &&
dst.dimension_7() == src.dimension_7() ) {
const size_t nbytes = sizeof(typename dst_type::value_type) * dst.span();
Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space >( dst.data() , src.data() , nbytes );
}
else if ( std::is_same< typename ViewTraits<DT,DP...>::value_type ,
typename ViewTraits<ST,SP...>::non_const_value_type >::value &&
(
( std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
typename ViewTraits<ST,SP...>::array_layout >::value
&&
std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
typename Kokkos::LayoutStride>::value
)
||
( ViewTraits<DT,DP...>::rank == 1 &&
ViewTraits<ST,SP...>::rank == 1 )
) &&
dst.span_is_contiguous() &&
src.span_is_contiguous() &&
dst.span() == src.span() &&
dst.dimension_0() == src.dimension_0() &&
dst.dimension_1() == src.dimension_1() &&
dst.dimension_2() == src.dimension_2() &&
dst.dimension_3() == src.dimension_3() &&
dst.dimension_4() == src.dimension_4() &&
dst.dimension_5() == src.dimension_5() &&
dst.dimension_6() == src.dimension_6() &&
dst.dimension_7() == src.dimension_7() &&
dst.stride_0() == src.stride_0() &&
dst.stride_1() == src.stride_1() &&
dst.stride_2() == src.stride_2() &&
dst.stride_3() == src.stride_3() &&
dst.stride_4() == src.stride_4() &&
dst.stride_5() == src.stride_5() &&
dst.stride_6() == src.stride_6() &&
dst.stride_7() == src.stride_7()
) {
const size_t nbytes = sizeof(typename dst_type::value_type) * dst.span();
Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space >( dst.data() , src.data() , nbytes );
}
else if ( DstExecCanAccessSrc ) {
// Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
Kokkos::Impl::ViewRemap< dst_type , src_type >( dst , src );
}
else if ( SrcExecCanAccessDst ) {
// Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
Kokkos::Impl::ViewRemap< dst_type , src_type , src_execution_space >( dst , src );
}
else {
Kokkos::Impl::throw_runtime_exception("deep_copy given views that would require a temporary allocation");
}
#if defined(KOKKOS_ENABLE_PROFILING)
if (Kokkos::Profiling::profileLibraryLoaded()) {
Kokkos::Profiling::endDeepCopy();
}
#endif
} // ( (void *) dst.data() != (void*) src.data() )
}
} /* namespace Kokkos */
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
/** \brief Deep copy a value from Host memory into a view. */
template< class ExecSpace ,class DT , class ... DP >
inline
void deep_copy
( const ExecSpace &
, const View<DT,DP...> & dst
, typename ViewTraits<DT,DP...>::const_value_type & value
, typename std::enable_if<
Kokkos::Impl::is_execution_space< ExecSpace >::value &&
std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value
>::type * = 0 )
{
static_assert(
std::is_same< typename ViewTraits<DT,DP...>::non_const_value_type ,
typename ViewTraits<DT,DP...>::value_type >::value
, "deep_copy requires non-const type" );
Kokkos::Impl::ViewFill< View<DT,DP...> >( dst , value );
}
/** \brief Deep copy into a value in Host memory from a view. */
template< class ExecSpace , class ST , class ... SP >
inline
void deep_copy
( const ExecSpace & exec_space
, typename ViewTraits<ST,SP...>::non_const_value_type & dst
, const View<ST,SP...> & src
, typename std::enable_if<
Kokkos::Impl::is_execution_space< ExecSpace >::value &&
std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value
>::type * = 0 )
{
static_assert( ViewTraits<ST,SP...>::rank == 0
, "ERROR: Non-rank-zero view in deep_copy( value , View )" );
typedef ViewTraits<ST,SP...> src_traits ;
typedef typename src_traits::memory_space src_memory_space ;
Kokkos::Impl::DeepCopy< HostSpace , src_memory_space , ExecSpace >
( exec_space , & dst , src.data() , sizeof(ST) );
}
//----------------------------------------------------------------------------
/** \brief A deep copy between views of compatible type, and rank zero. */
template< class ExecSpace , class DT , class ... DP , class ST , class ... SP >
inline
void deep_copy
( const ExecSpace & exec_space
, const View<DT,DP...> & dst
, const View<ST,SP...> & src
, typename std::enable_if<(
Kokkos::Impl::is_execution_space< ExecSpace >::value &&
std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value &&
std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value &&
( unsigned(ViewTraits<DT,DP...>::rank) == unsigned(0) &&
unsigned(ViewTraits<ST,SP...>::rank) == unsigned(0) )
)>::type * = 0 )
{
static_assert(
std::is_same< typename ViewTraits<DT,DP...>::value_type ,
typename ViewTraits<ST,SP...>::non_const_value_type >::value
, "deep_copy requires matching non-const destination type" );
typedef View<DT,DP...> dst_type ;
typedef View<ST,SP...> src_type ;
typedef typename dst_type::value_type value_type ;
typedef typename dst_type::memory_space dst_memory_space ;
typedef typename src_type::memory_space src_memory_space ;
if ( dst.data() != src.data() ) {
Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space , ExecSpace >
( exec_space , dst.data() , src.data() , sizeof(value_type) );
}
}
//----------------------------------------------------------------------------
/** \brief A deep copy between views of the default specialization, compatible type,
* same non-zero rank, same contiguous layout.
*/
template< class ExecSpace , class DT, class ... DP, class ST, class ... SP >
inline
void deep_copy
( const ExecSpace & exec_space
, const View<DT,DP...> & dst
, const View<ST,SP...> & src
, typename std::enable_if<(
Kokkos::Impl::is_execution_space< ExecSpace >::value &&
std::is_same< typename ViewTraits<DT,DP...>::specialize , void >::value &&
std::is_same< typename ViewTraits<ST,SP...>::specialize , void >::value &&
( unsigned(ViewTraits<DT,DP...>::rank) != 0 ||
unsigned(ViewTraits<ST,SP...>::rank) != 0 )
)>::type * = 0 )
{
static_assert(
std::is_same< typename ViewTraits<DT,DP...>::value_type ,
typename ViewTraits<DT,DP...>::non_const_value_type >::value
, "deep_copy requires non-const destination type" );
static_assert(
( unsigned(ViewTraits<DT,DP...>::rank) ==
unsigned(ViewTraits<ST,SP...>::rank) )
, "deep_copy requires Views of equal rank" );
typedef View<DT,DP...> dst_type ;
typedef View<ST,SP...> src_type ;
typedef typename dst_type::execution_space dst_execution_space ;
typedef typename src_type::execution_space src_execution_space ;
typedef typename dst_type::memory_space dst_memory_space ;
typedef typename src_type::memory_space src_memory_space ;
enum { DstExecCanAccessSrc =
Kokkos::Impl::SpaceAccessibility< dst_execution_space , src_memory_space >::accessible };
enum { SrcExecCanAccessDst =
Kokkos::Impl::SpaceAccessibility< src_execution_space , dst_memory_space >::accessible };
if ( (void *) dst.data() != (void*) src.data() ) {
// Concern: If overlapping views then a parallel copy will be erroneous.
// ...
// If same type, equal layout, equal dimensions, equal span, and contiguous memory then can byte-wise copy
if ( std::is_same< typename ViewTraits<DT,DP...>::value_type ,
typename ViewTraits<ST,SP...>::non_const_value_type >::value &&
(
std::is_same< typename ViewTraits<DT,DP...>::array_layout ,
typename ViewTraits<ST,SP...>::array_layout >::value
||
( ViewTraits<DT,DP...>::rank == 1 &&
ViewTraits<ST,SP...>::rank == 1 )
) &&
dst.span_is_contiguous() &&
src.span_is_contiguous() &&
dst.span() == src.span() &&
dst.dimension_0() == src.dimension_0() &&
dst.dimension_1() == src.dimension_1() &&
dst.dimension_2() == src.dimension_2() &&
dst.dimension_3() == src.dimension_3() &&
dst.dimension_4() == src.dimension_4() &&
dst.dimension_5() == src.dimension_5() &&
dst.dimension_6() == src.dimension_6() &&
dst.dimension_7() == src.dimension_7() ) {
const size_t nbytes = sizeof(typename dst_type::value_type) * dst.span();
Kokkos::Impl::DeepCopy< dst_memory_space , src_memory_space , ExecSpace >
( exec_space , dst.data() , src.data() , nbytes );
}
else if ( DstExecCanAccessSrc ) {
// Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
Kokkos::Impl::ViewRemap< dst_type , src_type >( dst , src );
}
else if ( SrcExecCanAccessDst ) {
// Copying data between views in accessible memory spaces and either non-contiguous or incompatible shape.
Kokkos::Impl::ViewRemap< dst_type , src_type , src_execution_space >( dst , src );
}
else {
Kokkos::Impl::throw_runtime_exception("deep_copy given views that would require a temporary allocation");
}
}
}
} /* namespace Kokkos */
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
namespace Impl {
// Deduce Mirror Types
template<class Space, class T, class ... P>
struct MirrorViewType {
// The incoming view_type
typedef typename Kokkos::View<T,P...> src_view_type;
// The memory space for the mirror view
typedef typename Space::memory_space memory_space;
// Check whether it is the same memory space
enum { is_same_memspace = std::is_same<memory_space,typename src_view_type::memory_space>::value };
// The array_layout
typedef typename src_view_type::array_layout array_layout;
// The data type (we probably want it non-const since otherwise we can't even deep_copy to it.
typedef typename src_view_type::non_const_data_type data_type;
// The destination view type if it is not the same memory space
typedef Kokkos::View<data_type,array_layout,Space> dest_view_type;
// If it is the same memory_space return the existsing view_type
// This will also keep the unmanaged trait if necessary
typedef typename std::conditional<is_same_memspace,src_view_type,dest_view_type>::type view_type;
};
template<class Space, class T, class ... P>
struct MirrorType {
// The incoming view_type
typedef typename Kokkos::View<T,P...> src_view_type;
// The memory space for the mirror view
typedef typename Space::memory_space memory_space;
// Check whether it is the same memory space
enum { is_same_memspace = std::is_same<memory_space,typename src_view_type::memory_space>::value };
// The array_layout
typedef typename src_view_type::array_layout array_layout;
// The data type (we probably want it non-const since otherwise we can't even deep_copy to it.
typedef typename src_view_type::non_const_data_type data_type;
// The destination view type if it is not the same memory space
typedef Kokkos::View<data_type,array_layout,Space> view_type;
};
}
template< class T , class ... P >
inline
typename Kokkos::View<T,P...>::HostMirror
create_mirror( const Kokkos::View<T,P...> & src
, typename std::enable_if<
! std::is_same< typename Kokkos::ViewTraits<T,P...>::array_layout
, Kokkos::LayoutStride >::value
>::type * = 0
)
{
typedef View<T,P...> src_type ;
typedef typename src_type::HostMirror dst_type ;
return dst_type( std::string( src.label() ).append("_mirror")
, src.dimension_0()
, src.dimension_1()
, src.dimension_2()
, src.dimension_3()
, src.dimension_4()
, src.dimension_5()
, src.dimension_6()
, src.dimension_7() );
}
template< class T , class ... P >
inline
typename Kokkos::View<T,P...>::HostMirror
create_mirror( const Kokkos::View<T,P...> & src
, typename std::enable_if<
std::is_same< typename Kokkos::ViewTraits<T,P...>::array_layout
, Kokkos::LayoutStride >::value
>::type * = 0
)
{
typedef View<T,P...> src_type ;
typedef typename src_type::HostMirror dst_type ;
Kokkos::LayoutStride layout ;
layout.dimension[0] = src.dimension_0();
layout.dimension[1] = src.dimension_1();
layout.dimension[2] = src.dimension_2();
layout.dimension[3] = src.dimension_3();
layout.dimension[4] = src.dimension_4();
layout.dimension[5] = src.dimension_5();
layout.dimension[6] = src.dimension_6();
layout.dimension[7] = src.dimension_7();
layout.stride[0] = src.stride_0();
layout.stride[1] = src.stride_1();
layout.stride[2] = src.stride_2();
layout.stride[3] = src.stride_3();
layout.stride[4] = src.stride_4();
layout.stride[5] = src.stride_5();
layout.stride[6] = src.stride_6();
layout.stride[7] = src.stride_7();
return dst_type( std::string( src.label() ).append("_mirror") , layout );
}
// Create a mirror in a new space (specialization for different space)
template<class Space, class T, class ... P>
typename Impl::MirrorType<Space,T,P ...>::view_type create_mirror(const Space& , const Kokkos::View<T,P...> & src) {
return typename Impl::MirrorType<Space,T,P ...>::view_type(src.label(),src.layout());
}
template< class T , class ... P >
inline
typename Kokkos::View<T,P...>::HostMirror
create_mirror_view( const Kokkos::View<T,P...> & src
, typename std::enable_if<(
std::is_same< typename Kokkos::View<T,P...>::memory_space
, typename Kokkos::View<T,P...>::HostMirror::memory_space
>::value
&&
std::is_same< typename Kokkos::View<T,P...>::data_type
, typename Kokkos::View<T,P...>::HostMirror::data_type
>::value
)>::type * = 0
)
{
return src ;
}
template< class T , class ... P >
inline
typename Kokkos::View<T,P...>::HostMirror
create_mirror_view( const Kokkos::View<T,P...> & src
, typename std::enable_if< ! (
std::is_same< typename Kokkos::View<T,P...>::memory_space
, typename Kokkos::View<T,P...>::HostMirror::memory_space
>::value
&&
std::is_same< typename Kokkos::View<T,P...>::data_type
, typename Kokkos::View<T,P...>::HostMirror::data_type
>::value
)>::type * = 0
)
{
return Kokkos::create_mirror( src );
}
// Create a mirror view in a new space (specialization for same space)
template<class Space, class T, class ... P>
typename Impl::MirrorViewType<Space,T,P ...>::view_type
create_mirror_view(const Space& , const Kokkos::View<T,P...> & src
, typename std::enable_if<Impl::MirrorViewType<Space,T,P ...>::is_same_memspace>::type* = 0 ) {
return src;
}
// Create a mirror view in a new space (specialization for different space)
template<class Space, class T, class ... P>
typename Impl::MirrorViewType<Space,T,P ...>::view_type
create_mirror_view(const Space& , const Kokkos::View<T,P...> & src
, typename std::enable_if<!Impl::MirrorViewType<Space,T,P ...>::is_same_memspace>::type* = 0 ) {
return typename Impl::MirrorViewType<Space,T,P ...>::view_type(src.label(),src.layout());
}
} /* namespace Kokkos */
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos {
/** \brief Resize a view with copying old data to new data at the corresponding indices. */
template< class T , class ... P >
inline
typename std::enable_if<
std::is_same<typename Kokkos::View<T,P...>::array_layout,Kokkos::LayoutLeft>::value ||
std::is_same<typename Kokkos::View<T,P...>::array_layout,Kokkos::LayoutRight>::value
>::type
resize( Kokkos::View<T,P...> & v ,
const size_t n0 = 0 ,
const size_t n1 = 0 ,
const size_t n2 = 0 ,
const size_t n3 = 0 ,
const size_t n4 = 0 ,
const size_t n5 = 0 ,
const size_t n6 = 0 ,
const size_t n7 = 0 )
{
typedef Kokkos::View<T,P...> view_type ;
static_assert( Kokkos::ViewTraits<T,P...>::is_managed , "Can only resize managed views" );
// Fix #904 by checking dimensions before actually resizing.
//
// Rank is known at compile time, so hopefully the compiler will
// remove branches that are compile-time false. The upcoming "if
// constexpr" language feature would make this certain.
if (view_type::Rank == 1 &&
n0 == static_cast<size_t> (v.extent(0))) {
return;
}
if (view_type::Rank == 2 &&
n0 == static_cast<size_t> (v.extent(0)) &&
n1 == static_cast<size_t> (v.extent(1))) {
return;
}
if (view_type::Rank == 3 &&
n0 == static_cast<size_t> (v.extent(0)) &&
n1 == static_cast<size_t> (v.extent(1)) &&
n2 == static_cast<size_t> (v.extent(2))) {
return;
}
if (view_type::Rank == 4 &&
n0 == static_cast<size_t> (v.extent(0)) &&
n1 == static_cast<size_t> (v.extent(1)) &&
n2 == static_cast<size_t> (v.extent(2)) &&
n3 == static_cast<size_t> (v.extent(3))) {
return;
}
if (view_type::Rank == 5 &&
n0 == static_cast<size_t> (v.extent(0)) &&
n1 == static_cast<size_t> (v.extent(1)) &&
n2 == static_cast<size_t> (v.extent(2)) &&
n3 == static_cast<size_t> (v.extent(3)) &&
n4 == static_cast<size_t> (v.extent(4))) {
return;
}
if (view_type::Rank == 6 &&
n0 == static_cast<size_t> (v.extent(0)) &&
n1 == static_cast<size_t> (v.extent(1)) &&
n2 == static_cast<size_t> (v.extent(2)) &&
n3 == static_cast<size_t> (v.extent(3)) &&
n4 == static_cast<size_t> (v.extent(4)) &&
n5 == static_cast<size_t> (v.extent(5))) {
return;
}
if (view_type::Rank == 7 &&
n0 == static_cast<size_t> (v.extent(0)) &&
n1 == static_cast<size_t> (v.extent(1)) &&
n2 == static_cast<size_t> (v.extent(2)) &&
n3 == static_cast<size_t> (v.extent(3)) &&
n4 == static_cast<size_t> (v.extent(4)) &&
n5 == static_cast<size_t> (v.extent(5)) &&
n6 == static_cast<size_t> (v.extent(6))) {
return;
}
if (view_type::Rank == 8 &&
n0 == static_cast<size_t> (v.extent(0)) &&
n1 == static_cast<size_t> (v.extent(1)) &&
n2 == static_cast<size_t> (v.extent(2)) &&
n3 == static_cast<size_t> (v.extent(3)) &&
n4 == static_cast<size_t> (v.extent(4)) &&
n5 == static_cast<size_t> (v.extent(5)) &&
n6 == static_cast<size_t> (v.extent(6)) &&
n7 == static_cast<size_t> (v.extent(7))) {
return;
}
// If Kokkos ever supports Views of rank > 8, the above code won't
// be incorrect, because avoiding reallocation in resize() is just
// an optimization.
// TODO (mfh 27 Jun 2017) If the old View has enough space but just
// different dimensions (e.g., if the product of the dimensions,
// including extra space for alignment, will not change), then
// consider just reusing storage. For now, Kokkos always
// reallocates if any of the dimensions change, even if the old View
// has enough space.
view_type v_resized( v.label(), n0, n1, n2, n3, n4, n5, n6, n7 );
Kokkos::Impl::ViewRemap< view_type , view_type >( v_resized , v );
v = v_resized ;
}
/** \brief Resize a view with copying old data to new data at the corresponding indices. */
template< class T , class ... P >
inline
void resize( Kokkos::View<T,P...> & v ,
const typename Kokkos::View<T,P...>::array_layout & layout)
{
typedef Kokkos::View<T,P...> view_type ;
static_assert( Kokkos::ViewTraits<T,P...>::is_managed , "Can only resize managed views" );
view_type v_resized( v.label(), layout );
Kokkos::Impl::ViewRemap< view_type , view_type >( v_resized , v );
v = v_resized ;
}
/** \brief Resize a view with discarding old data. */
template< class T , class ... P >
inline
typename std::enable_if<
std::is_same<typename Kokkos::View<T,P...>::array_layout,Kokkos::LayoutLeft>::value ||
std::is_same<typename Kokkos::View<T,P...>::array_layout,Kokkos::LayoutRight>::value
>::type
realloc( Kokkos::View<T,P...> & v ,
const size_t n0 = 0 ,
const size_t n1 = 0 ,
const size_t n2 = 0 ,
const size_t n3 = 0 ,
const size_t n4 = 0 ,
const size_t n5 = 0 ,
const size_t n6 = 0 ,
const size_t n7 = 0 )
{
typedef Kokkos::View<T,P...> view_type ;
static_assert( Kokkos::ViewTraits<T,P...>::is_managed , "Can only realloc managed views" );
const std::string label = v.label();
v = view_type(); // Deallocate first, if the only view to allocation
v = view_type( label, n0, n1, n2, n3, n4, n5, n6, n7 );
}
/** \brief Resize a view with discarding old data. */
template< class T , class ... P >
inline
void realloc( Kokkos::View<T,P...> & v ,
const typename Kokkos::View<T,P...>::array_layout & layout)
{
typedef Kokkos::View<T,P...> view_type ;
static_assert( Kokkos::ViewTraits<T,P...>::is_managed , "Can only realloc managed views" );
const std::string label = v.label();
v = view_type(); // Deallocate first, if the only view to allocation
v = view_type( label, layout );
}
} /* namespace Kokkos */
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
namespace Kokkos { namespace Impl {
template < class Specialize, typename A, typename B >
struct CommonViewValueType;
template < typename A, typename B >
struct CommonViewValueType< void, A, B >
{
using value_type = typename std::common_type< A , B >::type;
};
template < class Specialize, class ValueType >
struct CommonViewAllocProp;
template < class ValueType >
struct CommonViewAllocProp< void, ValueType >
{
using value_type = ValueType;
template < class ... Views >
CommonViewAllocProp( const Views & ... ) {}
};
template < class ... Views >
struct DeduceCommonViewAllocProp;
// Base case must provide types for:
// 1. specialize 2. value_type 3. is_view 4. prop_type
template < class FirstView >
struct DeduceCommonViewAllocProp< FirstView >
{
using specialize = typename FirstView::traits::specialize;
using value_type = typename FirstView::traits::value_type;
enum : bool { is_view = is_view< FirstView >::value };
using prop_type = CommonViewAllocProp< specialize, value_type >;
};
template < class FirstView, class ... NextViews >
struct DeduceCommonViewAllocProp< FirstView, NextViews... >
{
using NextTraits = DeduceCommonViewAllocProp< NextViews... >;
using first_specialize = typename FirstView::traits::specialize;
using first_value_type = typename FirstView::traits::value_type;
enum : bool { first_is_view = is_view< FirstView >::value };
using next_specialize = typename NextTraits::specialize;
using next_value_type = typename NextTraits::value_type;
enum : bool { next_is_view = NextTraits::is_view };
// common types
// determine specialize type
// if first and next specialize differ, but are not the same specialize, error out
static_assert( !(!std::is_same< first_specialize, next_specialize >::value && !std::is_same< first_specialize, void>::value && !std::is_same< void, next_specialize >::value) , "Kokkos DeduceCommonViewAllocProp ERROR: Only one non-void specialize trait allowed" );
// otherwise choose non-void specialize if either/both are non-void
using specialize = typename std::conditional< std::is_same< first_specialize, next_specialize >::value
, first_specialize
, typename std::conditional< ( std::is_same< first_specialize, void >::value
&& !std::is_same< next_specialize, void >::value)
, next_specialize
, first_specialize
>::type
>::type;
using value_type = typename CommonViewValueType< specialize, first_value_type, next_value_type >::value_type;
enum : bool { is_view = (first_is_view && next_is_view) };
using prop_type = CommonViewAllocProp< specialize, value_type >;
};
} // end namespace Impl
template < class ... Views >
using DeducedCommonPropsType = typename Impl::DeduceCommonViewAllocProp<Views...>::prop_type ;
// User function
template < class ... Views >
DeducedCommonPropsType<Views...>
common_view_alloc_prop( Views const & ... views )
{
return DeducedCommonPropsType<Views...>( views... );
}
} // namespace Kokkos
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
// For backward compatibility:
namespace Kokkos {
namespace Experimental {
using Kokkos::ViewTraits ;
using Kokkos::View ;
using Kokkos::Subview ;
using Kokkos::is_view ;
using Kokkos::subview ;
using Kokkos::ALL ;
using Kokkos::WithoutInitializing ;
using Kokkos::AllowPadding ;
using Kokkos::view_alloc ;
using Kokkos::view_wrap ;
using Kokkos::deep_copy ;
using Kokkos::create_mirror ;
using Kokkos::create_mirror_view ;
using Kokkos::resize ;
using Kokkos::realloc ;
namespace Impl {
using Kokkos::Impl::ViewFill ;
using Kokkos::Impl::ViewRemap ;
using Kokkos::Impl::ViewCtorProp ;
using Kokkos::Impl::is_view_label ;
using Kokkos::Impl::WithoutInitializing_t ;
using Kokkos::Impl::AllowPadding_t ;
using Kokkos::Impl::SharedAllocationRecord ;
using Kokkos::Impl::SharedAllocationTracker ;
using Kokkos::Impl::ViewMapping ;
using Kokkos::Impl::ViewDataAnalysis ;
} /* namespace Impl */
} /* namespace Experimental */
} /* namespace Kokkos */
namespace Kokkos {
namespace Impl {
using Kokkos::is_view ;
template< class SrcViewType
, class Arg0Type
, class Arg1Type
, class Arg2Type
, class Arg3Type
, class Arg4Type
, class Arg5Type
, class Arg6Type
, class Arg7Type
>
struct ViewSubview /* { typedef ... type ; } */ ;
} /* namespace Impl */
} /* namespace Kokkos */
#include <impl/Kokkos_Atomic_View.hpp>
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
#endif /* #ifndef KOKKOS_VIEW_HPP */