33#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
37#if defined(ALPAKA_ACC_GPU_CUDA_ENABLED) || defined(ALPAKA_ACC_GPU_HIP_ENABLED)
39# if !defined(ALPAKA_HOST_ONLY)
43# if defined(ALPAKA_ACC_GPU_CUDA_ENABLED) && !ALPAKA_LANG_CUDA
44# error If ALPAKA_ACC_GPU_CUDA_ENABLED is set, the compiler has to support CUDA!
47# if defined(ALPAKA_ACC_GPU_HIP_ENABLED) && !ALPAKA_LANG_HIP
48# error If ALPAKA_ACC_GPU_HIP_ENABLED is set, the compiler has to support HIP!
56# pragma clang diagnostic push
57# pragma clang diagnostic ignored "-Wunused-template"
63 template<
typename TKernelFnObj,
typename TAcc,
typename... TArgs>
66 TKernelFnObj
const kernelFnObj,
69 TAcc
const acc(threadElemExtent);
72# if !(ALPAKA_COMP_CLANG_CUDA && ALPAKA_COMP_CLANG)
74 std::is_same_v<decltype(kernelFnObj(const_cast<TAcc const&>(acc), args...)),
void>,
75 "The TKernelFnObj is required to return void!");
77 kernelFnObj(
const_cast<TAcc const&
>(acc), args...);
80# pragma clang diagnostic pop
83 template<
typename TKernelFnObj,
typename TAcc,
typename... TArgs>
88 =
gpuKernel<TKernelFnObj, TAcc, TArgs...>;
92 namespace uniform_cuda_hip
96 template<
typename TDim,
typename TIdx>
99 if constexpr(TDim::value > 0)
101 for(
auto i = std::min(
typename TDim::value_type{3}, TDim::value); i < TDim::value; ++i)
103 if(vec[TDim::value - 1u - i] != 1)
105 throw std::runtime_error(
106 "The CUDA/HIP accelerator supports a maximum of 3 dimensions. All "
107 "work division extents of the dimensions higher 3 have to be 1!");
113 template<
typename TDim,
typename TIdx>
117 if constexpr(TDim::value >= 1)
118 dim.x =
static_cast<unsigned>(vec[TDim::value - 1u]);
119 if constexpr(TDim::value >= 2)
120 dim.y =
static_cast<unsigned>(vec[TDim::value - 2u]);
121 if constexpr(TDim::value >= 3)
122 dim.z =
static_cast<unsigned>(vec[TDim::value - 3u]);
135 typename TKernelFnObj,
141 template<
typename TWorkDiv>
144 TKernelFnObj
const& kernelFnObj,
152 "The work division and the execution task have to be of the same dimensionality!");
156 std::tuple<remove_restrict_t<std::decay_t<TArgs>>...>
m_args;
167 typename TKernelFnObj,
181 typename TKernelFnObj,
195 typename TKernelFnObj,
209 typename TKernelFnObj,
224 typename TKernelFnObj,
239 typename TKernelFnObj,
243 uniform_cuda_hip::detail::QueueUniformCudaHipRt<TApi, TBlocking>,
254# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
263# if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
265 if constexpr(TCooperative)
269 throw std::runtime_error(
"This accelerator doesn't support cooperative groups functionality!");
282# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
283 std::cout << __func__ <<
" gridDim: (" << gridDim.z <<
", " << gridDim.y <<
", " << gridDim.x <<
")\n";
284 std::cout << __func__ <<
" blockDim: (" << blockDim.z <<
", " << blockDim.y <<
", " << blockDim.x
288# if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
293 throw std::runtime_error(
294 "The given work division is not valid or not supported by the device of type "
300 auto const blockSharedMemDynSizeBytes = std::apply(
310# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
312 std::cout << __func__ <<
" BlockSharedMemDynSizeBytes: " << blockSharedMemDynSizeBytes <<
" B"
319# if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
320 if constexpr(TCooperative)
323 int const maxActiveBlocks = std::apply(
334# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
335 std::cout <<
"cooperative kernel launch\n";
337 << maxActiveBlocks << std::endl;
340 if(maxActiveBlocks <= 0)
342 using namespace std::literals;
343 throw std::runtime_error(
345 +
" cannot be launched as a cooperative kernel with "s
346 + std::to_string(blockThreadExtent.prod()) +
" threads per block on the device "s
348 +
", because not even a single block can be active.\n"s
349 +
"Use alpaka::getMaxActiveBlocks(...) to check the block size at runtime."s);
352 int const requestedBlocks =
static_cast<int>(gridBlockExtent.prod());
353 if(requestedBlocks < 0 || requestedBlocks > maxActiveBlocks)
355 using namespace std::literals;
356 throw std::runtime_error(
357 "The requested number of blocks is larger than the device limit for the kernel "s
360 + std::to_string(gridBlockExtent.prod()) +
"\nmaximum allowed: "s
361 + std::to_string(maxActiveBlocks) +
"\n"s
362 +
"Use alpaka::getMaxActiveBlocks(...) to query the limit at runtime."s);
367# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
369 typename TApi::FuncAttributes_t funcAttrs;
371 std::cout << __func__ <<
" binaryVersion: " << funcAttrs.binaryVersion
372 <<
" constSizeBytes: " << funcAttrs.constSizeBytes <<
" B"
373 <<
" localSizeBytes: " << funcAttrs.localSizeBytes <<
" B"
374 <<
" maxThreadsPerBlock: " << funcAttrs.maxThreadsPerBlock
375 <<
" numRegs: " << funcAttrs.numRegs <<
" ptxVersion: " << funcAttrs.ptxVersion
376 <<
" sharedSizeBytes: " << funcAttrs.sharedSizeBytes <<
" B" << std::endl;
392 if constexpr(TCooperative)
394 void const* kernelArgs[] = {&threadElemExtent, &task.m_kernelFnObj, &args...};
399 const_cast<void**
>(kernelArgs),
400 static_cast<std::size_t
>(blockSharedMemDynSizeBytes),
401 queue.getNativeHandle()));
408 static_cast<std::size_t
>(blockSharedMemDynSizeBytes),
409 queue.getNativeHandle()>>>(threadElemExtent, task.m_kernelFnObj, args...);
419 std::ignore = TApi::streamSynchronize(queue.getNativeHandle());
423 using namespace std::literals;
424 std::string
const msg
437 template<
typename TApi,
typename TDev,
typename TDim,
typename TIdx,
typename TKernelFn,
typename... TArgs>
446 [[maybe_unused]] TDev
const& dev,
447 [[maybe_unused]] TKernelFn
const& kernelFn,
455 typename TApi::FuncAttributes_t funcAttrs;
458# pragma GCC diagnostic push
459# pragma GCC diagnostic ignored "-Wconditionally-supported"
462 TApi::funcGetAttributes(&funcAttrs,
reinterpret_cast<void const*
>(kernelName)));
464# pragma GCC diagnostic pop
468 kernelFunctionAttributes.
constSizeBytes = funcAttrs.constSizeBytes;
469 kernelFunctionAttributes.
localSizeBytes = funcAttrs.localSizeBytes;
472 kernelFunctionAttributes.
numRegs = funcAttrs.numRegs;
473 kernelFunctionAttributes.
asmVersion = funcAttrs.ptxVersion;
474 kernelFunctionAttributes.
maxThreadsPerBlock =
static_cast<int>(funcAttrs.maxThreadsPerBlock);
476# if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
477 printf(
"Kernel Function Attributes: \n");
478 printf(
"binaryVersion: %d \n", funcAttrs.binaryVersion);
480 "constSizeBytes: %lu \n localSizeBytes: %lu, sharedSizeBytes %lu maxDynamicSharedSizeBytes: %d "
482 funcAttrs.constSizeBytes,
483 funcAttrs.localSizeBytes,
484 funcAttrs.sharedSizeBytes,
485 funcAttrs.maxDynamicSharedSizeBytes);
488 "numRegs: %d, ptxVersion: %d \n maxThreadsPerBlock: %d .\n ",
490 funcAttrs.ptxVersion,
491 funcAttrs.maxThreadsPerBlock);
493 return kernelFunctionAttributes;
498 template<
typename TAcc,
typename TKernelFnObj,
typename TApi,
typename TDim,
typename TIdx,
typename... TArgs>
502 TKernelFnObj
const& kernelFnObj,
506 TArgs
const&... args) ->
int
508 auto const blockSharedMemDynSizeBytes
511# ifdef __CUDACC_DEBUG__
514 int numBlocksPerSm = 1;
517 int numBlocksPerSm = 0;
521 static_cast<int>(blockThreadExtent.prod()),
522 static_cast<std::size_t
>(blockSharedMemDynSizeBytes)));
527 return numBlocksPerSm *
static_cast<int>(multiProcessorCount);
539struct The_ALPAKA_KERNEL_NAME_macro_must_be_called_in_the_global_namespace;
541# define ALPAKA_KERNEL_NAME(KERNEL, NAME) \
543 struct The_ALPAKA_KERNEL_NAME_macro_must_be_called_in_the_global_namespace; \
547 The_ALPAKA_KERNEL_NAME_macro_must_be_called_in_the_global_namespace, \
548 ::The_ALPAKA_KERNEL_NAME_macro_must_be_called_in_the_global_namespace>, \
549 "The ALPAKA_KERNEL_NAME macro must be called in the global namespace"); \
551 template<typename TAcc, typename... TArgs> \
552 __global__ void NAME( \
553 alpaka::Vec<alpaka::Dim<TAcc>, alpaka::Idx<TAcc>> const extent, \
554 KERNEL const kernelFnObj, \
557 TAcc const acc(extent); \
558 kernelFnObj(const_cast<TAcc const&>(acc), args...); \
561 namespace alpaka::detail \
563 template<typename TAcc, typename... TArgs> \
564 inline void (*kernelName<KERNEL, TAcc, TArgs...>)( \
565 alpaka::Vec<alpaka::Dim<TAcc>, alpaka::Idx<TAcc>> const, \
568 = ::NAME<TAcc, TArgs...>; \
571struct The_ALPAKA_KERNEL_SCOPED_NAME_macro_must_be_called_in_the_global_namespace;
573# define ALPAKA_KERNEL_SCOPED_NAME(KERNEL, NAMESPACE, NAME) \
574 struct The_ALPAKA_KERNEL_SCOPED_NAME_macro_must_be_called_in_the_global_namespace; \
578 The_ALPAKA_KERNEL_SCOPED_NAME_macro_must_be_called_in_the_global_namespace, \
579 ::The_ALPAKA_KERNEL_SCOPED_NAME_macro_must_be_called_in_the_global_namespace>, \
580 "The ALPAKA_KERNEL_SCOPED_NAME macro must be called in the global namespace"); \
582 namespace NAMESPACE \
584 template<typename TAcc, typename... TArgs> \
585 __global__ void NAME( \
586 alpaka::Vec<alpaka::Dim<TAcc>, alpaka::Idx<TAcc>> const extent, \
587 KERNEL const kernelFnObj, \
590 TAcc const acc(extent); \
591 kernelFnObj(const_cast<TAcc const&>(acc), args...); \
595 namespace alpaka::detail \
597 template<typename TAcc, typename... TArgs> \
598 inline void (*kernelName<KERNEL, TAcc, TArgs...>)( \
599 alpaka::Vec<alpaka::Dim<TAcc>, alpaka::Idx<TAcc>> const, \
602 = ::NAMESPACE::NAME<TAcc, TArgs...>; \
610# define ALPAKA_KERNEL_NAME(KERNEL, NAME)
611# define ALPAKA_KERNEL_SCOPED_NAME(KERNEL, NAMESPACE, NAME)
619# define ALPAKA_KERNEL_NAME(KERNEL, NAME)
620# define ALPAKA_KERNEL_SCOPED_NAME(KERNEL, NAMESPACE, NAME)
#define ALPAKA_DEBUG_MINIMAL
The minimal debug level.
#define ALPAKA_DEBUG
Set the minimum log level if it is not defined.
#define ALPAKA_DEBUG_MINIMAL_LOG_SCOPE
A basic class holding the work division as grid block extent, block thread and thread element extent.
constexpr std::string_view demangled
__global__ void gpuKernel(Vec< Dim< TAcc >, Idx< TAcc > > const threadElemExtent, TKernelFnObj const kernelFnObj, TArgs... args)
The GPU CUDA/HIP kernel entry point.
void(* kernelName)(Vec< Dim< TAcc >, Idx< TAcc > > const, TKernelFnObj const, remove_restrict_t< std::decay_t< TArgs > >...)
The alpaka accelerator library.
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto getWorkDiv(TWorkDiv const &workDiv) -> Vec< Dim< TWorkDiv >, Idx< TWorkDiv > >
Get the extent requested.
ALPAKA_FN_HOST auto isValidWorkDiv(TWorkDiv const &workDiv, AccDevProps< TDim, TIdx > const &accDevProps) -> bool
Checks if the work division is supported.
typename trait::IdxType< T >::type Idx
typename remove_restrict< T >::type remove_restrict_t
Helper to remove restrict from a type.
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto getMaxActiveBlocks(TDev const &device, TKernelFnObj const &kernelFnObj, alpaka::Vec< TDim, TIdx > const &blockThreadExtent, alpaka::Vec< TDim, TIdx > const &threadElemExtent, TArgs const &... args) -> int
ALPAKA_FN_HOST auto getDev(T const &t)
ALPAKA_FN_HOST auto getAccName() -> std::string
ALPAKA_NO_HOST_ACC_WARNING ALPAKA_FN_HOST_ACC auto getBlockSharedMemDynSizeBytes(TKernelFnObj const &kernelFnObj, Vec< TDim, Idx< TAcc > > const &blockThreadExtent, Vec< TDim, Idx< TAcc > > const &threadElemExtent, TArgs const &... args) -> std::size_t
typename trait::DimType< T >::type Dim
The dimension type trait alias template to remove the ::type.
Kernel function attributes struct. Attributes are filled by calling the API of the accelerator using ...
std::size_t constSizeBytes
std::size_t localSizeBytes
std::size_t sharedSizeBytes
int maxDynamicSharedSizeBytes
The accelerator type trait.
The dimension getter type trait.
The structure template to access to the functions attributes of a kernel function object.
The device properties get trait.
Get maximum requested blocks for cooperative kernel trait.