alpaka
Abstraction Library for Parallel Kernel Acceleration
Loading...
Searching...
No Matches
trait.hpp
Go to the documentation of this file.
1/* Copyright 2024 René Widera
2 * SPDX-License-Identifier: MPL-2.0
3 */
4
5#pragma once
6
7#include "Handle.hpp"
10#include "alpaka/executor.hpp"
13#include "alpaka/tag.hpp"
14
15#include <type_traits>
16
17namespace alpaka::onHost
18{
19 namespace trait
20 {
22 {
23 template<alpaka::concepts::Api T_Api>
24 struct Op : std::false_type
25 {
26 };
27 };
28
30 {
31 template<alpaka::concepts::Executor T_Executor, typename T_Device>
32 struct Op : std::false_type
33 {
34 };
35 };
36
37 template<alpaka::concepts::Executor T_Executor, internal::concepts::DeviceHandle T_DeviceHandle>
38 struct IsExecutorSupportedBy::Op<T_Executor, T_DeviceHandle>
39 : IsExecutorSupportedBy::Op<T_Executor, typename T_DeviceHandle::element_type>
40 {
41 };
42
44 {
45 template<alpaka::concepts::DeviceKind T_DeviceKind, typename T_Api>
46 struct Op : std::false_type
47 {
48 };
49 };
50
51 template<typename T_Kernel, concepts::ThreadSpec T_Spec>
53 {
54 BlockDynSharedMemBytes(T_Kernel kernel, T_Spec spec)
55 {
56 alpaka::unused(kernel, spec);
57 }
58
59 /** Get amount of dynamic shared memory in bytes.
60 *
61 * @attention requires (false) is disabling the function if you specialize these traits remove the require
62 * statement. Disabling is required to enable the trait evaluation only in cases where the user is defining
63 * the trait.
64 */
65 uint32_t operator()(auto const&... args) const requires(false)
66 {
67 alpaka::unused(args...);
68 return 0;
69 }
70 };
71
72 template<onHost::concepts::ThreadSpec T_ThreadSpec, alpaka::concepts::KernelBundle T_KernelBundle>
74 {
75 static constexpr bool zeroSharedMemory = true;
76
77 uint32_t operator()(T_ThreadSpec const spec, [[maybe_unused]] T_KernelBundle const& kernelBundle) const
78 {
79 alpaka::unused(spec);
80 return 0u;
81 }
82 };
83
84 template<concepts::ThreadSpec T_Spec, typename T_KernelFn, typename... T_Args>
85 requires requires() { std::declval<T_KernelFn>().dynSharedMemBytes; } || requires() {
86 BlockDynSharedMemBytes<T_KernelFn, T_Spec>{std::declval<T_KernelFn>(), std::declval<T_Spec>()}(
87 std::declval<remove_restrict_t<std::decay_t<T_Args>>>()...);
88 }
89 struct GetDynSharedMemBytes<T_Spec, KernelBundle<T_KernelFn, T_Args...>>
90 {
91 uint32_t operator()(
92 T_Spec const spec,
93 [[maybe_unused]] KernelBundle<T_KernelFn, T_Args...> const& kernelBundle) const
94 {
95 if constexpr(requires {
96 BlockDynSharedMemBytes<T_KernelFn, T_Spec>{kernelBundle.m_kernelFn, spec}(
97 std::declval<remove_restrict_t<std::decay_t<T_Args>>>()...);
98 })
99 {
100 return alpaka::apply(
101 [&](auto const&... args)
102 { return BlockDynSharedMemBytes<T_KernelFn, T_Spec>{kernelBundle.m_kernelFn, spec}(args...); },
103 kernelBundle.m_args);
104 }
105 else
106 {
107 return kernelBundle.m_kernelFn.dynSharedMemBytes;
108 }
109 }
110 };
111
112 template<onHost::concepts::ThreadSpec T_ThreadSpec, alpaka::concepts::KernelBundle T_KernelBundle>
113 struct HasUserDefinedDynSharedMemBytes : std::true_type
114 {
115 };
116
117 template<onHost::concepts::ThreadSpec T_ThreadSpec, alpaka::concepts::KernelBundle T_KernelBundle>
122
123 // required to return a compile time constant
125 {
126 template<
128 alpaka::concepts::DeviceKind T_DeviceKind,
130 struct Op
131 {
132 consteval uint32_t operator()(T_Api const, T_DeviceKind const, T_Exec const) const
133 {
134 static_assert(
135 sizeof(T_Api) && false,
136 "Missing definition of GetMaxThreadsPerBlock for this combination of API, device kind, "
137 "and executor.");
138 return 1u;
139 }
140 };
141 };
142
143 } // namespace trait
144
146 {
147 return trait::IsPlatformAvailable::Op<std::decay_t<decltype(api)>>::value;
148 }
149
150 consteval bool isExecutorSupportedBy(auto executor, internal::concepts::DeviceHandle auto const& deviceHandle)
151 {
152 return trait::IsExecutorSupportedBy::Op<ALPAKA_TYPEOF(executor), ALPAKA_TYPEOF(deviceHandle)>::value;
153 }
154
155 constexpr auto supportedExecutors(internal::concepts::DeviceHandle auto deviceHandle, auto const listOfExecutors)
156 {
157 return meta::filter(
158 // we can not use isExecutorSupportedBy() because gcc14 is stricter in the detection which functions can
159 // be evaluated at compile time
160 [&](auto executor) constexpr
161 { return trait::IsExecutorSupportedBy::Op<ALPAKA_TYPEOF(executor), ALPAKA_TYPEOF(deviceHandle)>::value; },
162 listOfExecutors);
163 }
164
165 /** Select a default executor for the given device.
166 *
167 * Picks the first executor (with the most parallelism) supported by the device out of all known executors.
168 */
169 constexpr auto defaultExecutor(internal::concepts::DeviceHandle auto deviceHandle)
170 {
171 return std::get<0>(supportedExecutors(deviceHandle, exec::allExecutors));
172 }
173
174 constexpr auto supportedDevices(auto const api)
175 {
176 return meta::filter(
177 // we can not use isExecutorSupportedBy() because gcc14 is stricter in the detection which functions can
178 // be evaluated at compile time
179 [&](auto devTag) constexpr
182 }
183
184 template<onHost::concepts::ThreadSpec T_ThreadSpec, alpaka::concepts::KernelBundle T_KernelBundle>
185 constexpr uint32_t getDynSharedMemBytes(T_ThreadSpec spec, T_KernelBundle const& kernelBundle)
186 {
188 }
189
190 template<onHost::concepts::ThreadSpec T_ThreadSpec, alpaka::concepts::KernelBundle T_KernelBundle>
191 consteval bool hasUserDefinedDynSharedMemBytes(T_ThreadSpec spec, T_KernelBundle const& kernelBundle)
192 {
193 alpaka::unused(spec, kernelBundle);
195 }
196
197 /** A safe(ish) compile time lower bound on max threads per block for a given combination of API, device kind and
198 * executor.
199 *
200 * Returns the minimum number of threads-per-block guaranteed to be supported across
201 * all devices of the executor's backend family. The actual device may support more;
202 * this is a conservative bound for compile-time clamping of block sizes.
203 *
204 * @attention Due to lmem, shared memory or register usage the actual limit could be lower. In this case
205 * the kernel launched using this compile time max will fail at runtime with invalid kernel configuration. We can
206 * not avoid this at compile time.
207 *
208 */
209 template<alpaka::concepts::Api T_Api, alpaka::concepts::DeviceKind T_DeviceKind, alpaka::concepts::Executor T_Exec>
210 consteval uint32_t getMaxThreadsPerBlock(T_Api api, T_DeviceKind deviceKind, T_Exec exec)
211 {
213 }
214
215} // namespace alpaka::onHost
The class used to bind kernel function object and arguments together. Once an instance of this class ...
#define ALPAKA_TYPEOF(...)
Get the type of instance.
Definition common.hpp:154
Concept to check for APIs.
Definition api.hpp:42
Concept to check if something is a device kind.
Definition tag.hpp:145
Concept to check for an executor.
Definition trait.hpp:133
Concept to check if a type is a ThreadSpec.
constexpr auto allDevices
Definition tag.hpp:210
constexpr auto allExecutors
list of all executors supported by alpaka
Definition executor.hpp:21
constexpr auto filter(auto const unaryConditionFn, auto const list)
Definition filter.hpp:13
Functionality which is usable on the host CPU controller thread.
Definition api.hpp:40
consteval bool hasUserDefinedDynSharedMemBytes(T_ThreadSpec spec, T_KernelBundle const &kernelBundle)
Definition trait.hpp:191
constexpr auto defaultExecutor(internal::concepts::DeviceHandle auto deviceHandle)
Select a default executor for the given device.
Definition trait.hpp:169
constexpr auto supportedDevices(auto const api)
Definition trait.hpp:174
consteval uint32_t getMaxThreadsPerBlock(T_Api api, T_DeviceKind deviceKind, T_Exec exec)
A safe(ish) compile time lower bound on max threads per block for a given combination of API,...
Definition trait.hpp:210
consteval bool isExecutorSupportedBy(auto executor, internal::concepts::DeviceHandle auto const &deviceHandle)
Definition trait.hpp:150
consteval bool isPlatformAvaiable(alpaka::concepts::Api auto api)
Definition trait.hpp:145
constexpr auto supportedExecutors(internal::concepts::DeviceHandle auto deviceHandle, auto const listOfExecutors)
Definition trait.hpp:155
constexpr uint32_t getDynSharedMemBytes(T_ThreadSpec spec, T_KernelBundle const &kernelBundle)
Definition trait.hpp:185
ALPAKA_FN_INLINE constexpr decltype(auto) apply(T_Func &&func, T_TupleLike &&tuple)
Applies a function to the elements of a tuple-like object.
Definition apply.hpp:35
STL namespace.
BlockDynSharedMemBytes(T_Kernel kernel, T_Spec spec)
Definition trait.hpp:54
uint32_t operator()(auto const &... args) const
Get amount of dynamic shared memory in bytes.
Definition trait.hpp:65
uint32_t operator()(T_Spec const spec, KernelBundle< T_KernelFn, T_Args... > const &kernelBundle) const
Definition trait.hpp:91
static constexpr bool zeroSharedMemory
Definition trait.hpp:75
uint32_t operator()(T_ThreadSpec const spec, T_KernelBundle const &kernelBundle) const
Definition trait.hpp:77
consteval uint32_t operator()(T_Api const, T_DeviceKind const, T_Exec const) const
Definition trait.hpp:132