Skip to content

Commit

Permalink
Merge pull request #7074 from crtrott/space-aware-accessor
Browse files Browse the repository at this point in the history
SpaceAwareAccessor
  • Loading branch information
crtrott committed Jun 19, 2024
2 parents 1e14d04 + 7b962ce commit 362c9d7
Show file tree
Hide file tree
Showing 6 changed files with 409 additions and 10 deletions.
16 changes: 11 additions & 5 deletions core/src/Kokkos_View.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ static_assert(false,
#ifdef KOKKOS_ENABLE_IMPL_MDSPAN
#include <View/MDSpan/Kokkos_MDSpan_Extents.hpp>
#include <View/MDSpan/Kokkos_MDSpan_Layout.hpp>
#include <View/MDSpan/Kokkos_MDSpan_Accessor.hpp>
#endif
#include <Kokkos_MinMax.hpp>

Expand Down Expand Up @@ -393,8 +394,11 @@ struct MDSpanViewTraits<Traits,
typename Traits::data_type>::type;
using mdspan_layout_type =
typename Impl::LayoutFromArrayLayout<typename Traits::array_layout>::type;
using mdspan_type =
mdspan<typename Traits::value_type, extents_type, mdspan_layout_type>;
using accessor_type = Impl::SpaceAwareAccessor<
typename Traits::memory_space,
Kokkos::default_accessor<typename Traits::value_type>>;
using mdspan_type = mdspan<typename Traits::value_type, extents_type,
mdspan_layout_type, accessor_type>;
};
} // namespace Impl
#endif // KOKKOS_ENABLE_IMPL_MDSPAN
Expand Down Expand Up @@ -1748,13 +1752,15 @@ class View : public ViewTraits<DataType, Properties...> {
Impl::mapping_from_view_mapping<mdspan_type>(m_map)};
}

