Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:10:59

0001 // @(#)root/tmva $Id$
0002 // Author: Lorenzo Moneta
0003 /*************************************************************************
0004  * Copyright (C) 2019, ROOT/TMVA                                         *
0005  * All rights reserved.                                                  *
0006  *                                                                       *
0007  * For the licensing terms see $ROOTSYS/LICENSE.                         *
0008  * For the list of contributors see $ROOTSYS/README/CREDITS.             *
0009  *************************************************************************/
0010 
0011 //////////////////////////////////////////////////////////////////////////
0012 //
0013 //  Defining Executor classes to be used in TMVA
0014 // wrapping the functionality of the ROOT TThreadExecutor and
0015 // ROOT TSequential Executor
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 /// Base Executor class
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    /// Default constructor of TMVA Executor class
0048    /// if ROOT::EnableImplicitMT has not been called then by default a serial executor will be created
0049    /// A user can create a thread pool and enable multi-thread excution by calling
0050    /// 
0051    /// ~~~{.cpp}
0052    /// TMVA::Config::Instance()::%EnableMT(int nthreads);
0053    /// ~~~
0054    ///
0055    /// For releasing the thread pool used by TMVA one can do it by calling
0056    ///
0057    ///     TMVA::Config::Instance()::%DisableMT();
0058    ////////////////////////////////////////////
0059    Executor() {
0060       // enable MT in TMVA if ROOT::IsImplicitMT is enabled
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       // case of single thread usage
0069       if (!fMTExecImpl)
0070          fSeqExecImpl = std::unique_ptr<ROOT::TSequentialExecutor>(new ROOT::TSequentialExecutor());
0071    }
0072 
0073    //////////////////////////////////////
0074    /// Constructor of TMVA Executor class
0075    /// Explicit specify the number of threads. In this case if nthreads is > 1 a multi-threaded executor will be created and
0076    /// TMVA will run in MT.
0077    /// If nthreads = 1 instead TMVA will run in sequential mode
0078    /// If nthreads = 0 TMVA will use the default thread pool size
0079    ////////////////////////////////////////////
0080    explicit Executor(int nthreads) {
0081       // enable MT in TMVA if :
0082       //  - no specific MT
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       // case of single thread usage
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    /// wrap TExecutor::Foreach
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 /*nChunks*/ = 0){
0134       fSeqExecImpl->Foreach(func, args);
0135     }
0136 #endif
0137 
0138    /// Wrap TExecutor::Map functions
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    /// Wrap TExecutor::MapReduce functions
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    ///Wrap Reduce function
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    //template<class T> T* Reduce(const std::vector<T*> &mergeObjs);
0173 
0174 #ifdef R__USE_IMT
0175    std::unique_ptr<ROOT::TThreadExecutor>  fMTExecImpl;
0176 #else
0177    std::unique_ptr<ROOT::TSequentialExecutor> fMTExecImpl; // if not using MT the two pointers will be of same type
0178 #endif
0179    std::unique_ptr<ROOT::TSequentialExecutor> fSeqExecImpl;
0180 };
0181 
0182 }  // end namespace TMVA
0183 
0184 #endif