Logo ROOT  
Reference Guide
 
Loading...
Searching...
No Matches
TExecutor.hxx
Go to the documentation of this file.
1// @(#)root/thread:$Id$
2// Author: Xavier Valls September 2020
3
4/*************************************************************************
5 * Copyright (C) 1995-2020, Rene Brun and Fons Rademakers. *
6 * All rights reserved. *
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. *
9 * For the list of contributors see $ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11#ifndef ROOT_TExecutor
12#define ROOT_TExecutor
13
14#include "ROOT/RConfig.hxx"
16#include "ROOT/TSeq.hxx"
18#ifdef R__USE_IMT
20#endif
21#ifndef R__WIN32
23#endif
24#include "TROOT.h"
26
27#include <initializer_list>
28#include <memory>
29#include <thread>
30#include <type_traits> //std::enable_if, std::result_of
31#include <stdexcept> //std::invalid_argument
32#include <utility> //std::move
33
34namespace ROOT{
35
36namespace Internal{
37class TExecutor: public TExecutorCRTP<TExecutor> {
39public:
40
41 /// \brief Class constructor. Sets the default execution policy and initializes the corresponding executor.
42 /// Defaults to multithreaded execution policy if ROOT is compiled with IMT=ON and IsImplicitMTEnabled. Otherwise it defaults to a serial execution policy
43 /// \param nWorkers [optional] Number of parallel workers, only taken into account if the execution policy is kMultiThread
44 explicit TExecutor(unsigned nWorkers = 0) :
46
47 /// \brief Class constructor. Sets the execution policy and initializes the corresponding executor.
48 /// \param execPolicy Execution policy(kMultiThread, kMultiprocess, kSerial) to process the data
49 /// \param nWorkers [optional] Number of parallel workers, only taken into account if the execution policy is kMultiThread
50 explicit TExecutor(ROOT::EExecutionPolicy execPolicy, unsigned nWorkers = 0);
51
52 TExecutor(const TExecutor &) = delete;
53 TExecutor &operator=(const TExecutor &) = delete;
54
55 /// Return the execution policy the executor is set to
57
58 // Map
59 //
61
62 // MapReduce
63 // the late return types also check at compile-time whether redfunc is compatible with func,
64 // other than checking that func is compatible with the type of arguments.
65 // a static_assert check in TExecutor::Reduce is used to check that redfunc is compatible with the type returned by func
67 template<class F, class R, class Cond = noReferenceCond<F>>
68 auto MapReduce(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> typename std::result_of<F()>::type;
69 template<class F, class INTEGER, class R, class Cond = noReferenceCond<F, INTEGER>>
70 auto MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(INTEGER)>::type;
71 template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
72 auto MapReduce(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type;
73 template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
74 auto MapReduce(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type;
75 template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
76 auto MapReduce(F func, const std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type;
77
78 // Reduce
79 //
81
82 unsigned GetPoolSize() const;
83
84private:
85 // Implementation of the Map functions declared in the parent class (TExecutorCRTP)
86 //
87 template<class F, class Cond = noReferenceCond<F>>
88 auto MapImpl(F func, unsigned nTimes) -> std::vector<typename std::result_of<F()>::type>;
89 template<class F, class INTEGER, class Cond = noReferenceCond<F, INTEGER>>
90 auto MapImpl(F func, ROOT::TSeq<INTEGER> args) -> std::vector<typename std::result_of<F(INTEGER)>::type>;
91 template<class F, class T, class Cond = noReferenceCond<F, T>>
92 auto MapImpl(F func, std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type>;
93 template<class F, class T, class Cond = noReferenceCond<F, T>>
94 auto MapImpl(F func, const std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type>;
95
97
98 // When they are not available, we use a placeholder type instead of TThreadExecutor or TProcessExecutor.
99 // The corresponding data members will not be used.
101#ifdef R__USE_IMT
102# define R__EXECUTOR_THREAD ROOT::TThreadExecutor
103#else
104# define R__EXECUTOR_THREAD Unused_t
105#endif
106#ifndef R__WIN32
107# define R__EXECUTOR_PROCESS ROOT::TProcessExecutor
108#else
109# define R__EXECUTOR_PROCESS Unused_t
110#endif
111
112 std::unique_ptr<R__EXECUTOR_THREAD> fThreadExecutor;
113 std::unique_ptr<R__EXECUTOR_PROCESS> fProcessExecutor;
114 std::unique_ptr<ROOT::TSequentialExecutor> fSequentialExecutor;
115
116#undef R__EXECUTOR_THREAD
117#undef R__EXECUTOR_PROCESS
118
119 /// \brief Helper class to get the correct return type from the Map function,
120 /// necessary to infer the ResolveExecutorAndMap function type
121 template<class F, class CONTAINER>
122 struct MapRetType {
123 using type = typename std::result_of<F(typename CONTAINER::value_type)>::type;
124 };
125
126 template<class F>
127 struct MapRetType<F, unsigned> {
128 using type = typename std::result_of<F()>::type;
129 };
130
131
132 /// \brief Function called from Map to select and execute the correct Executor
133 /// according to the set Execution Policy.
134 template<class F, class T>
135 auto ResolveExecutorAndMap(F func, T&& args) -> std::vector<typename MapRetType<F, typename std::decay<T>::type>::type> {
136 std::vector<typename MapRetType<F, typename std::decay<T>::type>::type> res;
137 switch(fExecPolicy) {
139 res = fSequentialExecutor->Map(func, std::forward<T>(args));
140 break;
142 res = fThreadExecutor->Map(func, std::forward<T>(args));
143 break;
145 res = fProcessExecutor->Map(func, std::forward<T>(args));
146 break;
147 default:
148 break;
149 }
150 return res;
151 }
152};
153
154
155//////////////////////////////////////////////////////////////////////////
156/// \brief Execute a function without arguments several times.
157/// Implementation of the Map method.
158///
159/// \copydetails TExecutorCRTP::Map(F func,unsigned nTimes)
160template<class F, class Cond>
161auto TExecutor::MapImpl(F func, unsigned nTimes) -> std::vector<typename std::result_of<F()>::type> {
162 return ResolveExecutorAndMap(func, nTimes);
163}
164
165//////////////////////////////////////////////////////////////////////////
166/// \brief Execute a function over a sequence of indexes.
167/// Implementation of the Map method.
168///
169/// \copydetails TExecutorCRTP::Map(F func,ROOT::TSeq<INTEGER> args)
170template<class F, class INTEGER, class Cond>
171auto TExecutor::MapImpl(F func, ROOT::TSeq<INTEGER> args) -> std::vector<typename std::result_of<F(INTEGER)>::type> {
172 return ResolveExecutorAndMap(func, args);
173}
174
175//////////////////////////////////////////////////////////////////////////
176/// \brief Execute a function over the elements of a vector.
177/// Implementation of the Map method.
178///
179/// \copydetails TExecutorCRTP::Map(F func,std::vector<T> &args)
180template<class F, class T, class Cond>
181auto TExecutor::MapImpl(F func, std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type> {
182 return ResolveExecutorAndMap(func, args);
183}
184
185//////////////////////////////////////////////////////////////////////////
186/// \brief Execute a function over the elements of an immutable vector.
187/// Implementation of the Map method.
188///
189/// \copydetails TExecutorCRTP::Map(F func,const std::vector<T> &args)
190template<class F, class T, class Cond>
191auto TExecutor::MapImpl(F func, const std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type> {
192 return ResolveExecutorAndMap(func, args);
193}
194
195//////////////////////////////////////////////////////////////////////////
196/// \brief Execute a function `nTimes` (Map) and accumulate the results into a single value (Reduce).
197/// Benefits from partial reduction into `nChunks` intermediate results if the execution policy is multithreaded.
198/// Otherwise, <b>it ignores the nChunks argument</b> and performs a normal MapReduce operation.
199///
200/// \param func Function to be executed. Must take an element of the sequence passed as second argument as a parameter.
201/// \param nTimes Number of times function should be called.
202/// \param redfunc Reduction function to combine the results of the calls to `func` into partial results, and these
203/// into a final result. Must return the same type as `func`.
204/// \param nChunks Number of chunks to split the input data for processing.
205/// \return A value result of "reducing" the vector returned by the Map operation into a single object.
206template<class F, class R, class Cond>
207auto TExecutor::MapReduce(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> typename std::result_of<F()>::type {
208 if (fExecPolicy == ROOT::EExecutionPolicy::kMultiThread) {
209 return fThreadExecutor->MapReduce(func, nTimes, redfunc, nChunks);
210 }
211 return Reduce(Map(func, nTimes), redfunc);
212}
213
214//////////////////////////////////////////////////////////////////////////
215/// \brief Execute a function over a sequence of indexes (Map) and accumulate the results into a single value (Reduce).
216/// Benefits from partial reduction into `nChunks` intermediate results if the execution policy is multithreaded.
217/// Otherwise, <b>it ignores the nChunks argument</b> and performs a normal MapReduce operation.
218///
219/// \param func Function to be executed. Must take an element of the sequence passed assecond argument as a parameter.
220/// \param args Sequence of indexes to execute `func` on.
221/// \param redfunc Reduction function to combine the results of the calls to `func` into partial results, and these
222/// into a final result. Must return the same type as `func`.
223/// \param nChunks Number of chunks to split the input data for processing.
224/// \return A value result of "reducing" the vector returned by the Map operation into a single object.
225template<class F, class INTEGER, class R, class Cond>
226auto TExecutor::MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(INTEGER)>::type {
227 if (fExecPolicy == ROOT::EExecutionPolicy::kMultiThread) {
228 return fThreadExecutor->MapReduce(func, args, redfunc, nChunks);
229 }
230 return Reduce(Map(func, args), redfunc);
231}
232
233//////////////////////////////////////////////////////////////////////////
234/// \brief Execute a function over the elements of an initializer_list (Map) and accumulate the results into a single value (Reduce).
235/// Benefits from partial reduction into `nChunks` intermediate results if the execution policy is multithreaded.
236/// Otherwise, <b>it ignores the nChunks argument</b> and performs a normal MapReduce operation.
237///
238/// \param func Function to be executed. Must take an element of the sequence passed assecond argument as a parameter.
239/// \param args initializer_list for a vector to apply `func` on.
240/// \param redfunc Reduction function to combine the results of the calls to `func` into partial results, and these
241/// into a final result. Must return the same type as `func`.
242/// \param nChunks Number of chunks to split the input data for processing.
243/// \return A value result of "reducing" the vector returned by the Map operation into a single object.
244template<class F, class T, class R, class Cond>
245auto TExecutor::MapReduce(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type {
246 if (fExecPolicy == ROOT::EExecutionPolicy::kMultiThread) {
247 return fThreadExecutor->MapReduce(func, args, redfunc, nChunks);
248 }
249 return Reduce(Map(func, args), redfunc);
250}
251
252//////////////////////////////////////////////////////////////////////////
253/// \brief Execute a function over the elements of a vector (Map) and accumulate the results into a single value (Reduce).
254/// Benefits from partial reduction into `nChunks` intermediate results if the execution policy is multithreaded.
255/// Otherwise, <b>it ignores the nChunks argument</b> and performs a normal MapReduce operation.
256///
257/// \param func Function to be executed. Must take an element of the sequence passed assecond argument as a parameter.
258/// \param args Vector of elements passed as an argument to `func`.
259/// \param redfunc Reduction function to combine the results of the calls to `func` into partial results, and these
260/// into a final result. Must return the same type as `func`.
261/// \param nChunks Number of chunks to split the input data for processing.
262/// \return A value result of "reducing" the vector returned by the Map operation into a single object.
263template<class F, class T, class R, class Cond>
264auto TExecutor::MapReduce(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type {
265 if (fExecPolicy == ROOT::EExecutionPolicy::kMultiThread) {
266 return fThreadExecutor->MapReduce(func, args, redfunc, nChunks);
267 }
268 return Reduce(Map(func, args), redfunc);
269}
270
271//////////////////////////////////////////////////////////////////////////
272/// \brief Execute a function over the elements of an immutable vector (Map) and accumulate the results into a single value (Reduce).
273/// Benefits from partial reduction into `nChunks` intermediate results if the execution policy is multithreaded.
274/// Otherwise, <b>it ignores the nChunks argument</b> and performs a normal MapReduce operation.
275///
276/// \param func Function to be executed. Must take an element of the sequence passed assecond argument as a parameter.
277/// \param args Immutable vector, whose elements are passed as an argument to `func`.
278/// \param redfunc Reduction function to combine the results of the calls to `func` into partial results, and these
279/// into a final result. Must return the same type as `func`.
280/// \param nChunks Number of chunks to split the input data for processing.
281/// \return A value result of "reducing" the vector returned by the Map operation into a single object.
282template<class F, class T, class R, class Cond>
283auto TExecutor::MapReduce(F func, const std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type {
284 if (fExecPolicy == ROOT::EExecutionPolicy::kMultiThread) {
285 return fThreadExecutor->MapReduce(func, args, redfunc, nChunks);
286 }
287 return Reduce(Map(func, args), redfunc);
288}
289
290//////////////////////////////////////////////////////////////////////////
291/// \brief Return the number of pooled workers.
292///
293/// \return The number of workers in the pool in the executor used as a backend.
294
295inline unsigned TExecutor::GetPoolSize() const
296{
297 unsigned poolSize{0u};
298 switch(fExecPolicy){
300 poolSize = fSequentialExecutor->GetPoolSize();
301 break;
303 poolSize = fThreadExecutor->GetPoolSize();
304 break;
306 poolSize = fProcessExecutor->GetPoolSize();
307 break;
308 default:
309 break;
310 }
311 return poolSize;
312}
313
314} // namespace Internal
315} // namespace ROOT
316
317#endif
int type
Definition TGX11.cxx:121
This class implements the interface to execute the same task multiple times, sequentially or in paral...
Definition TExecutor.hxx:37
auto MapReduce(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> typename std::result_of< F()>::type
Execute a function nTimes (Map) and accumulate the results into a single value (Reduce).
auto ResolveExecutorAndMap(F func, T &&args) -> std::vector< typename MapRetType< F, typename std::decay< T >::type >::type >
Function called from Map to select and execute the correct Executor according to the set Execution Po...
std::unique_ptr< R__EXECUTOR_THREAD > fThreadExecutor
std::unique_ptr< ROOT::TSequentialExecutor > fSequentialExecutor
ROOT::EExecutionPolicy Policy() const
Return the execution policy the executor is set to.
Definition TExecutor.hxx:56
auto MapImpl(F func, unsigned nTimes) -> std::vector< typename std::result_of< F()>::type >
Execute a function without arguments several times.
TExecutor(unsigned nWorkers=0)
Class constructor.
Definition TExecutor.hxx:44
TExecutor & operator=(const TExecutor &)=delete
TExecutor(const TExecutor &)=delete
ROOT::EExecutionPolicy fExecPolicy
Definition TExecutor.hxx:96
std::unique_ptr< R__EXECUTOR_PROCESS > fProcessExecutor
unsigned GetPoolSize() const
Return the number of pooled workers.
This class defines an interface to execute the same task multiple times, possibly in parallel and wit...
auto Map(F func, unsigned nTimes) -> std::vector< typename std::result_of< F()>::type >
Execute a function without arguments several times.
T * Reduce(const std::vector< T * > &mergeObjs)
"Reduce" an std::vector into a single object by using the object's Merge method.
A pseudo container class which is a generator of indices.
Definition TSeq.hxx:66
#define F(x, y, z)
tbb::task_arena is an alias of tbb::interface7::task_arena, which doesn't allow to forward declare tb...
Bool_t IsImplicitMTEnabled()
Returns true if the implicit multi-threading in ROOT is enabled.
Definition TROOT.cxx:558
typename std::result_of< F()>::type type
Helper class to get the correct return type from the Map function, necessary to infer the ResolveExec...
typename std::result_of< F(typename CONTAINER::value_type)>::type type