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"
15#include "ROOT/RMakeUnique.hxx"
17#include "ROOT/TSeq.hxx"
19#ifdef R__USE_IMT
21#endif
22#ifndef R__WIN32
24#endif
25#include "TROOT.h"
27
28#include <initializer_list>
29#include <memory>
30#include <thread>
31#include <type_traits> //std::enable_if, std::result_of
32#include <stdexcept> //std::invalid_argument
33#include <utility> //std::move
34
35namespace ROOT{
36
37namespace Internal{
38class TExecutor: public TExecutorCRTP<TExecutor> {
40public:
41
42 /// \brief Class constructor. Sets the default execution policy and initializes the corresponding executor.
43 /// Defaults to multithreaded execution policy if ROOT is compiled with IMT=ON and IsImplicitMTEnabled. Otherwise it defaults to a serial execution policy
44 /// \param nWorkers [optional] Number of parallel workers, only taken into account if the execution policy is kMultiThread
45 explicit TExecutor(unsigned nWorkers = 0) :
47
48 /// \brief Class constructor. Sets the execution policy and initializes the corresponding executor.
49 /// \param execPolicy Execution policy(kMultiThread, kMultiprocess, kSerial) to process the data
50 /// \param nWorkers [optional] Number of parallel workers, only taken into account if the execution policy is kMultiThread
51 explicit TExecutor(ROOT::EExecutionPolicy execPolicy, unsigned nWorkers = 0);
52
53 TExecutor(const TExecutor &) = delete;
54 TExecutor &operator=(const TExecutor &) = delete;
55
56 /// Return the execution policy the executor is set to
58
59 // Map
60 //
62
63 // MapReduce
64 // the late return types also check at compile-time whether redfunc is compatible with func,
65 // other than checking that func is compatible with the type of arguments.
66 // a static_assert check in TExecutor::Reduce is used to check that redfunc is compatible with the type returned by func
68 template<class F, class R, class Cond = noReferenceCond<F>>
69 auto MapReduce(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> typename std::result_of<F()>::type;
70 template<class F, class INTEGER, class R, class Cond = noReferenceCond<F, INTEGER>>
71 auto MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(INTEGER)>::type;
72 template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
73 auto MapReduce(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type;
74 template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
75 auto MapReduce(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type;
76 template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
77 auto MapReduce(F func, const std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type;
78
79 // Reduce
80 //
82
83 unsigned GetPoolSize() const;
84
85private:
86 // Implementation of the Map functions declared in the parent class (TExecutorCRTP)
87 //
88 template<class F, class Cond = noReferenceCond<F>>
89 auto MapImpl(F func, unsigned nTimes) -> std::vector<typename std::result_of<F()>::type>;
90 template<class F, class INTEGER, class Cond = noReferenceCond<F, INTEGER>>
91 auto MapImpl(F func, ROOT::TSeq<INTEGER> args) -> std::vector<typename std::result_of<F(INTEGER)>::type>;
92 template<class F, class T, class Cond = noReferenceCond<F, T>>
93 auto MapImpl(F func, std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type>;
94 template<class F, class T, class Cond = noReferenceCond<F, T>>
95 auto MapImpl(F func, const std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type>;
96
98
99 // When they are not available, we use a placeholder type instead of TThreadExecutor or TProcessExecutor.
100 // The corresponding data members will not be used.
102#ifdef R__USE_IMT
103# define R__EXECUTOR_THREAD ROOT::TThreadExecutor
104#else
105# define R__EXECUTOR_THREAD Unused_t
106#endif
107#ifndef R__WIN32
108# define R__EXECUTOR_PROCESS ROOT::TProcessExecutor
109#else
110# define R__EXECUTOR_PROCESS Unused_t
111#endif
112
113 std::unique_ptr<R__EXECUTOR_THREAD> fThreadExecutor;
114 std::unique_ptr<R__EXECUTOR_PROCESS> fProcessExecutor;
115 std::unique_ptr<ROOT::TSequentialExecutor> fSequentialExecutor;
116
117#undef R__EXECUTOR_THREAD
118#undef R__EXECUTOR_PROCESS
119
120 /// \brief Helper class to get the correct return type from the Map function,
121 /// necessary to infer the ResolveExecutorAndMap function type
122 template<class F, class CONTAINER>
123 struct MapRetType {
124 using type = typename std::result_of<F(typename CONTAINER::value_type)>::type;
125 };
126
127 template<class F>
128 struct MapRetType<F, unsigned> {
129 using type = typename std::result_of<F()>::type;
130 };
131
132
133 /// \brief Function called from Map to select and execute the correct Executor
134 /// according to the set Execution Policy.
135 template<class F, class T>
136 auto ResolveExecutorAndMap(F func, T&& args) -> std::vector<typename MapRetType<F, typename std::decay<T>::type>::type> {
137 std::vector<typename MapRetType<F, typename std::decay<T>::type>::type> res;
138 switch(fExecPolicy) {
140 res = fSequentialExecutor->Map(func, std::forward<T>(args));
141 break;
143 res = fThreadExecutor->Map(func, std::forward<T>(args));
144 break;
146 res = fProcessExecutor->Map(func, std::forward<T>(args));
147 break;
148 default:
149 break;
150 }
151 return res;
152 }
153};
154
155
156//////////////////////////////////////////////////////////////////////////
157/// \brief Execute a function without arguments several times.
158/// Implementation of the Map method.
159///
160/// \copydetails TExecutorCRTP::Map(F func,unsigned nTimes)
161template<class F, class Cond>
162auto TExecutor::MapImpl(F func, unsigned nTimes) -> std::vector<typename std::result_of<F()>::type> {
163 return ResolveExecutorAndMap(func, nTimes);
164}
165
166//////////////////////////////////////////////////////////////////////////
167/// \brief Execute a function over a sequence of indexes.
168/// Implementation of the Map method.
169///
170/// \copydetails TExecutorCRTP::Map(F func,ROOT::TSeq<INTEGER> args)
171template<class F, class INTEGER, class Cond>
172auto TExecutor::MapImpl(F func, ROOT::TSeq<INTEGER> args) -> std::vector<typename std::result_of<F(INTEGER)>::type> {
173 return ResolveExecutorAndMap(func, args);
174}
175
176//////////////////////////////////////////////////////////////////////////
177/// \brief Execute a function over the elements of a vector.
178/// Implementation of the Map method.
179///
180/// \copydetails TExecutorCRTP::Map(F func,std::vector<T> &args)
181template<class F, class T, class Cond>
182auto TExecutor::MapImpl(F func, std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type> {
183 return ResolveExecutorAndMap(func, args);
184}
185
186//////////////////////////////////////////////////////////////////////////
187/// \brief Execute a function over the elements of an immutable vector.
188/// Implementation of the Map method.
189///
190/// \copydetails TExecutorCRTP::Map(F func,const std::vector<T> &args)
191template<class F, class T, class Cond>
192auto TExecutor::MapImpl(F func, const std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type> {
193 return ResolveExecutorAndMap(func, args);
194}
195
196//////////////////////////////////////////////////////////////////////////
197/// \brief Execute a function `nTimes` (Map) and accumulate the results into a single value (Reduce).
198/// Benefits from partial reduction into `nChunks` intermediate results if the execution policy is multithreaded.
199/// Otherwise, <b>it ignores the nChunks argument</b> and performs a normal MapReduce operation.
200///
201/// \param func Function to be executed. Must take an element of the sequence passed as second argument as a parameter.
202/// \param nTimes Number of times function should be called.
203/// \param redfunc Reduction function to combine the results of the calls to `func` into partial results, and these
204/// into a final result. Must return the same type as `func`.
205/// \param nChunks Number of chunks to split the input data for processing.
206/// \return A value result of "reducing" the vector returned by the Map operation into a single object.
207template<class F, class R, class Cond>
208auto TExecutor::MapReduce(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> typename std::result_of<F()>::type {
209 if (fExecPolicy == ROOT::EExecutionPolicy::kMultiThread) {
210 return fThreadExecutor->MapReduce(func, nTimes, redfunc, nChunks);
211 }
212 return Reduce(Map(func, nTimes), redfunc);
213}
214
215//////////////////////////////////////////////////////////////////////////
216/// \brief Execute a function over a sequence of indexes (Map) and accumulate the results into a single value (Reduce).
217/// Benefits from partial reduction into `nChunks` intermediate results if the execution policy is multithreaded.
218/// Otherwise, <b>it ignores the nChunks argument</b> and performs a normal MapReduce operation.
219///
220/// \param func Function to be executed. Must take an element of the sequence passed assecond argument as a parameter.
221/// \param args Sequence of indexes to execute `func` on.
222/// \param redfunc Reduction function to combine the results of the calls to `func` into partial results, and these
223/// into a final result. Must return the same type as `func`.
224/// \param nChunks Number of chunks to split the input data for processing.
225/// \return A value result of "reducing" the vector returned by the Map operation into a single object.
226template<class F, class INTEGER, class R, class Cond>
227auto TExecutor::MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(INTEGER)>::type {
228 if (fExecPolicy == ROOT::EExecutionPolicy::kMultiThread) {
229 return fThreadExecutor->MapReduce(func, args, redfunc, nChunks);
230 }
231 return Reduce(Map(func, args), redfunc);
232}
233
234//////////////////////////////////////////////////////////////////////////
235/// \brief Execute a function over the elements of an initializer_list (Map) and accumulate the results into a single value (Reduce).
236/// Benefits from partial reduction into `nChunks` intermediate results if the execution policy is multithreaded.
237/// Otherwise, <b>it ignores the nChunks argument</b> and performs a normal MapReduce operation.
238///
239/// \param func Function to be executed. Must take an element of the sequence passed assecond argument as a parameter.
240/// \param args initializer_list for a vector to apply `func` on.
241/// \param redfunc Reduction function to combine the results of the calls to `func` into partial results, and these
242/// into a final result. Must return the same type as `func`.
243/// \param nChunks Number of chunks to split the input data for processing.
244/// \return A value result of "reducing" the vector returned by the Map operation into a single object.
245template<class F, class T, class R, class Cond>
246auto TExecutor::MapReduce(F func, std::initializer_list<T> args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type {
247 if (fExecPolicy == ROOT::EExecutionPolicy::kMultiThread) {
248 return fThreadExecutor->MapReduce(func, args, redfunc, nChunks);
249 }
250 return Reduce(Map(func, args), redfunc);
251}
252
253//////////////////////////////////////////////////////////////////////////
254/// \brief Execute a function over the elements of a vector (Map) and accumulate the results into a single value (Reduce).
255/// Benefits from partial reduction into `nChunks` intermediate results if the execution policy is multithreaded.
256/// Otherwise, <b>it ignores the nChunks argument</b> and performs a normal MapReduce operation.
257///
258/// \param func Function to be executed. Must take an element of the sequence passed assecond argument as a parameter.
259/// \param args Vector of elements passed as an argument to `func`.
260/// \param redfunc Reduction function to combine the results of the calls to `func` into partial results, and these
261/// into a final result. Must return the same type as `func`.
262/// \param nChunks Number of chunks to split the input data for processing.
263/// \return A value result of "reducing" the vector returned by the Map operation into a single object.
264template<class F, class T, class R, class Cond>
265auto TExecutor::MapReduce(F func, std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type {
266 if (fExecPolicy == ROOT::EExecutionPolicy::kMultiThread) {
267 return fThreadExecutor->MapReduce(func, args, redfunc, nChunks);
268 }
269 return Reduce(Map(func, args), redfunc);
270}
271
272//////////////////////////////////////////////////////////////////////////
273/// \brief Execute a function over the elements of an immutable vector (Map) and accumulate the results into a single value (Reduce).
274/// Benefits from partial reduction into `nChunks` intermediate results if the execution policy is multithreaded.
275/// Otherwise, <b>it ignores the nChunks argument</b> and performs a normal MapReduce operation.
276///
277/// \param func Function to be executed. Must take an element of the sequence passed assecond argument as a parameter.
278/// \param args Immutable vector, whose elements are passed as an argument to `func`.
279/// \param redfunc Reduction function to combine the results of the calls to `func` into partial results, and these
280/// into a final result. Must return the same type as `func`.
281/// \param nChunks Number of chunks to split the input data for processing.
282/// \return A value result of "reducing" the vector returned by the Map operation into a single object.
283template<class F, class T, class R, class Cond>
284auto TExecutor::MapReduce(F func, const std::vector<T> &args, R redfunc, unsigned nChunks) -> typename std::result_of<F(T)>::type {
285 if (fExecPolicy == ROOT::EExecutionPolicy::kMultiThread) {
286 return fThreadExecutor->MapReduce(func, args, redfunc, nChunks);
287 }
288 return Reduce(Map(func, args), redfunc);
289}
290
291//////////////////////////////////////////////////////////////////////////
292/// \brief Return the number of pooled workers.
293///
294/// \return The number of workers in the pool in the executor used as a backend.
295
296inline unsigned TExecutor::GetPoolSize() const
297{
298 unsigned poolSize{0u};
299 switch(fExecPolicy){
301 poolSize = fSequentialExecutor->GetPoolSize();
302 break;
304 poolSize = fThreadExecutor->GetPoolSize();
305 break;
307 poolSize = fProcessExecutor->GetPoolSize();
308 break;
309 default:
310 break;
311 }
312 return poolSize;
313}
314
315} // namespace Internal
316} // namespace ROOT
317
318#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:38
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:57
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:45
TExecutor & operator=(const TExecutor &)=delete
TExecutor(const TExecutor &)=delete
ROOT::EExecutionPolicy fExecPolicy
Definition TExecutor.hxx:97
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:556
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