From 70cb3980d77d371ccf55c999e96de24aeb1fe022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Widera?= Date: Wed, 28 Jun 2023 15:01:35 +0200 Subject: [PATCH] show better error message if kernel argument is not trivially copyable fix #1922 Currently, alpaka is checking all kernel arguments with the fold expression that all arguments are trivially copyable. The problem is if one argument is not trivially copyable the user does not know which. By checking each argument separately and providing the index to the validator class the user gets the information on which argument produces issues. This simplifies the debugging a lot. --- include/alpaka/kernel/Traits.hpp | 113 ++++++++++++++++++------------- 1 file changed, 66 insertions(+), 47 deletions(-) diff --git a/include/alpaka/kernel/Traits.hpp b/include/alpaka/kernel/Traits.hpp index 33032cdb5c57..3d37428efe7e 100644 --- a/include/alpaka/kernel/Traits.hpp +++ b/include/alpaka/kernel/Traits.hpp @@ -199,70 +199,89 @@ namespace alpaka static_assert(std::is_same_v, "The TKernelFnObj is required to return void!"); } }; - } // namespace detail - //! Creates a kernel execution task. - //! - //! \tparam TAcc The accelerator type. - //! \param workDiv The index domain work division. - //! \param kernelFnObj The kernel function object which should be executed. - //! \param args,... The kernel invocation arguments. - //! \return The kernel execution task. + + template + struct AssertArgumentNTriviallyCopyable + { + static_assert(std::is_trivially_copyable_v, "Kernel N arguments must be trivially copyable!"); + }; + + template + void assertTriviallyCopyable(std::tuple&&, std::index_sequence) + { + (AssertArgumentNTriviallyCopyable>, I>{}, ...); + } + + //! Check that each argument type is trivially copyable + template + void assertTriviallyCopyable(T&&...) + { + assertTriviallyCopyable(std::tuple{}, std::make_index_sequence{}); + ! + } + } +} // namespace detail +//! Creates a kernel execution task. +//! +//! \tparam TAcc The accelerator type. +//! \param workDiv The index domain work division. +//! \param kernelFnObj The kernel function object which should be executed. +//! \param args,... The kernel invocation arguments. +//! \return The kernel execution task. #if BOOST_COMP_CLANG # pragma clang diagnostic pop #endif - template - ALPAKA_FN_HOST auto createTaskKernel(TWorkDiv const& workDiv, TKernelFnObj const& kernelFnObj, TArgs&&... args) - { - // check for void return type - detail::CheckFnReturnType{}(kernelFnObj, args...); +template +ALPAKA_FN_HOST auto createTaskKernel(TWorkDiv const& workDiv, TKernelFnObj const& kernelFnObj, TArgs&&... args) +{ + // check for void return type + detail::CheckFnReturnType{}(kernelFnObj, args...); #if BOOST_COMP_NVCC - static_assert( - std::is_trivially_copyable_v || __nv_is_extended_device_lambda_closure_type(TKernelFnObj) - || __nv_is_extended_host_device_lambda_closure_type(TKernelFnObj), - "Kernels must be trivially copyable or an extended CUDA lambda expression!"); + static_assert( + std::is_trivially_copyable_v || __nv_is_extended_device_lambda_closure_type(TKernelFnObj) + || __nv_is_extended_host_device_lambda_closure_type(TKernelFnObj), + "Kernels must be trivially copyable or an extended CUDA lambda expression!"); #else - static_assert(std::is_trivially_copyable_v, "Kernels must be trivially copyable!"); + static_assert(std::is_trivially_copyable_v, "Kernels must be trivially copyable!"); #endif - static_assert( - (std::is_trivially_copyable_v> && ...), - "Kernel arguments must be trivially copyable!"); - static_assert( - Dim>::value == Dim::value, - "The dimensions of TAcc and TWorkDiv have to be identical!"); - static_assert( - std::is_same_v>, Idx>, - "The idx type of TAcc and the idx type of TWorkDiv have to be identical!"); + detail::assertTriviallyCopyable(std::forward>(args)...); + static_assert( + Dim>::value == Dim::value, + "The dimensions of TAcc and TWorkDiv have to be identical!"); + static_assert( + std::is_same_v>, Idx>, + "The idx type of TAcc and the idx type of TWorkDiv have to be identical!"); #if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL - std::cout << __func__ << " workDiv: " << workDiv - << ", kernelFnObj: " << core::demangled << std::endl; + std::cout << __func__ << " workDiv: " << workDiv + << ", kernelFnObj: " << core::demangled << std::endl; #endif - return trait::CreateTaskKernel::createTaskKernel( - workDiv, - kernelFnObj, - std::forward(args)...); - } + return trait::CreateTaskKernel::createTaskKernel( + workDiv, + kernelFnObj, + std::forward(args)...); +} #if BOOST_COMP_CLANG # pragma clang diagnostic push # pragma clang diagnostic ignored \ "-Wdocumentation" // clang does not support the syntax for variadic template arguments "args,..." #endif - //! Executes the given kernel in the given queue. - //! - //! \tparam TAcc The accelerator type. - //! \param queue The queue to enqueue the view copy task into. - //! \param workDiv The index domain work division. - //! \param kernelFnObj The kernel function object which should be executed. - //! \param args,... The kernel invocation arguments. +//! Executes the given kernel in the given queue. +//! +//! \tparam TAcc The accelerator type. +//! \param queue The queue to enqueue the view copy task into. +//! \param workDiv The index domain work division. +//! \param kernelFnObj The kernel function object which should be executed. +//! \param args,... The kernel invocation arguments. #if BOOST_COMP_CLANG # pragma clang diagnostic pop #endif - template - ALPAKA_FN_HOST auto exec(TQueue& queue, TWorkDiv const& workDiv, TKernelFnObj const& kernelFnObj, TArgs&&... args) - -> void - { - enqueue(queue, createTaskKernel(workDiv, kernelFnObj, std::forward(args)...)); - } +template +ALPAKA_FN_HOST auto exec(TQueue& queue, TWorkDiv const& workDiv, TKernelFnObj const& kernelFnObj, TArgs&&... args) + -> void +{ + enqueue(queue, createTaskKernel(workDiv, kernelFnObj, std::forward(args)...)); +} } // namespace alpaka