12#ifndef ROOT_TThreadExecutor
13#define ROOT_TThreadExecutor
15#include "RConfigure.h"
20# if !defined(__ROOTCLING__) && !defined(G__DICTIONARY)
21#error "Cannot use ROOT::TThreadExecutor when build option imt=Off."
33#include <initializer_list>
45 TThreadExecutor &pool, std::unique_ptr<ROOT::Internal::IMTUtils::RAbstractTBBRangeImpl> rangeImpl,
58 void Foreach(F func,
unsigned nTimes,
unsigned nChunks = 0);
59 template<
class F,
class INTEGER>
61 template<
class F,
class T>
62 void Foreach(F func, std::initializer_list<T> args,
unsigned nChunks = 0);
63 template<
class F,
class T>
64 void Foreach(F func, std::vector<T> &args,
unsigned nChunks = 0);
65 template<
class F,
class T>
66 void Foreach(F func,
const std::vector<T> &args,
unsigned nChunks = 0);
73 template <
class F,
class R,
class Cond = val
idMapReturnCond<F>>
74 auto Map(F func,
unsigned nTimes,
R redfunc,
unsigned nChunks) -> std::vector<InvokeResult_t<F>>;
75 template <
class F,
class INTEGER,
class R,
class Cond = val
idMapReturnCond<F, INTEGER>>
77 -> std::vector<InvokeResult_t<F, INTEGER>>;
78 template <
class F,
class T,
class R,
class Cond = val
idMapReturnCond<F, T>>
79 auto Map(F func, std::initializer_list<T> args,
R redfunc,
unsigned nChunks) -> std::vector<InvokeResult_t<F, T>>;
80 template <
class F,
class T,
class R,
class Cond = val
idMapReturnCond<F, T>>
81 auto Map(F func, std::vector<T> &args,
R redfunc,
unsigned nChunks) -> std::vector<InvokeResult_t<F, T>>;
82 template <
class F,
class T,
class R,
class Cond = val
idMapReturnCond<F, T>>
83 auto Map(F func,
const std::vector<T> &args,
R redfunc,
unsigned nChunks) -> std::vector<InvokeResult_t<F, T>>;
94 template <
class F,
class R,
class Cond = val
idMapReturnCond<F>>
96 template <
class F,
class R,
class Cond = val
idMapReturnCond<F>>
98 template <
class F,
class INTEGER,
class R,
class Cond = val
idMapReturnCond<F, INTEGER>>
100 template <
class F,
class T,
class R,
class Cond = val
idMapReturnCond<F, T>>
102 template <
class F,
class T,
class R,
class Cond = val
idMapReturnCond<F, T>>
104 template <
class F,
class T,
class R,
class Cond = val
idMapReturnCond<F, T>>
106 template <
class F,
class T,
class R,
class Cond = val
idMapReturnCond<F, T>>
108 template <
class F,
class T,
class R,
class Cond = val
idMapReturnCond<F, T>>
112 template<
class T,
class R>
auto Reduce(
const std::vector<T> &objs,
R redfunc) ->
decltype(redfunc(objs));
113 template<
class T,
class BINARYOP>
auto Reduce(
const std::vector<T> &objs, BINARYOP redfunc) ->
decltype(redfunc(objs.front(), objs.front()));
120 template <
class F,
class Cond = val
idMapReturnCond<F>>
121 auto MapImpl(F func,
unsigned nTimes) -> std::vector<InvokeResult_t<F>>;
122 template <
class F,
class INTEGER,
class Cond = val
idMapReturnCond<F, INTEGER>>
124 template <
class F,
class T,
class Cond = val
idMapReturnCond<F, T>>
125 auto MapImpl(F func, std::vector<T> &args) -> std::vector<InvokeResult_t<F, T>>;
126 template <
class F,
class T,
class Cond = val
idMapReturnCond<F, T>>
127 auto MapImpl(F func,
const std::vector<T> &args) -> std::vector<InvokeResult_t<F, T>>;
130 void ParallelFor(
unsigned start,
unsigned end,
unsigned step,
const std::function<
void(
unsigned int i)> &
f);
131 void ParallelFor(std::unique_ptr<ROOT::Internal::IMTUtils::RAbstractTBBRangeImpl> rangeImpl,
133 double ParallelReduce(
const std::vector<double> &objs,
const std::function<
double(
double a,
double b)> &redfunc);
134 float ParallelReduce(
const std::vector<float> &objs,
const std::function<
float(
float a,
float b)> &redfunc);
135 template<
class T,
class R>
136 auto SeqReduce(
const std::vector<T> &objs,
R redfunc) ->
decltype(redfunc(objs));
139 std::shared_ptr<ROOT::Internal::RTaskArenaWrapper>
fTaskArenaW =
nullptr;
153 ParallelFor(0U, nTimes, 1, [&](
unsigned int){func();});
157 unsigned step = (nTimes + nChunks - 1) / nChunks;
158 auto lambda = [&](
unsigned int i)
160 for (
unsigned j = 0; j < step && (i + j) < nTimes; j++) {
173 template<
class F,
class INTEGER>
179 unsigned start = *args.
begin();
180 unsigned end = *args.
end();
181 unsigned seqStep = args.
step();
182 unsigned step = (end - start + nChunks - 1) / nChunks;
184 auto lambda = [&](
unsigned int i)
186 for (
unsigned j = 0; j < step && (i + j) < end; j+=seqStep) {
199 template<
class F,
class T>
201 std::vector<T> vargs(std::move(args));
211 template<
class F,
class T>
213 unsigned int nToProcess = args.size();
215 ParallelFor(0U, nToProcess, 1, [&](
unsigned int i){func(args[i]);});
219 unsigned step = (nToProcess + nChunks - 1) / nChunks;
220 auto lambda = [&](
unsigned int i)
222 for (
unsigned j = 0; j < step && (i + j) < nToProcess; j++) {
235 template<
class F,
class T>
237 unsigned int nToProcess = args.size();
239 ParallelFor(0U, nToProcess, 1, [&](
unsigned int i){func(args[i]);});
243 unsigned step = (nToProcess + nChunks - 1) / nChunks;
244 auto lambda = [&](
unsigned int i)
246 for (
unsigned j = 0; j < step && (i + j) < nToProcess; j++) {
258 template <
class F,
class Cond>
261 using retType =
decltype(func());
262 std::vector<retType> reslist(nTimes);
263 auto lambda = [&](
unsigned int i)
267 ParallelFor(0U, nTimes, 1, lambda);
277 template <
class F,
class INTEGER,
class Cond>
280 using retType =
decltype(func(*args.begin()));
281 std::vector<retType> reslist(args.size());
282 auto lambda = [&](
unsigned int i) { reslist[i] = func(args[i]); };
283 ParallelFor(0U, args.size(), 1, lambda);
293 template <
class F,
class R,
class Cond>
298 return Map(func, nTimes);
301 unsigned step = (nTimes + nChunks - 1) / nChunks;
303 unsigned actualChunks = (nTimes + step - 1) / step;
304 using retType =
decltype(func());
305 std::vector<retType> reslist(actualChunks);
306 auto lambda = [&](
unsigned int i)
308 std::vector<retType> partialResults(std::min(nTimes-i, step));
309 for (
unsigned j = 0; j < step && (i + j) < nTimes; j++) {
310 partialResults[j] = func();
312 reslist[i / step] = Reduce(partialResults, redfunc);
314 ParallelFor(0U, nTimes, step, lambda);
324 template <
class F,
class T,
class Cond>
328 using retType =
decltype(func(args.front()));
330 unsigned int nToProcess = args.size();
331 std::vector<retType> reslist(nToProcess);
333 auto lambda = [&](
unsigned int i)
335 reslist[i] = func(args[i]);
338 ParallelFor(0U, nToProcess, 1, lambda);
348 template <
class F,
class T,
class Cond>
352 using retType =
decltype(func(args.front()));
354 unsigned int nToProcess = args.size();
355 std::vector<retType> reslist(nToProcess);
357 auto lambda = [&](
unsigned int i)
359 reslist[i] = func(args[i]);
362 ParallelFor(0U, nToProcess, 1, lambda);
372 template <
class F,
class INTEGER,
class R,
class Cond>
374 -> std::vector<InvokeResult_t<F, INTEGER>>
378 return Map(func, args);
381 unsigned nToProcess = args.size();
382 unsigned step = (nToProcess + nChunks - 1) / nChunks;
384 unsigned actualChunks = (nToProcess + step - 1) / step;
386 using retType =
decltype(func(*args.begin()));
387 std::vector<retType> reslist(actualChunks);
388 auto lambda = [&](
unsigned int i) {
389 std::vector<retType> partialResults(std::min(step, nToProcess - i));
390 for (
unsigned j = 0; j < partialResults.size(); j++) {
391 partialResults[j] = func(args[i + j]);
393 reslist[i / step] = Reduce(partialResults, redfunc);
396 ParallelFor(0U, nToProcess, step, lambda);
406 template <
class F,
class T,
class R,
class Cond>
408 -> std::vector<InvokeResult_t<F, T>>
412 return Map(func, args);
415 unsigned int nToProcess = args.size();
416 unsigned step = (nToProcess + nChunks - 1) / nChunks;
418 unsigned actualChunks = (nToProcess + step - 1) / step;
420 using retType =
decltype(func(args.front()));
421 std::vector<retType> reslist(actualChunks);
422 auto lambda = [&](
unsigned int i) {
423 std::vector<retType> partialResults(std::min(step, nToProcess - i));
424 for (
unsigned j = 0; j < partialResults.size(); j++) {
425 partialResults[j] = func(args[i + j]);
427 reslist[i / step] = Reduce(partialResults, redfunc);
430 ParallelFor(0U, nToProcess, step, lambda);
440 template <
class F,
class T,
class R,
class Cond>
442 -> std::vector<InvokeResult_t<F, T>>
446 return Map(func, args);
449 unsigned int nToProcess = args.size();
450 unsigned step = (nToProcess + nChunks - 1) / nChunks;
452 unsigned actualChunks = (nToProcess + step - 1) / step;
454 using retType =
decltype(func(args.front()));
455 std::vector<retType> reslist(actualChunks);
456 auto lambda = [&](
unsigned int i) {
457 std::vector<retType> partialResults(std::min(step, nToProcess - i));
458 for (
unsigned j = 0; j < partialResults.size(); j++) {
459 partialResults[j] = func(args[i + j]);
461 reslist[i / step] = Reduce(partialResults, redfunc);
464 ParallelFor(0U, nToProcess, step, lambda);
474 template <
class F,
class T,
class R,
class Cond>
476 -> std::vector<InvokeResult_t<F, T>>
478 std::vector<T> vargs(std::move(args));
479 const auto &reslist = Map(func, vargs, redfunc, nChunks);
486 template <
class F,
class R,
class Cond>
489 return Reduce(Map(func, nTimes), redfunc);
497 template <
class F,
class R,
class Cond>
500 return Reduce(Map(func, nTimes, redfunc, nChunks), redfunc);
508 template <
class F,
class INTEGER,
class R,
class Cond>
512 return Reduce(Map(func, args, redfunc, nChunks), redfunc);
520 template <
class F,
class T,
class R,
class Cond>
524 return Reduce(Map(func, args, redfunc, nChunks), redfunc);
530 template <
class F,
class T,
class R,
class Cond>
533 return Reduce(Map(func, args), redfunc);
539 template <
class F,
class T,
class R,
class Cond>
542 return Reduce(Map(func, args), redfunc);
550 template <
class F,
class T,
class R,
class Cond>
553 return Reduce(Map(func, args, redfunc, nChunks), redfunc);
561 template <
class F,
class T,
class R,
class Cond>
565 return Reduce(Map(func, args, redfunc, nChunks), redfunc);
570 template<
class T,
class R>
574 static_assert(std::is_same<
decltype(redfunc(objs)), T>
::value,
"redfunc does not have the correct signature");
575 return SeqReduce(objs, redfunc);
585 template<
class T,
class BINARYOP>
589 static_assert(std::is_same<
decltype(redfunc(objs.front(), objs.front())), T>
::value,
"redfunc does not have the correct signature");
590 return ParallelReduce(objs, redfunc);
599 template<
class T,
class R>
602 return redfunc(objs);
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void value
Abstract implementation of the oneAPI Range requirements.
This class defines an interface to execute the same task multiple times, possibly in parallel and wit...
ROOT::TypeTraits::InvokeResult_t< F, Args... > InvokeResult_t
A pseudo container class which is a generator of indices.
This class provides a simple interface to execute the same task multiple times in parallel threads,...
auto SeqReduce(const std::vector< T > &objs, R redfunc) -> decltype(redfunc(objs))
"Reduce", sequentially, an std::vector into a single object
auto Map(F func, unsigned nTimes, R redfunc, unsigned nChunks) -> std::vector< InvokeResult_t< F > >
Execute a function nTimes in parallel, dividing the execution in nChunks and providing a result per c...
unsigned GetPoolSize() const
Returns the number of worker threads in the task arena.
friend void ROOT::Internal::IMTUtils::ParallelFor(TThreadExecutor &pool, std::unique_ptr< ROOT::Internal::IMTUtils::RAbstractTBBRangeImpl > rangeImpl, const std::function< void(const ROOT::Internal::IMTUtils::RAbstractTBBRangeImpl &)> &body)
auto MapReduce(F func, unsigned nTimes, R redfunc) -> InvokeResult_t< F >
Execute a function nTimes in parallel (Map) and accumulate the results into a single value (Reduce).
std::shared_ptr< ROOT::Internal::RTaskArenaWrapper > fTaskArenaW
Pointer to the TBB task arena wrapper.
auto Reduce(const std::vector< T > &objs, R redfunc) -> decltype(redfunc(objs))
"Reduce" an std::vector into a single object by passing a function as the second argument defining th...
void Foreach(F func, unsigned nTimes, unsigned nChunks=0)
Execute a function without arguments several times in parallel, dividing the execution in nChunks.
TThreadExecutor(UInt_t nThreads=0u)
Class constructor.
double ParallelReduce(const std::vector< double > &objs, const std::function< double(double a, double b)> &redfunc)
"Reduce" in parallel an std::vector<double> into a single double value
TThreadExecutor & operator=(const TThreadExecutor &)=delete
TThreadExecutor(const TThreadExecutor &)=delete
auto MapImpl(F func, unsigned nTimes) -> std::vector< InvokeResult_t< F > >
Execute a function without arguments several times in parallel.
void ParallelFor(ROOT::TThreadExecutor &pool, std::unique_ptr< RAbstractTBBRangeImpl > rangeImpl, const std::function< void(const RAbstractTBBRangeImpl &)> &body)