Skip to content

Commit

Permalink
Merge pull request kokkos#7334 from crtrott/view_typedefs
Browse files Browse the repository at this point in the history
View-refactor: update View Typedefs: add some from mdspan and fix uniform const types
  • Loading branch information
crtrott authored Sep 16, 2024
2 parents af8df13 + 18eef21 commit 0721025
Show file tree
Hide file tree
Showing 4 changed files with 301 additions and 7 deletions.
21 changes: 18 additions & 3 deletions core/src/View/Kokkos_ViewLegacy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,24 @@ class View : public ViewTraits<DataType, Properties...> {
using uniform_runtime_const_nomemspace_type =
typename Impl::ViewUniformType<View, 0>::runtime_const_nomemspace_type;

using reference_type = typename map_type::reference_type;
using pointer_type = typename map_type::pointer_type;

// Typedefs from mdspan
// using extents_type -> not applicable
// Defining layout_type here made MSVC+CUDA fail
// using layout_type = typename traits::array_layout;
// using accessor_type -> not applicable
// using mapping_type -> not applicable
using element_type = typename traits::value_type;
// using value_type -> conflicts with traits::value_type
using index_type = typename traits::memory_space::size_type;
// using size_type -> already from traits::size_type; where it is
// memory_space::size_type
using rank_type = size_t;
using data_handle_type = pointer_type;
using reference = reference_type;

//----------------------------------------
// Domain rank and extents

Expand Down Expand Up @@ -394,9 +412,6 @@ class View : public ViewTraits<DataType, Properties...> {
//----------------------------------------
// Range span is the span which contains all members.

using reference_type = typename map_type::reference_type;
using pointer_type = typename map_type::pointer_type;

enum {
reference_type_is_lvalue_reference =
std::is_lvalue_reference_v<reference_type>
Expand Down
12 changes: 8 additions & 4 deletions core/src/View/Kokkos_ViewUniformType.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,14 @@ namespace Impl {
template <class ScalarType, int Rank>
struct ViewScalarToDataType {
using type = typename ViewScalarToDataType<ScalarType, Rank - 1>::type *;
using const_type =
typename ViewScalarToDataType<ScalarType, Rank - 1>::const_type *;
};

template <class ScalarType>
struct ViewScalarToDataType<ScalarType, 0> {
using type = ScalarType;
using type = ScalarType;
using const_type = const ScalarType;
};

template <class LayoutType, int Rank>
Expand All @@ -49,12 +52,13 @@ struct ViewUniformLayout<Kokkos::LayoutRight, 1> {
template <class ViewType, int Traits>
struct ViewUniformType {
using data_type = typename ViewType::data_type;
using const_data_type = std::add_const_t<typename ViewType::data_type>;
using const_data_type = typename ViewType::const_data_type;
using runtime_data_type =
typename ViewScalarToDataType<typename ViewType::value_type,
ViewType::rank>::type;
using runtime_const_data_type = typename ViewScalarToDataType<
std::add_const_t<typename ViewType::value_type>, ViewType::rank>::type;
using runtime_const_data_type =
typename ViewScalarToDataType<typename ViewType::value_type,
ViewType::rank>::const_type;

using array_layout =
typename ViewUniformLayout<typename ViewType::array_layout,
Expand Down
1 change: 1 addition & 0 deletions core/unit_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ SET(COMPILE_ONLY_SOURCES
TestVersionMacros.cpp
TestViewRank.cpp
TestViewTypeTraits.cpp
TestViewTypedefs.cpp
TestTypeInfo.cpp
TestTypeList.cpp
TestMDRangePolicyCTAD.cpp
Expand Down
274 changes: 274 additions & 0 deletions core/unit_test/TestViewTypedefs.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
//@HEADER
// ************************************************************************
//
// Kokkos v. 4.0
// Copyright (2022) National Technology & Engineering
// Solutions of Sandia, LLC (NTESS).
//
// Under the terms of Contract DE-NA0003525 with NTESS,
// the U.S. Government retains certain rights in this software.
//
// Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
// See https://kokkos.org/LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//@HEADER

#include <Kokkos_Core.hpp>

namespace {

// clang-format off
template<class DataType>
struct data_analysis {
using data_type = DataType;
using const_data_type = const DataType;
using runtime_data_type = DataType;
using runtime_const_data_type = const DataType;
using non_const_data_type = std::remove_const_t<DataType>;
};

template<class DataType>
struct data_analysis<DataType*> {
using data_type = typename data_analysis<DataType>::data_type*;
using const_data_type = typename data_analysis<DataType>::const_data_type*;
using runtime_data_type = typename data_analysis<DataType>::runtime_data_type*;
using runtime_const_data_type = typename data_analysis<DataType>::runtime_const_data_type*;
using non_const_data_type = typename data_analysis<DataType>::non_const_data_type*;
};

template<class DataType, size_t N>
struct data_analysis<DataType[N]> {
using data_type = typename data_analysis<DataType>::data_type[N];
using const_data_type = typename data_analysis<DataType>::const_data_type[N];
using runtime_data_type = typename data_analysis<DataType>::runtime_data_type*;
using runtime_const_data_type = typename data_analysis<DataType>::runtime_const_data_type*;
using non_const_data_type = typename data_analysis<DataType>::non_const_data_type[N];
};

template<class ViewType, class ViewTraitsType, class DataType, class Layout, class Space, class MemoryTraitsType,
class HostMirrorSpace, class ValueType, class ReferenceType>
constexpr bool test_view_typedefs_impl() {
// ========================
// inherited from ViewTraits
// ========================
static_assert(std::is_same_v<typename ViewType::data_type, DataType>);
static_assert(std::is_same_v<typename ViewType::const_data_type, typename data_analysis<DataType>::const_data_type>);
static_assert(std::is_same_v<typename ViewType::non_const_data_type, typename data_analysis<DataType>::non_const_data_type>);

// these should be deprecated and for proper testing (I.e. where this is different from data_type)
// we would need ensemble types which use the hidden View dimension facility of View (i.e. which make
// "specialize" not void)
static_assert(std::is_same_v<typename ViewType::scalar_array_type, DataType>);
static_assert(std::is_same_v<typename ViewType::const_scalar_array_type, typename data_analysis<DataType>::const_data_type>);
static_assert(std::is_same_v<typename ViewType::non_const_scalar_array_type, typename data_analysis<DataType>::non_const_data_type>);
static_assert(std::is_same_v<typename ViewType::specialize, void>);

// value_type definition conflicts with mdspan value_type
static_assert(std::is_same_v<typename ViewType::value_type, ValueType>);
static_assert(std::is_same_v<typename ViewType::const_value_type, const ValueType>);
static_assert(std::is_same_v<typename ViewType::non_const_value_type, std::remove_const_t<ValueType>>);

// should maybe be deprecated
static_assert(std::is_same_v<typename ViewType::array_layout, Layout>);

// should be deprecated and is some complicated impl type
static_assert(!std::is_void_v<typename ViewType::dimension>);

static_assert(std::is_same_v<typename ViewType::execution_space, typename Space::execution_space>);
static_assert(std::is_same_v<typename ViewType::memory_space, typename Space::memory_space>);
static_assert(std::is_same_v<typename ViewType::device_type, Kokkos::Device<typename ViewType::execution_space, typename ViewType::memory_space>>);
static_assert(std::is_same_v<typename ViewType::memory_traits, MemoryTraitsType>);
static_assert(std::is_same_v<typename ViewType::host_mirror_space, HostMirrorSpace>);
static_assert(std::is_same_v<typename ViewType::size_type, typename ViewType::memory_space::size_type>);

// should be deprecated in favor of reference
static_assert(std::is_same_v<typename ViewType::reference_type, ReferenceType>);
// should be deprecated in favor of data_handle_type
static_assert(std::is_same_v<typename ViewType::pointer_type, ValueType*>);

// =========================================
// in Legacy View: some helper View variants
// =========================================
static_assert(std::is_same_v<typename ViewType::traits, ViewTraitsType>);
static_assert(std::is_same_v<typename ViewType::array_type,
Kokkos::View<typename ViewType::scalar_array_type, typename ViewType::array_layout,
typename ViewType::device_type, typename ViewTraitsType::hooks_policy,
typename ViewType::memory_traits>>);
static_assert(std::is_same_v<typename ViewType::const_type,
Kokkos::View<typename ViewType::const_data_type, typename ViewType::array_layout,
typename ViewType::device_type, typename ViewTraitsType::hooks_policy,
typename ViewType::memory_traits>>);
static_assert(std::is_same_v<typename ViewType::non_const_type,
Kokkos::View<typename ViewType::non_const_data_type, typename ViewType::array_layout,
typename ViewType::device_type, typename ViewTraitsType::hooks_policy,
typename ViewType::memory_traits>>);
static_assert(std::is_same_v<typename ViewType::host_mirror_type,
Kokkos::View<typename ViewType::non_const_data_type, typename ViewType::array_layout,
Kokkos::Device<Kokkos::DefaultHostExecutionSpace,
typename ViewType::host_mirror_space::memory_space>,
typename ViewTraitsType::hooks_policy>>);

using uniform_layout_type = std::conditional_t<ViewType::rank()==0 || (ViewType::rank()==0 &&
std::is_same_v<Layout, Kokkos::LayoutRight>),
Kokkos::LayoutLeft, Layout>;

// Uhm uniformtype removes all memorytraits?
static_assert(std::is_same_v<typename ViewType::uniform_type,
Kokkos::View<typename ViewType::data_type, uniform_layout_type,
typename ViewType::device_type, Kokkos::MemoryTraits<0>>>);
static_assert(std::is_same_v<typename ViewType::uniform_const_type,
Kokkos::View<typename ViewType::const_data_type, uniform_layout_type,
typename ViewType::device_type, Kokkos::MemoryTraits<0>>>);
static_assert(std::is_same_v<typename ViewType::uniform_runtime_type,
Kokkos::View<typename data_analysis<DataType>::runtime_data_type, uniform_layout_type,
typename ViewType::device_type, Kokkos::MemoryTraits<0>>>);
static_assert(std::is_same_v<typename ViewType::uniform_runtime_const_type,
Kokkos::View<typename data_analysis<DataType>::runtime_const_data_type, uniform_layout_type,
typename ViewType::device_type, Kokkos::MemoryTraits<0>>>);

using anonymous_device_type = Kokkos::Device<typename ViewType::execution_space, Kokkos::AnonymousSpace>;
static_assert(std::is_same_v<typename ViewType::uniform_nomemspace_type,
Kokkos::View<typename ViewType::data_type, uniform_layout_type,
anonymous_device_type, Kokkos::MemoryTraits<0>>>);
static_assert(std::is_same_v<typename ViewType::uniform_const_nomemspace_type,
Kokkos::View<typename ViewType::const_data_type, uniform_layout_type,
anonymous_device_type, Kokkos::MemoryTraits<0>>>);
static_assert(std::is_same_v<typename ViewType::uniform_runtime_nomemspace_type,
Kokkos::View<typename data_analysis<DataType>::runtime_data_type, uniform_layout_type,
anonymous_device_type, Kokkos::MemoryTraits<0>>>);
static_assert(std::is_same_v<typename ViewType::uniform_runtime_const_nomemspace_type,
Kokkos::View<typename data_analysis<DataType>::runtime_const_data_type, uniform_layout_type,
anonymous_device_type, Kokkos::MemoryTraits<0>>>);


// ==================================
// mdspan compatibility
// ==================================

// This typedef caused some weird issue with MSVC+NVCC
// static_assert(std::is_same_v<typename ViewType::layout_type, Layout>);
// Not supported yet
// static_assert(std::is_same_v<typename ViewType::extents_type, >);
// static_assert(std::is_same_v<typename ViewType::mapping_type, >);
// static_assert(std::is_same_v<typename ViewType::accessor_type, >);

static_assert(std::is_same_v<typename ViewType::element_type, ValueType>);
// should be remove_const_t<element_type>
static_assert(std::is_same_v<typename ViewType::value_type, ValueType>);
// should be extents_type::index_type
static_assert(std::is_same_v<typename ViewType::index_type, typename Space::memory_space::size_type>);
// this isn't given in View since for example SYCL has "int" as its size_type
// static_assert(std::is_same_v<typename ViewType::size_type, std::make_unsigned_t<typename ViewType::index_type>>);
static_assert(std::is_same_v<typename ViewType::rank_type, size_t>);

// should come from accessor_type
static_assert(std::is_same_v<typename ViewType::data_handle_type, typename ViewType::pointer_type>);
static_assert(std::is_same_v<typename ViewType::reference, typename ViewType::reference_type>);
return true;
};

// Helper function to unpack data type and other args from the View, and pass them on
template<class T, class ... ViewArgs>
struct ViewParams {};

template<class L, class S, class M, class HostMirrorSpace, class ValueType, class ReferenceType, class T, class ... ViewArgs>
constexpr bool test_view_typedefs(ViewParams<T, ViewArgs...>) {
return test_view_typedefs_impl<Kokkos::View<T, ViewArgs...>, Kokkos::ViewTraits<T, ViewArgs...>,
T, L, S, M, HostMirrorSpace, ValueType, ReferenceType>();
}


constexpr bool is_host_exec = std::is_same_v<Kokkos::DefaultExecutionSpace, Kokkos::DefaultHostExecutionSpace>;

#if defined(KOKKOS_ENABLE_CUDA_UVM) || defined(KOKKOS_ENABLE_IMPL_CUDA_UNIFIED_MEMORY) || defined(KOKKOS_ENABLE_IMPL_HIP_UNIFIED_MEMORY)
constexpr bool has_unified = true;
#else
constexpr bool has_unified = false;
#endif

// The test take explicit template arguments for: LayoutType, Space, MemoryTraits, HostMirrorSpace, ValueType, ReferenceType
// The ViewParams is just a type pack for the View template arguments

// Kokkos::View<int>
namespace TestInt {
using layout_type = Kokkos::DefaultExecutionSpace::array_layout;
using space = Kokkos::DefaultExecutionSpace;
using memory_traits = Kokkos::MemoryTraits<0>;
// HostMirrorSpace is a mess so: if the default exec is a host exec, that is it
using host_mirror_space = std::conditional_t<is_host_exec, Kokkos::DefaultExecutionSpace,
// otherwise if unified memory is not on its HostSpace
std::conditional_t<!has_unified, Kokkos::HostSpace,
// otherwise its the following Device type
Kokkos::Device<Kokkos::DefaultHostExecutionSpace, typename Kokkos::DefaultExecutionSpace::memory_space>>>;
static_assert(test_view_typedefs<layout_type, space, memory_traits, host_mirror_space, int, int&>(
ViewParams<int>{}));
}

// Kokkos::View<int, DefaultExecutionSpace>
namespace TestIntDefaultExecutionSpace {
using layout_type = Kokkos::DefaultExecutionSpace::array_layout;
using space = Kokkos::DefaultExecutionSpace;
using memory_traits = Kokkos::MemoryTraits<0>;
// HostMirrorSpace is a mess so: if the default exec is a host exec, it is HostSpace (note difference from View<int> ...)
using host_mirror_space = std::conditional_t<is_host_exec, Kokkos::HostSpace,
// otherwise if unified memory is not on its also HostSpace!
std::conditional_t<!has_unified, Kokkos::HostSpace,
// otherwise its the following memory space ...
Kokkos::DefaultExecutionSpace::memory_space>>;
static_assert(test_view_typedefs<layout_type, space, memory_traits, host_mirror_space, int, int&>(
ViewParams<int, Kokkos::DefaultExecutionSpace>{}));
}

// Kokkos::View<const float**, Kokkos::HostSpace>
namespace TestFloatPPHostSpace {
using layout_type = Kokkos::LayoutRight;
using space = Kokkos::HostSpace;
using memory_traits = Kokkos::MemoryTraits<0>;
using host_mirror_space = Kokkos::HostSpace;
static_assert(test_view_typedefs<layout_type, space, memory_traits, host_mirror_space, const float, const float&>(
ViewParams<const float**, Kokkos::HostSpace>{}));
}

// Kokkos::View<float*[3], Kokkos::LayoutLeft>
namespace TestFloatP3LayoutLeft {
using layout_type = Kokkos::LayoutLeft;
using space = Kokkos::DefaultExecutionSpace;
using memory_traits = Kokkos::MemoryTraits<0>;
// HostMirrorSpace is a mess so: if the default exec is a host exec, that is it
using host_mirror_space = std::conditional_t<is_host_exec, Kokkos::DefaultExecutionSpace,
// otherwise if unified memory is not on its HostSpace
std::conditional_t<!has_unified, Kokkos::HostSpace,
// otherwise its the following Device type
Kokkos::Device<Kokkos::DefaultHostExecutionSpace, typename Kokkos::DefaultExecutionSpace::memory_space>>>;
static_assert(test_view_typedefs<layout_type, space, memory_traits, host_mirror_space, float, float&>(
ViewParams<float*[3], Kokkos::LayoutLeft>{}));
}

// Kokkos::View<float[2][3], Kokkos::Device<Kokkos::DefaultHostExecutionSpace, Kokkos::HostSpace>>
namespace TestFloatPPDeviceDefaultHostExecHostSpace {
using layout_type = Kokkos::LayoutRight;
using space = Kokkos::Device<Kokkos::DefaultHostExecutionSpace, Kokkos::HostSpace>;
using memory_traits = Kokkos::MemoryTraits<0>;
using host_mirror_space = Kokkos::HostSpace;
static_assert(test_view_typedefs<layout_type, space, memory_traits, host_mirror_space, float, float&>(
ViewParams<float[2][3], Kokkos::LayoutRight, Kokkos::Device<Kokkos::DefaultHostExecutionSpace, Kokkos::HostSpace>>{}));
}

// Kokkos::View<int, Kokkos::MemoryTraits<Kokkos::Atomic>>
namespace TestIntAtomic {
using layout_type = Kokkos::DefaultExecutionSpace::array_layout;
using space = Kokkos::DefaultExecutionSpace;
using memory_traits = Kokkos::MemoryTraits<Kokkos::Atomic>;
// HostMirrorSpace is a mess so: if the default exec is a host exec, that is it
using host_mirror_space = std::conditional_t<is_host_exec, Kokkos::DefaultExecutionSpace,
// otherwise if unified memory is not on its HostSpace
std::conditional_t<!has_unified, Kokkos::HostSpace,
// otherwise its the following Device type
Kokkos::Device<Kokkos::DefaultHostExecutionSpace, typename Kokkos::DefaultExecutionSpace::memory_space>>>;
static_assert(test_view_typedefs<layout_type, space, memory_traits, host_mirror_space, int,
Kokkos::Impl::AtomicDataElement<Kokkos::ViewTraits<int, Kokkos::MemoryTraits<Kokkos::Atomic>>>>(
ViewParams<int, Kokkos::MemoryTraits<Kokkos::Atomic>>{}));
}
// clang-format on
} // namespace

0 comments on commit 0721025

Please sign in to comment.