17 #include "tbb/task_scheduler_observer.h" 18 #include "tbb/tbb_thread.h" 19 #include "tbb/tick_count.h" 27 namespace Concurrency {
37 declareProperty(
"ThreadInitTools", m_threadInitTools,
"ToolHandleArray of IThreadInitTools" );
47 warning() <<
"Base class could not be initialized" <<
endmsg;
51 if ( m_threadInitTools.retrieve().isFailure() ) {
52 error() <<
"Unable to retrieve ThreadInitTools Array" <<
endmsg;
56 if ( m_threadInitTools.size() != 0 ) {
57 info() <<
"retrieved " << m_threadInitTools.size() <<
" thread init tools" <<
endmsg;
59 info() <<
"no thread init tools attached" <<
endmsg;
70 warning() <<
"Looks like the ThreadPoolSvc was created, but thread pool " 71 <<
"was never initialized" <<
endmsg;
81 tbb::spin_mutex::scoped_lock lock( m_initMutex );
83 m_threadPoolSize = poolSize;
85 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"ThreadPoolSvc::initPool() poolSize = " << poolSize <<
endmsg;
99 if ( -100 != m_threadPoolSize ) {
100 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"Initialising a thread pool of size " << m_threadPoolSize <<
endmsg;
104 int thePoolSize = m_threadPoolSize;
105 if ( thePoolSize >= 0 ) thePoolSize += 1;
107 if ( m_threadPoolSize == -1 ) {
110 thePoolSize = m_threadPoolSize;
111 }
else if ( m_threadPoolSize < -1 ) {
112 fatal() <<
"Unexpected ThreadPoolSize \"" << m_threadPoolSize <<
"\". Allowed negative values are " 113 <<
"-1 (use all available cores) and -100 (don't use a thread pool)" <<
endmsg;
117 #if TBB_INTERFACE_VERSION_MAJOR < 12 118 m_tbbSchedInit = std::make_unique<tbb::task_scheduler_init>( thePoolSize );
119 #endif // TBB_INTERFACE_VERSION_MAJOR < 12 121 m_tbbgc = std::make_unique<tbb::global_control>( global_control::max_allowed_parallelism, thePoolSize );
126 m_barrier = std::make_unique<boost::barrier>( thePoolSize );
131 m_tbbgc = std::make_unique<tbb::global_control>( global_control::max_allowed_parallelism, 0 );
135 debug() <<
"Thread Pool initialization complete. Max task concurrency: " 136 << tbb::global_control::active_value( global_control::max_allowed_parallelism ) <<
endmsg;
146 tbb::spin_mutex::scoped_lock lock( m_initMutex );
147 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"ThreadPoolSvc::terminatePool()" <<
endmsg;
150 error() <<
"Trying to terminate uninitialized thread pool!" <<
endmsg;
155 const bool terminate =
true;
158 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"Thread pool termination complete!" <<
endmsg;
167 const std::string taskType = terminate ?
"termination" :
"initialization";
171 if ( tbb::global_control::active_value( global_control::max_allowed_parallelism ) > 0 ) {
174 for (
int i = 0; i < m_threadPoolSize; ++i ) {
175 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"creating ThreadInitTask " << i <<
endmsg;
176 tbb::task* t =
new ( tbb::task::allocate_root() )
177 ThreadInitTask( m_threadInitTools, m_barrier.get(), serviceLocator(), terminate );
180 tbb::task::enqueue( *t );
185 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"waiting at barrier for all ThreadInitTool to finish executing" <<
endmsg;
190 for (
auto& t : m_threadInitTools ) {
192 int numInit = t->nInit();
194 int expectedNumInit = terminate ? 0 : m_threadPoolSize;
195 if ( numInit != expectedNumInit ) {
197 ost <<
"not all threads " << ( terminate ?
"terminated" :
"initialized" ) <<
" for tool " << t <<
" : " 198 << t->nInit() <<
" out of " << m_threadPoolSize <<
" are currently active.";
215 if ( msgLevel(
MSG::DEBUG ) ) debug() <<
"launching ThreadInitTask " << taskType <<
"in this thread." <<
endmsg;
216 boost::barrier* noBarrier =
nullptr;
217 ThreadInitTask theTask( m_threadInitTools, noBarrier, serviceLocator(), terminate );
223 error() <<
"a ThreadInitTask failed to execute successfully" <<
endmsg;
250 error() <<
"initThisThread triggered, but thread already initialized" <<
endmsg;
254 boost::barrier* noBarrier =
nullptr;
255 ThreadInitTask theTask( m_threadInitTools, noBarrier, serviceLocator(),
false );
StatusCode finalize() override final
Finalise.
static GAUDI_API void setNumThreads(const std::size_t &nT)
StatusCode initialize() override
tbb::task * execute() override
Execute the task.
Define general base for Gaudi exception.
The ISvcLocator is the interface implemented by the Service Factory in the Application Manager to loc...
StatusCode terminatePool() override final
Terminate the thread pool and launch thread termination tasks.
Special TBB task used by ThreadPoolSvc to wrap execution of IThreadInitTools.
constexpr static const auto SUCCESS
virtual void initThisThread() override
T hardware_concurrency(T... args)
#define GAUDI_NO_SANITIZE_ADDRESS
#define DECLARE_COMPONENT(type)
This class is used for returning status codes from appropriate routines.
StatusCode initialize() override final
Initialise.
thread_local bool ThreadInitDone
Base class used to extend a class implementing other interfaces.
A service which initializes a TBB thread pool.
constexpr static const auto FAILURE
StatusCode initPool(const int &poolSize) override final
Initialize the thread pool and launch the ThreadInitTasks.
StatusCode launchTasks(bool finalize=false)
Launch tasks to execute the ThreadInitTools.
Header file for std:chrono::duration-based Counters.
MsgStream & endmsg(MsgStream &s)
MsgStream Modifier: endmsg. Calls the output method of the MsgStream.