Kokkos Core Kernels Package Version of the Day
Loading...
Searching...
No Matches
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>
19static_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
35namespace Kokkos {
36
37// Schedules for Execution Policies
38struct Static {};
39struct Dynamic {};
40
41// Schedule Wrapper Type
42template <class T>
43struct Schedule {
44 static_assert(std::is_same<T, Static>::value ||
45 std::is_same<T, Dynamic>::value,
46 "Kokkos: Invalid Schedule<> type.");
47 using schedule_type = Schedule;
48 using type = T;
49};
50
51// Specify Iteration Index Type
52template <typename T>
53struct IndexType {
54 static_assert(std::is_integral<T>::value, "Kokkos: Invalid IndexType<>.");
55 using index_type = IndexType;
56 using type = T;
57};
58
59namespace Experimental {
60struct WorkItemProperty {
61 template <unsigned long Property>
62 struct ImplWorkItemProperty {
63 static const unsigned value = Property;
64 using work_item_property = ImplWorkItemProperty<Property>;
65 };
66
67 constexpr static const ImplWorkItemProperty<0> None =
68 ImplWorkItemProperty<0>();
69 constexpr static const ImplWorkItemProperty<1> HintLightWeight =
70 ImplWorkItemProperty<1>();
71 constexpr static const ImplWorkItemProperty<2> HintHeavyWeight =
72 ImplWorkItemProperty<2>();
73 constexpr static const ImplWorkItemProperty<4> HintRegular =
74 ImplWorkItemProperty<4>();
75 constexpr static const ImplWorkItemProperty<8> HintIrregular =
76 ImplWorkItemProperty<8>();
77 constexpr static const ImplWorkItemProperty<16> ImplForceGlobalLaunch =
78 ImplWorkItemProperty<16>();
79 using None_t = ImplWorkItemProperty<0>;
80 using HintLightWeight_t = ImplWorkItemProperty<1>;
81 using HintHeavyWeight_t = ImplWorkItemProperty<2>;
82 using HintRegular_t = ImplWorkItemProperty<4>;
83 using HintIrregular_t = ImplWorkItemProperty<8>;
84 using ImplForceGlobalLaunch_t = ImplWorkItemProperty<16>;
85};
86
87template <unsigned long pv1, unsigned long pv2>
88inline constexpr WorkItemProperty::ImplWorkItemProperty<pv1 | pv2> operator|(
89 WorkItemProperty::ImplWorkItemProperty<pv1>,
90 WorkItemProperty::ImplWorkItemProperty<pv2>) {
91 return WorkItemProperty::ImplWorkItemProperty<pv1 | pv2>();
92}
93
94template <unsigned long pv1, unsigned long pv2>
95inline constexpr WorkItemProperty::ImplWorkItemProperty<pv1 & pv2> operator&(
96 WorkItemProperty::ImplWorkItemProperty<pv1>,
97 WorkItemProperty::ImplWorkItemProperty<pv2>) {
98 return WorkItemProperty::ImplWorkItemProperty<pv1 & pv2>();
99}
100
101template <unsigned long pv1, unsigned long pv2>
102inline constexpr bool operator==(WorkItemProperty::ImplWorkItemProperty<pv1>,
103 WorkItemProperty::ImplWorkItemProperty<pv2>) {
104 return pv1 == pv2;
105}
106
107} // namespace Experimental
108
113template <unsigned int maxT = 0 /* Max threads per block */
114 ,
115 unsigned int minB = 0 /* Min blocks per SM */
116 >
120 static unsigned int constexpr maxTperB{maxT};
121 static unsigned int constexpr minBperSM{minB};
122};
123
124} // namespace Kokkos
125
126//----------------------------------------------------------------------------
127//----------------------------------------------------------------------------
128
129namespace Kokkos {
130
131#define KOKKOS_IMPL_IS_CONCEPT(CONCEPT) \
132 template <typename T> \
133 struct is_##CONCEPT { \
134 private: \
135 template <typename U> \
136 using have_t = typename U::CONCEPT; \
137 template <typename U> \
138 using have_type_t = typename U::CONCEPT##_type; \
139 \
140 public: \
141 static constexpr bool value = \
142 std::is_base_of<detected_t<have_t, T>, T>::value || \
143 std::is_base_of<detected_t<have_type_t, T>, T>::value; \
144 constexpr operator bool() const noexcept { return value; } \
145 }; \
146 template <typename T> \
147 inline constexpr bool is_##CONCEPT##_v = is_##CONCEPT<T>::value;
148
149// Public concept:
150
151KOKKOS_IMPL_IS_CONCEPT(memory_space)
152KOKKOS_IMPL_IS_CONCEPT(memory_traits)
153KOKKOS_IMPL_IS_CONCEPT(execution_space)
154KOKKOS_IMPL_IS_CONCEPT(execution_policy)
155KOKKOS_IMPL_IS_CONCEPT(array_layout)
156KOKKOS_IMPL_IS_CONCEPT(reducer)
157KOKKOS_IMPL_IS_CONCEPT(team_handle)
158namespace Experimental {
159KOKKOS_IMPL_IS_CONCEPT(work_item_property)
160KOKKOS_IMPL_IS_CONCEPT(hooks_policy)
161} // namespace Experimental
162
163namespace Impl {
164
165// Implementation concept:
166
167KOKKOS_IMPL_IS_CONCEPT(thread_team_member)
168KOKKOS_IMPL_IS_CONCEPT(host_thread_team_member)
169KOKKOS_IMPL_IS_CONCEPT(graph_kernel)
170
171} // namespace Impl
172
173#undef KOKKOS_IMPL_IS_CONCEPT
174
175} // namespace Kokkos
176
177namespace Kokkos {
178namespace Impl {
179
180template <class Object>
181class has_member_team_shmem_size {
182 template <typename T>
183 static int32_t test_for_member(decltype(&T::team_shmem_size)) {
184 return int32_t(0);
185 }
186 template <typename T>
187 static int64_t test_for_member(...) {
188 return int64_t(0);
189 }
190
191 public:
192 constexpr static bool value =
193 sizeof(test_for_member<Object>(nullptr)) == sizeof(int32_t);
194};
195
196template <class Object>
197class has_member_shmem_size {
198 template <typename T>
199 static int32_t test_for_member(decltype(&T::shmem_size_me)) {
200 return int32_t(0);
201 }
202 template <typename T>
203 static int64_t test_for_member(...) {
204 return int64_t(0);
205 }
206
207 public:
208 constexpr static bool value =
209 sizeof(test_for_member<Object>(0)) == sizeof(int32_t);
210};
211
212} // namespace Impl
213} // namespace Kokkos
214//----------------------------------------------------------------------------
215
216namespace Kokkos {
217
218template <class ExecutionSpace, class MemorySpace>
219struct Device {
221 "Execution space is not valid");
223 "Memory space is not valid");
224 using execution_space = ExecutionSpace;
225 using memory_space = MemorySpace;
226 using device_type = Device<execution_space, memory_space>;
227};
228
229namespace Impl {
230
231template <typename T>
232struct is_device_helper : std::false_type {};
233
234template <typename ExecutionSpace, typename MemorySpace>
235struct is_device_helper<Device<ExecutionSpace, MemorySpace>> : std::true_type {
236};
237
238} // namespace Impl
239
240template <typename T>
241using is_device = typename Impl::is_device_helper<std::remove_cv_t<T>>::type;
242
243template <typename T>
244inline constexpr bool is_device_v = is_device<T>::value;
245
246//----------------------------------------------------------------------------
247
248template <typename T>
249struct is_space {
250 private:
251 template <typename, typename = void>
252 struct exe : std::false_type {
253 using space = void;
254 };
255
256 template <typename, typename = void>
257 struct mem : std::false_type {
258 using space = void;
259 };
260
261 template <typename, typename = void>
262 struct dev : std::false_type {
263 using space = void;
264 };
265
266 template <typename U>
267 struct exe<U, std::conditional_t<true, void, typename U::execution_space>>
268 : std::is_same<U, typename U::execution_space>::type {
269 using space = typename U::execution_space;
270 };
271
272 template <typename U>
273 struct mem<U, std::conditional_t<true, void, typename U::memory_space>>
274 : std::is_same<U, typename U::memory_space>::type {
275 using space = typename U::memory_space;
276 };
277
278 template <typename U>
279 struct dev<U, std::conditional_t<true, void, typename U::device_type>>
280 : std::is_same<U, typename U::device_type>::type {
281 using space = typename U::device_type;
282 };
283
284 using is_exe = typename is_space<T>::template exe<std::remove_cv_t<T>>;
285 using is_mem = typename is_space<T>::template mem<std::remove_cv_t<T>>;
286 using is_dev = typename is_space<T>::template dev<std::remove_cv_t<T>>;
287
288 public:
289 static constexpr bool value = is_exe::value || is_mem::value || is_dev::value;
290
291 constexpr operator bool() const noexcept { return value; }
292
293 using execution_space = typename is_exe::space;
294 using memory_space = typename is_mem::space;
295
296 // For backward compatibility, deprecated in favor of
297 // Kokkos::Impl::HostMirror<S>::host_mirror_space
298
299 private:
300 // The actual definitions for host_memory_space and host_execution_spaces are
301 // in do_not_use_host_memory_space and do_not_use_host_execution_space to be
302 // able to use them within this class without deprecation warnings.
303 using do_not_use_host_memory_space = std::conditional_t<
304 std::is_same<memory_space, Kokkos::HostSpace>::value
305#if defined(KOKKOS_ENABLE_CUDA)
306 || std::is_same<memory_space, Kokkos::CudaUVMSpace>::value ||
307 std::is_same<memory_space, Kokkos::CudaHostPinnedSpace>::value
308#elif defined(KOKKOS_ENABLE_HIP)
309 || std::is_same<memory_space, Kokkos::HIPHostPinnedSpace>::value ||
310 std::is_same<memory_space, Kokkos::HIPManagedSpace>::value
311#elif defined(KOKKOS_ENABLE_SYCL)
312 || std::is_same<memory_space,
313 Kokkos::Experimental::SYCLSharedUSMSpace>::value ||
314 std::is_same<memory_space,
315 Kokkos::Experimental::SYCLHostUSMSpace>::value
316#endif
317 ,
318 memory_space, Kokkos::HostSpace>;
319
320 using do_not_use_host_execution_space = std::conditional_t<
321#if defined(KOKKOS_ENABLE_CUDA)
322 std::is_same<execution_space, Kokkos::Cuda>::value ||
323#elif defined(KOKKOS_ENABLE_HIP)
324 std::is_same<execution_space, Kokkos::HIP>::value ||
325#elif defined(KOKKOS_ENABLE_SYCL)
326 std::is_same<execution_space, Kokkos::Experimental::SYCL>::value ||
327#elif defined(KOKKOS_ENABLE_OPENMPTARGET)
328 std::is_same<execution_space,
329 Kokkos::Experimental::OpenMPTarget>::value ||
330#endif
331 false,
332 Kokkos::DefaultHostExecutionSpace, execution_space>;
333};
334
335} // namespace Kokkos
336
337//----------------------------------------------------------------------------
338
339namespace Kokkos {
340namespace Impl {
341
347template <typename DstMemorySpace, typename SrcMemorySpace>
351 "template arguments must be memory spaces");
352
360 enum { assignable = std::is_same<DstMemorySpace, SrcMemorySpace>::value };
361
365 enum { accessible = assignable };
366
370 enum { deepcopy = assignable };
371};
372
373} // namespace Impl
374} // namespace Kokkos
375
376namespace Kokkos {
377
397template <typename AccessSpace, typename MemorySpace>
399 private:
400 static_assert(Kokkos::is_space<AccessSpace>::value,
401 "template argument #1 must be a Kokkos space");
402
404 "template argument #2 must be a Kokkos memory space");
405
406 // The input AccessSpace may be a Device<ExecSpace,MemSpace>
407 // verify that it is a valid combination of spaces.
409 typename AccessSpace::execution_space::memory_space,
410 typename AccessSpace::memory_space>::accessible,
411 "template argument #1 is an invalid space");
412
414 typename AccessSpace::execution_space::memory_space, MemorySpace>;
415
416 using mem_access =
417 Kokkos::Impl::MemorySpaceAccess<typename AccessSpace::memory_space,
418 MemorySpace>;
419
420 public:
426 enum { accessible = exe_access::accessible };
427
433 enum {
434 assignable = is_memory_space<AccessSpace>::value && mem_access::assignable
435 };
436
438 enum { deepcopy = mem_access::deepcopy };
439
440 // What intercessory space for AccessSpace::execution_space
441 // to be able to access MemorySpace?
442 // If same memory space or not accessible use the AccessSpace
443 // else construct a device with execution space and memory space.
444 using space = std::conditional_t<
445 std::is_same<typename AccessSpace::memory_space, MemorySpace>::value ||
446 !exe_access::accessible,
449};
450
451} // namespace Kokkos
452
453//----------------------------------------------------------------------------
454
455#endif // KOKKOS_CORE_CONCEPTS_HPP
A thread safe view to a bitset.
Memory management for host memory.
Access relationship between DstMemorySpace and SrcMemorySpace.
Specify Launch Bounds for CUDA execution.
Can AccessSpace access MemorySpace ?