Logo ROOT  
Reference Guide
TExecutor.hxx
Go to the documentation of this file.
1 // @(#)root/thread:$Id$
2 // Author: Xavier Valls March 2016
3 
4 /*************************************************************************
5  * Copyright (C) 1995-2006, 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 
12 #ifndef ROOT_TExecutor
13 #define ROOT_TExecutor
14 
15 #include "ROOT/TSeq.hxx"
16 #include "TList.h"
17 #include <vector>
18 
19 //////////////////////////////////////////////////////////////////////////
20 ///
21 /// \class ROOT::TExecutor
22 /// \brief This class defines an interface to execute the same task
23 /// multiple times in parallel, possibly with different arguments every
24 /// time. The classes implementing it mimic the behaviour of python's pool.Map method.
25 ///
26 /// ###ROOT::TExecutor::Map
27 /// The two possible usages of the Map method are:\n
28 /// * Map(F func, unsigned nTimes): func is executed nTimes with no arguments
29 /// * Map(F func, T& args): func is executed on each element of the collection of arguments args
30 ///
31 /// For either signature, func is executed as many times as needed by a pool of
32 /// nThreads threads; It defaults to the number of cores.\n
33 /// A collection containing the result of each execution is returned.\n
34 /// **Note:** the user is responsible for the deletion of any object that might
35 /// be created upon execution of func, returned objects included: ROOT::TExecutor never
36 /// deletes what it returns, it simply forgets it.\n
37 ///
38 /// \param func
39 /// \parblock
40 /// a lambda expression, an std::function, a loaded macro, a
41 /// functor class or a function that takes zero arguments (for the first signature)
42 /// or one (for the second signature).
43 /// \endparblock
44 /// \param args
45 /// \parblock
46 /// a standard vector, a ROOT::TSeq of integer type or an initializer list for the second signature.
47 /// An integer only for the first.\n
48 /// \endparblock
49 ///
50 /// **Note:** in cases where the function to be executed takes more than
51 /// zero/one argument but all are fixed except zero/one, the function can be wrapped
52 /// in a lambda or via std::bind to give it the right signature.\n
53 ///
54 /// #### Return value:
55 /// An std::vector. The elements in the container
56 /// will be the objects returned by func.
57 
58 namespace ROOT {
59 
60 template<class subc>
61 class TExecutor {
62 public:
63  explicit TExecutor() = default;
64  explicit TExecutor(size_t /* nThreads */ ){};
65 
66  template< class F, class... T>
67  using noReferenceCond = typename std::enable_if<"Function can't return a reference" && !(std::is_reference<typename std::result_of<F(T...)>::type>::value)>::type;
68 
69  // // Map
70  // //these late return types allow for a compile-time check of compatibility between function signatures and args,
71  // //and a compile-time check that the argument list implements a front() method (all STL sequence containers have it)
72  template<class F, class Cond = noReferenceCond<F>>
73  auto Map(F func, unsigned nTimes) -> std::vector<typename std::result_of<F()>::type>;
74  template<class F, class INTEGER, class Cond = noReferenceCond<F, INTEGER>>
75  auto Map(F func, ROOT::TSeq<INTEGER> args) -> std::vector<typename std::result_of<F(INTEGER)>::type>;
76  /// \cond
77  template<class F, class T, class Cond = noReferenceCond<F, T>>
78  auto Map(F func, std::initializer_list<T> args) -> std::vector<typename std::result_of<F(T)>::type>;
79  /// \endcond
80  template<class F, class T, class Cond = noReferenceCond<F, T>>
81  auto Map(F func, std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type>;
82 
83  // // MapReduce
84  // // the late return types also check at compile-time whether redfunc is compatible with func,
85  // // other than checking that func is compatible with the type of arguments.
86  // // a static_assert check in TExecutor<subc>::Reduce is used to check that redfunc is compatible with the type returned by func
87  template<class F, class INTEGER, class R, class Cond = noReferenceCond<F, INTEGER>>
88  auto MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc) -> typename std::result_of<F(INTEGER)>::type;
89  /// \cond
90  template<class F, class T, class R, class Cond = noReferenceCond<F, T>>
91  auto MapReduce(F func, std::initializer_list<T> args, R redfunc) -> typename std::result_of<F(T)>::type;
92  /// \endcond
93  template<class F, class T, class Cond = noReferenceCond<F, T>>
94  T* MapReduce(F func, std::vector<T*> &args);
95 
96  template<class T> T* Reduce(const std::vector<T*> &mergeObjs);
97 
98 private:
99  inline subc & Derived()
100  {
101  return *static_cast<subc*>(this);
102  }
103 };
104 
105 //////////////////////////////////////////////////////////////////////////
106 /// Execute func (with no arguments) nTimes in parallel.
107 /// A vector containg executions' results is returned.
108 /// Functions that take more than zero arguments can be executed (with
109 /// fixed arguments) by wrapping them in a lambda or with std::bind.
110 template<class subc> template<class F, class Cond>
111 auto TExecutor<subc>::Map(F func, unsigned nTimes) -> std::vector<typename std::result_of<F()>::type>
112 {
113  return Derived().Map(func, nTimes);
114 }
115 
116 //////////////////////////////////////////////////////////////////////////
117 /// Execute func in parallel, taking an element of a
118 /// sequence as argument. Divides and groups the executions in nChunks with partial reduction;
119 /// A vector containg partial reductions' results is returned.
120 template<class subc> template<class F, class INTEGER, class Cond>
121 auto TExecutor<subc>::Map(F func, ROOT::TSeq<INTEGER> args) -> std::vector<typename std::result_of<F(INTEGER)>::type>
122 {
123  return Derived().Map(func, args);
124 }
125 
126 //////////////////////////////////////////////////////////////////////////
127 /// Execute func in parallel, taking an element of the std::initializer_list
128 /// as argument. Divides and groups the executions in nChunks with partial reduction;
129 /// A vector containg partial reductions' results is returned.
130 template<class subc> template<class F, class T, class Cond>
131 auto TExecutor<subc>::Map(F func, std::initializer_list<T> args) -> std::vector<typename std::result_of<F(T)>::type>
132 {
133  std::vector<T> vargs(std::move(args));
134  return Map(func, vargs);
135 }
136 
137 //////////////////////////////////////////////////////////////////////////
138 /// Execute func in parallel, taking an element of an
139 /// std::vector as argument.
140 /// A vector containg executions' results is returned.
141 // actual implementation of the Map method. all other calls with arguments eventually
142 // call this one
143 template<class subc> template<class F, class T, class Cond>
144 auto TExecutor<subc>::Map(F func, std::vector<T> &args) -> std::vector<typename std::result_of<F(T)>::type>
145 {
146  return Derived().Map(func, args);
147 }
148 
149 //////////////////////////////////////////////////////////////////////////
150 /// This method behaves just like Map, but an additional redfunc function
151 /// must be provided. redfunc is applied to the vector Map would return and
152 /// must return the same type as func. In practice, redfunc can be used to
153 /// "squash" the vector returned by Map into a single object by merging,
154 /// adding, mixing the elements of the vector.
155 template<class subc> template<class F, class INTEGER, class R, class Cond>
156 auto TExecutor<subc>::MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc) -> typename std::result_of<F(INTEGER)>::type
157 {
158  std::vector<INTEGER> vargs(args.size());
159  std::copy(args.begin(), args.end(), vargs.begin());
160  return Derived().MapReduce(func, vargs, redfunc);
161 }
162 
163 template<class subc> template<class F, class T, class R, class Cond>
164 auto TExecutor<subc>::MapReduce(F func, std::initializer_list<T> args, R redfunc) -> typename std::result_of<F(T)>::type
165 {
166  std::vector<T> vargs(std::move(args));
167  return Derived().MapReduce(func, vargs, redfunc);
168 }
169 
170 template<class subc> template<class F, class T, class Cond>
171 T* TExecutor<subc>::MapReduce(F func, std::vector<T*> &args)
172 {
173  return Derived().Reduce(Map(func, args));
174 }
175 
176 //////////////////////////////////////////////////////////////////////////
177 /// "Reduce" an std::vector into a single object by using the object's Merge
178 //Reduction for objects with the Merge() method
179 template<class subc> template<class T>
180 T* TExecutor<subc>::Reduce(const std::vector<T*> &mergeObjs)
181 {
182  TList l;
183  for(unsigned i =1; i<mergeObjs.size(); i++){
184  l.Add(mergeObjs[i]);
185  }
186  // use clone to return a new object
187  auto retHist = dynamic_cast<T*>((mergeObjs.front())->Clone());
188  if (retHist) retHist->Merge(&l);
189  return retHist;
190 }
191 
192 } // end namespace ROOT
193 
194 #endif
l
auto * l
Definition: textangle.C:4
ROOT::TExecutor
This class defines an interface to execute the same task multiple times in parallel,...
Definition: TExecutor.hxx:61
F
#define F(x, y, z)
ROOT::TExecutor::MapReduce
auto MapReduce(F func, ROOT::TSeq< INTEGER > args, R redfunc) -> typename std::result_of< F(INTEGER)>::type
This method behaves just like Map, but an additional redfunc function must be provided.
Definition: TExecutor.hxx:156
ROOT::TExecutor::TExecutor
TExecutor()=default
TList.h
R
#define R(a, b, c, d, e, f, g, h, i)
Definition: RSha256.hxx:128
ROOT::TExecutor::Map
auto Map(F func, unsigned nTimes) -> std::vector< typename std::result_of< F()>::type >
Execute func (with no arguments) nTimes in parallel.
Definition: TExecutor.hxx:111
ROOT::TExecutor::TExecutor
TExecutor(size_t)
Definition: TExecutor.hxx:64
TSeq.hxx
ROOT::TExecutor< TThreadExecutor >::noReferenceCond
typename std::enable_if<"Function can't return a reference" &&!(std::is_reference< typename std::result_of< F(T...)>::type >::value)>::type noReferenceCond
Definition: TExecutor.hxx:67
ROOT::TExecutor::Derived
subc & Derived()
Definition: TExecutor.hxx:99
ROOT::Math::Chebyshev::T
double T(double x)
Definition: ChebyshevPol.h:52
ROOT::TSeq
A pseudo container class which is a generator of indices.
Definition: TSeq.hxx:66
type
int type
Definition: TGX11.cxx:121
ROOT::VecOps::Map
auto Map(Args &&... args) -> decltype(ROOT::Detail::VecOps::MapFromTuple(std::forward_as_tuple(args...), std::make_index_sequence< sizeof...(args) - 1 >()))
Create new collection applying a callable to the elements of the input collection.
Definition: RVec.hxx:909
ROOT
VSD Structures.
Definition: StringConv.hxx:21
TList
Definition: TList.h:44
ROOT::TExecutor::Reduce
T * Reduce(const std::vector< T * > &mergeObjs)
"Reduce" an std::vector into a single object by using the object's Merge
Definition: TExecutor.hxx:180