ROOT   Reference Guide
TExecutor.cxx
Go to the documentation of this file.
1// @(#)root/thread:$Id$
2// Author: Xavier Valls September 2020
3
4/*************************************************************************
7 * *
8 * For the licensing terms see $ROOTSYS/LICENSE. * 9 * For the list of contributors see$ROOTSYS/README/CREDITS. *
10 *************************************************************************/
11
12#include "ROOT/TExecutor.hxx"
13
14//////////////////////////////////////////////////////////////////////////
15///
16/// \class ROOT::Internal::TExecutor
17/// \brief This class implements the interface to execute the same task
18/// multiple times, sequentially or in parallel depending on the execution policy passed
19/// as a first parameter on construction, and possibly with different arguments every time.
20///
21/// ###ROOT::Internal::TExecutor::Map
22/// The two possible usages of the Map method are:\n
23/// * Map(F func, unsigned nTimes): func is executed nTimes with no arguments
24/// * Map(F func, T& args): func is executed on each element of the collection of arguments args
25///
26/// For either signature, func is executed as many times as needed by a pool of
27/// n workers; where n tipically defaults to the number of cores.\n
28/// A collection containing the result of each execution is returned.\n
29/// **Note:** the user is responsible for the deletion of any object that might
30/// be created upon execution of func, returned objects included. ROOT::::Internal::TExecutor never
31/// deletes what it returns, it simply forgets it.\n
32///
33/// \param func
34/// \parblock
35/// a callable object, such as a lambda expression, an std::function, a
36/// functor object or a function that takes zero arguments (for the first signature)
37/// or one (for the second signature).
38/// \endparblock
39/// \param args
40/// \parblock
41/// a standard vector, a ROOT::TSeq of integer type or an initializer list for the second signature.
42/// An integer only for the first.\n
43/// \endparblock
44///
45/// **Note:** in cases where the function to be executed takes more than
46/// zero/one argument but all are fixed except zero/one, the function can be wrapped
47/// in a lambda or via std::bind to give it the right signature.\n
48///
49/// #### Return value:
50/// An std::vector. The elements in the container
51/// will be the objects returned by func.
52///
53/// ### ROOT::Internal::TExecutor::MapReduce
54/// This set of methods behaves exactly like Map, but takes an additional
55/// function as a third argument. This function is applied to the set of
56/// objects returned by the corresponding Map execution to "squash" them
57/// into a single object.
58///
59/// An integer can be passed as the fourth argument indicating the number of chunks we want to divide our work in.
60/// <b>(Note: Please be aware that chunking is only available when the policy is kMultiThread, ignoring this argument in other cases)</b>
61/// This may be useful to avoid the overhead introduced when running really short tasks. In this case, the reduction
62/// function should be independent of the size of the vector returned by Map due to optimization of the number of
63/// chunks.
64///
65/// #### Examples:
66/// ~~~{.cpp}
67/// root[] ROOT::Internal::TExecutor pool; auto ten = pool.MapReduce([]() { return 1; }, 10, [](const std::vector<int> &v) { return std::accumulate(v.begin(), v.end(), 0); })
68/// root[] ROOT::Internal::TExecutor pool(ROOT::EExecutionPolicy::kMultiProcess); auto hist = pool.MapReduce(CreateAndFillHists, 10, PoolUtils::ReduceObjects);
69/// ~~~
70///
71//////////////////////////////////////////////////////////////////////////
72
73
74namespace ROOT {
75namespace Internal {
76TExecutor::TExecutor(ROOT::EExecutionPolicy execPolicy, unsigned nWorkers): fExecPolicy(execPolicy) {
77 switch(fExecPolicy) {
79 fSequentialExecutor = std::make_unique<ROOT::TSequentialExecutor>();
80 break;
81#ifdef R__USE_IMT
84 break;
85#endif
86#ifndef R__WIN32
88 fProcessExecutor = std::make_unique<ROOT::TProcessExecutor>(nWorkers);
89 break;
90#endif
91 default:
92 throw std::invalid_argument(
93 "Invalid execution policy. Potential issues:\n* kMultiThread policy not available when ROOT is compiled with IMT=OFF.\n* kMultiprocess policy not available on Windows");
94 }
95}
96}
97}