//@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 #include static_assert(false, "Including non-public Kokkos header files is not allowed."); #endif #ifndef KOKKOS_CORE_CONCEPTS_HPP #define KOKKOS_CORE_CONCEPTS_HPP #include // Needed for 'is_space::host_mirror_space #include #include //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- namespace Kokkos { // Schedules for Execution Policies struct Static {}; struct Dynamic {}; // Schedule Wrapper Type template struct Schedule { static_assert(std::is_same::value || std::is_same::value, "Kokkos: Invalid Schedule<> type."); using schedule_type = Schedule; using type = T; }; // Specify Iteration Index Type template struct IndexType { static_assert(std::is_integral::value, "Kokkos: Invalid IndexType<>."); using index_type = IndexType; using type = T; }; namespace Experimental { struct WorkItemProperty { template struct ImplWorkItemProperty { static const unsigned value = Property; using work_item_property = ImplWorkItemProperty; }; constexpr static const ImplWorkItemProperty<0> None = ImplWorkItemProperty<0>(); constexpr static const ImplWorkItemProperty<1> HintLightWeight = ImplWorkItemProperty<1>(); constexpr static const ImplWorkItemProperty<2> HintHeavyWeight = ImplWorkItemProperty<2>(); constexpr static const ImplWorkItemProperty<4> HintRegular = ImplWorkItemProperty<4>(); constexpr static const ImplWorkItemProperty<8> HintIrregular = ImplWorkItemProperty<8>(); constexpr static const ImplWorkItemProperty<16> ImplForceGlobalLaunch = ImplWorkItemProperty<16>(); using None_t = ImplWorkItemProperty<0>; using HintLightWeight_t = ImplWorkItemProperty<1>; using HintHeavyWeight_t = ImplWorkItemProperty<2>; using HintRegular_t = ImplWorkItemProperty<4>; using HintIrregular_t = ImplWorkItemProperty<8>; using ImplForceGlobalLaunch_t = ImplWorkItemProperty<16>; }; template inline constexpr WorkItemProperty::ImplWorkItemProperty operator|( WorkItemProperty::ImplWorkItemProperty, WorkItemProperty::ImplWorkItemProperty) { return WorkItemProperty::ImplWorkItemProperty(); } template inline constexpr WorkItemProperty::ImplWorkItemProperty operator&( WorkItemProperty::ImplWorkItemProperty, WorkItemProperty::ImplWorkItemProperty) { return WorkItemProperty::ImplWorkItemProperty(); } template inline constexpr bool operator==(WorkItemProperty::ImplWorkItemProperty, WorkItemProperty::ImplWorkItemProperty) { return pv1 == pv2; } } // namespace Experimental /**\brief Specify Launch Bounds for CUDA execution. * * If no launch bounds specified then do not set launch bounds. */ template struct LaunchBounds { using launch_bounds = LaunchBounds; using type = LaunchBounds; static constexpr unsigned int maxTperB{maxT}; static constexpr unsigned int minBperSM{minB}; }; } // namespace Kokkos //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- namespace Kokkos { #define KOKKOS_IMPL_IS_CONCEPT(CONCEPT) \ template \ struct is_##CONCEPT { \ private: \ template \ using have_t = typename U::CONCEPT; \ template \ using have_type_t = typename U::CONCEPT##_type; \ \ public: \ static constexpr bool value = \ std::is_base_of, T>::value || \ std::is_base_of, T>::value; \ constexpr operator bool() const noexcept { return value; } \ }; \ template \ inline constexpr bool is_##CONCEPT##_v = is_##CONCEPT::value; // Public concept: KOKKOS_IMPL_IS_CONCEPT(memory_space) KOKKOS_IMPL_IS_CONCEPT(memory_traits) KOKKOS_IMPL_IS_CONCEPT(execution_space) KOKKOS_IMPL_IS_CONCEPT(execution_policy) KOKKOS_IMPL_IS_CONCEPT(array_layout) KOKKOS_IMPL_IS_CONCEPT(reducer) KOKKOS_IMPL_IS_CONCEPT(team_handle) namespace Experimental { KOKKOS_IMPL_IS_CONCEPT(work_item_property) KOKKOS_IMPL_IS_CONCEPT(hooks_policy) } // namespace Experimental namespace Impl { // Implementation concept: KOKKOS_IMPL_IS_CONCEPT(thread_team_member) KOKKOS_IMPL_IS_CONCEPT(host_thread_team_member) KOKKOS_IMPL_IS_CONCEPT(graph_kernel) } // namespace Impl #undef KOKKOS_IMPL_IS_CONCEPT } // namespace Kokkos namespace Kokkos { namespace Impl { template class has_member_team_shmem_size { template static int32_t test_for_member(decltype(&T::team_shmem_size)) { return int32_t(0); } template static int64_t test_for_member(...) { return int64_t(0); } public: constexpr static bool value = sizeof(test_for_member(nullptr)) == sizeof(int32_t); }; template class has_member_shmem_size { template static int32_t test_for_member(decltype(&T::shmem_size_me)) { return int32_t(0); } template static int64_t test_for_member(...) { return int64_t(0); } public: constexpr static bool value = sizeof(test_for_member(0)) == sizeof(int32_t); }; } // namespace Impl } // namespace Kokkos //---------------------------------------------------------------------------- namespace Kokkos { template struct Device { static_assert(Kokkos::is_execution_space::value, "Execution space is not valid"); static_assert(Kokkos::is_memory_space::value, "Memory space is not valid"); using execution_space = ExecutionSpace; using memory_space = MemorySpace; using device_type = Device; }; namespace Impl { template struct is_device_helper : std::false_type {}; template struct is_device_helper> : std::true_type { }; } // namespace Impl template using is_device = typename Impl::is_device_helper>::type; template inline constexpr bool is_device_v = is_device::value; //---------------------------------------------------------------------------- template struct is_space { private: template struct exe : std::false_type { using space = void; }; template struct mem : std::false_type { using space = void; }; template struct dev : std::false_type { using space = void; }; template struct exe> : std::is_same::type { using space = typename U::execution_space; }; template struct mem> : std::is_same::type { using space = typename U::memory_space; }; template struct dev> : std::is_same::type { using space = typename U::device_type; }; using is_exe = typename is_space::template exe>; using is_mem = typename is_space::template mem>; using is_dev = typename is_space::template dev>; public: static constexpr bool value = is_exe::value || is_mem::value || is_dev::value; constexpr operator bool() const noexcept { return value; } using execution_space = typename is_exe::space; using memory_space = typename is_mem::space; // For backward compatibility, deprecated in favor of // Kokkos::Impl::HostMirror::host_mirror_space private: // The actual definitions for host_memory_space and host_execution_spaces are // in do_not_use_host_memory_space and do_not_use_host_execution_space to be // able to use them within this class without deprecation warnings. using do_not_use_host_memory_space = std::conditional_t< std::is_same::value #if defined(KOKKOS_ENABLE_CUDA) || std::is_same::value || std::is_same::value #elif defined(KOKKOS_ENABLE_HIP) || std::is_same::value || std::is_same::value #elif defined(KOKKOS_ENABLE_SYCL) || std::is_same::value || std::is_same::value #endif , memory_space, Kokkos::HostSpace>; using do_not_use_host_execution_space = std::conditional_t< #if defined(KOKKOS_ENABLE_CUDA) std::is_same::value || #elif defined(KOKKOS_ENABLE_HIP) std::is_same::value || #elif defined(KOKKOS_ENABLE_SYCL) std::is_same::value || #elif defined(KOKKOS_ENABLE_OPENMPTARGET) std::is_same::value || #endif false, Kokkos::DefaultHostExecutionSpace, execution_space>; }; } // namespace Kokkos //---------------------------------------------------------------------------- namespace Kokkos { namespace Impl { /**\brief Access relationship between DstMemorySpace and SrcMemorySpace * * The default case can assume accessibility for the same space. * Specializations must be defined for different memory spaces. */ template struct MemorySpaceAccess { static_assert(Kokkos::is_memory_space::value && Kokkos::is_memory_space::value, "template arguments must be memory spaces"); /**\brief Can a View (or pointer) to memory in SrcMemorySpace * be assigned to a View (or pointer) to memory marked DstMemorySpace. * * 1. DstMemorySpace::execution_space == SrcMemorySpace::execution_space * 2. All execution spaces that can access DstMemorySpace can also access * SrcMemorySpace. */ enum { assignable = std::is_same::value }; /**\brief For all DstExecSpace::memory_space == DstMemorySpace * DstExecSpace can access SrcMemorySpace. */ enum { accessible = assignable }; /**\brief Does a DeepCopy capability exist * to DstMemorySpace from SrcMemorySpace */ enum { deepcopy = assignable }; }; } // namespace Impl } // namespace Kokkos namespace Kokkos { /**\brief Can AccessSpace access MemorySpace ? * * Requires: * Kokkos::is_space< AccessSpace >::value * Kokkos::is_memory_space< MemorySpace >::value * * Can AccessSpace::execution_space access MemorySpace ? * enum : bool { accessible }; * * Is View assignable from View ? * enum : bool { assignable }; * * If ! accessible then through which intercessory memory space * should a be used to deep copy memory for * AccessSpace::execution_space * to get access. * When AccessSpace::memory_space == Kokkos::HostSpace * then space is the View host mirror space. */ template struct SpaceAccessibility { private: static_assert(Kokkos::is_space::value, "template argument #1 must be a Kokkos space"); static_assert(Kokkos::is_memory_space::value, "template argument #2 must be a Kokkos memory space"); // The input AccessSpace may be a Device // verify that it is a valid combination of spaces. static_assert(Kokkos::Impl::MemorySpaceAccess< typename AccessSpace::execution_space::memory_space, typename AccessSpace::memory_space>::accessible, "template argument #1 is an invalid space"); using exe_access = Kokkos::Impl::MemorySpaceAccess< typename AccessSpace::execution_space::memory_space, MemorySpace>; using mem_access = Kokkos::Impl::MemorySpaceAccess; public: /**\brief Can AccessSpace::execution_space access MemorySpace ? * * Default based upon memory space accessibility. * Specialization required for other relationships. */ enum { accessible = exe_access::accessible }; /**\brief Can assign to AccessSpace from MemorySpace ? * * Default based upon memory space accessibility. * Specialization required for other relationships. */ enum { assignable = is_memory_space::value && mem_access::assignable }; /**\brief Can deep copy to AccessSpace::memory_Space from MemorySpace ? */ enum { deepcopy = mem_access::deepcopy }; // What intercessory space for AccessSpace::execution_space // to be able to access MemorySpace? // If same memory space or not accessible use the AccessSpace // else construct a device with execution space and memory space. using space = std::conditional_t< std::is_same::value || !exe_access::accessible, AccessSpace, Kokkos::Device>; }; } // namespace Kokkos //---------------------------------------------------------------------------- #endif // KOKKOS_CORE_CONCEPTS_HPP