diff --git a/core/base/inc/TROOT.h b/core/base/inc/TROOT.h index 82da4d81de093..ca70c2892101b 100644 --- a/core/base/inc/TROOT.h +++ b/core/base/inc/TROOT.h @@ -73,7 +73,7 @@ namespace Internal { TParBranchProcessingRAII() { EnableParBranchProcessing(); } ~TParBranchProcessingRAII() { DisableParBranchProcessing(); } }; - + // Manage parallel tree processing void EnableParTreeProcessing(); void DisableParTreeProcessing(); @@ -95,6 +95,7 @@ namespace ROOT { void DisableImplicitMT(); Bool_t IsImplicitMTEnabled(); UInt_t GetImplicitMTPoolSize(); + UInt_t GetAvailableThreads(); } class TROOT : public TDirectory { diff --git a/core/base/src/TROOT.cxx b/core/base/src/TROOT.cxx index f357dad02bdf0..46edea6ce5a0c 100644 --- a/core/base/src/TROOT.cxx +++ b/core/base/src/TROOT.cxx @@ -577,6 +577,21 @@ namespace Internal { #endif } + //////////////////////////////////////////////////////////////////////////////// + /// Returns the number of concurrent threads supported by the implementation. + /// In the IMT case returns the number of logical CPUs available to the current process in accordance with its TBB affinity mask. + UInt_t GetNThreadsAvailable() + { +#ifdef R__USE_IMT + static UInt_t (*sym)() = (UInt_t(*)())Internal::GetSymInLibImt("ROOT_TImplicitMT_GetNThreadsAvailable"); + if (sym) + return sym(); + else + return 0; +#else + return std::thread::hardware_concurrency(); +#endif + } } TROOT *ROOT::Internal::gROOTLocal = ROOT::GetROOT(); diff --git a/core/imt/inc/ROOT/TPoolManager.hxx b/core/imt/inc/ROOT/TPoolManager.hxx index 5268edb8833aa..afb4bf99f1b0c 100644 --- a/core/imt/inc/ROOT/TPoolManager.hxx +++ b/core/imt/inc/ROOT/TPoolManager.hxx @@ -72,6 +72,11 @@ namespace ROOT { /// The number of threads will be able to change calling the factory function again after the last /// remaining shared_ptr owning the object is destroyed or reasigned, which will trigger the destructor of the manager. std::shared_ptr GetPoolManager(UInt_t nThreads = 0); + + + /// Get the number of logical CPUs in the system. + /// In case of having an affinity mask (TBB), return the number of logical CPUs available to the current process in accordance with it. + Int_t GetNThreadsAvailable(); } } diff --git a/core/imt/src/TImplicitMT.cxx b/core/imt/src/TImplicitMT.cxx index 297cf3e27d299..415f2b627dc73 100644 --- a/core/imt/src/TImplicitMT.cxx +++ b/core/imt/src/TImplicitMT.cxx @@ -80,6 +80,10 @@ extern "C" UInt_t ROOT_TImplicitMT_GetImplicitMTPoolSize() return ROOT::Internal::TPoolManager::GetPoolSize(); }; +extern "C" UInt_t ROOT_TImplicitMT_GetNThreadsAvailable() +{ + return ROOT::Internal::GetNThreadsAvailable(); +}; extern "C" void ROOT_TImplicitMT_EnableParBranchProcessing() { diff --git a/core/imt/src/TPoolManager.cxx b/core/imt/src/TPoolManager.cxx index 27fde084b1719..81d0e4febcf27 100644 --- a/core/imt/src/TPoolManager.cxx +++ b/core/imt/src/TPoolManager.cxx @@ -55,5 +55,10 @@ namespace ROOT { } return GetWP().lock(); } + + Int_t GetNThreadsAvailable() + { + return tbb::task_scheduler_init::default_num_threads(); + } } }