/home/users/khuck/src/hpx-lsu/hpx/parallel/executors/executor_parameter_traits.hpp

Line% of fetchesSource
1  
//  Copyright (c) 2007-2016 Hartmut Kaiser
2  
//
3  
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
4  
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5  
6  
/// \file parallel/executors/executor_parameter_traits.hpp
7  
8  
#if !defined(HPX_PARALLEL_EXECUTOR_PARAMETER_TRAITS_JUL_30_2015_0914PM)
9  
#define HPX_PARALLEL_EXECUTOR_PARAMETER_TRAITS_JUL_30_2015_0914PM
10  
11  
#include <hpx/config.hpp>
12  
#include <hpx/parallel/config/inline_namespace.hpp>
13  
#include <hpx/parallel/executors/executor_traits.hpp>
14  
#include <hpx/traits/has_member_xxx.hpp>
15  
#include <hpx/traits/is_executor_parameters.hpp>
16  
#include <hpx/traits/detail/wrap_int.hpp>
17  
#include <hpx/util/always_void.hpp>
18  
#include <hpx/util/decay.hpp>
19  
20  
#include <cstddef>
21  
#include <type_traits>
22  
#include <utility>
23  
#include <vector>
24  
25  
namespace hpx { namespace parallel { HPX_INLINE_NAMESPACE(v3)
26  
{
27  
    ///////////////////////////////////////////////////////////////////////////
28  
    // Placeholder type to use predefined executor parameters
29  
    struct sequential_executor_parameters : executor_parameters_tag {};
30  
31  
    ///////////////////////////////////////////////////////////////////////////
32  
    /// \cond NOINTERNAL
33  
    namespace detail
34  
    {
35  
        // If an executor exposes 'executor_parameter_type' this type is
36  
        // assumed to represent the default parameters for the given executor
37  
        // type.
38  
        template <typename Executor, typename Enable = void>
39  
        struct extract_executor_parameters
40  
        {
41  
            // by default, assume sequential execution
42  
            typedef sequential_executor_parameters type;
43  
        };
44  
45  
        template <typename Executor>
46  
        struct extract_executor_parameters<Executor,
47  
            typename hpx::util::always_void<
48  
                typename Executor::executor_parameters_type
49  
            >::type>
50  
        {
51  
            typedef typename Executor::executor_parameters_type type;
52  
        };
53  
54  
        ///////////////////////////////////////////////////////////////////////
55  
        // If a parameters type exposes 'has_variable_chunk_size' aliased to
56  
        // std::true_type it is assumed that the number of loop iterations to
57  
        // combine is different for each of the generated chunks.
58  
        template <typename Parameters, typename Enable = void>
59  
        struct extract_has_variable_chunk_size
60  
        {
61  
            // by default, assume equally sized chunks
62  
            typedef std::false_type type;
63  
        };
64  
65  
        template <typename Parameters>
66  
        struct extract_has_variable_chunk_size<Parameters,
67  
            typename hpx::util::always_void<
68  
                typename Parameters::has_variable_chunk_size
69  
            >::type>
70  
        {
71  
            typedef typename Parameters::has_variable_chunk_size type;
72  
        };
73  
74  
        ///////////////////////////////////////////////////////////////////////
75  
        template <typename Parameters_>
76  
        struct processing_units_count_parameter_helper
77  
        {
78  
            template <typename Parameters>
79  
            static std::size_t call(hpx::traits::detail::wrap_int,
80  
                Parameters && params)
81  
            {
82  
                return hpx::get_os_thread_count();
83  
            }
84  
85  
            template <typename Parameters>
86  
            static auto call(int, Parameters && params)
87  
            ->  decltype(params.processing_units_count())
88  
            {
89  
                return params.processing_units_count();
90  
            }
91  
92  
            static std::size_t call(Parameters_& params)
93  
            {
94  
                return call(0, params);
95  
            }
96  
97  
            template <typename Parameters>
98  
            static std::size_t call(Parameters params)
99  
            {
100  
                return call(static_cast<Parameters_&>(params));
101  
            }
102  
        };
103  
104  
        template <typename Parameters>
105  
        std::size_t call_processing_units_parameter_count(Parameters && params)
106  
        {
107  
            return processing_units_count_parameter_helper<
108  
                    typename hpx::util::decay_unwrap<Parameters>::type
109  
                >::call(std::forward<Parameters>(params));
110  
        }
111  
112  
        HPX_HAS_MEMBER_XXX_TRAIT_DEF(processing_units_count);
113  
114  
        ///////////////////////////////////////////////////////////////////////
115  
        template <typename Parameters_>
116  
        struct get_chunk_size_helper
117  
        {
118  
            template <typename Parameters, typename Executor, typename F>
119  
            static std::size_t
120  
            call(hpx::traits::detail::wrap_int, Parameters &&, Executor &&,
121  
                F &&, std::size_t cores, std::size_t num_tasks)
122  
            {
123  
                return num_tasks;       // assume sequential execution
124  
            }
125  
126  
            template <typename Parameters, typename Executor, typename F>
127  
            static auto call(int, Parameters && params, Executor && exec,
128  
                    F && f, std::size_t cores, std::size_t num_tasks)
129  
            ->  decltype(
130  
                    params.get_chunk_size(std::forward<Executor>(exec),
131  
                        std::forward<F>(f), cores, num_tasks)
132  
                )
133  
            {
134  
                return params.get_chunk_size(std::forward<Executor>(exec),
135  
                    std::forward<F>(f), cores, num_tasks);
136  
            }
137  
138  
            template <typename Executor, typename F>
139  
            static std::size_t
140  
            call(Parameters_& params, Executor && exec, F && f,
141  
                std::size_t cores, std::size_t num_tasks)
142  
            {
143  
                return call(0, params, std::forward<Executor>(exec),
144  
                    std::forward<F>(f), cores, num_tasks);
145  
            }
146  
147  
            template <typename Parameters, typename Executor, typename F>
148  
            static std::size_t
149  
            call(Parameters params, Executor && exec, F && f,
150  
                std::size_t cores, std::size_t num_tasks)
151  
            {
152  
                return call(static_cast<Parameters_&>(params),
153  
                    std::forward<Executor>(exec), std::forward<F>(f),
154  
                    cores, num_tasks);
155  
            }
156  
        };
157  
158  
        template <typename Parameters, typename Executor, typename F>
159  
        std::size_t call_get_chunk_size(Parameters && params, Executor && exec,
160  
            F && f, std::size_t cores, std::size_t num_tasks)
161  
        {
162  
            return get_chunk_size_helper<
163  
                    typename hpx::util::decay_unwrap<Parameters>::type
164  
                >::call(std::forward<Parameters>(params),
165  
                    std::forward<Executor>(exec), std::forward<F>(f),
166  
                    cores, num_tasks);
167  
        }
168  
169  
        HPX_HAS_MEMBER_XXX_TRAIT_DEF(get_chunk_size);
170  
171  
        ///////////////////////////////////////////////////////////////////////
172  
        template <typename Parameters_>
173  
        struct maximal_number_of_chunks_helper
174  
        {
175  
            template <typename Parameters, typename Executor>
176  
            static std::size_t
177  
            call(hpx::traits::detail::wrap_int, Parameters &&, Executor &&,
178  
                std::size_t cores, std::size_t num_tasks)
179  
            {
180  
                return 4 * cores;       // assume 4 times the number of cores
181  
            }
182  
183  
            template <typename Parameters, typename Executor>
184  
            static auto call(int, Parameters && params, Executor && exec,
185  
                    std::size_t cores, std::size_t num_tasks)
186  
            ->  decltype(
187  
                    params.maximal_number_of_chunks(
188  
                        std::forward<Executor>(exec), cores, num_tasks)
189  
                )
190  
            {
191  
                return params.maximal_number_of_chunks(
192  
                    std::forward<Executor>(exec), cores, num_tasks);
193  
            }
194  
195  
            template <typename Executor>
196  
            static std::size_t
197  
            call(Parameters_& params, Executor && exec, std::size_t cores,
198  
                std::size_t num_tasks)
199  
            {
200  
                return call(0, params, std::forward<Executor>(exec), cores,
201  
                    num_tasks);
202  
            }
203  
204  
            template <typename Parameters, typename Executor>
205  
            static std::size_t
206  
            call(Parameters params, Executor && exec, std::size_t cores,
207  
                std::size_t num_tasks)
208  
            {
209  
                return call(static_cast<Parameters_&>(params),
210  
                    std::forward<Executor>(exec), cores, num_tasks);
211  
            }
212  
        };
213  
214  
        template <typename Parameters, typename Executor>
215  
        std::size_t call_maximal_number_of_chunks(Parameters && params,
216  
            Executor && exec, std::size_t cores, std::size_t num_tasks)
217  
        {
218  
            return maximal_number_of_chunks_helper<
219  
                    typename hpx::util::decay_unwrap<Parameters>::type
220  
                >::call(std::forward<Parameters>(params),
221  
                    std::forward<Executor>(exec), cores, num_tasks);
222  
        }
223  
224  
        HPX_HAS_MEMBER_XXX_TRAIT_DEF(maximal_number_of_chunks);
225  
226  
        ///////////////////////////////////////////////////////////////////////
227  
        template <typename Parameters_>
228  
        struct reset_thread_distribution_helper
229  
        {
230  
            template <typename Parameters, typename Executor>
231  
            static void call(hpx::traits::detail::wrap_int, Parameters &&,
232  
                Executor &&)
233  
            {
234  
            }
235  
236  
            template <typename Parameters, typename Executor>
237  
            static auto call(int, Parameters && params, Executor && exec)
238  
            ->  decltype(
239  
                    params.reset_thread_distribution(
240  
                        std::forward<Executor>(exec))
241  
                )
242  
            {
243  
                params.reset_thread_distribution(std::forward<Executor>(exec));
244  
            }
245  
246  
            template <typename Executor>
247  
            static void call(Parameters_& params, Executor && exec)
248  
            {
249  
                call(0, params, std::forward<Executor>(exec));
250  
            }
251  
252  
            template <typename Parameters, typename Executor>
253  
            static void call(Parameters params, Executor && exec)
254  
            {
255  
                call(static_cast<Parameters_&>(params),
256  
                    std::forward<Executor>(exec));
257  
            }
258  
        };
259  
260  
        template <typename Parameters, typename Executor>
261  
        void call_reset_thread_distribution(Parameters && params,
262  
            Executor && exec)
263  
        {
264  
            reset_thread_distribution_helper<
265  
                    typename hpx::util::decay_unwrap<Parameters>::type
266  
                >::call(std::forward<Parameters>(params),
267  
                    std::forward<Executor>(exec));
268  
        }
269  
270  
        HPX_HAS_MEMBER_XXX_TRAIT_DEF(reset_thread_distribution);
271  
272  
        ///////////////////////////////////////////////////////////////////////
273  
        template <typename Parameters_>
274  
        struct mark_begin_execution_helper
275  
        {
276  
            template <typename Parameters>
277  
            static void call(hpx::traits::detail::wrap_int, Parameters &&)
278  
            {
279  
            }
280  
281  
            template <typename Parameters>
282  
            static auto call(int, Parameters && params)
283  
            ->  decltype(params.mark_begin_execution())
284  
            {
285  
                params.mark_begin_execution();
286  
            }
287  
288  
            static void call(Parameters_& params)
289  
            {
290  
                call(0, params);
291  
            }
292  
293  
            template <typename Parameters>
294  
            static void call(Parameters params)
295  
            {
296  
                call(static_cast<Parameters_&>(params));
297  
            }
298  
        };
299  
300  
        template <typename Parameters>
301  
        void call_mark_begin_execution(Parameters && params)
302  
        {
303  
            mark_begin_execution_helper<
304  
                    typename hpx::util::decay_unwrap<Parameters>::type
305  
                >::call(std::forward<Parameters>(params));
306  
        }
307  
308  
        HPX_HAS_MEMBER_XXX_TRAIT_DEF(mark_begin_execution);
309  
310  
        ///////////////////////////////////////////////////////////////////////
311  
        template <typename Parameters_>
312  
        struct mark_end_execution_helper
313  
        {
314  
            template <typename Parameters>
315  
            static void call(hpx::traits::detail::wrap_int, Parameters &&)
316  
            {
317  
            }
318  
319  
            template <typename Parameters>
320  
            static auto call(int, Parameters && params)
321  
            ->  decltype(params.mark_end_execution())
322  
            {
323  
                params.mark_end_execution();
324  
            }
325  
326  
            static void call(Parameters_& params)
327  
            {
328  
                call(0, params);
329  
            }
330  
331  
            template <typename Parameters>
332  
            static void call(Parameters params)
333  
            {
334  
                call(static_cast<Parameters_&>(params));
335  
            }
336  
        };
337  
338  
        template <typename Parameters>
339  
        void call_mark_end_execution(Parameters && params)
340  
        {
341  
            mark_end_execution_helper<
342  
                    typename hpx::util::decay_unwrap<Parameters>::type
343  
                >::call(std::forward<Parameters>(params));
344  
        }
345  
346  
        HPX_HAS_MEMBER_XXX_TRAIT_DEF(mark_end_execution);
347  
    }
348  
    /// \endcond
349  
350  
    ///////////////////////////////////////////////////////////////////////////
351  
    /// The executor_parameter_traits type is used to manage parameters for
352  
    /// an executor.
353  
    template <typename Parameters, typename Enable>
354  
    struct executor_parameter_traits
355  
    {
356  
        /// The type of the executor associated with this instance of
357  
        /// \a executor_traits
358  
        typedef Parameters executor_parameters_type;
359  
360  
        /// The compile-time information about whether the number of loop
361  
        /// iterations to combine is different for each of the generated chunks.
362  
        ///
363  
        /// \note This calls extracts parameters_type::has_variable_chunk_size,
364  
        ///       if available, otherwise it returns std::false_type.
365  
        ///
366  
        typedef typename detail::extract_has_variable_chunk_size<
367  
                executor_parameters_type
368  
            >::type has_variable_chunk_size;
369  
370  
        /// Return the number of invocations of the given function \a f which
371  
        /// should be combined into a single task
372  
        ///
373  
        /// \param params   [in] The executor parameters object to use for
374  
        ///                 determining the chunk size for the given number of
375  
        ///                 tasks \a num_tasks.
376  
        /// \param exec     [in] The executor object which will be used
377  
        ///                 for scheduling of the loop iterations.
378  
        /// \param f        [in] The function which will be optionally scheduled
379  
        ///                 using the given executor.
380  
        /// \param cores    [in] The number of cores the number of chunks
381  
        ///                 should be determined for.
382  
        /// \param num_tasks [in] The number of tasks the chunk size should be
383  
        ///                 determined for
384  
        ///
385  
        /// \note  The parameter \a f is expected to be a nullary function
386  
        ///        returning a `std::size_t` representing the number of
387  
        ///        iteration the function has already executed (i.e. which
388  
        ///        don't have to be scheduled anymore).
389  
        ///
390  
        template <typename Parameters_, typename Executor, typename F>
391  
        static std::size_t get_chunk_size(Parameters_ && params,
392  
            Executor && exec, F && f, std::size_t cores, std::size_t num_tasks)
393  
        {
394  
            return detail::call_get_chunk_size(std::forward<Parameters_>(params),
395  
                std::forward<Executor>(exec), std::forward<F>(f), cores, num_tasks);
396  
        }
397  
398  
        /// Return the largest reasonable number of chunks to create for a
399  
        /// single algorithm invocation.
400  
        ///
401  
        /// \param params   [in] The executor parameters object to use for
402  
        ///                 determining the number of chunks for the given
403  
        ///                 number of \a cores.
404  
        /// \param exec     [in] The executor object which will be used
405  
        ///                 for scheduling of the loop iterations.
406  
        /// \param cores    [in] The number of cores the number of chunks
407  
        ///                 should be determined for.
408  
        /// \param num_tasks [in] The number of tasks the chunk size should be
409  
        ///                 determined for
410  
        ///
411  
        template <typename Parameters_, typename Executor>
412  
        static std::size_t maximal_number_of_chunks(
413  
            Parameters_ && params, Executor && exec, std::size_t cores,
414  
            std::size_t num_tasks)
415  
        {
416  
            return detail::call_maximal_number_of_chunks(
417  
                std::forward<Parameters_>(params), std::forward<Executor>(exec),
418  
                cores, num_tasks);
419  
        }
420  
421  
        /// Reset the internal round robin thread distribution scheme for the
422  
        /// given executor.
423  
        ///
424  
        /// \param params   [in] The executor parameters object to use for
425  
        ///                 resetting the thread distribution scheme.
426  
        /// \param exec     [in] The executor object to use.
427  
        ///
428  
        /// \note This calls params.reset_thread_distribution(exec) if it exists;
429  
        ///       otherwise it does nothing.
430  
        ///
431  
        template <typename Parameters_, typename Executor>
432  
        static void reset_thread_distribution(Parameters_ && params,
433  
            Executor && exec)
434  
        {
435  
            detail::call_reset_thread_distribution(
436  
                std::forward<Parameters_>(params), std::forward<Executor>(exec));
437  
        }
438  
439  
        /// Retrieve the number of (kernel-)threads used by the associated
440  
        /// executor.
441  
        ///
442  
        /// \param params [in] The executor parameters object to use as a
443  
        ///              fallback if the executor does not expose
444  
        ///
445  
        /// \note This calls params.processing_units_count() if it exists;
446  
        ///       otherwise it forwards the request to the executor parameters
447  
        ///       object.
448  
        ///
449  
        template <typename Parameters_>
450  
        static std::size_t processing_units_count(Parameters_ && params)
451  
        {
452  
            return detail::call_processing_units_parameter_count(
453  
                std::forward<Parameters_>(params));
454  
        }
455  
456  
        /// Mark the begin of a parallel algorithm execution
457  
        ///
458  
        /// \param params [in] The executor parameters object to use as a
459  
        ///              fallback if the executor does not expose
460  
        ///
461  
        /// \note This calls params.mark_begin_execution(exec) if it exists;
462  
        ///       otherwise it does nothing.
463  
        ///
464  
        template <typename Parameters_>
465  
        static void mark_begin_execution(Parameters_ && params)
466  
        {
467  
            detail::call_mark_begin_execution(std::forward<Parameters_>(params));
468  
        }
469  
470  
        /// Mark the end of a parallel algorithm execution
471  
        ///
472  
        /// \param params [in] The executor parameters object to use as a
473  
        ///              fallback if the executor does not expose
474  
        ///
475  
        /// \note This calls params.mark_end_execution(exec) if it exists;
476  
        ///       otherwise it does nothing.
477  
        ///
478  
        template <typename Parameters_>
479  
        static void mark_end_execution(Parameters_ && params)
480  
        {
481  
            detail::call_mark_end_execution(std::forward<Parameters_>(params));
482  
        }
483  
    };
484  
485  
    ///////////////////////////////////////////////////////////////////////////
486  
    // defined in hpx/traits/is_executor_parameters.hpp
487  
    ///
488  
    /// 1. The type is_executor_parameters can be used to detect executor
489  
    ///    parameters types for the purpose of excluding function signatures
490  
    ///    from otherwise ambiguous overload resolution participation.
491  
    /// 2. If T is the type of a standard or implementation-defined executor,
492  
    ///    is_executor_parameters<T> shall be publicly derived from
493  
    ///    integral_constant<bool, true>, otherwise from
494  
    ///    integral_constant<bool, false>.
495  
    /// 3. The behavior of a program that adds specializations for
496  
    ///    is_executor_parameters is undefined.
497  
    ///
498  
    template <typename T>
499  
    struct is_executor_parameters;
500  
}}}
501  
502  
#endif
503  

Copyright (c) 2006-2012 Rogue Wave Software, Inc. All Rights Reserved.
Patents pending.