Kokkos Core Kernels Package  Version of the Day
Kokkos_Concepts.hpp
1 /*
2 //@HEADER
3 // ************************************************************************
4 //
5 // Kokkos v. 3.0
6 // Copyright (2020) National Technology & Engineering
7 // Solutions of Sandia, LLC (NTESS).
8 //
9 // Under the terms of Contract DE-NA0003525 with NTESS,
10 // the U.S. Government retains certain rights in this software.
11 //
12 // Redistribution and use in source and binary forms, with or without
13 // modification, are permitted provided that the following conditions are
14 // met:
15 //
16 // 1. Redistributions of source code must retain the above copyright
17 // notice, this list of conditions and the following disclaimer.
18 //
19 // 2. Redistributions in binary form must reproduce the above copyright
20 // notice, this list of conditions and the following disclaimer in the
21 // documentation and/or other materials provided with the distribution.
22 //
23 // 3. Neither the name of the Corporation nor the names of the
24 // contributors may be used to endorse or promote products derived from
25 // this software without specific prior written permission.
26 //
27 // THIS SOFTWARE IS PROVIDED BY NTESS "AS IS" AND ANY
28 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
30 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NTESS OR THE
31 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
32 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
33 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
34 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
35 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
36 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
37 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 //
39 // Questions? Contact Christian R. Trott (crtrott@sandia.gov)
40 //
41 // ************************************************************************
42 //@HEADER
43 */
44 
45 #ifndef KOKKOS_CORE_CONCEPTS_HPP
46 #define KOKKOS_CORE_CONCEPTS_HPP
47 
48 #include <type_traits>
49 
50 // Needed for 'is_space<S>::host_mirror_space
51 #include <Kokkos_Core_fwd.hpp>
52 
53 //----------------------------------------------------------------------------
54 //----------------------------------------------------------------------------
55 
56 namespace Kokkos {
57 
58 // Schedules for Execution Policies
59 struct Static {};
60 struct Dynamic {};
61 
62 // Schedule Wrapper Type
63 template <class T>
64 struct Schedule {
65  static_assert(std::is_same<T, Static>::value ||
66  std::is_same<T, Dynamic>::value,
67  "Kokkos: Invalid Schedule<> type.");
68  using schedule_type = Schedule;
69  using type = T;
70 };
71 
72 // Specify Iteration Index Type
73 template <typename T>
74 struct IndexType {
75  static_assert(std::is_integral<T>::value, "Kokkos: Invalid IndexType<>.");
76  using index_type = IndexType;
77  using type = T;
78 };
79 
80 namespace Experimental {
81 struct WorkItemProperty {
82  template <unsigned long Property>
83  struct ImplWorkItemProperty {
84  static const unsigned value = Property;
85  using work_item_property = ImplWorkItemProperty<Property>;
86  };
87 
88  constexpr static const ImplWorkItemProperty<0> None =
89  ImplWorkItemProperty<0>();
90  constexpr static const ImplWorkItemProperty<1> HintLightWeight =
91  ImplWorkItemProperty<1>();
92  constexpr static const ImplWorkItemProperty<2> HintHeavyWeight =
93  ImplWorkItemProperty<2>();
94  constexpr static const ImplWorkItemProperty<4> HintRegular =
95  ImplWorkItemProperty<4>();
96  constexpr static const ImplWorkItemProperty<8> HintIrregular =
97  ImplWorkItemProperty<8>();
98  using None_t = ImplWorkItemProperty<0>;
99  using HintLightWeight_t = ImplWorkItemProperty<1>;
100  using HintHeavyWeight_t = ImplWorkItemProperty<2>;
101  using HintRegular_t = ImplWorkItemProperty<4>;
102  using HintIrregular_t = ImplWorkItemProperty<8>;
103 };
104 
105 template <unsigned long pv1, unsigned long pv2>
106 inline constexpr WorkItemProperty::ImplWorkItemProperty<pv1 | pv2> operator|(
107  WorkItemProperty::ImplWorkItemProperty<pv1>,
108  WorkItemProperty::ImplWorkItemProperty<pv2>) {
109  return WorkItemProperty::ImplWorkItemProperty<pv1 | pv2>();
110 }
111 
112 template <unsigned long pv1, unsigned long pv2>
113 inline constexpr WorkItemProperty::ImplWorkItemProperty<pv1 & pv2> operator&(
114  WorkItemProperty::ImplWorkItemProperty<pv1>,
115  WorkItemProperty::ImplWorkItemProperty<pv2>) {
116  return WorkItemProperty::ImplWorkItemProperty<pv1 & pv2>();
117 }
118 
119 template <unsigned long pv1, unsigned long pv2>
120 inline constexpr bool operator==(WorkItemProperty::ImplWorkItemProperty<pv1>,
121  WorkItemProperty::ImplWorkItemProperty<pv2>) {
122  return pv1 == pv2;
123 }
124 
125 } // namespace Experimental
126 
131 template <unsigned int maxT = 0 /* Max threads per block */
132  ,
133  unsigned int minB = 0 /* Min blocks per SM */
134  >
135 struct LaunchBounds {
136  using launch_bounds = LaunchBounds;
138  static unsigned int constexpr maxTperB{maxT};
139  static unsigned int constexpr minBperSM{minB};
140 };
141 
142 } // namespace Kokkos
143 
144 //----------------------------------------------------------------------------
145 //----------------------------------------------------------------------------
146 
147 namespace Kokkos {
148 
149 #define KOKKOS_IMPL_IS_CONCEPT(CONCEPT) \
150  template <typename T> \
151  struct is_##CONCEPT { \
152  private: \
153  template <typename, typename = std::true_type> \
154  struct have : std::false_type {}; \
155  template <typename U> \
156  struct have<U, typename std::is_base_of<typename U::CONCEPT, U>::type> \
157  : std::true_type {}; \
158  template <typename U> \
159  struct have<U, \
160  typename std::is_base_of<typename U::CONCEPT##_type, U>::type> \
161  : std::true_type {}; \
162  \
163  public: \
164  static constexpr bool value = \
165  is_##CONCEPT::template have<typename std::remove_cv<T>::type>::value; \
166  constexpr operator bool() const noexcept { return value; } \
167  };
168 
169 // Public concept:
170 
171 KOKKOS_IMPL_IS_CONCEPT(memory_space)
172 KOKKOS_IMPL_IS_CONCEPT(memory_traits)
173 KOKKOS_IMPL_IS_CONCEPT(execution_space)
174 KOKKOS_IMPL_IS_CONCEPT(execution_policy)
175 KOKKOS_IMPL_IS_CONCEPT(array_layout)
176 KOKKOS_IMPL_IS_CONCEPT(reducer)
177 namespace Experimental {
178 KOKKOS_IMPL_IS_CONCEPT(work_item_property)
179 }
180 
181 namespace Impl {
182 
183 // For backward compatibility:
184 
185 using Kokkos::is_array_layout;
186 using Kokkos::is_execution_policy;
187 using Kokkos::is_execution_space;
188 using Kokkos::is_memory_space;
189 using Kokkos::is_memory_traits;
190 
191 // Implementation concept:
192 
193 KOKKOS_IMPL_IS_CONCEPT(iteration_pattern)
194 KOKKOS_IMPL_IS_CONCEPT(schedule_type)
195 KOKKOS_IMPL_IS_CONCEPT(index_type)
196 KOKKOS_IMPL_IS_CONCEPT(launch_bounds)
197 KOKKOS_IMPL_IS_CONCEPT(thread_team_member)
198 KOKKOS_IMPL_IS_CONCEPT(host_thread_team_member)
199 KOKKOS_IMPL_IS_CONCEPT(graph_kernel)
200 
201 } // namespace Impl
202 
203 #undef KOKKOS_IMPL_IS_CONCEPT
204 
205 } // namespace Kokkos
206 
207 namespace Kokkos {
208 namespace Impl {
209 
210 template <class Object>
211 class has_member_team_shmem_size {
212  template <typename T>
213  static int32_t test_for_member(decltype(&T::team_shmem_size)) {
214  return int32_t(0);
215  }
216  template <typename T>
217  static int64_t test_for_member(...) {
218  return int64_t(0);
219  }
220 
221  public:
222  constexpr static bool value =
223  sizeof(test_for_member<Object>(nullptr)) == sizeof(int32_t);
224 };
225 
226 template <class Object>
227 class has_member_shmem_size {
228  template <typename T>
229  static int32_t test_for_member(decltype(&T::shmem_size_me)) {
230  return int32_t(0);
231  }
232  template <typename T>
233  static int64_t test_for_member(...) {
234  return int64_t(0);
235  }
236 
237  public:
238  constexpr static bool value =
239  sizeof(test_for_member<Object>(0)) == sizeof(int32_t);
240 };
241 
242 } // namespace Impl
243 } // namespace Kokkos
244 //----------------------------------------------------------------------------
245 
246 namespace Kokkos {
247 
248 template <class ExecutionSpace, class MemorySpace>
249 struct Device {
250  static_assert(Kokkos::is_execution_space<ExecutionSpace>::value,
251  "Execution space is not valid");
252  static_assert(Kokkos::is_memory_space<MemorySpace>::value,
253  "Memory space is not valid");
254  using execution_space = ExecutionSpace;
255  using memory_space = MemorySpace;
256  using device_type = Device<execution_space, memory_space>;
257 };
258 
259 namespace Impl {
260 
261 template <typename T>
262 struct is_device_helper : std::false_type {};
263 
264 template <typename ExecutionSpace, typename MemorySpace>
265 struct is_device_helper<Device<ExecutionSpace, MemorySpace>> : std::true_type {
266 };
267 
268 } // namespace Impl
269 
270 template <typename T>
271 using is_device =
272  typename Impl::is_device_helper<typename std::remove_cv<T>::type>::type;
273 
274 //----------------------------------------------------------------------------
275 
276 template <typename T>
277 struct is_space {
278  private:
279  template <typename, typename = void>
280  struct exe : std::false_type {
281  using space = void;
282  };
283 
284  template <typename, typename = void>
285  struct mem : std::false_type {
286  using space = void;
287  };
288 
289  template <typename, typename = void>
290  struct dev : std::false_type {
291  using space = void;
292  };
293 
294  template <typename U>
295  struct exe<U, typename std::conditional<true, void,
296  typename U::execution_space>::type>
297  : std::is_same<U, typename U::execution_space>::type {
298  using space = typename U::execution_space;
299  };
300 
301  template <typename U>
302  struct mem<
303  U, typename std::conditional<true, void, typename U::memory_space>::type>
304  : std::is_same<U, typename U::memory_space>::type {
305  using space = typename U::memory_space;
306  };
307 
308  template <typename U>
309  struct dev<
310  U, typename std::conditional<true, void, typename U::device_type>::type>
311  : std::is_same<U, typename U::device_type>::type {
312  using space = typename U::device_type;
313  };
314 
315  using is_exe =
316  typename is_space<T>::template exe<typename std::remove_cv<T>::type>;
317  using is_mem =
318  typename is_space<T>::template mem<typename std::remove_cv<T>::type>;
319  using is_dev =
320  typename is_space<T>::template dev<typename std::remove_cv<T>::type>;
321 
322  public:
323  static constexpr bool value = is_exe::value || is_mem::value || is_dev::value;
324 
325  constexpr operator bool() const noexcept { return value; }
326 
327  using execution_space = typename is_exe::space;
328  using memory_space = typename is_mem::space;
329 
330  // For backward compatibility, deprecated in favor of
331  // Kokkos::Impl::HostMirror<S>::host_mirror_space
332 
333  using host_memory_space = typename std::conditional<
334  std::is_same<memory_space, Kokkos::HostSpace>::value
335 #if defined(KOKKOS_ENABLE_CUDA)
336  || std::is_same<memory_space, Kokkos::CudaUVMSpace>::value ||
337  std::is_same<memory_space, Kokkos::CudaHostPinnedSpace>::value
338 #endif /* #if defined( KOKKOS_ENABLE_CUDA ) */
339  ,
340  memory_space, Kokkos::HostSpace>::type;
341 
342 #if defined(KOKKOS_ENABLE_CUDA)
343  using host_execution_space = typename std::conditional<
344  std::is_same<execution_space, Kokkos::Cuda>::value,
345  Kokkos::DefaultHostExecutionSpace, execution_space>::type;
346 #else
347 #if defined(KOKKOS_ENABLE_OPENMPTARGET)
348  using host_execution_space = typename std::conditional<
349  std::is_same<execution_space, Kokkos::Experimental::OpenMPTarget>::value,
350  Kokkos::DefaultHostExecutionSpace, execution_space>::type;
351 #else
352  using host_execution_space = execution_space;
353 #endif
354 #endif
355 
356  using host_mirror_space = typename std::conditional<
357  std::is_same<execution_space, host_execution_space>::value &&
358  std::is_same<memory_space, host_memory_space>::value,
359  T, Kokkos::Device<host_execution_space, host_memory_space>>::type;
360 };
361 
362 // For backward compatibility
363 
364 namespace Impl {
365 
366 using Kokkos::is_space;
367 
368 }
369 
370 } // namespace Kokkos
371 
372 //----------------------------------------------------------------------------
373 
374 namespace Kokkos {
375 namespace Impl {
376 
382 template <typename DstMemorySpace, typename SrcMemorySpace>
384  static_assert(Kokkos::is_memory_space<DstMemorySpace>::value &&
385  Kokkos::is_memory_space<SrcMemorySpace>::value,
386  "template arguments must be memory spaces");
387 
395  enum { assignable = std::is_same<DstMemorySpace, SrcMemorySpace>::value };
396 
400  enum { accessible = assignable };
401 
405  enum { deepcopy = assignable };
406 };
407 
408 } // namespace Impl
409 } // namespace Kokkos
410 
411 namespace Kokkos {
412 
432 template <typename AccessSpace, typename MemorySpace>
434  private:
435  static_assert(Kokkos::is_space<AccessSpace>::value,
436  "template argument #1 must be a Kokkos space");
437 
438  static_assert(Kokkos::is_memory_space<MemorySpace>::value,
439  "template argument #2 must be a Kokkos memory space");
440 
441  // The input AccessSpace may be a Device<ExecSpace,MemSpace>
442  // verify that it is a valid combination of spaces.
443  static_assert(Kokkos::Impl::MemorySpaceAccess<
444  typename AccessSpace::execution_space::memory_space,
445  typename AccessSpace::memory_space>::accessible,
446  "template argument #1 is an invalid space");
447 
449  typename AccessSpace::execution_space::memory_space, MemorySpace>;
450 
451  using mem_access =
452  Kokkos::Impl::MemorySpaceAccess<typename AccessSpace::memory_space,
453  MemorySpace>;
454 
455  public:
461  enum { accessible = exe_access::accessible };
462 
468  enum {
469  assignable = is_memory_space<AccessSpace>::value && mem_access::assignable
470  };
471 
473  enum { deepcopy = mem_access::deepcopy };
474 
475  // What intercessory space for AccessSpace::execution_space
476  // to be able to access MemorySpace?
477  // If same memory space or not accessible use the AccessSpace
478  // else construct a device with execution space and memory space.
479  using space = typename std::conditional<
480  std::is_same<typename AccessSpace::memory_space, MemorySpace>::value ||
481  !exe_access::accessible,
482  AccessSpace,
483  Kokkos::Device<typename AccessSpace::execution_space, MemorySpace>>::type;
484 };
485 
486 } // namespace Kokkos
487 
488 namespace Kokkos {
489 namespace Impl {
490 
491 using Kokkos::SpaceAccessibility; // For backward compatibility
492 
493 }
494 } // namespace Kokkos
495 
496 //----------------------------------------------------------------------------
497 
498 #endif // KOKKOS_CORE_CONCEPTS_HPP
Can AccessSpace access MemorySpace ?
Memory management for host memory.
None
Specify Launch Bounds for CUDA execution.
Definition: dummy.cpp:3
Access relationship between DstMemorySpace and SrcMemorySpace.