Class that provides a pool of continuously running threads that can be used for reducing overhead in SMP computations. More...
#include <cmtkThreadPool.h>
Classes | |
class | ThreadPoolArg |
Thread function arguments: identify pool and index of thread in it. More... | |
Public Types | |
typedef ThreadPool | Self |
This class. | |
typedef SmartPointer< Self > | SmartPtr |
Smart pointer. | |
typedef void(* | TaskFunction )(void *const args, const size_t taskIdx, const size_t taskCnt, const size_t threadIdx, const size_t threadCont) |
Task function: this is the interface for the functions called by the pooled threads to do the actual work. | |
Public Member Functions | |
ThreadPool (const size_t nThreads=0) | |
Constructor: create a pool of nThreads running threads. | |
~ThreadPool () | |
Destructor: stop all running threads. | |
size_t | GetNumberOfThreads () const |
Return number of threads in the pool. | |
template<class TParam > | |
void | Run (TaskFunction taskFunction, std::vector< TParam > &taskParameters, const size_t numberOfTasksOverride=0) |
Run actual worker functions through running threads. | |
void | ThreadFunction (const size_t threadIdx) |
This function is run as a thread. | |
Static Public Member Functions | |
static Self & | GetGlobalThreadPool () |
Get reference to global thread pool. | |
Private Member Functions | |
void | StartThreads () |
Start threads for this pool. | |
void | EndThreads () |
End threads for this pool. | |
Private Attributes | |
ThreadSemaphore | m_TaskWaitingSemaphore |
Semaphore to signal running threads when tasks are waiting. | |
ThreadSemaphore | m_ThreadWaitingSemaphore |
Semaphore that threads use to signal when tasks they are ready for the next task. | |
size_t | m_NumberOfTasks |
Total number of tasks to execute. | |
size_t | m_NextTaskIndex |
Index of next available task. | |
MutexLock | m_NextTaskIndexLock |
Lock to ensure exclusive access to the task index counter. | |
TaskFunction | m_TaskFunction |
The current task function. | |
std::vector< void * > | m_TaskParameters |
Task function parameter pointers. | |
std::vector< Self::ThreadPoolArg > | m_ThreadArgs |
Thread function parameters. | |
size_t | m_NumberOfThreads |
Number of running threads. | |
bool | m_ThreadsRunning |
Flag whether threads for this pool are running. | |
bool | m_ContinueThreads |
Flag whether threads should continue or terminate. |
Class that provides a pool of continuously running threads that can be used for reducing overhead in SMP computations.
Every instance of this class starts a pool of threads upon initialization, which can later be used to execute arbitrary tasks. The threads are held via a semaphore, which are used to signal the availability of an arbitrary number of tasks. Once the task semaphores have been posted, the calling function waits for the running threads to signal back the same number of completed tasks via a second semaphore.
The main advantages of this thread execution framework are:
1. On platforms with inefficient, slow thread creation and joining (Win32), the use and re-use of a persistent set of threads greatly improves run-time efficiency and reduces overhead.
2. A single computation can be broken into more tasks than there are threads running, i.e., more tasks than there are CPUs available. This allows for load balancing, because tasks that complete faster than others will free the executing thread, which is then available to process the next available task without waiting for any other threads.
This class provides a global thread pool, which can (and should) be shared by all computations in a process. Creating additional thread pool instances should hardly ever be necessary.
To run tasks on the global thread pool, simply create a std::vector that contains a parameter block for each task. The size of the vector also determines the number of tasks to run. For example, the thread parameter could simply be a pointer to the current instance ("this") of a class that acts as the client that requests a parallel computation:
#include <vector> #include <System/cmtkThreadPool.h> class ComputationClass { public: typedef ComputationClass Self; void ComputeUsingSMP() { // run approximately four times as many tasks as there are threads (only one task for single thread) const size_t numberOfTasks = 4 * ThreadPool::GlobalThreadPool.GetNumberOfThreads() - 3; std::vector<Self*> taskParamaters( numberOfTasks, this ); cmtk::ThreadPool::GlobalThreadPool.Run( ComputeTask, taskParameters ); } void ComputeTask( void *const arg, const size_t taskIdx, const size_t taskCnt, const size_t threadIdx, const size_t threadCnt ) { Self* Caller = static_cast<Self*>( arg ); // more things to do for "Caller" // taskIdx is the index of this task; taskCnt is the total number of tasks. These two determine what part of the total work must be done. // threadIdx is the index of the "physical" thread out of threadCnt threads that are running in this pool. If temporary memory is allocated // for this function, then threadIdx can be used to index this temporary storage, thus allowing us to get by with threadCnt many spaces, // rather than taskCnt many, which is usuallu much larger. } }; *
Definition at line 105 of file cmtkThreadPool.h.
typedef ThreadPool cmtk::ThreadPool::Self |
This class.
Definition at line 111 of file cmtkThreadPool.h.