Merge pull request #14827 from YashasSamaga:cuda4dnn-csl-low
[platform/upstream/opencv.git] / modules / dnn / src / cuda / kernel_dispatcher.hpp
1 // This file is part of OpenCV project.
2 // It is subject to the license terms in the LICENSE file found in the top-level directory
3 // of this distribution and at http://opencv.org/license.html.
4
5 #ifndef OPENCV_DNN_SRC_CUDA_KERNEL_DISPATCHER_HPP
6 #define OPENCV_DNN_SRC_CUDA_KERNEL_DISPATCHER_HPP
7
8 #include <cstddef>
9 #include <type_traits>
10
11 /* The performance of many kernels are highly dependent on the tensor rank. Instead of having
12  * one kernel which can work with the maximally ranked tensors, we make one kernel for each supported
13  * tensor rank. This is to ensure that the requirements of the maximally ranked tensors do not take a
14  * toll on the performance of the operation for low ranked tensors. Hence, many kernels take the tensor
15  * rank as a template parameter.
16  *
17  * The kernel is a template and we have different instantiations for each rank. This causes the following pattern
18  * to arise frequently:
19  *
20  * if(rank == 3)
21  *     kernel<T, 3>();
22  * else if(rank == 2)
23  *     kernel<T, 2>();
24  * else
25  *     kernel<T, 1>();
26  *
27  * The rank is a runtime variable. To facilitate creation of such structures, we use GENERATE_KERNEL_DISPATCHER.
28  * This macro creates a function which selects the correct kernel instantiation at runtime.
29  *
30  * Example:
31  *
32  * // function which setups the kernel and launches it
33  * template <class T, std::size_t Rank>
34  * void launch_some_kernel(...);
35  *
36  * // creates the dispatcher named "some_dispatcher" which invokves the correct instantiation of "launch_some_kernel"
37  * GENERATE_KERNEL_DISPATCHER(some_dispatcher, launch_some_kernel);
38  *
39  * // internal API function
40  * template <class T>
41  * void some(...) {
42  *    // ...
43  *    auto rank = input.rank();
44  *    some_dispatcher<T, MIN_RANK, MAX_RANK>(rank, ...);
45  * }
46  */
47
48 /*
49  * name     name of the dispatcher function that is generated
50  * func     template function that requires runtime selection
51  *
52  * T        first template parameter to `func`
53  * start    starting rank
54  * end      ending rank (inclusive)
55  *
56  * Executes func<T, selector> based on runtime `selector` argument given `selector` lies
57  * within the range [start, end]. If outside the range, no instantiation of `func` is executed.
58  */
59 #define GENERATE_KERNEL_DISPATCHER(name,func);                                          \
60     template <class T, std::size_t start, std::size_t end, class... Args> static        \
61     typename std::enable_if<start == end, void>                                         \
62     ::type name(int selector, Args&& ...args) {                                         \
63         if(selector == start)                                                           \
64             func<T, start>(std::forward<Args>(args)...);                                \
65     }                                                                                   \
66                                                                                         \
67     template <class T, std::size_t start, std::size_t end, class... Args> static        \
68     typename std::enable_if<start != end, void>                                         \
69     ::type name(int selector, Args&& ...args) {                                         \
70         if(selector == start)                                                           \
71             func<T, start>(std::forward<Args>(args)...);                                \
72         else                                                                            \
73             name<T, start + 1, end, Args...>(selector, std::forward<Args>(args)...);    \
74     }
75
76 #endif /* OPENCV_DNN_SRC_CUDA_KERNEL_DISPATCHER_HPP */