template <class OtherAccessorType =
Kokkos::default_accessor<typename traits::value_type>,
template <class OtherAccessorType = Impl::SpaceAwareAccessor<
typename traits::memory_space,
Kokkos::default_accessor<typename traits::value_type>>,
typename = std::enable_if_t<std::is_assignable_v<
typename traits::value_type*&,
typename OtherAccessorType::data_handle_type>>>
KOKKOS_INLINE_FUNCTION constexpr auto to_mdspan(
const OtherAccessorType& other_accessor = OtherAccessorType()) {
const OtherAccessorType& other_accessor =
typename Impl::MDSpanViewTraits<traits>::accessor_type()) {
using mdspan_type = typename Impl::MDSpanViewTraits<traits>::mdspan_type;
using ret_mdspan_type =
mdspan<typename mdspan_type::element_type,
Expand Down
161 changes: 161 additions & 0 deletions core/src/View/MDSpan/Kokkos_MDSpan_Accessor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
//@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

#ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
static_assert(false,
"Including non-public Kokkos header files is not allowed.");
#endif

#ifndef KOKKOS_MDSPAN_ACCESSOR_HPP
#define KOKKOS_MDSPAN_ACCESSOR_HPP

#include <Kokkos_Macros.hpp>
#include <Kokkos_Concepts.hpp>
#include <Kokkos_Core_fwd.hpp>

namespace Kokkos {

// For now use the accessors in Impl namespace, as an
// implementation detail for rebasing View on mdspan
namespace Impl {

template <class MemorySpace, class NestedAccessor>
struct SpaceAwareAccessor {
using element_type = typename NestedAccessor::element_type;
using reference = typename NestedAccessor::reference;
using data_handle_type = typename NestedAccessor::data_handle_type;

using offset_policy =
SpaceAwareAccessor<MemorySpace, typename NestedAccessor::offset_policy>;

using memory_space = MemorySpace;

static_assert(is_memory_space_v<memory_space>);

KOKKOS_DEFAULTED_FUNCTION
constexpr SpaceAwareAccessor() = default;

template <class OtherNestedAccessorType,
std::enable_if_t<std::is_constructible_v<NestedAccessor,
OtherNestedAccessorType>,
int> = 0>
KOKKOS_FUNCTION constexpr SpaceAwareAccessor(
const SpaceAwareAccessor<MemorySpace, OtherNestedAccessorType>&
other) noexcept
: nested_acc(other.nested_acc) {}

template <class OtherNestedAccessorType,
std::enable_if_t<std::is_constructible_v<NestedAccessor,
OtherNestedAccessorType>,
int> = 0>
KOKKOS_FUNCTION constexpr SpaceAwareAccessor(
const SpaceAwareAccessor<AnonymousSpace, OtherNestedAccessorType>&
other) noexcept
: nested_acc(other.nested_acc) {}

KOKKOS_FUNCTION
SpaceAwareAccessor(const NestedAccessor& acc) : nested_acc(acc) {}

KOKKOS_FUNCTION
explicit operator NestedAccessor() const { return nested_acc; }

KOKKOS_FUNCTION
constexpr reference access(data_handle_type p, size_t i) const noexcept {
Kokkos::Impl::runtime_check_memory_access_violation<memory_space>(
"Kokkos::SpaceAwareAccessor ERROR: attempt to access inaccessible "
"memory space");
return nested_acc.access(p, i);
}

KOKKOS_FUNCTION
constexpr data_handle_type offset(data_handle_type p, size_t i) const
noexcept {
return nested_acc.offset(p, i);
}

private:
// We either compile with our custom mdspan impl
// in which case we discover inside it whether no_unique_address
// works, or we use C++23 in which case it better be available
#ifdef _MDSPAN_NO_UNIQUE_ADDRESS
_MDSPAN_NO_UNIQUE_ADDRESS
#else
[[no_unique_address]]
#endif
NestedAccessor nested_acc;
template <class, class>
friend struct SpaceAwareAccessor;
};

template <class NestedAccessor>
struct SpaceAwareAccessor<AnonymousSpace, NestedAccessor> {
using element_type = typename NestedAccessor::element_type;
using reference = typename NestedAccessor::reference;
using data_handle_type = typename NestedAccessor::data_handle_type;

using offset_policy =
SpaceAwareAccessor<AnonymousSpace,
typename NestedAccessor::offset_policy>;

using memory_space = AnonymousSpace;

KOKKOS_DEFAULTED_FUNCTION
constexpr SpaceAwareAccessor() = default;

template <class OtherMemorySpace, class OtherNestedAccessorType,
std::enable_if_t<std::is_constructible_v<NestedAccessor,
OtherNestedAccessorType>,
int> = 0>
KOKKOS_FUNCTION constexpr SpaceAwareAccessor(
const SpaceAwareAccessor<OtherMemorySpace, OtherNestedAccessorType>&
other) noexcept
: nested_acc(other.nested_acc) {}

KOKKOS_FUNCTION
SpaceAwareAccessor(const NestedAccessor& acc) : nested_acc(acc) {}

KOKKOS_FUNCTION
explicit operator NestedAccessor() const { return nested_acc; }

KOKKOS_FUNCTION
constexpr reference access(data_handle_type p, size_t i) const noexcept {
return nested_acc.access(p, i);
}

KOKKOS_FUNCTION
constexpr data_handle_type offset(data_handle_type p, size_t i) const
noexcept {
return nested_acc.offset(p, i);
}

private:
// We either compile with our custom mdspan impl
// in which case we discover inside it whether no_unique_address
// works, or we use C++23 in which case it better be available
#ifdef _MDSPAN_NO_UNIQUE_ADDRESS
_MDSPAN_NO_UNIQUE_ADDRESS
#else
[[no_unique_address]]
#endif
NestedAccessor nested_acc;
template <class, class>
friend struct SpaceAwareAccessor;
};

} // namespace Impl
} // namespace Kokkos

#endif
8 changes: 7 additions & 1 deletion core/unit_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,16 @@ foreach(Tag Threads;Serial;OpenMP;Cuda;HPX;OpenMPTarget;OpenACC;HIP;SYCL)
Reductions
Reductions_DeviceView
SharedAlloc
SpaceAwareAccessorAccessViolation
SpaceAwareAccessor
Swap
)
IF (NOT Kokkos_ENABLE_IMPL_MDSPAN)
LIST(REMOVE_ITEM ${Tag}_TESTNAMES1B MDSpanConversion)
LIST(REMOVE_ITEM ${Tag}_TESTNAMES1B
MDSpanConversion
SpaceAwareAccessorAccessViolation
SpaceAwareAccessor
)
ENDIF()
foreach(Name IN LISTS ${Tag}_TESTNAMES1B)
set(file ${dir}/Test${Tag}_${Name}.cpp)
Expand Down
10 changes: 6 additions & 4 deletions core/unit_test/TestMDSpanConversion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,13 +120,15 @@ struct TestViewMDSpanConversion {
}
// test conversion operator to different mdspan type
{
using element_type = const typename natural_mdspan_type::element_type;
using mdspan_type = Kokkos::mdspan<
using element_type = const typename natural_mdspan_type::element_type;
using const_acc_type = Kokkos::Impl::SpaceAwareAccessor<
typename ViewType::memory_space,
Kokkos::default_accessor<element_type>>;
using mdspan_type = Kokkos::mdspan<
element_type,
Kokkos::dextents<typename natural_mdspan_type::index_type,
natural_mdspan_type::rank()>,
typename natural_mdspan_type::layout_type,
Kokkos::default_accessor<element_type>>;
typename natural_mdspan_type::layout_type, const_acc_type>;
mdspan_type cvt = v;
ASSERT_EQ(cvt.data_handle(), v.data());
ASSERT_EQ(cvt.mapping(), ref_layout_mapping);
Expand Down
98 changes: 98 additions & 0 deletions core/unit_test/TestSpaceAwareAccessor.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
//@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>
#include <type_traits>

#include <gtest/gtest.h>

template <class T, class ExecutionSpace>
void test_space_aware_accessor() {
using memory_space_t = typename ExecutionSpace::memory_space;
using value_type = std::remove_const_t<T>;
Kokkos::View<value_type*, ExecutionSpace> v("V", 100);

Kokkos::parallel_for(
Kokkos::RangePolicy<ExecutionSpace>(0, v.extent(0)),
KOKKOS_LAMBDA(int i) { v(i) = i; });

int errors;
using acc_t = Kokkos::Impl::SpaceAwareAccessor<memory_space_t,
Kokkos::default_accessor<T>>;
acc_t acc{};
typename acc_t::data_handle_type ptr = v.data();

Kokkos::parallel_reduce(
Kokkos::RangePolicy<ExecutionSpace>(0, v.extent(0)),
KOKKOS_LAMBDA(int i, int& error) {
if (acc.access(ptr, i) != ptr[i]) error++;
static_assert(std::is_same_v<typename acc_t::element_type, T>);
static_assert(std::is_same_v<typename acc_t::reference, T&>);
static_assert(std::is_same_v<typename acc_t::data_handle_type, T*>);
static_assert(std::is_same_v<typename acc_t::offset_policy, acc_t>);
static_assert(
std::is_same_v<typename acc_t::memory_space, memory_space_t>);
#if defined(KOKKOS_ENABLE_CXX20) || defined(KOKKOS_ENABLE_CXX23) || \
defined(KOKKOS_ENABLE_CXX26)
static_assert(std::is_empty_v<acc_t>);
#endif
},
errors);
ASSERT_EQ(errors, 0);
}

void test_space_aware_accessor_conversion() {
using ExecutionSpace = TEST_EXECSPACE;
using memory_space_t = typename ExecutionSpace::memory_space;
using T = float;
using acc_t = Kokkos::Impl::SpaceAwareAccessor<memory_space_t,
Kokkos::default_accessor<T>>;
using const_acc_t =
Kokkos::Impl::SpaceAwareAccessor<memory_space_t,
Kokkos::default_accessor<const T>>;
using int_acc_t =
Kokkos::Impl::SpaceAwareAccessor<memory_space_t,
Kokkos::default_accessor<int>>;
using host_acc_t =
Kokkos::Impl::SpaceAwareAccessor<Kokkos::HostSpace,
Kokkos::default_accessor<T>>;
using anon_acc_t =
Kokkos::Impl::SpaceAwareAccessor<Kokkos::AnonymousSpace,
Kokkos::default_accessor<T>>;

Kokkos::parallel_for(
Kokkos::RangePolicy<ExecutionSpace>(0, 1), KOKKOS_LAMBDA(int) {
static_assert(std::is_constructible_v<const_acc_t, acc_t>);
static_assert(std::is_convertible_v<acc_t, const_acc_t>);
static_assert(!std::is_constructible_v<acc_t, const_acc_t>);
static_assert(!std::is_constructible_v<acc_t, int_acc_t>);
static_assert(std::is_constructible_v<acc_t, host_acc_t> ==
std::is_same_v<memory_space_t, Kokkos::HostSpace>);
static_assert(std::is_constructible_v<anon_acc_t, acc_t>);
static_assert(std::is_constructible_v<acc_t, anon_acc_t>);
static_assert(std::is_convertible_v<anon_acc_t, acc_t>);
static_assert(std::is_convertible_v<acc_t, anon_acc_t>);
});
}

TEST(TEST_CATEGORY, space_aware_accessor) {
using ExecutionSpace = TEST_EXECSPACE;
test_space_aware_accessor<int, ExecutionSpace>();
test_space_aware_accessor<double, ExecutionSpace>();
test_space_aware_accessor<const int, ExecutionSpace>();
test_space_aware_accessor<const double, ExecutionSpace>();
test_space_aware_accessor_conversion();
}
Loading

0 comments on commit 362c9d7

Please sign in to comment.