File indexing completed on 2025-01-18 10:10:59
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef ROOT_TMVA_Executor
0019 #define ROOT_TMVA_Executor
0020
0021 #include <memory>
0022 #include <vector>
0023
0024 #include <ROOT/TSequentialExecutor.hxx>
0025 #ifdef R__USE_IMT
0026 #include <ROOT/TThreadExecutor.hxx>
0027 #endif
0028
0029 #include <TROOT.h>
0030 #include <TError.h>
0031
0032 namespace TMVA {
0033
0034
0035
0036 class Executor {
0037
0038 template <typename F, typename... Args>
0039 using InvokeResult_t = ROOT::TypeTraits::InvokeResult_t<F, Args...>;
0040
0041 public:
0042 template <class F, class... T>
0043 using noReferenceCond = typename std::enable_if_t<"Function can't return a reference" &&
0044 !(std::is_reference<InvokeResult_t<F, T...>>::value)>;
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059 Executor() {
0060
0061 if (ROOT::IsImplicitMTEnabled() ) {
0062 #ifdef R__USE_IMT
0063 fMTExecImpl = std::unique_ptr< ROOT::TThreadExecutor>(new ROOT::TThreadExecutor());
0064 #else
0065 ::Error("Executor","Cannot have TMVA in multi-threads mode when ROOT is built without IMT");
0066 #endif
0067 }
0068
0069 if (!fMTExecImpl)
0070 fSeqExecImpl = std::unique_ptr<ROOT::TSequentialExecutor>(new ROOT::TSequentialExecutor());
0071 }
0072
0073
0074
0075
0076
0077
0078
0079
0080 explicit Executor(int nthreads) {
0081
0082
0083 if ( nthreads != 1 ) {
0084 #ifdef R__USE_IMT
0085 fMTExecImpl = std::unique_ptr< ROOT::TThreadExecutor>(new ROOT::TThreadExecutor(nthreads));
0086 #else
0087 ::Error("Executor","Cannot have TMVA in multi-threads mode when ROOT is built without IMT");
0088 #endif
0089 }
0090
0091 if (!fMTExecImpl)
0092 fSeqExecImpl = std::unique_ptr<ROOT::TSequentialExecutor>(new ROOT::TSequentialExecutor());
0093 }
0094
0095 #ifdef R__USE_IMT
0096 ROOT::TThreadExecutor * GetMultiThreadExecutor() {
0097 if (fMTExecImpl) return fMTExecImpl.get();
0098 else {
0099 fMTExecImpl = std::unique_ptr< ROOT::TThreadExecutor>(new ROOT::TThreadExecutor());
0100 Info("GetThreadExecutor","Creating a TThread executor with a pool with a default size of %d",fMTExecImpl->GetPoolSize());
0101 return fMTExecImpl.get();
0102 }
0103 }
0104 #endif
0105
0106 unsigned int GetPoolSize() const {
0107 if (!fMTExecImpl) return 1;
0108 #ifdef R__USE_IMT
0109 return fMTExecImpl->GetPoolSize();
0110 #else
0111 return 1;
0112 #endif
0113 }
0114
0115
0116 template<class Function>
0117 void Foreach(Function func, unsigned int nTimes, unsigned nChunks = 0) {
0118 if (fMTExecImpl) fMTExecImpl->Foreach(func,nTimes, nChunks);
0119 else fSeqExecImpl->Foreach(func,nTimes);
0120 }
0121 template<class Function, class T>
0122 void Foreach(Function func, std::vector<T> & args, unsigned nChunks = 0) {
0123 if (fMTExecImpl) fMTExecImpl->Foreach(func,args, nChunks);
0124 else fSeqExecImpl->Foreach(func, args);
0125 }
0126 template<class Function, class INTEGER>
0127 #ifdef R__USE_IMT
0128 void Foreach(Function func, ROOT::TSeq<INTEGER> args, unsigned nChunks = 0){
0129 if (fMTExecImpl) fMTExecImpl->Foreach(func,args, nChunks);
0130 else fSeqExecImpl->Foreach(func, args);
0131 }
0132 #else
0133 void Foreach(Function func, ROOT::TSeq<INTEGER> args, unsigned = 0){
0134 fSeqExecImpl->Foreach(func, args);
0135 }
0136 #endif
0137
0138
0139 template <class F, class Cond = noReferenceCond<F>>
0140 auto Map(F func, unsigned nTimes) -> std::vector<InvokeResult_t<F>>
0141 {
0142 if (fMTExecImpl) return fMTExecImpl->Map(func,nTimes);
0143 else return fSeqExecImpl->Map(func, nTimes);
0144 }
0145 template <class F, class INTEGER, class Cond = noReferenceCond<F, INTEGER>>
0146 auto Map(F func, ROOT::TSeq<INTEGER> args) -> std::vector<InvokeResult_t<F, INTEGER>>
0147 {
0148 if (fMTExecImpl) return fMTExecImpl->Map(func,args);
0149 else return fSeqExecImpl->Map(func, args);
0150 }
0151
0152
0153 template <class F, class INTEGER, class R, class Cond = noReferenceCond<F, INTEGER>>
0154 auto MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc) -> InvokeResult_t<F, INTEGER>
0155 {
0156 if (fMTExecImpl) return fMTExecImpl->MapReduce(func, args, redfunc);
0157 else return fSeqExecImpl->MapReduce(func, args, redfunc);
0158 }
0159 template <class F, class INTEGER, class R, class Cond = noReferenceCond<F, INTEGER>>
0160 auto MapReduce(F func, ROOT::TSeq<INTEGER> args, R redfunc, unsigned nChunks) -> InvokeResult_t<F, INTEGER>
0161 {
0162 if (fMTExecImpl) return fMTExecImpl->MapReduce(func, args, redfunc, nChunks);
0163 else return fSeqExecImpl->MapReduce(func, args, redfunc);
0164 }
0165
0166
0167 template<class T, class R>
0168 auto Reduce(const std::vector<T> &objs, R redfunc) -> decltype(redfunc(objs)) {
0169 if (fMTExecImpl) return fMTExecImpl->Reduce(objs, redfunc);
0170 else return fSeqExecImpl->Reduce(objs, redfunc);
0171 }
0172
0173
0174 #ifdef R__USE_IMT
0175 std::unique_ptr<ROOT::TThreadExecutor> fMTExecImpl;
0176 #else
0177 std::unique_ptr<ROOT::TSequentialExecutor> fMTExecImpl;
0178 #endif
0179 std::unique_ptr<ROOT::TSequentialExecutor> fSeqExecImpl;
0180 };
0181
0182 }
0183
0184 #endif