Skip to content

Commit

Permalink
CTAD (deduction guides) for MDRangePolicy (kokkos#5516)
Browse files Browse the repository at this point in the history
* CTAD for MDRangePolicy

* WIP: Moved CTAD tests from TestMDRangePolicyConstructors.hpp to
TestMDRangePolicyCTAD.cpp

* WIP Added [[maybe_unused]] to all static inline variables in
CTAD tests

* Removed TEST_EXECSPACE from the MDRangePolicy CTAD tests
(as that isn't needed for compile time only tests) and
associated cleanup

* Marked
struct ImplicitlyConvertibleToDefaultExecutionSpace::operator Kokkos::DefaultExecutionSpace() const;
as [[maybe_unused]] to make it consistent with the
other policy CTAD tests (in other PRs)

* Added a Workaround for nvc++ (CUDA-11.7-NVHPC) ignoring
[[maybe_unused]] on

ImplicitlyConvertibleToDefaultExecutionSpace::operator
Kokkos::DefaultExecutionSpace() const

by defining it and implicitly calling it in another [[maybe_unused]] static inline
variable.

* Workaround for HIP-ROCm-5.2 "declared but never referenced"

* Added MDRangePolicy CTAD tests for initializer_lists
Fixed a comment
  • Loading branch information
nliber committed Mar 8, 2024
1 parent 6db04b3 commit cfc260a
Show file tree
Hide file tree
Showing 3 changed files with 209 additions and 5 deletions.
75 changes: 70 additions & 5 deletions core/src/KokkosExp_MDRangePolicy.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,9 +155,20 @@ TileSizeProperties get_tile_size_properties(const ExecutionSpace&) {

// multi-dimensional iteration pattern
template <typename... Properties>
struct MDRangePolicy : public Kokkos::Impl::PolicyTraits<Properties...> {
using traits = Kokkos::Impl::PolicyTraits<Properties...>;
using range_policy = RangePolicy<Properties...>;
struct MDRangePolicy;

// Note: If MDRangePolicy has a primary template, implicit CTAD (deduction
// guides) are generated -> MDRangePolicy<> by some compilers, which is
// incorrect. By making it a template specialization instead, no implicit CTAD
// is generated. This works because there has to be at least one property
// specified (which is Rank<...>); otherwise, we'd get the static_assert
// "Kokkos::Error: MD iteration pattern not defined". This template
// specialization uses <P, Properties...> in all places for correctness.
template <typename P, typename... Properties>
struct MDRangePolicy<P, Properties...>
: public Kokkos::Impl::PolicyTraits<P, Properties...> {
using traits = Kokkos::Impl::PolicyTraits<P, Properties...>;
using range_policy = RangePolicy<P, Properties...>;

typename traits::execution_space m_space;

Expand All @@ -166,8 +177,8 @@ struct MDRangePolicy : public Kokkos::Impl::PolicyTraits<Properties...> {
typename traits::schedule_type, typename traits::index_type>;

using execution_policy =
MDRangePolicy<Properties...>; // needed for is_execution_space
// interrogation
MDRangePolicy<P, Properties...>; // needed for is_execution_policy
// interrogation

template <class... OtherProperties>
friend struct MDRangePolicy;
Expand Down Expand Up @@ -377,6 +388,60 @@ struct MDRangePolicy : public Kokkos::Impl::PolicyTraits<Properties...> {
}
};

template <typename LT, size_t N, typename UT>
MDRangePolicy(const LT (&)[N], const UT (&)[N])->MDRangePolicy<Rank<N>>;

template <typename LT, size_t N, typename UT, typename TT, size_t TN>
MDRangePolicy(const LT (&)[N], const UT (&)[N], const TT (&)[TN])
->MDRangePolicy<Rank<N>>;

template <typename LT, size_t N, typename UT>
MDRangePolicy(DefaultExecutionSpace const&, const LT (&)[N], const UT (&)[N])
->MDRangePolicy<Rank<N>>;

template <typename LT, size_t N, typename UT, typename TT, size_t TN>
MDRangePolicy(DefaultExecutionSpace const&, const LT (&)[N], const UT (&)[N],
const TT (&)[TN])
->MDRangePolicy<Rank<N>>;

template <typename ES, typename LT, size_t N, typename UT,
typename = std::enable_if_t<is_execution_space_v<ES>>>
MDRangePolicy(ES const&, const LT (&)[N], const UT (&)[N])
->MDRangePolicy<ES, Rank<N>>;

template <typename ES, typename LT, size_t N, typename UT, typename TT,
size_t TN, typename = std::enable_if_t<is_execution_space_v<ES>>>
MDRangePolicy(ES const&, const LT (&)[N], const UT (&)[N], const TT (&)[TN])
->MDRangePolicy<ES, Rank<N>>;

template <typename T, size_t N>
MDRangePolicy(Array<T, N> const&, Array<T, N> const&)->MDRangePolicy<Rank<N>>;

template <typename T, size_t N, size_t NT>
MDRangePolicy(Array<T, N> const&, Array<T, N> const&, Array<T, NT> const&)
->MDRangePolicy<Rank<N>>;

template <typename T, size_t N>
MDRangePolicy(DefaultExecutionSpace const&, Array<T, N> const&,
Array<T, N> const&)
->MDRangePolicy<Rank<N>>;

template <typename T, size_t N, size_t NT>
MDRangePolicy(DefaultExecutionSpace const&, Array<T, N> const&,
Array<T, N> const&, Array<T, NT> const&)
->MDRangePolicy<Rank<N>>;

template <typename ES, typename T, size_t N,
typename = std::enable_if_t<is_execution_space_v<ES>>>
MDRangePolicy(ES const&, Array<T, N> const&, Array<T, N> const&)
->MDRangePolicy<ES, Rank<N>>;

template <typename ES, typename T, size_t N, size_t NT,
typename = std::enable_if_t<is_execution_space_v<ES>>>
MDRangePolicy(ES const&, Array<T, N> const&, Array<T, N> const&,
Array<T, NT> const&)
->MDRangePolicy<ES, Rank<N>>;

} // namespace Kokkos

#endif // KOKKOS_CORE_EXP_MD_RANGE_POLICY_HPP
1 change: 1 addition & 0 deletions core/unit_test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ SET(COMPILE_ONLY_SOURCES
TestViewRank.cpp
TestViewTypeTraits.cpp
TestTypeList.cpp
TestMDRangePolicyCTAD.cpp
view/TestExtentsDatatypeConversion.cpp
)

Expand Down
138 changes: 138 additions & 0 deletions core/unit_test/TestMDRangePolicyCTAD.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
//@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 {

struct TestMDRangePolicyCTAD {
template <typename... Ts>
static void maybe_unused(Ts&&...) {}

struct SomeExecutionSpace {
using execution_space = SomeExecutionSpace;
using size_type = size_t;
};
static_assert(Kokkos::is_execution_space_v<SomeExecutionSpace>);

struct ImplicitlyConvertibleToDefaultExecutionSpace {
[[maybe_unused]] operator Kokkos::DefaultExecutionSpace() const {
return Kokkos::DefaultExecutionSpace();
}
};
static_assert(!Kokkos::is_execution_space_v<
ImplicitlyConvertibleToDefaultExecutionSpace>);

[[maybe_unused]] static inline Kokkos::DefaultExecutionSpace des;
[[maybe_unused]] static inline ImplicitlyConvertibleToDefaultExecutionSpace
notEs;
[[maybe_unused]] static inline SomeExecutionSpace ses;

[[maybe_unused]] static inline int t[5];
[[maybe_unused]] static inline int64_t tt[5];
[[maybe_unused]] static inline Kokkos::Array<int64_t, 3> a;
[[maybe_unused]] static inline Kokkos::Array<int64_t, 2> aa;

// Workaround for nvc++ (CUDA-11.7-NVHPC) ignoring [[maybe_unused]] on
// ImplicitlyConvertibleToDefaultExecutionSpace::operator
// Kokkos::DefaultExecutionSpace() const
[[maybe_unused]] static inline Kokkos::DefaultExecutionSpace notEsToDes =
notEs;

// Workaround for HIP-ROCm-5.2 "declared but never referenced"
TestMDRangePolicyCTAD() {
maybe_unused(des, notEs, ses, t, tt, a, aa, notEsToDes);
}

// MDRangePolicy with C array parameters

static_assert(
std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<std::size(t)>>,
decltype(Kokkos::MDRangePolicy(t, t))>);
static_assert(
std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<std::size(t)>>,
decltype(Kokkos::MDRangePolicy(t, t, tt))>);
static_assert(
std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<std::size(t)>>,
decltype(Kokkos::MDRangePolicy(des, t, tt))>);
static_assert(
std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<std::size(t)>>,
decltype(Kokkos::MDRangePolicy(notEs, t, t))>);

static_assert(
std::is_same_v<
Kokkos::MDRangePolicy<SomeExecutionSpace, Kokkos::Rank<std::size(t)>>,
decltype(Kokkos::MDRangePolicy(ses, t, t))>);

// MDRangePolicy with Kokkos::initializer_list parameters

static_assert(std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<6>>,
decltype(Kokkos::MDRangePolicy(
{1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6}))>);

[[maybe_unused]] static inline int64_t i64;
static_assert(std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<6>>,
decltype(Kokkos::MDRangePolicy(
{1, 2, 3, 4, 5, 6}, {1, 2, 3, 4, 5, 6},
{i64, i64, i64, i64, i64, i64}))>);

static_assert(std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<6>>,
decltype(Kokkos::MDRangePolicy(
des, {1, 2, 3, 4, 5, 6},
{i64, i64, i64, i64, i64, i64}))>);

static_assert(
std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<6>>,
decltype(Kokkos::MDRangePolicy(notEs, {1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6}))>);

static_assert(
std::is_same_v<Kokkos::MDRangePolicy<SomeExecutionSpace, Kokkos::Rank<6>>,
decltype(Kokkos::MDRangePolicy(ses, {1, 2, 3, 4, 5, 6},
{1, 2, 3, 4, 5, 6}))>);

// MDRangePolicy with Kokkos::Array parameters

static_assert(
std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<std::size(a)>>,
decltype(Kokkos::MDRangePolicy(a, a))>);
static_assert(
std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<std::size(a)>>,
decltype(Kokkos::MDRangePolicy(a, a, aa))>);
static_assert(
std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<std::size(a)>>,
decltype(Kokkos::MDRangePolicy(des, a, a))>);
static_assert(
std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<std::size(a)>>,
decltype(Kokkos::MDRangePolicy(notEs, a, a))>);
static_assert(
std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<std::size(a)>>,
decltype(Kokkos::MDRangePolicy(des, a, a, aa))>);
static_assert(
std::is_same_v<Kokkos::MDRangePolicy<Kokkos::Rank<std::size(a)>>,
decltype(Kokkos::MDRangePolicy(notEs, a, a, aa))>);

static_assert(
std::is_same_v<
Kokkos::MDRangePolicy<SomeExecutionSpace, Kokkos::Rank<std::size(a)>>,
decltype(Kokkos::MDRangePolicy(ses, a, a))>);
static_assert(
std::is_same_v<
Kokkos::MDRangePolicy<SomeExecutionSpace, Kokkos::Rank<std::size(a)>>,
decltype(Kokkos::MDRangePolicy(ses, a, a, aa))>);
};

} // namespace

0 comments on commit cfc260a

Please sign in to comment.