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