Kokkos Core Kernels Package  Version of the Day
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
Kokkos_Concepts.hpp
1 //@HEADER
2 // ************************************************************************
3 //
4 // Kokkos v. 4.0
5 // Copyright (2022) National Technology & Engineering
6 // Solutions of Sandia, LLC (NTESS).
7 //
8 // Under the terms of Contract DE-NA0003525 with NTESS,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Part of Kokkos, under the Apache License v2.0 with LLVM Exceptions.
12 // See https://kokkos.org/LICENSE for license information.
13 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
14 //
15 //@HEADER
16 
17 #ifndef KOKKOS_IMPL_PUBLIC_INCLUDE
18 #include <Kokkos_Macros.hpp>
19 static_assert(false,
20  "Including non-public Kokkos header files is not allowed.");
21 #endif
22 #ifndef KOKKOS_CORE_CONCEPTS_HPP
23 #define KOKKOS_CORE_CONCEPTS_HPP
24 
25 #include <type_traits>
26 
27 // Needed for 'is_space<S>::host_mirror_space
28 #include <Kokkos_Core_fwd.hpp>
29 
30 #include <Kokkos_DetectionIdiom.hpp>
31 
32 //----------------------------------------------------------------------------
33 //----------------------------------------------------------------------------
34 
35 namespace Kokkos {
36 
37 // Schedules for Execution Policies
38 struct Static {};
39 struct Dynamic {};
40 
41 // Schedule Wrapper Type
42 template <class T>
43 struct Schedule {
44  static_assert(std::is_same_v<T, Static> || std::is_same_v<T, Dynamic>,
45  "Kokkos: Invalid Schedule<> type.");
46  using schedule_type = Schedule;
47  using type = T;
48 };
49 
50 // Specify Iteration Index Type
51 template <typename T>
52 struct IndexType {
53  static_assert(std::is_integral_v<T>, "Kokkos: Invalid IndexType<>.");
54  using index_type = IndexType;
55  using type = T;
56 };
57 
58 namespace Experimental {
59 struct WorkItemProperty {
60  template <unsigned long Property>
61  struct ImplWorkItemProperty {
62  static const unsigned value = Property;
63  using work_item_property = ImplWorkItemProperty<Property>;
64  };
65 
66  constexpr static const ImplWorkItemProperty<0> None =
67  ImplWorkItemProperty<0>();
68  constexpr static const ImplWorkItemProperty<1> HintLightWeight =
69  ImplWorkItemProperty<1>();
70  constexpr static const ImplWorkItemProperty<2> HintHeavyWeight =
71  ImplWorkItemProperty<2>();
72  constexpr static const ImplWorkItemProperty<4> HintRegular =
73  ImplWorkItemProperty<4>();
74  constexpr static const ImplWorkItemProperty<8> HintIrregular =
75  ImplWorkItemProperty<8>();
76  constexpr static const ImplWorkItemProperty<16> ImplForceGlobalLaunch =
77  ImplWorkItemProperty<16>();
78  using None_t = ImplWorkItemProperty<0>;
79  using HintLightWeight_t = ImplWorkItemProperty<1>;
80  using HintHeavyWeight_t = ImplWorkItemProperty<2>;
81  using HintRegular_t = ImplWorkItemProperty<4>;
82  using HintIrregular_t = ImplWorkItemProperty<8>;
83  using ImplForceGlobalLaunch_t = ImplWorkItemProperty<16>;
84 };
85 
86 template <unsigned long pv1, unsigned long pv2>
87 inline constexpr WorkItemProperty::ImplWorkItemProperty<pv1 | pv2> operator|(
88  WorkItemProperty::ImplWorkItemProperty<pv1>,
89  WorkItemProperty::ImplWorkItemProperty<pv2>) {
90  return WorkItemProperty::ImplWorkItemProperty<pv1 | pv2>();
91 }
92 
93 template <unsigned long pv1, unsigned long pv2>
94 inline constexpr WorkItemProperty::ImplWorkItemProperty<pv1 & pv2> operator&(
95  WorkItemProperty::ImplWorkItemProperty<pv1>,
96  WorkItemProperty::ImplWorkItemProperty<pv2>) {
97  return WorkItemProperty::ImplWorkItemProperty<pv1 & pv2>();
98 }
99 
100 template <unsigned long pv1, unsigned long pv2>
101 inline constexpr bool operator==(WorkItemProperty::ImplWorkItemProperty<pv1>,
102  WorkItemProperty::ImplWorkItemProperty<pv2>) {
103  return pv1 == pv2;
104 }
105 
106 } // namespace Experimental
107 
112 template <unsigned int maxT = 0 /* Max threads per block */
113  ,
114  unsigned int minB = 0 /* Min blocks per SM */
115  >
116 struct LaunchBounds {
117  using launch_bounds = LaunchBounds;
119  static constexpr unsigned int maxTperB{maxT};
120  static constexpr unsigned int minBperSM{minB};
121 };
122 
123 } // namespace Kokkos
124 
125 //----------------------------------------------------------------------------
126 //----------------------------------------------------------------------------
127 
128 namespace Kokkos {
129 
130 #define KOKKOS_IMPL_IS_CONCEPT(CONCEPT) \
131  template <typename T> \
132  struct is_##CONCEPT { \
133  private: \
134  template <typename U> \
135  using have_t = typename U::CONCEPT; \
136  template <typename U> \
137  using have_type_t = typename U::CONCEPT##_type; \
138  \
139  public: \
140  static constexpr bool value = \
141  std::is_base_of_v<detected_t<have_t, T>, T> || \
142  std::is_base_of_v<detected_t<have_type_t, T>, T>; \
143  constexpr operator bool() const noexcept { return value; } \
144  }; \
145  template <typename T> \
146  inline constexpr bool is_##CONCEPT##_v = is_##CONCEPT<T>::value;
147 
148 // Public concept:
149 
150 KOKKOS_IMPL_IS_CONCEPT(memory_space)
151 KOKKOS_IMPL_IS_CONCEPT(memory_traits)
152 KOKKOS_IMPL_IS_CONCEPT(execution_space)
153 KOKKOS_IMPL_IS_CONCEPT(execution_policy)
154 KOKKOS_IMPL_IS_CONCEPT(array_layout)
155 KOKKOS_IMPL_IS_CONCEPT(reducer)
156 KOKKOS_IMPL_IS_CONCEPT(team_handle)
157 namespace Experimental {
158 KOKKOS_IMPL_IS_CONCEPT(work_item_property)
159 KOKKOS_IMPL_IS_CONCEPT(hooks_policy)
160 } // namespace Experimental
161 
162 namespace Impl {
163 
164 // Implementation concept:
165 
166 KOKKOS_IMPL_IS_CONCEPT(thread_team_member)
167 KOKKOS_IMPL_IS_CONCEPT(host_thread_team_member)
168 KOKKOS_IMPL_IS_CONCEPT(graph_kernel)
169 
170 } // namespace Impl
171 
172 #undef KOKKOS_IMPL_IS_CONCEPT
173 
174 } // namespace Kokkos
175 
176 namespace Kokkos {
177 namespace Impl {
178 
179 template <class Object>
180 class has_member_team_shmem_size {
181  template <typename T>
182  static int32_t test_for_member(decltype(&T::team_shmem_size)) {
183  return int32_t(0);
184  }
185  template <typename T>
186  static int64_t test_for_member(...) {
187  return int64_t(0);
188  }
189 
190  public:
191  constexpr static bool value =
192  sizeof(test_for_member<Object>(nullptr)) == sizeof(int32_t);
193 };
194 
195 template <class Object>
196 class has_member_shmem_size {
197  template <typename T>
198  static int32_t test_for_member(decltype(&T::shmem_size_me)) {
199  return int32_t(0);
200  }
201  template <typename T>
202  static int64_t test_for_member(...) {
203  return int64_t(0);
204  }
205 
206  public:
207  constexpr static bool value =
208  sizeof(test_for_member<Object>(0)) == sizeof(int32_t);
209 };
210 
211 } // namespace Impl
212 } // namespace Kokkos
213 //----------------------------------------------------------------------------
214 
215 namespace Kokkos {
216 
217 template <class ExecutionSpace, class MemorySpace>
218 struct Device {
219  static_assert(Kokkos::is_execution_space<ExecutionSpace>::value,
220  "Execution space is not valid");
221  static_assert(Kokkos::is_memory_space<MemorySpace>::value,
222  "Memory space is not valid");
223  using execution_space = ExecutionSpace;
224  using memory_space = MemorySpace;
225  using device_type = Device<execution_space, memory_space>;
226 };
227 
228 namespace Impl {
229 
230 template <typename T>
231 struct is_device_helper : std::false_type {};
232 
233 template <typename ExecutionSpace, typename MemorySpace>
234 struct is_device_helper<Device<ExecutionSpace, MemorySpace>> : std::true_type {
235 };
236 
237 } // namespace Impl
238 
239 template <typename T>
240 using is_device = typename Impl::is_device_helper<std::remove_cv_t<T>>::type;
241 
242 template <typename T>
243 inline constexpr bool is_device_v = is_device<T>::value;
244 
245 //----------------------------------------------------------------------------
246 
247 template <typename T>
248 struct is_space {
249  private:
250  template <typename, typename = void>
251  struct exe : std::false_type {
252  using space = void;
253  };
254 
255  template <typename, typename = void>
256  struct mem : std::false_type {
257  using space = void;
258  };
259 
260  template <typename, typename = void>
261  struct dev : std::false_type {
262  using space = void;
263  };
264 
265  template <typename U>
266  struct exe<U, std::conditional_t<true, void, typename U::execution_space>>
267  : std::is_same<U, typename U::execution_space>::type {
268  using space = typename U::execution_space;
269  };
270 
271  template <typename U>
272  struct mem<U, std::conditional_t<true, void, typename U::memory_space>>
273  : std::is_same<U, typename U::memory_space>::type {
274  using space = typename U::memory_space;
275  };
276 
277  template <typename U>
278  struct dev<U, std::conditional_t<true, void, typename U::device_type>>
279  : std::is_same<U, typename U::device_type>::type {
280  using space = typename U::device_type;
281  };
282 
283  using is_exe = typename is_space<T>::template exe<std::remove_cv_t<T>>;
284  using is_mem = typename is_space<T>::template mem<std::remove_cv_t<T>>;
285  using is_dev = typename is_space<T>::template dev<std::remove_cv_t<T>>;
286 
287  public:
288  static constexpr bool value = is_exe::value || is_mem::value || is_dev::value;
289 
290  constexpr operator bool() const noexcept { return value; }
291 
292  using execution_space = typename is_exe::space;
293  using memory_space = typename is_mem::space;
294 };
295 
296 } // namespace Kokkos
297 
298 //----------------------------------------------------------------------------
299 
300 namespace Kokkos {
301 namespace Impl {
302 
308 template <typename DstMemorySpace, typename SrcMemorySpace>
310  static_assert(Kokkos::is_memory_space<DstMemorySpace>::value &&
311  Kokkos::is_memory_space<SrcMemorySpace>::value,
312  "template arguments must be memory spaces");
313 
321  enum { assignable = std::is_same_v<DstMemorySpace, SrcMemorySpace> };
322 
326  enum { accessible = assignable };
327 
331  enum { deepcopy = assignable };
332 };
333 
334 } // namespace Impl
335 } // namespace Kokkos
336 
337 namespace Kokkos {
338 
358 template <typename AccessSpace, typename MemorySpace>
360  private:
361  static_assert(Kokkos::is_space<AccessSpace>::value,
362  "template argument #1 must be a Kokkos space");
363 
364  static_assert(Kokkos::is_memory_space<MemorySpace>::value,
365  "template argument #2 must be a Kokkos memory space");
366 
367  // The input AccessSpace may be a Device<ExecSpace,MemSpace>
368  // verify that it is a valid combination of spaces.
369  static_assert(Kokkos::Impl::MemorySpaceAccess<
370  typename AccessSpace::execution_space::memory_space,
371  typename AccessSpace::memory_space>::accessible,
372  "template argument #1 is an invalid space");
373 
375  typename AccessSpace::execution_space::memory_space, MemorySpace>;
376 
377  using mem_access =
378  Kokkos::Impl::MemorySpaceAccess<typename AccessSpace::memory_space,
379  MemorySpace>;
380 
381  public:
387  enum { accessible = exe_access::accessible };
388 
394  enum {
395  assignable = is_memory_space<AccessSpace>::value && mem_access::assignable
396  };
397 
399  enum { deepcopy = mem_access::deepcopy };
400 
401  // What intercessory space for AccessSpace::execution_space
402  // to be able to access MemorySpace?
403  // If same memory space or not accessible use the AccessSpace
404  // else construct a device with execution space and memory space.
405  using space = std::conditional_t<
406  std::is_same_v<typename AccessSpace::memory_space, MemorySpace> ||
407  !exe_access::accessible,
408  AccessSpace,
409  Kokkos::Device<typename AccessSpace::execution_space, MemorySpace>>;
410 };
411 
412 } // namespace Kokkos
413 
414 //----------------------------------------------------------------------------
415 
416 #endif // KOKKOS_CORE_CONCEPTS_HPP
Can AccessSpace access MemorySpace ?
Specify Launch Bounds for CUDA execution.
Access relationship between DstMemorySpace and SrcMemorySpace.